/contrib/games/opentyrian/.editorconfig |
---|
0,0 → 1,26 |
root = true |
[*] |
charset = utf-8 |
trim_trailing_whitespace = true |
end_of_line = lf |
insert_final_newline = true |
[Makefile] |
indent_style = tab |
[*.sln] |
charset = utf-8-bom |
indent_style = tab |
end_of_line = crlf |
insert_final_newline = false |
[*.{vcxproj,props.template}] |
indent_style = space |
indent_size = 2 |
end_of_line = crlf |
insert_final_newline = false |
[*.rc] |
charset = latin1 |
end_of_line = crlf |
/contrib/games/opentyrian/.gitignore |
---|
0,0 → 1,36 |
/data/ |
opentyrian.cfg |
tyrian.cfg |
tyrian.sav |
# Text editor detritus |
*~ |
*.swp |
# Make build output |
/obj/ |
/src/*.gch |
/opentyrian |
# Windows build output |
/opentyrian.exe |
/SDL.dll |
/SDL_net.dll |
# Windows runtime output |
/stderr.txt |
/stdout.txt |
# MSVC build output and project |
/opentyrian-*.exe |
/opentyrian-*.ilk |
/opentyrian-*.pdb |
/opentyrian-*.iobj |
/opentyrian-*.ipdb |
/visualc/.vs/ |
/visualc/*.props |
/visualc/*.user |
# Doxygen output |
/doc/doxygen/ |
/contrib/games/opentyrian/Makefile |
---|
0,0 → 1,88 |
CC = kos32-gcc |
LD = kos32-ld |
OBJCOPY = kos32-objcopy |
KPACK = kpack |
TYRIAN = opentyrian |
SDK_DIR = $(abspath ../../sdk) |
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident \ |
-U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -D_KOLIBRI \ |
-DTYRIAN_DIR='"/kolibrios/games/tyrian"' -DSDL_strlcpy=strncpy \ |
-D_GNU_SOURCE=1 -D_REENTRANT -DNDEBUG -Wno-missing-field-initializers |
LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds -Map=output.map --image-base 0 --subsystem native |
INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -Isrc |
LIBPATH = -L$(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib -L $(SDK_DIR)/lib |
OBJS = ./src/scroller.o \ |
./src/config.o \ |
./src/game_menu.o \ |
./src/file.o \ |
./src/opentyr.o \ |
./src/sndmast.o \ |
./src/sizebuf.o \ |
./src/video_scale.o \ |
./src/loudness.o \ |
./src/palette.o \ |
./src/joystick.o \ |
./src/lds_play.o \ |
./src/font.o \ |
./src/config_file.o \ |
./src/network.o \ |
./src/helptext.o \ |
./src/xmas.o \ |
./src/keyboard.o \ |
./src/jukebox.o \ |
./src/picload.o \ |
./src/shots.o \ |
./src/setup.o \ |
./src/mouse.o \ |
./src/musmast.o \ |
./src/nortvars.o \ |
./src/backgrnd.o \ |
./src/destruct.o \ |
./src/lvllib.o \ |
./src/video_scale_hqNx.o \ |
./src/std_support.o \ |
./src/mtrand.o \ |
./src/sprite.o \ |
./src/episodes.o \ |
./src/arg_parse.o \ |
./src/opl.o \ |
./src/video.o \ |
./src/editship.o \ |
./src/vga_palette.o \ |
./src/pcxload.o \ |
./src/fonthand.o \ |
./src/mainint.o \ |
./src/tyrian2.o \ |
./src/lvlmast.o \ |
./src/animlib.o \ |
./src/pcxmast.o \ |
./src/menus.o \ |
./src/starlib.o \ |
./src/player.o \ |
./src/nortsong.o \ |
./src/vga256d.o \ |
./src/varz.o \ |
./src/params.o \ |
./SDL/joystick_stub.o \ |
./SDL/SDL_wave.o \ |
./SDL/SDL_audiocvt.o \ |
./SDL/uSDL.o |
LIBS = -lgcc -lSDLn -lsound -lc.dll |
$(TYRIAN): $(OBJS) |
$(LD) $(LDFLAGS) $(LIBPATH) $(OBJS) -o $(TYRIAN) $(LIBS) |
$(OBJCOPY) $(TYRIAN) -O binary |
$(KPACK) --nologo $(TYRIAN) |
%.o : %.c |
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< |
clean: |
rm src/*.o |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/games/opentyrian/Makefile.linux |
---|
0,0 → 1,141 |
# BUILD SETTINGS ############################################################### |
ifneq ($(filter Msys Cygwin, $(shell uname -o)), ) |
PLATFORM := WIN32 |
TYRIAN_DIR = C:\\TYRIAN |
else |
PLATFORM := UNIX |
TYRIAN_DIR = $(gamesdir)/tyrian |
endif |
WITH_NETWORK := true |
################################################################################ |
# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html |
SHELL = /bin/sh |
CC ?= gcc |
INSTALL ?= install |
PKG_CONFIG ?= pkg-config |
VCS_IDREV ?= (git describe --tags || git rev-parse --short HEAD) |
INSTALL_PROGRAM ?= $(INSTALL) |
INSTALL_DATA ?= $(INSTALL) -m 644 |
prefix ?= /usr/local |
exec_prefix ?= $(prefix) |
bindir ?= $(exec_prefix)/bin |
datarootdir ?= $(prefix)/share |
datadir ?= $(datarootdir) |
docdir ?= $(datarootdir)/doc/opentyrian |
mandir ?= $(datarootdir)/man |
man6dir ?= $(mandir)/man6 |
man6ext ?= .6 |
# see http://www.pathname.com/fhs/pub/fhs-2.3.html |
gamesdir ?= $(datadir)/games |
### |
TARGET := opentyrian |
SRCS := $(wildcard src/*.c) |
OBJS := $(SRCS:src/%.c=obj/%.o) |
DEPS := $(SRCS:src/%.c=obj/%.d) |
### |
ifeq ($(WITH_NETWORK), true) |
EXTRA_CPPFLAGS += -DWITH_NETWORK |
endif |
OPENTYRIAN_VERSION := $(shell $(VCS_IDREV) 2>/dev/null && \ |
touch src/opentyrian_version.h) |
ifneq ($(OPENTYRIAN_VERSION), ) |
EXTRA_CPPFLAGS += -DOPENTYRIAN_VERSION='"$(OPENTYRIAN_VERSION)"' |
endif |
CPPFLAGS := -DNDEBUG |
CFLAGS := -pedantic |
CFLAGS += -MMD |
CFLAGS += -Wall \ |
-Wextra \ |
-Wno-missing-field-initializers |
CFLAGS += -O2 |
CFLAGS += -DuSDL_Delay=SDL_Delay |
LDFLAGS := |
LDLIBS := |
ifeq ($(WITH_NETWORK), true) |
SDL_CPPFLAGS := $(shell $(PKG_CONFIG) sdl SDL_net --cflags) |
SDL_LDFLAGS := $(shell $(PKG_CONFIG) sdl SDL_net --libs-only-L --libs-only-other) |
SDL_LDLIBS := $(shell $(PKG_CONFIG) sdl SDL_net --libs-only-l) |
else |
SDL_CPPFLAGS := $(shell $(PKG_CONFIG) sdl --cflags) |
SDL_LDFLAGS := $(shell $(PKG_CONFIG) sdl --libs-only-L --libs-only-other) |
SDL_LDLIBS := $(shell $(PKG_CONFIG) sdl --libs-only-l) |
endif |
ALL_CPPFLAGS = -DTARGET_$(PLATFORM) \ |
-DTYRIAN_DIR='"$(TYRIAN_DIR)"' \ |
$(EXTRA_CPPFLAGS) \ |
$(SDL_CPPFLAGS) \ |
$(CPPFLAGS) |
ALL_CFLAGS = -std=iso9899:1999 \ |
$(CFLAGS) |
ALL_LDFLAGS = $(SDL_LDFLAGS) \ |
$(LDFLAGS) |
ALL_LDLIBS = -lm \ |
$(SDL_LDLIBS) \ |
$(LDLIBS) |
### |
.PHONY : all |
all : $(TARGET) |
.PHONY : debug |
debug : CPPFLAGS += -UNDEBUG |
debug : CFLAGS += -Werror |
debug : CFLAGS += -O0 |
debug : CFLAGS += -g3 |
debug : all |
.PHONY : installdirs |
installdirs : |
mkdir -p $(DESTDIR)$(bindir) |
mkdir -p $(DESTDIR)$(docdir) |
mkdir -p $(DESTDIR)$(man6dir) |
.PHONY : install |
install : $(TARGET) installdirs |
$(INSTALL_PROGRAM) $(TARGET) $(DESTDIR)$(bindir)/ |
$(INSTALL_DATA) CREDITS NEWS README $(DESTDIR)$(docdir)/ |
$(INSTALL_DATA) linux/man/opentyrian.6 $(DESTDIR)$(man6dir)/opentyrian$(man6ext) |
.PHONY : uninstall |
uninstall : |
rm -f $(DESTDIR)$(bindir)/$(TARGET) |
rm -f $(DESTDIR)$(docdir)/{CREDITS,NEWS,README} |
rm -f $(DESTDIR)$(man6dir)/opentyrian$(man6ext) |
.PHONY : clean |
clean : |
rm -f $(OBJS) |
rm -f $(DEPS) |
rm -f $(TARGET) |
$(TARGET) : $(OBJS) |
$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ $(ALL_LDLIBS) |
-include $(DEPS) |
obj/%.o : src/%.c |
@mkdir -p "$(dir $@)" |
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $< |
/contrib/games/opentyrian/SDL/SDL_audiocvt.c |
---|
0,0 → 1,642 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
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 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 |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_audiocvt.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* Functions for audio drivers to perform runtime conversion of audio format */ |
#include <stdio.h> |
#include "SDL_error.h" |
#include "SDL_audio.h" |
/* Effectively mix right and left channels into a single channel */ |
void SDL_ConvertMono(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Sint32 sample; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to mono\n"); |
#endif |
switch (format&0x8018) { |
case AUDIO_U8: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
sample = src[0] + src[1]; |
if ( sample > 255 ) { |
*dst = 255; |
} else { |
*dst = sample; |
} |
src += 2; |
dst += 1; |
} |
} |
break; |
case AUDIO_S8: { |
Sint8 *src, *dst; |
src = (Sint8 *)cvt->buf; |
dst = (Sint8 *)cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
sample = src[0] + src[1]; |
if ( sample > 127 ) { |
*dst = 127; |
} else |
if ( sample < -128 ) { |
*dst = -128; |
} else { |
*dst = sample; |
} |
src += 2; |
dst += 1; |
} |
} |
break; |
case AUDIO_U16: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) == 0x1000 ) { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Uint16)((src[0]<<8)|src[1])+ |
(Uint16)((src[2]<<8)|src[3]); |
if ( sample > 65535 ) { |
dst[0] = 0xFF; |
dst[1] = 0xFF; |
} else { |
dst[1] = (sample&0xFF); |
sample >>= 8; |
dst[0] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} else { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Uint16)((src[1]<<8)|src[0])+ |
(Uint16)((src[3]<<8)|src[2]); |
if ( sample > 65535 ) { |
dst[0] = 0xFF; |
dst[1] = 0xFF; |
} else { |
dst[0] = (sample&0xFF); |
sample >>= 8; |
dst[1] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} |
} |
break; |
case AUDIO_S16: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) == 0x1000 ) { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Sint16)((src[0]<<8)|src[1])+ |
(Sint16)((src[2]<<8)|src[3]); |
if ( sample > 32767 ) { |
dst[0] = 0x7F; |
dst[1] = 0xFF; |
} else |
if ( sample < -32768 ) { |
dst[0] = 0x80; |
dst[1] = 0x00; |
} else { |
dst[1] = (sample&0xFF); |
sample >>= 8; |
dst[0] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} else { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Sint16)((src[1]<<8)|src[0])+ |
(Sint16)((src[3]<<8)|src[2]); |
if ( sample > 32767 ) { |
dst[1] = 0x7F; |
dst[0] = 0xFF; |
} else |
if ( sample < -32768 ) { |
dst[1] = 0x80; |
dst[0] = 0x00; |
} else { |
dst[0] = (sample&0xFF); |
sample >>= 8; |
dst[1] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} |
} |
break; |
} |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Duplicate a mono channel to both stereo channels */ |
void SDL_ConvertStereo(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to stereo\n"); |
#endif |
if ( (format & 0xFF) == 16 ) { |
Uint16 *src, *dst; |
src = (Uint16 *)(cvt->buf+cvt->len_cvt); |
dst = (Uint16 *)(cvt->buf+cvt->len_cvt*2); |
for ( i=cvt->len_cvt/2; i; --i ) { |
dst -= 2; |
src -= 1; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
} else { |
Uint8 *src, *dst; |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
dst -= 2; |
src -= 1; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
} |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 8-bit to 16-bit - LSB */ |
void SDL_Convert16LSB(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 16-bit LSB\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[1] = *src; |
dst[0] = 0; |
} |
format = ((format & ~0x0008) | AUDIO_U16LSB); |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 8-bit to 16-bit - MSB */ |
void SDL_Convert16MSB(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 16-bit MSB\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[0] = *src; |
dst[1] = 0; |
} |
format = ((format & ~0x0008) | AUDIO_U16MSB); |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 16-bit to 8-bit */ |
void SDL_Convert8(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 8-bit\n"); |
#endif |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ |
++src; |
} |
for ( i=cvt->len_cvt/2; i; --i ) { |
*dst = *src; |
src += 2; |
dst += 1; |
} |
format = ((format & ~0x9010) | AUDIO_U8); |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Toggle signed/unsigned */ |
void SDL_ConvertSign(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *data; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio signedness\n"); |
#endif |
data = cvt->buf; |
if ( (format & 0xFF) == 16 ) { |
if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ |
++data; |
} |
for ( i=cvt->len_cvt/2; i; --i ) { |
*data ^= 0x80; |
data += 2; |
} |
} else { |
for ( i=cvt->len_cvt; i; --i ) { |
*data++ ^= 0x80; |
} |
} |
format = (format ^ 0x8000); |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Toggle endianness */ |
void SDL_ConvertEndian(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *data, tmp; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio endianness\n"); |
#endif |
data = cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
tmp = data[0]; |
data[0] = data[1]; |
data[1] = tmp; |
data += 2; |
} |
format = (format ^ 0x1000); |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert rate up by multiple of 2 */ |
void SDL_RateMUL2(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate * 2\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
switch (format & 0xFF) { |
case 8: |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
break; |
case 16: |
for ( i=cvt->len_cvt/2; i; --i ) { |
src -= 2; |
dst -= 4; |
dst[0] = src[0]; |
dst[1] = src[1]; |
dst[2] = src[0]; |
dst[3] = src[1]; |
} |
break; |
} |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert rate down by multiple of 2 */ |
void SDL_RateDIV2(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate / 2\n"); |
#endif |
src = cvt->buf; |
dst = cvt->buf; |
switch (format & 0xFF) { |
case 8: |
for ( i=cvt->len_cvt/2; i; --i ) { |
dst[0] = src[0]; |
src += 2; |
dst += 1; |
} |
break; |
case 16: |
for ( i=cvt->len_cvt/4; i; --i ) { |
dst[0] = src[0]; |
dst[1] = src[1]; |
src += 4; |
dst += 2; |
} |
break; |
} |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Very slow rate conversion routine */ |
void SDL_RateSLOW(SDL_AudioCVT *cvt, Uint16 format) |
{ |
double ipos; |
int i, clen; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr); |
#endif |
clen = (int)((double)cvt->len_cvt / cvt->rate_incr); |
if ( cvt->rate_incr > 1.0 ) { |
switch (format & 0xFF) { |
case 8: { |
Uint8 *output; |
output = cvt->buf; |
ipos = 0.0; |
for ( i=clen; i; --i ) { |
*output = cvt->buf[(int)ipos]; |
ipos += cvt->rate_incr; |
output += 1; |
} |
} |
break; |
case 16: { |
Uint16 *output; |
clen &= ~1; |
output = (Uint16 *)cvt->buf; |
ipos = 0.0; |
for ( i=clen/2; i; --i ) { |
*output=((Uint16 *)cvt->buf)[(int)ipos]; |
ipos += cvt->rate_incr; |
output += 1; |
} |
} |
break; |
} |
} else { |
switch (format & 0xFF) { |
case 8: { |
Uint8 *output; |
output = cvt->buf+clen; |
ipos = (double)cvt->len_cvt; |
for ( i=clen; i; --i ) { |
ipos -= cvt->rate_incr; |
output -= 1; |
*output = cvt->buf[(int)ipos]; |
} |
} |
break; |
case 16: { |
Uint16 *output; |
clen &= ~1; |
output = (Uint16 *)(cvt->buf+clen); |
ipos = (double)cvt->len_cvt/2; |
for ( i=clen/2; i; --i ) { |
ipos -= cvt->rate_incr; |
output -= 1; |
*output=((Uint16 *)cvt->buf)[(int)ipos]; |
} |
} |
break; |
} |
} |
cvt->len_cvt = clen; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
int SDL_ConvertAudio(SDL_AudioCVT *cvt) |
{ |
/* Make sure there's data to convert */ |
if ( cvt->buf == NULL ) { |
SDL_SetError("No buffer allocated for conversion"); |
return(-1); |
} |
/* Return okay if no conversion is necessary */ |
cvt->len_cvt = cvt->len; |
if ( cvt->filters[0] == NULL ) { |
return(0); |
} |
/* Set up the conversion and go! */ |
cvt->filter_index = 0; |
cvt->filters[0](cvt, cvt->src_format); |
return(0); |
} |
/* Creates a set of audio filters to convert from one format to another. |
Returns -1 if the format conversion is not supported, or 1 if the |
audio filter is set up. |
*/ |
int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, |
Uint16 src_format, Uint8 src_channels, int src_rate, |
Uint16 dst_format, Uint8 dst_channels, int dst_rate) |
{ |
/* Start off with no conversion necessary */ |
cvt->needed = 0; |
cvt->filter_index = 0; |
cvt->filters[0] = NULL; |
cvt->len_mult = 1; |
cvt->len_ratio = 1.0; |
/* First filter: Endian conversion from src to dst */ |
if ( (src_format & 0x1000) != (dst_format & 0x1000) |
&& ((src_format & 0xff) != 8) ) { |
cvt->filters[cvt->filter_index++] = SDL_ConvertEndian; |
} |
/* Second filter: Sign conversion -- signed/unsigned */ |
if ( (src_format & 0x8000) != (dst_format & 0x8000) ) { |
cvt->filters[cvt->filter_index++] = SDL_ConvertSign; |
} |
/* Next filter: Convert 16 bit <--> 8 bit PCM */ |
if ( (src_format & 0xFF) != (dst_format & 0xFF) ) { |
switch (dst_format&0x10FF) { |
case AUDIO_U8: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert8; |
cvt->len_ratio /= 2; |
break; |
case AUDIO_U16LSB: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert16LSB; |
cvt->len_mult *= 2; |
cvt->len_ratio *= 2; |
break; |
case AUDIO_U16MSB: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert16MSB; |
cvt->len_mult *= 2; |
cvt->len_ratio *= 2; |
break; |
} |
} |
/* Last filter: Mono/Stereo conversion */ |
if ( src_channels != dst_channels ) { |
while ( (src_channels*2) <= dst_channels ) { |
cvt->filters[cvt->filter_index++] = |
SDL_ConvertStereo; |
cvt->len_mult *= 2; |
src_channels *= 2; |
cvt->len_ratio *= 2; |
} |
/* This assumes that 4 channel audio is in the format: |
Left {front/back} + Right {front/back} |
so converting to L/R stereo works properly. |
*/ |
while ( ((src_channels%2) == 0) && |
((src_channels/2) >= dst_channels) ) { |
cvt->filters[cvt->filter_index++] = |
SDL_ConvertMono; |
src_channels /= 2; |
cvt->len_ratio /= 2; |
} |
if ( src_channels != dst_channels ) { |
/* Uh oh.. */; |
} |
} |
/* Do rate conversion */ |
cvt->rate_incr = 0.0; |
if ( (src_rate/100) != (dst_rate/100) ) { |
Uint32 hi_rate, lo_rate; |
int len_mult; |
double len_ratio; |
void (*rate_cvt)(SDL_AudioCVT *cvt, Uint16 format); |
if ( src_rate > dst_rate ) { |
hi_rate = src_rate; |
lo_rate = dst_rate; |
rate_cvt = SDL_RateDIV2; |
len_mult = 1; |
len_ratio = 0.5; |
} else { |
hi_rate = dst_rate; |
lo_rate = src_rate; |
rate_cvt = SDL_RateMUL2; |
len_mult = 2; |
len_ratio = 2.0; |
} |
/* If hi_rate = lo_rate*2^x then conversion is easy */ |
while ( ((lo_rate*2)/100) <= (hi_rate/100) ) { |
cvt->filters[cvt->filter_index++] = rate_cvt; |
cvt->len_mult *= len_mult; |
lo_rate *= 2; |
cvt->len_ratio *= len_ratio; |
} |
/* We may need a slow conversion here to finish up */ |
if ( (lo_rate/100) != (hi_rate/100) ) { |
#if 1 |
/* The problem with this is that if the input buffer is |
say 1K, and the conversion rate is say 1.1, then the |
output buffer is 1.1K, which may not be an acceptable |
buffer size for the audio driver (not a power of 2) |
*/ |
/* For now, punt and hope the rate distortion isn't great. |
*/ |
#else |
if ( src_rate < dst_rate ) { |
cvt->rate_incr = (double)lo_rate/hi_rate; |
cvt->len_mult *= 2; |
cvt->len_ratio /= cvt->rate_incr; |
} else { |
cvt->rate_incr = (double)hi_rate/lo_rate; |
cvt->len_ratio *= cvt->rate_incr; |
} |
cvt->filters[cvt->filter_index++] = SDL_RateSLOW; |
#endif |
} |
} |
/* Set up the filter information */ |
if ( cvt->filter_index != 0 ) { |
cvt->needed = 1; |
cvt->src_format = src_format; |
cvt->dst_format = dst_format; |
cvt->len = 0; |
cvt->buf = NULL; |
cvt->filters[cvt->filter_index] = NULL; |
} |
return(cvt->needed); |
} |
/contrib/games/opentyrian/SDL/SDL_mixer.c |
---|
0,0 → 1,218 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
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 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 |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_mixer.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* This provides the default mixing callback for the SDL audio routines */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_audio.h" |
#include "SDL_mutex.h" |
#include "SDL_timer.h" |
#include "SDL_sysaudio.h" |
SDL_AudioDevice *current_audio = NULL; |
/* This table is used to add two sound values together and pin |
* the value to avoid overflow. (used with permission from ARDI) |
* Changed to use 0xFE instead of 0xFF for better sound quality. |
*/ |
static const Uint8 mix8[] = |
{ |
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, 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, 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, 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, 0x00, 0x01, 0x02, 0x03, |
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, |
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, |
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, |
0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, |
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, |
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, |
0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, |
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, |
0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, |
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, |
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, |
0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, |
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, |
0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, |
0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, |
0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, |
0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, |
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, |
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, |
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, |
0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, |
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE |
}; |
/* The volume ranges from 0 - 128 */ |
#define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME) |
#define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) |
void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) |
{ |
Uint16 format; |
if ( volume == 0 ) { |
return; |
} |
/* Mix the user-level audio format */ |
if ( current_audio ) { |
if ( current_audio->convert.needed ) { |
format = current_audio->convert.src_format; |
} else { |
format = current_audio->spec.format; |
} |
} else { |
format = AUDIO_S16; |
} |
format = AUDIO_S16; |
switch (format) { |
case AUDIO_U8: { |
Uint8 src_sample; |
while ( len-- ) { |
src_sample = *src; |
ADJUST_VOLUME_U8(src_sample, volume); |
*dst = mix8[*dst+src_sample]; |
++dst; |
++src; |
} |
} |
break; |
case AUDIO_S8: { |
Sint8 *dst8, *src8; |
Sint8 src_sample; |
int dst_sample; |
const int max_audioval = ((1<<(8-1))-1); |
const int min_audioval = -(1<<(8-1)); |
src8 = (Sint8 *)src; |
dst8 = (Sint8 *)dst; |
while ( len-- ) { |
src_sample = *src8; |
ADJUST_VOLUME(src_sample, volume); |
dst_sample = *dst8 + src_sample; |
if ( dst_sample > max_audioval ) { |
*dst8 = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
*dst8 = min_audioval; |
} else { |
*dst8 = dst_sample; |
} |
++dst8; |
++src8; |
} |
} |
break; |
case AUDIO_S16LSB: { |
Sint16 src1, src2; |
int dst_sample; |
const int max_audioval = ((1<<(16-1))-1); |
const int min_audioval = -(1<<(16-1)); |
len /= 2; |
while ( len-- ) { |
src1 = ((src[1])<<8|src[0]); |
ADJUST_VOLUME(src1, volume); |
src2 = ((dst[1])<<8|dst[0]); |
src += 2; |
dst_sample = src1+src2; |
if ( dst_sample > max_audioval ) { |
dst_sample = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
dst_sample = min_audioval; |
} |
dst[0] = dst_sample&0xFF; |
dst_sample >>= 8; |
dst[1] = dst_sample&0xFF; |
dst += 2; |
} |
} |
break; |
case AUDIO_S16MSB: { |
Sint16 src1, src2; |
int dst_sample; |
const int max_audioval = ((1<<(16-1))-1); |
const int min_audioval = -(1<<(16-1)); |
len /= 2; |
while ( len-- ) { |
src1 = ((src[0])<<8|src[1]); |
ADJUST_VOLUME(src1, volume); |
src2 = ((dst[0])<<8|dst[1]); |
src += 2; |
dst_sample = src1+src2; |
if ( dst_sample > max_audioval ) { |
dst_sample = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
dst_sample = min_audioval; |
} |
dst[1] = dst_sample&0xFF; |
dst_sample >>= 8; |
dst[0] = dst_sample&0xFF; |
dst += 2; |
} |
} |
break; |
default: /* If this happens... FIXME! */ |
SDL_SetError("SDL_MixAudio(): unknown audio format"); |
return; |
} |
} |
/contrib/games/opentyrian/SDL/SDL_sysaudio.h |
---|
0,0 → 1,150 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
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 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 |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_sysaudio.h,v 1.8 2001/07/23 02:58:42 slouken Exp $"; |
#endif |
#ifndef _SDL_sysaudio_h |
#define _SDL_sysaudio_h |
#include "SDL_mutex.h" |
#include "SDL_thread.h" |
/* The SDL audio driver */ |
typedef struct SDL_AudioDevice SDL_AudioDevice; |
/* Define the SDL audio driver structure */ |
#define _THIS SDL_AudioDevice *_this |
#ifndef _STATUS |
#define _STATUS SDL_status *status |
#endif |
struct SDL_AudioDevice { |
/* * * */ |
/* The name of this audio driver */ |
const char *name; |
/* * * */ |
/* The description of this audio driver */ |
const char *desc; |
/* * * */ |
/* Public driver functions */ |
int (*OpenAudio)(_THIS, SDL_AudioSpec *spec); |
void (*ThreadInit)(_THIS); /* Called by audio thread at start */ |
void (*WaitAudio)(_THIS); |
void (*PlayAudio)(_THIS); |
Uint8 *(*GetAudioBuf)(_THIS); |
void (*WaitDone)(_THIS); |
void (*CloseAudio)(_THIS); |
/* * * */ |
/* Data common to all devices */ |
/* The current audio specification (shared with audio thread) */ |
SDL_AudioSpec spec; |
/* An audio conversion block for audio format emulation */ |
SDL_AudioCVT convert; |
/* Current state flags */ |
int enabled; |
int paused; |
int opened; |
/* Fake audio buffer for when the audio hardware is busy */ |
Uint8 *fake_stream; |
/* A semaphore for locking the mixing buffers */ |
SDL_mutex *mixer_lock; |
/* A thread to feed the audio device */ |
SDL_Thread *thread; |
Uint32 threadid; |
/* * * */ |
/* Data private to this driver */ |
struct SDL_PrivateAudioData *hidden; |
/* * * */ |
/* The function used to dispose of this structure */ |
void (*free)(_THIS); |
}; |
#undef _THIS |
typedef struct AudioBootStrap { |
const char *name; |
const char *desc; |
int (*available)(void); |
SDL_AudioDevice *(*create)(int devindex); |
} AudioBootStrap; |
#ifdef OPENBSD_AUDIO_SUPPORT |
extern AudioBootStrap OPENBSD_AUDIO_bootstrap; |
#endif |
#ifdef OSS_SUPPORT |
extern AudioBootStrap DSP_bootstrap; |
extern AudioBootStrap DMA_bootstrap; |
#endif |
#ifdef ALSA_SUPPORT |
extern AudioBootStrap ALSA_bootstrap; |
#endif |
#if (defined(unix) && !defined(__CYGWIN32__)) && \ |
!defined(OSS_SUPPORT) && !defined(ALSA_SUPPORT) |
extern AudioBootStrap AUDIO_bootstrap; |
#endif |
#ifdef ARTSC_SUPPORT |
extern AudioBootStrap ARTSC_bootstrap; |
#endif |
#ifdef ESD_SUPPORT |
extern AudioBootStrap ESD_bootstrap; |
#endif |
#ifdef NAS_SUPPORT |
extern AudioBootStrap NAS_bootstrap; |
#endif |
#ifdef ENABLE_DIRECTX |
extern AudioBootStrap DSOUND_bootstrap; |
#endif |
#ifdef ENABLE_WINDIB |
extern AudioBootStrap WAVEOUT_bootstrap; |
#endif |
#ifdef _AIX |
extern AudioBootStrap Paud_bootstrap; |
#endif |
#ifdef __BEOS__ |
extern AudioBootStrap BAUDIO_bootstrap; |
#endif |
#if defined(macintosh) || TARGET_API_MAC_CARBON |
extern AudioBootStrap SNDMGR_bootstrap; |
#endif |
#ifdef ENABLE_AHI |
extern AudioBootStrap AHI_bootstrap; |
#endif |
#ifdef DISKAUD_SUPPORT |
extern AudioBootStrap DISKAUD_bootstrap; |
#endif |
/* This is the current audio device */ |
extern SDL_AudioDevice *current_audio; |
#endif /* _SDL_sysaudio_h */ |
/contrib/games/opentyrian/SDL/SDL_wave.c |
---|
0,0 → 1,591 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
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 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 |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_wave.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
#ifndef DISABLE_FILE |
/* Microsoft WAVE file loading routines */ |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_error.h" |
#include "SDL_audio.h" |
#include "SDL_wave.h" |
#include "SDL_endian.h" |
#ifndef NELEMS |
#define NELEMS(array) ((sizeof array)/(sizeof array[0])) |
#endif |
static int ReadChunk(SDL_RWops *src, Chunk *chunk); |
struct MS_ADPCM_decodestate { |
Uint8 hPredictor; |
Uint16 iDelta; |
Sint16 iSamp1; |
Sint16 iSamp2; |
}; |
static struct MS_ADPCM_decoder { |
WaveFMT wavefmt; |
Uint16 wSamplesPerBlock; |
Uint16 wNumCoef; |
Sint16 aCoeff[7][2]; |
/* * * */ |
struct MS_ADPCM_decodestate state[2]; |
} MS_ADPCM_state; |
static int InitMS_ADPCM(WaveFMT *format) |
{ |
Uint8 *rogue_feel; |
Uint16 extra_info; |
int i; |
/* Set the rogue pointer to the MS_ADPCM specific data */ |
MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
MS_ADPCM_state.wavefmt.bitspersample = |
SDL_SwapLE16(format->bitspersample); |
rogue_feel = (Uint8 *)format+sizeof(*format); |
if ( sizeof(*format) == 16 ) { |
extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
MS_ADPCM_state.wNumCoef = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
if ( MS_ADPCM_state.wNumCoef != 7 ) { |
SDL_SetError("Unknown set of MS_ADPCM coefficients"); |
return(-1); |
} |
for ( i=0; i<MS_ADPCM_state.wNumCoef; ++i ) { |
MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
return(0); |
} |
static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, |
Uint8 nybble, Sint16 *coeff) |
{ |
const Sint32 max_audioval = ((1<<(16-1))-1); |
const Sint32 min_audioval = -(1<<(16-1)); |
const Sint32 adaptive[] = { |
230, 230, 230, 230, 307, 409, 512, 614, |
768, 614, 512, 409, 307, 230, 230, 230 |
}; |
Sint32 new_sample, delta; |
new_sample = ((state->iSamp1 * coeff[0]) + |
(state->iSamp2 * coeff[1]))/256; |
if ( nybble & 0x08 ) { |
new_sample += state->iDelta * (nybble-0x10); |
} else { |
new_sample += state->iDelta * nybble; |
} |
if ( new_sample < min_audioval ) { |
new_sample = min_audioval; |
} else |
if ( new_sample > max_audioval ) { |
new_sample = max_audioval; |
} |
delta = ((Sint32)state->iDelta * adaptive[nybble])/256; |
if ( delta < 16 ) { |
delta = 16; |
} |
state->iDelta = delta; |
state->iSamp2 = state->iSamp1; |
state->iSamp1 = new_sample; |
return(new_sample); |
} |
static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
{ |
struct MS_ADPCM_decodestate *state[2]; |
Uint8 *freeable, *encoded, *decoded; |
Sint32 encoded_len, samplesleft; |
Sint8 nybble, stereo; |
Sint16 *coeff[2]; |
Sint32 new_sample; |
/* Allocate the proper sized output buffer */ |
encoded_len = *audio_len; |
encoded = *audio_buf; |
freeable = *audio_buf; |
*audio_len = (encoded_len/MS_ADPCM_state.wavefmt.blockalign) * |
MS_ADPCM_state.wSamplesPerBlock* |
MS_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
*audio_buf = (Uint8 *)malloc(*audio_len); |
if ( *audio_buf == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
decoded = *audio_buf; |
/* Get ready... Go! */ |
stereo = (MS_ADPCM_state.wavefmt.channels == 2); |
state[0] = &MS_ADPCM_state.state[0]; |
state[1] = &MS_ADPCM_state.state[stereo]; |
while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) { |
/* Grab the initial information for this block */ |
state[0]->hPredictor = *encoded++; |
if ( stereo ) { |
state[1]->hPredictor = *encoded++; |
} |
state[0]->iDelta = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iDelta = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
state[0]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
state[0]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor]; |
coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor]; |
/* Store the two initial samples we start with */ |
decoded[0] = state[0]->iSamp2&0xFF; |
decoded[1] = state[0]->iSamp2>>8; |
decoded += 2; |
if ( stereo ) { |
decoded[0] = state[1]->iSamp2&0xFF; |
decoded[1] = state[1]->iSamp2>>8; |
decoded += 2; |
} |
decoded[0] = state[0]->iSamp1&0xFF; |
decoded[1] = state[0]->iSamp1>>8; |
decoded += 2; |
if ( stereo ) { |
decoded[0] = state[1]->iSamp1&0xFF; |
decoded[1] = state[1]->iSamp1>>8; |
decoded += 2; |
} |
/* Decode and store the other samples in this block */ |
samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)* |
MS_ADPCM_state.wavefmt.channels; |
while ( samplesleft > 0 ) { |
nybble = (*encoded)>>4; |
new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2; |
nybble = (*encoded)&0x0F; |
new_sample = MS_ADPCM_nibble(state[1],nybble,coeff[1]); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2; |
++encoded; |
samplesleft -= 2; |
} |
encoded_len -= MS_ADPCM_state.wavefmt.blockalign; |
} |
free(freeable); |
return(0); |
} |
struct IMA_ADPCM_decodestate { |
Sint32 sample; |
Sint8 index; |
}; |
static struct IMA_ADPCM_decoder { |
WaveFMT wavefmt; |
Uint16 wSamplesPerBlock; |
/* * * */ |
struct IMA_ADPCM_decodestate state[2]; |
} IMA_ADPCM_state; |
static int InitIMA_ADPCM(WaveFMT *format) |
{ |
Uint8 *rogue_feel; |
Uint16 extra_info; |
/* Set the rogue pointer to the IMA_ADPCM specific data */ |
IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
IMA_ADPCM_state.wavefmt.bitspersample = |
SDL_SwapLE16(format->bitspersample); |
rogue_feel = (Uint8 *)format+sizeof(*format); |
if ( sizeof(*format) == 16 ) { |
extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
return(0); |
} |
static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state,Uint8 nybble) |
{ |
const Sint32 max_audioval = ((1<<(16-1))-1); |
const Sint32 min_audioval = -(1<<(16-1)); |
const int index_table[16] = { |
-1, -1, -1, -1, |
2, 4, 6, 8, |
-1, -1, -1, -1, |
2, 4, 6, 8 |
}; |
const Sint32 step_table[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 |
}; |
Sint32 delta, step; |
/* Compute difference and new sample value */ |
step = step_table[state->index]; |
delta = step >> 3; |
if ( nybble & 0x04 ) delta += step; |
if ( nybble & 0x02 ) delta += (step >> 1); |
if ( nybble & 0x01 ) delta += (step >> 2); |
if ( nybble & 0x08 ) delta = -delta; |
state->sample += delta; |
/* Update index value */ |
state->index += index_table[nybble]; |
if ( state->index > 88 ) { |
state->index = 88; |
} else |
if ( state->index < 0 ) { |
state->index = 0; |
} |
/* Clamp output sample */ |
if ( state->sample > max_audioval ) { |
state->sample = max_audioval; |
} else |
if ( state->sample < min_audioval ) { |
state->sample = min_audioval; |
} |
return(state->sample); |
} |
/* Fill the decode buffer with a channel block of data (8 samples) */ |
static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, |
int channel, int numchannels, struct IMA_ADPCM_decodestate *state) |
{ |
int i; |
Sint8 nybble; |
Sint32 new_sample; |
decoded += (channel * 2); |
for ( i=0; i<4; ++i ) { |
nybble = (*encoded)&0x0F; |
new_sample = IMA_ADPCM_nibble(state, nybble); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2 * numchannels; |
nybble = (*encoded)>>4; |
new_sample = IMA_ADPCM_nibble(state, nybble); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2 * numchannels; |
++encoded; |
} |
} |
static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
{ |
struct IMA_ADPCM_decodestate *state; |
Uint8 *freeable, *encoded, *decoded; |
Sint32 encoded_len, samplesleft; |
int c, channels; |
/* Check to make sure we have enough variables in the state array */ |
channels = IMA_ADPCM_state.wavefmt.channels; |
if ( channels > NELEMS(IMA_ADPCM_state.state) ) { |
SDL_SetError("IMA ADPCM decoder can only handle %d channels", |
NELEMS(IMA_ADPCM_state.state)); |
return(-1); |
} |
state = IMA_ADPCM_state.state; |
/* Allocate the proper sized output buffer */ |
encoded_len = *audio_len; |
encoded = *audio_buf; |
freeable = *audio_buf; |
*audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * |
IMA_ADPCM_state.wSamplesPerBlock* |
IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
*audio_buf = (Uint8 *)malloc(*audio_len); |
if ( *audio_buf == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
decoded = *audio_buf; |
/* Get ready... Go! */ |
while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) { |
/* Grab the initial information for this block */ |
for ( c=0; c<channels; ++c ) { |
/* Fill the state information for this block */ |
state[c].sample = ((encoded[1]<<8)|encoded[0]); |
encoded += 2; |
if ( state[c].sample & 0x8000 ) { |
state[c].sample -= 0x10000; |
} |
state[c].index = *encoded++; |
/* Reserved byte in buffer header, should be 0 */ |
if ( *encoded++ != 0 ) { |
/* Uh oh, corrupt data? Buggy code? */; |
} |
/* Store the initial sample we start with */ |
decoded[0] = state[c].sample&0xFF; |
decoded[1] = state[c].sample>>8; |
decoded += 2; |
} |
/* Decode and store the other samples in this block */ |
samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels; |
while ( samplesleft > 0 ) { |
for ( c=0; c<channels; ++c ) { |
Fill_IMA_ADPCM_block(decoded, encoded, |
c, channels, &state[c]); |
encoded += 4; |
samplesleft -= 8; |
} |
decoded += (channels * 8 * 2); |
} |
encoded_len -= IMA_ADPCM_state.wavefmt.blockalign; |
} |
free(freeable); |
return(0); |
} |
SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) |
{ |
int was_error; |
Chunk chunk; |
int lenread; |
int MS_ADPCM_encoded, IMA_ADPCM_encoded; |
int samplesize; |
/* WAV magic header */ |
Uint32 RIFFchunk; |
Uint32 wavelen; |
Uint32 WAVEmagic; |
/* FMT chunk */ |
WaveFMT *format = NULL; |
/* Make sure we are passed a valid data source */ |
was_error = 0; |
if ( src == NULL ) { |
was_error = 1; |
goto done; |
} |
/* Check the magic header */ |
RIFFchunk = SDL_ReadLE32(src); |
wavelen = SDL_ReadLE32(src); |
WAVEmagic = SDL_ReadLE32(src); |
if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) { |
SDL_SetError("Unrecognized file type (not WAVE)"); |
was_error = 1; |
goto done; |
} |
/* Read the audio data format chunk */ |
chunk.data = NULL; |
do { |
if ( chunk.data != NULL ) { |
free(chunk.data); |
} |
lenread = ReadChunk(src, &chunk); |
if ( lenread < 0 ) { |
was_error = 1; |
goto done; |
} |
} while ( (chunk.magic == FACT) || (chunk.magic == LIST) ); |
/* Decode the audio data format */ |
format = (WaveFMT *)chunk.data; |
if ( chunk.magic != FMT ) { |
SDL_SetError("Complex WAVE files not supported"); |
was_error = 1; |
goto done; |
} |
MS_ADPCM_encoded = IMA_ADPCM_encoded = 0; |
switch (SDL_SwapLE16(format->encoding)) { |
case PCM_CODE: |
/* We can understand this */ |
break; |
case MS_ADPCM_CODE: |
/* Try to understand this */ |
if ( InitMS_ADPCM(format) < 0 ) { |
was_error = 1; |
goto done; |
} |
MS_ADPCM_encoded = 1; |
break; |
case IMA_ADPCM_CODE: |
/* Try to understand this */ |
if ( InitIMA_ADPCM(format) < 0 ) { |
was_error = 1; |
goto done; |
} |
IMA_ADPCM_encoded = 1; |
break; |
default: |
SDL_SetError("Unknown WAVE data format: 0x%.4x", |
SDL_SwapLE16(format->encoding)); |
was_error = 1; |
goto done; |
} |
memset(spec, 0, (sizeof *spec)); |
spec->freq = SDL_SwapLE32(format->frequency); |
switch (SDL_SwapLE16(format->bitspersample)) { |
case 4: |
if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) { |
spec->format = AUDIO_S16; |
} else { |
was_error = 1; |
} |
break; |
case 8: |
spec->format = AUDIO_U8; |
break; |
case 16: |
spec->format = AUDIO_S16; |
break; |
default: |
was_error = 1; |
break; |
} |
if ( was_error ) { |
SDL_SetError("Unknown %d-bit PCM data format", |
SDL_SwapLE16(format->bitspersample)); |
goto done; |
} |
spec->channels = (Uint8)SDL_SwapLE16(format->channels); |
spec->samples = 4096; /* Good default buffer size */ |
/* Read the audio data chunk */ |
*audio_buf = NULL; |
do { |
if ( *audio_buf != NULL ) { |
free(*audio_buf); |
} |
lenread = ReadChunk(src, &chunk); |
if ( lenread < 0 ) { |
was_error = 1; |
goto done; |
} |
*audio_len = lenread; |
*audio_buf = chunk.data; |
} while ( chunk.magic != DATA ); |
if ( MS_ADPCM_encoded ) { |
if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
was_error = 1; |
goto done; |
} |
} |
if ( IMA_ADPCM_encoded ) { |
if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
was_error = 1; |
goto done; |
} |
} |
/* Don't return a buffer that isn't a multiple of samplesize */ |
samplesize = ((spec->format & 0xFF)/8)*spec->channels; |
*audio_len &= ~(samplesize-1); |
done: |
if ( format != NULL ) { |
free(format); |
} |
if ( freesrc && src ) { |
SDL_RWclose(src); |
} |
if ( was_error ) { |
spec = NULL; |
} |
return(spec); |
} |
/* Since the WAV memory is allocated in the shared library, it must also |
be freed here. (Necessary under Win32, VC++) |
*/ |
void SDL_FreeWAV(Uint8 *audio_buf) |
{ |
if ( audio_buf != NULL ) { |
free(audio_buf); |
} |
} |
static int ReadChunk(SDL_RWops *src, Chunk *chunk) |
{ |
chunk->magic = SDL_ReadLE32(src); |
chunk->length = SDL_ReadLE32(src); |
chunk->data = (Uint8 *)malloc(chunk->length); |
if ( chunk->data == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) { |
SDL_Error(SDL_EFREAD); |
free(chunk->data); |
return(-1); |
} |
return(chunk->length); |
} |
#endif /* ENABLE_FILE */ |
/contrib/games/opentyrian/SDL/SDL_wave.h |
---|
0,0 → 1,65 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
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 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 |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_wave.h,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* WAVE files are little-endian */ |
/*******************************************/ |
/* Define values for Microsoft WAVE format */ |
/*******************************************/ |
#define RIFF 0x46464952 /* "RIFF" */ |
#define WAVE 0x45564157 /* "WAVE" */ |
#define FACT 0x74636166 /* "fact" */ |
#define LIST 0x5453494c /* "LIST" */ |
#define FMT 0x20746D66 /* "fmt " */ |
#define DATA 0x61746164 /* "data" */ |
#define PCM_CODE 0x0001 |
#define MS_ADPCM_CODE 0x0002 |
#define IMA_ADPCM_CODE 0x0011 |
#define WAVE_MONO 1 |
#define WAVE_STEREO 2 |
/* Normally, these three chunks come consecutively in a WAVE file */ |
typedef struct WaveFMT { |
/* Not saved in the chunk we read: |
Uint32 FMTchunk; |
Uint32 fmtlen; |
*/ |
Uint16 encoding; |
Uint16 channels; /* 1 = mono, 2 = stereo */ |
Uint32 frequency; /* One of 11025, 22050, or 44100 Hz */ |
Uint32 byterate; /* Average bytes per second */ |
Uint16 blockalign; /* Bytes per sample block */ |
Uint16 bitspersample; /* One of 8, 12, 16, or 4 for ADPCM */ |
} WaveFMT; |
/* The general chunk found in the WAVE file */ |
typedef struct Chunk { |
Uint32 magic; |
Uint32 length; |
Uint8 *data; /* Data includes magic and length */ |
} Chunk; |
/contrib/games/opentyrian/SDL/joystick_stub.c |
---|
0,0 → 1,153 |
/// JOYSTICK STUB FOR Wolfenstein 3D port to KolibriOS |
/// Ported by maxcodehack and turbocat2001 |
/* Set up for C function definitions, even when using C++ */ |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** @file SDL_joystick.h |
* @note In order to use these functions, SDL_Init() must have been called |
* with the SDL_INIT_JOYSTICK flag. This causes SDL to scan the system |
* for joysticks, and load appropriate drivers. |
*/ |
/** The joystick structure used to identify an SDL joystick */ |
struct _SDL_Joystick; |
typedef struct _SDL_Joystick SDL_Joystick; |
/* Function prototypes */ |
/** |
* Count the number of joysticks attached to the system |
*/ |
int SDL_NumJoysticks(void){}; |
/** |
* Get the implementation dependent name of a joystick. |
* |
* This can be called before any joysticks are opened. |
* If no name can be found, this function returns NULL. |
*/ |
const char * SDL_JoystickName(int device_index){}; |
/** |
* Open a joystick for use. |
* |
* @param[in] device_index |
* The index passed as an argument refers to |
* the N'th joystick on the system. This index is the value which will |
* identify this joystick in future joystick events. |
* |
* @return This function returns a joystick identifier, or NULL if an error occurred. |
*/ |
SDL_Joystick * SDL_JoystickOpen(int device_index){}; |
/** |
* Returns 1 if the joystick has been opened, or 0 if it has not. |
*/ |
int SDL_JoystickOpened(int device_index){}; |
/** |
* Get the device index of an opened joystick. |
*/ |
int SDL_JoystickIndex(SDL_Joystick *joystick){}; |
/** |
* Get the number of general axis controls on a joystick |
*/ |
int SDL_JoystickNumAxes(SDL_Joystick *joystick){}; |
/** |
* Get the number of trackballs on a joystick |
* |
* Joystick trackballs have only relative motion events associated |
* with them and their state cannot be polled. |
*/ |
int SDL_JoystickNumBalls(SDL_Joystick *joystick){}; |
/** |
* Get the number of POV hats on a joystick |
*/ |
int SDL_JoystickNumHats(SDL_Joystick *joystick){}; |
/** |
* Get the number of buttons on a joystick |
*/ |
int SDL_JoystickNumButtons(SDL_Joystick *joystick){}; |
/** |
* Update the current state of the open joysticks. |
* |
* This is called automatically by the event loop if any joystick |
* events are enabled. |
*/ |
void SDL_JoystickUpdate(void){}; |
/** |
* Enable/disable joystick event polling. |
* |
* If joystick events are disabled, you must call SDL_JoystickUpdate() |
* yourself and check the state of the joystick when you want joystick |
* information. |
* |
* @param[in] state The state can be one of SDL_QUERY, SDL_ENABLE or SDL_IGNORE. |
*/ |
int SDL_JoystickEventState(int state){}; |
/** |
* Get the current state of an axis control on a joystick |
* |
* @param[in] axis The axis indices start at index 0. |
* |
* @return The state is a value ranging from -32768 to 32767. |
*/ |
int SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis){}; |
/** |
* @name Hat Positions |
* The return value of SDL_JoystickGetHat() is one of the following positions: |
*/ |
/*@{*/ |
#define SDL_HAT_CENTERED 0x00 |
#define SDL_HAT_UP 0x01 |
#define SDL_HAT_RIGHT 0x02 |
#define SDL_HAT_DOWN 0x04 |
#define SDL_HAT_LEFT 0x08 |
#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) |
#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) |
#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) |
#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) |
/*@}*/ |
/** |
* Get the current state of a POV hat on a joystick |
* |
* @param[in] hat The hat indices start at index 0. |
*/ |
int SDL_JoystickGetHat(SDL_Joystick *joystick, int hat){}; |
/** |
* Get the ball axis change since the last poll |
* |
* @param[in] ball The ball indices start at index 0. |
* |
* @return This returns 0, or -1 if you passed it invalid parameters. |
*/ |
int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy){}; |
/** |
* Get the current state of a button on a joystick |
* |
* @param[in] button The button indices start at index 0. |
*/ |
int SDL_JoystickGetButton(SDL_Joystick *joystick, int button){}; |
/** |
* Close a joystick previously opened with SDL_JoystickOpen() |
*/ |
void SDL_JoystickClose(SDL_Joystick *joystick){}; |
/* Ends C function definitions when using C++ */ |
#ifdef __cplusplus |
} |
#endif |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/contrib/games/opentyrian/SDL/uSDL.c |
---|
0,0 → 1,53 |
#include <SDL.h> |
#include <stdlib.h> |
#include <string.h> |
#define asm_inline __asm__ __volatile__ |
#pragma pack(push,1) |
typedef union{ |
unsigned val; |
struct{ |
short h; |
short w; |
}; |
}ksys_screen_t; |
#pragma pack(pop) |
static inline |
void _ksys_change_window(int new_x, int new_y, int new_w, int new_h) |
{ |
asm_inline( |
"int $0x40" |
::"a"(67), "b"(new_x), "c"(new_y), "d"(new_w),"S"(new_h) |
); |
} |
static inline |
ksys_screen_t _ksys_screen_size() |
{ |
ksys_screen_t size; |
asm_inline( |
"int $0x40" |
:"=a"(size) |
:"a"(14) |
:"memory" |
); |
return size; |
} |
void uSDL_SetWinCenter(unsigned w, unsigned h){ |
ksys_screen_t screen_size= _ksys_screen_size(); |
int new_x = screen_size.w/2-w/2; |
int new_y = screen_size.h/2-h/2; |
_ksys_change_window(new_x, new_y, -1, -1); |
} |
void uSDL_Delay(unsigned ms){ |
unsigned start = SDL_GetTicks(); |
do{ |
asm_inline("int $0x40" :: "a"(5),"b"(1)); |
}while (SDL_GetTicks()-start < ms); |
} |
/contrib/games/opentyrian/src/animlib.c |
---|
0,0 → 1,431 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "animlib.h" |
#include "file.h" |
#include "keyboard.h" |
#include "network.h" |
#include "nortsong.h" |
#include "palette.h" |
#include "sizebuf.h" |
#include "video.h" |
#include <assert.h> |
/*** Structs ***/ |
/* The actual header has a lot of fields that are basically useless to us since |
* we both set our own framerate and the format itself only allows for |
* 320x200x8. Should a (nonexistent) ani be played that doesn't have the same |
* assumed values we are going to use, TOO BAD. It'll just be treated as |
* corrupt in playback. |
*/ |
#define PALETTE_OFFSET 0x100 // 128 + sizeof(header) |
#define PAGEHEADER_OFFSET 0x500 // PALETTE_OFFSET + sizeof(palette) |
#define ANIM_OFFSET 0x0B00 // PAGEHEADER_OFFSET + sizeof(largepageheader) * 256 |
#define ANI_PAGE_SIZE 0x10000 // 65536. |
typedef struct anim_FileHeader_s |
{ |
unsigned int nlps; /* Number of 'pages', max 256. */ |
unsigned int nRecords; /* Number of 'records', max 65535 */ |
} anim_FileHeader_t; |
typedef struct anim_LargePageHeader_s |
{ |
unsigned int baseRecord; /* The first record's number */ |
unsigned int nRecords; /* Number of records. Supposedly there are bit flags but I saw no such code */ |
unsigned int nBytes; /* Number of bytes used, excluding headers */ |
} anim_LargePageHeader_t; |
/*** Globals ***/ |
Uint8 CurrentPageBuffer[65536]; |
anim_LargePageHeader_t PageHeader[256]; |
unsigned int CurrentPageRecordSizes[256]; |
anim_LargePageHeader_t CurrentPageHeader; |
anim_FileHeader_t FileHeader; |
unsigned int Curlpnum; |
FILE * InFile; |
/*** Function decs ***/ |
int JE_playRunSkipDump( Uint8 *, unsigned int ); |
void JE_closeAnim( void ); |
int JE_loadAnim( const char * ); |
int JE_renderFrame( unsigned int ); |
int JE_findPage ( unsigned int ); |
int JE_drawFrame( unsigned int ); |
int JE_loadPage( unsigned int ); |
/*** Implementation ***/ |
/* Loads the given page into memory. |
* |
* Returns 0 on success or nonzero on failure (bad data) |
*/ |
int JE_loadPage( unsigned int pagenumber ) |
{ |
unsigned int i, pageSize; |
if (Curlpnum == pagenumber) { return(0); } /* Already loaded */ |
Curlpnum = pagenumber; |
/* We need to seek to the page and load it into our buffer. |
* Pages have a fixed size of 0x10000; any left over space is padded |
* unless it's the end of the file. |
* |
* Pages repeat their headers for some reason. They then have two bytes of |
* padding folowed by a word for every record. THEN the data starts. |
*/ |
fseek(InFile, ANIM_OFFSET + (pagenumber * ANI_PAGE_SIZE), SEEK_SET); |
efread(&CurrentPageHeader.baseRecord, 2, 1, InFile); |
efread(&CurrentPageHeader.nRecords, 2, 1, InFile); |
efread(&CurrentPageHeader.nBytes, 2, 1, InFile); |
fseek(InFile, 2, SEEK_CUR); |
for (i = 0; i < CurrentPageHeader.nRecords; i++) |
{ |
efread(&CurrentPageRecordSizes[i], 2, 1, InFile); |
} |
/* What remains is the 'compressed' data */ |
efread(CurrentPageBuffer, 1, CurrentPageHeader.nBytes, InFile); |
/* Okay, we've succeeded in all our IO checks. Now, make sure the |
* headers aren't lying or damaged or something. |
*/ |
pageSize = 0; |
for (i = 0; i < CurrentPageHeader.nRecords; i++) |
{ |
pageSize += CurrentPageRecordSizes[i]; |
} |
if(pageSize != CurrentPageHeader.nBytes) { return(-1); } |
/* So far, so good */ |
return(0); |
} |
int JE_drawFrame( unsigned int framenumber ) |
{ |
int ret; |
ret = JE_loadPage(framenumber); |
if (ret) { return(ret); } |
ret = JE_renderFrame (framenumber); |
if (ret) { return(ret); } |
return(0); |
} |
int JE_findPage( unsigned int framenumber ) |
{ |
unsigned int i; |
for (i = 0; i < FileHeader.nlps; i++) |
{ |
if (PageHeader[i].baseRecord <= framenumber |
&& PageHeader[i].baseRecord + PageHeader[i].nRecords > framenumber) |
{ |
return(i); |
} |
} |
return(-1); /* Did not find */ |
} |
int JE_renderFrame( unsigned int framenumber ) |
{ |
unsigned int i, offset, destframe; |
destframe = framenumber - CurrentPageHeader.baseRecord; |
offset = 0; |
for (i = 0; i < destframe; i++) |
{ |
offset += CurrentPageRecordSizes[i]; |
} |
return (JE_playRunSkipDump(CurrentPageBuffer + offset + 4, CurrentPageRecordSizes[destframe] - 4)); |
} |
void JE_playAnim( const char *animfile, JE_byte startingframe, JE_byte speed ) |
{ |
unsigned int i; |
int pageNum; |
if (JE_loadAnim(animfile) != 0) |
{ |
return; /* Failed to open or process file */ |
} |
/* Blank screen */ |
JE_clr256(VGAScreen); |
JE_showVGA(); |
/* re FileHeader.nRecords-1: It's -1 in the pascal too. |
* The final frame is a delta of the first, and we don't need that. |
* We could also, if we ever ended up needing to loop anis, check |
* the bools in the header to see if we should render the last |
* frame. But that's never going to be encessary :) |
*/ |
for (i = startingframe; i < FileHeader.nRecords-1; i++) |
{ |
/* Handle boring crap */ |
setjasondelay(speed); |
/* Load required frame. The loading function is smart enough to not re-load an already loaded frame */ |
pageNum = JE_findPage(i); |
if(pageNum == -1) { break; } |
if (JE_loadPage(pageNum) != 0) { break; } |
/* render frame. */ |
if (JE_renderFrame(i) != 0) { break; } |
JE_showVGA(); |
/* Return early if user presses a key */ |
service_SDL_events(true); |
if (newkey) |
{ |
break; |
} |
/* Wait until we need the next frame */ |
NETWORK_KEEP_ALIVE(); |
wait_delay(); |
} |
JE_closeAnim(); |
} |
/* loadAnim opens the file and loads data from it into the header structs. |
* It should take care to clean up after itself should an error occur. |
*/ |
int JE_loadAnim( const char *filename ) |
{ |
unsigned int i, fileSize; |
char temp[4]; |
Curlpnum = -1; |
InFile = dir_fopen(data_dir(), filename, "rb"); |
if(InFile == NULL) |
{ |
return(-1); |
} |
fileSize = ftell_eof(InFile); |
if(fileSize < ANIM_OFFSET) |
{ |
/* We don't know the exact size our file should be yet, |
* but we do know it should be way more than this */ |
fclose(InFile); |
return(-1); |
} |
/* Read in the header. The header is 256 bytes long or so, |
* but that includes a lot of padding as well as several |
* vars we really don't care about. We shall check the ID and extract |
* the handful of vars we care about. Every value in the header that |
* is constant will be ignored. |
*/ |
efread(&temp, 1, 4, InFile); /* The ID, should equal "LPF " */ |
fseek(InFile, 2, SEEK_CUR); /* skip over this word */ |
efread(&FileHeader.nlps, 2, 1, InFile); /* Number of pages */ |
efread(&FileHeader.nRecords, 4, 1, InFile); /* Number of records */ |
if (memcmp(temp, "LPF ", 4) != 0 |
|| FileHeader.nlps == 0 || FileHeader.nRecords == 0 |
|| FileHeader.nlps > 256 || FileHeader.nRecords > 65535) |
{ |
fclose(InFile); |
return(-1); |
} |
/* Read in headers */ |
fseek(InFile, PAGEHEADER_OFFSET, SEEK_SET); |
for (i = 0; i < FileHeader.nlps; i++) |
{ |
efread(&PageHeader[i].baseRecord, 2, 1, InFile); |
efread(&PageHeader[i].nRecords, 2, 1, InFile); |
efread(&PageHeader[i].nBytes, 2, 1, InFile); |
} |
/* Now we have enough information to calculate the 'expected' file size. |
* Our calculation SHOULD be equal to fileSize, but we won't begrudge |
* padding */ |
if (fileSize < (FileHeader.nlps-1) * ANI_PAGE_SIZE + ANIM_OFFSET |
+ PageHeader[FileHeader.nlps-1].nBytes |
+ PageHeader[FileHeader.nlps-1].nRecords * 2 + 8) |
{ |
fclose(InFile); |
return(-1); |
} |
/* Now read in the palette. */ |
fseek(InFile, PALETTE_OFFSET, SEEK_SET); |
for (i = 0; i < 256; i++) |
{ |
efread(&colors[i].b, 1, 1, InFile); |
efread(&colors[i].g, 1, 1, InFile); |
efread(&colors[i].r, 1, 1, InFile); |
efread(&colors[i].unused, 1, 1, InFile); |
} |
set_palette(colors, 0, 255); |
/* Whew! That was hard. Let's go grab some beers! */ |
return(0); |
} |
void JE_closeAnim( void ) |
{ |
fclose(InFile); |
} |
/* RunSkipDump decompresses the video. There are three operations, run, skip, |
* and dump. They can be used in either byte or word variations, making six |
* possible actions, and there's a seventh 'stop' action, which looks |
* like 0x80 0x00 0x00. |
* |
* Run is a memset. |
* Dump is a memcpy. |
* Skip leaves the old data intact and simply increments the pointers. |
* |
* returns 0 on success or 1 if decompressing failed. Failure to decompress |
* indicates a broken or malicious file; playback should terminate. |
*/ |
int JE_playRunSkipDump( Uint8 *incomingBuffer, unsigned int IncomingBufferLength ) |
{ |
sizebuf_t Buffer_IN, Buffer_OUT; |
sizebuf_t * pBuffer_IN = &Buffer_IN, * pBuffer_OUT = &Buffer_OUT; |
#define ANI_SHORT_RLE 0x00 |
#define ANI_SHORT_SKIP 0x80 |
#define ANI_LONG_OP 0x80 |
#define ANI_LONG_COPY_OR_RLE 0x8000 |
#define ANI_LONG_RLE 0x4000 |
#define ANI_STOP 0x0000 |
SZ_Init(pBuffer_IN, incomingBuffer, IncomingBufferLength); |
SZ_Init(pBuffer_OUT, VGAScreen->pixels, VGAScreen->h * VGAScreen->pitch); |
/* 320x200 is the only supported format. |
* Assert is here as a hint should our screen size ever changes. |
* As for how to decompress to the wrong screen size... */ |
assert(VGAScreen->h * VGAScreen->pitch == 320 * 200); |
while (1) |
{ |
/* Get one byte. This byte may have flags that tell us more */ |
unsigned int opcode = MSG_ReadByte(pBuffer_IN); |
/* Before we continue, check the error states/ |
* We should *probably* check these after every read and write, but |
* I've rigged it so that the buffers will never go out of bounds. |
* So we can afford to be lazy; if the buffer overflows below it will |
* silently fail its writes and we'll catch the failure on our next |
* run through the loop. A failure means we should be |
* leaving ANYWAY. The contents of our buffers doesn't matter. |
*/ |
if (SZ_Error(pBuffer_IN) || SZ_Error(pBuffer_OUT)) |
{ |
return(-1); |
} |
/* Divide into 'short' and 'long' */ |
if (opcode == ANI_LONG_OP) /* long ops */ |
{ |
opcode = MSG_ReadWord(pBuffer_IN); |
if (opcode == ANI_STOP) /* We are done decompressing. Leave */ |
{ |
break; |
} |
else if (!(opcode & ANI_LONG_COPY_OR_RLE)) /* If it's not those two, it's a skip */ |
{ |
unsigned int count = opcode; |
SZ_Seek(pBuffer_OUT, count, SEEK_CUR); |
} |
else /* Now things get a bit more interesting... */ |
{ |
opcode &= ~ANI_LONG_COPY_OR_RLE; /* Clear that flag */ |
if (opcode & ANI_LONG_RLE) /* RLE */ |
{ |
unsigned int count = opcode & ~ANI_LONG_RLE; /* Clear flag */ |
/* Extract another byte */ |
unsigned int value = MSG_ReadByte(pBuffer_IN); |
/* The actual run */ |
SZ_Memset(pBuffer_OUT, value, count); |
} |
else |
{ /* Long copy */ |
unsigned int count = opcode; |
/* Copy */ |
SZ_Memcpy2(pBuffer_OUT, pBuffer_IN, count); |
} |
} |
} /* End of long ops */ |
else /* short ops */ |
{ |
if (opcode & ANI_SHORT_SKIP) /* Short skip, move pointer only */ |
{ |
unsigned int count = opcode & ~ANI_SHORT_SKIP; /* clear flag to get count */ |
SZ_Seek(pBuffer_OUT, count, SEEK_CUR); |
} |
else if (opcode == ANI_SHORT_RLE) /* Short RLE, memset the destination */ |
{ |
/* Extract a few more bytes */ |
unsigned int count = MSG_ReadByte(pBuffer_IN); |
unsigned int value = MSG_ReadByte(pBuffer_IN); |
/* Run */ |
SZ_Memset(pBuffer_OUT, value, count); |
} |
else /* Short copy, memcpy from src to dest. */ |
{ |
unsigned int count = opcode; |
/* Dump */ |
SZ_Memcpy2(pBuffer_OUT, pBuffer_IN, count); |
} |
} /* End of short ops */ |
} |
/* And that's that */ |
return(0); |
} |
/contrib/games/opentyrian/src/animlib.h |
---|
0,0 → 1,27 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef ANIMLIB_H |
#define ANIMLIB_H |
#include "opentyr.h" |
void JE_playAnim( const char *animfile, JE_byte startingframe, JE_byte speed ); |
#endif /* ANIMLIB_H */ |
/contrib/games/opentyrian/src/arg_parse.c |
---|
0,0 → 1,248 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "arg_parse.h" |
#include "std_support.h" |
#ifndef _GNU_SOURCE |
#define _GNU_SOURCE |
#endif |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
static void permute( const char *argv[], int *first_nonopt, int *first_opt, int after_opt ); |
static int parse_short_opt( int argc, const char *const argv[], const Options *options, Option *option ); |
static int parse_long_opt( int argc, const char *const argv[], const Options *options, Option *option ); |
Option parse_args( int argc, const char *argv[], const Options *options ) |
{ |
static int argn = 1; |
static bool no_more_options = false; |
static int first_nonopt = 1; |
Option option = { NOT_OPTION, NULL, 0 }; |
option.argn = first_nonopt; |
while (argn < argc) |
{ |
size_t arg_len = strlen(argv[argn]); |
if (!no_more_options && |
argv[argn][0] == '-' && // first char is '-' |
arg_len > 1) // option is not "-" |
{ |
option.argn = argn; |
if (argv[argn][1] == '-') // string begins with "--" |
{ |
if (arg_len == 2) // "--" alone indicates end of options |
{ |
++argn; |
no_more_options = true; |
} |
else |
{ |
argn = parse_long_opt(argc, argv, options, &option); |
} |
} |
else |
{ |
argn = parse_short_opt(argc, argv, options, &option); |
} |
// shift option in front of non-options |
permute(argv, &first_nonopt, &option.argn, argn); |
// don't include "--" in non-options |
if (no_more_options) |
++option.argn; |
break; |
} |
else |
{ |
// skip non-options, permute later when option encountered |
++argn; |
} |
} |
return option; |
} |
static void permute( const char *argv[], int *first_nonopt, int *first_opt, int after_opt ) |
{ |
const int nonopts = *first_opt - *first_nonopt; |
// slide each of the options in front of the non-options |
for (int i = *first_opt; i < after_opt; ++i) |
{ |
for (int j = i; j > *first_nonopt; --j) |
{ |
// swap argv[j] and argv[j - 1] |
const char *temp = argv[j]; |
argv[j] = argv[j - 1]; |
argv[j - 1] = temp; |
} |
// position of first non-option shifts right once for each option |
++(*first_nonopt); |
} |
// position of first option is initial position of first non-option |
*first_opt -= nonopts; |
} |
static int parse_short_opt( int argc, const char *const argv[], const Options *options, Option *option ) |
{ |
static size_t offset = 1; // ignore the "-" |
int argn = option->argn; |
const char *arg = argv[argn]; |
const size_t arg_len = strlen(arg); |
const bool arg_attached = (offset + 1 < arg_len), // possible argument attached? |
last_in_argv = (argn == argc - 1); |
option->value = INVALID_OPTION; |
for (; !(options->short_opt == 0 && |
options->long_opt == NULL); ++options) |
{ |
if (options->short_opt != 0 && |
options->short_opt == arg[offset]) |
{ |
option->value = options->value; |
if (options->has_arg) |
{ |
if (arg_attached) // arg direclty follows option |
{ |
option->arg = arg + offset + 1; |
offset = arg_len; |
} |
else if (!last_in_argv) // arg is next in argv |
{ |
option->arg = argv[++argn]; |
offset = arg_len; |
} |
else |
{ |
option->value = OPTION_MISSING_ARG; |
break; |
} |
} |
break; |
} |
} |
switch (option->value) |
{ |
case INVALID_OPTION: |
fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], argv[option->argn][offset]); |
break; |
case OPTION_MISSING_ARG: |
fprintf(stderr, "%s: option requires an argument -- '%c'\n", argv[0], argv[option->argn][offset]); |
break; |
} |
if (++offset >= arg_len) |
{ |
++argn; |
offset = 1; |
} |
return argn; // which arg in argv that parse_args() should examine when called again |
} |
static int parse_long_opt( int argc, const char *const argv[], const Options *options, Option *option ) |
{ |
int argn = option->argn; |
const char *arg = argv[argn] + 2; // ignore the "--" |
const size_t arg_len = strlen(arg), |
arg_opt_len = ot_strchrnul(arg, '=') - arg; // length before "=" |
const bool arg_attached = (arg_opt_len < arg_len), // argument attached using "="? |
last_in_argv = (argn == argc - 1); |
option->value = INVALID_OPTION; |
for (; !(options->short_opt == 0 && |
options->long_opt == NULL); ++options) |
{ |
if (options->long_opt != NULL && |
strncmp(options->long_opt, arg, arg_opt_len) == 0) // matches (partially, at least) |
{ |
if (option->value != INVALID_OPTION) // other match already found |
{ |
option->value = AMBIGUOUS_OPTION; |
break; |
} |
option->value = options->value; |
if (options->has_arg) |
{ |
if (arg_attached) // arg is after "=" |
{ |
option->arg = arg + arg_opt_len + 1; |
} |
else if (!last_in_argv) // arg is next in argv |
{ |
option->arg = argv[++argn]; |
} |
else // arg is missing |
{ |
option->value = OPTION_MISSING_ARG; |
// can't break, gotta check for ambiguity |
} |
} |
if (arg_opt_len == strlen(options->long_opt)) // exact match |
break; |
// can't break for partial match, gotta check for ambiguity |
} |
} |
switch (option->value) |
{ |
case INVALID_OPTION: |
fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[option->argn]); |
break; |
case AMBIGUOUS_OPTION: |
fprintf(stderr, "%s: option '%s' is ambiguous\n", argv[0], argv[option->argn]); |
break; |
case OPTION_MISSING_ARG: |
fprintf(stderr, "%s: option '%s' requires an argument\n", argv[0], argv[option->argn]); |
break; |
} |
++argn; |
return argn; // which arg in argv that parse_args() should examine when called again |
} |
/contrib/games/opentyrian/src/arg_parse.h |
---|
0,0 → 1,58 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef ARG_PARSE_H |
#define ARG_PARSE_H |
#include <stdbool.h> |
// this is essentially a reimplementation of getopt_long() |
typedef struct |
{ |
int value; |
char short_opt; |
const char *long_opt; |
bool has_arg; |
} |
Options; |
enum |
{ |
// indicates that argv[argn..argc) are not options |
NOT_OPTION = 0, |
/* behavior of parse_args() is undefined after |
it has returned any of the following values */ |
INVALID_OPTION = -1, |
AMBIGUOUS_OPTION = -2, |
OPTION_MISSING_ARG = -3 |
}; |
typedef struct |
{ |
int value; |
const char *arg; |
int argn; |
} |
Option; |
Option parse_args( int argc, const char *argv[], const Options *options ); |
#endif /* ARG_PARSE_H */ |
/contrib/games/opentyrian/src/backgrnd.c |
---|
0,0 → 1,527 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "backgrnd.h" |
#include "config.h" |
#include "mtrand.h" |
#include "opentyr.h" |
#include "varz.h" |
#include "video.h" |
#include <assert.h> |
/*Special Background 2 and Background 3*/ |
/*Back Pos 3*/ |
JE_word backPos, backPos2, backPos3; |
JE_word backMove, backMove2, backMove3; |
/*Main Maps*/ |
JE_word mapX, mapY, mapX2, mapX3, mapY2, mapY3; |
JE_byte **mapYPos, **mapY2Pos, **mapY3Pos; |
JE_word mapXPos, oldMapXOfs, mapXOfs, mapX2Ofs, mapX2Pos, mapX3Pos, oldMapX3Ofs, mapX3Ofs, tempMapXOfs; |
intptr_t mapXbpPos, mapX2bpPos, mapX3bpPos; |
JE_byte map1YDelay, map1YDelayMax, map2YDelay, map2YDelayMax; |
JE_boolean anySmoothies; |
JE_byte smoothie_data[9]; /* [1..9] */ |
void JE_darkenBackground( JE_word neat ) /* wild detail level */ |
{ |
Uint8 *s = VGAScreen->pixels; /* screen pointer, 8-bit specific */ |
int x, y; |
s += 24; |
for (y = 184; y; y--) |
{ |
for (x = 264; x; x--) |
{ |
*s = ((((*s & 0x0f) << 4) - (*s & 0x0f) + ((((x - neat - y) >> 2) + *(s-2) + (y == 184 ? 0 : *(s-(VGAScreen->pitch-1)))) & 0x0f)) >> 4) | (*s & 0xf0); |
s++; |
} |
s += VGAScreen->pitch - 264; |
} |
} |
void blit_background_row( SDL_Surface *surface, int x, int y, Uint8 **map ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x, |
*pixels_ll = (Uint8 *)surface->pixels, // lower limit |
*pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (int y = 0; y < 28; y++) |
{ |
// not drawing on screen yet; skip y |
if ((pixels + (12 * 24)) < pixels_ll) |
{ |
pixels += surface->pitch; |
continue; |
} |
for (int tile = 0; tile < 12; tile++) |
{ |
Uint8 *data = *(map + tile); |
// no tile; skip tile |
if (data == NULL) |
{ |
pixels += 24; |
continue; |
} |
data += y * 24; |
for (int x = 24; x; x--) |
{ |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll && *data != 0) |
*pixels = *data; |
pixels++; |
data++; |
} |
} |
pixels += surface->pitch - 12 * 24; |
} |
} |
void blit_background_row_blend( SDL_Surface *surface, int x, int y, Uint8 **map ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x, |
*pixels_ll = (Uint8 *)surface->pixels, // lower limit |
*pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (int y = 0; y < 28; y++) |
{ |
// not drawing on screen yet; skip y |
if ((pixels + (12 * 24)) < pixels_ll) |
{ |
pixels += surface->pitch; |
continue; |
} |
for (int tile = 0; tile < 12; tile++) |
{ |
Uint8 *data = *(map + tile); |
// no tile; skip tile |
if (data == NULL) |
{ |
pixels += 24; |
continue; |
} |
data += y * 24; |
for (int x = 24; x; x--) |
{ |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll && *data != 0) |
*pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2); |
pixels++; |
data++; |
} |
} |
pixels += surface->pitch - 12 * 24; |
} |
} |
void draw_background_1( SDL_Surface *surface ) |
{ |
SDL_FillRect(surface, NULL, 0); |
Uint8 **map = (Uint8 **)mapYPos + mapXbpPos - 12; |
for (int i = -1; i < 7; i++) |
{ |
blit_background_row(surface, mapXPos, (i * 28) + backPos, map); |
map += 14; |
} |
} |
void draw_background_2( SDL_Surface *surface ) |
{ |
if (map2YDelayMax > 1 && backMove2 < 2) |
backMove2 = (map2YDelay == 1) ? 1 : 0; |
if (background2 != 0) |
{ |
// water effect combines background 1 and 2 by syncronizing the x coordinate |
int x = smoothies[1] ? mapXPos : mapX2Pos; |
Uint8 **map = (Uint8 **)mapY2Pos + (smoothies[1] ? mapXbpPos : mapX2bpPos) - 12; |
for (int i = -1; i < 7; i++) |
{ |
blit_background_row(surface, x, (i * 28) + backPos2, map); |
map += 14; |
} |
} |
/*Set Movement of background*/ |
if (--map2YDelay == 0) |
{ |
map2YDelay = map2YDelayMax; |
backPos2 += backMove2; |
if (backPos2 > 27) |
{ |
backPos2 -= 28; |
mapY2--; |
mapY2Pos -= 14; /*Map Width*/ |
} |
} |
} |
void draw_background_2_blend( SDL_Surface *surface ) |
{ |
if (map2YDelayMax > 1 && backMove2 < 2) |
backMove2 = (map2YDelay == 1) ? 1 : 0; |
Uint8 **map = (Uint8 **)mapY2Pos + mapX2bpPos - 12; |
for (int i = -1; i < 7; i++) |
{ |
blit_background_row_blend(surface, mapX2Pos, (i * 28) + backPos2, map); |
map += 14; |
} |
/*Set Movement of background*/ |
if (--map2YDelay == 0) |
{ |
map2YDelay = map2YDelayMax; |
backPos2 += backMove2; |
if (backPos2 > 27) |
{ |
backPos2 -= 28; |
mapY2--; |
mapY2Pos -= 14; /*Map Width*/ |
} |
} |
} |
void draw_background_3( SDL_Surface *surface ) |
{ |
/* Movement of background */ |
backPos3 += backMove3; |
if (backPos3 > 27) |
{ |
backPos3 -= 28; |
mapY3--; |
mapY3Pos -= 15; /*Map Width*/ |
} |
Uint8 **map = (Uint8 **)mapY3Pos + mapX3bpPos - 12; |
for (int i = -1; i < 7; i++) |
{ |
blit_background_row(surface, mapX3Pos, (i * 28) + backPos3, map); |
map += 15; |
} |
} |
void JE_filterScreen( JE_shortint col, JE_shortint int_) |
{ |
Uint8 *s = NULL; /* screen pointer, 8-bit specific */ |
int x, y; |
unsigned int temp; |
if (filterFade) |
{ |
levelBrightness += levelBrightnessChg; |
if ((filterFadeStart && levelBrightness < -14) || levelBrightness > 14) |
{ |
levelBrightnessChg = -levelBrightnessChg; |
filterFadeStart = false; |
levelFilter = levelFilterNew; |
} |
if (!filterFadeStart && levelBrightness == 0) |
{ |
filterFade = false; |
levelBrightness = -99; |
} |
} |
if (col != -99 && filtrationAvail) |
{ |
s = VGAScreen->pixels; |
s += 24; |
col <<= 4; |
for (y = 184; y; y--) |
{ |
for (x = 264; x; x--) |
{ |
*s = col | (*s & 0x0f); |
s++; |
} |
s += VGAScreen->pitch - 264; |
} |
} |
if (int_ != -99 && explosionTransparent) |
{ |
s = VGAScreen->pixels; |
s += 24; |
for (y = 184; y; y--) |
{ |
for (x = 264; x; x--) |
{ |
temp = (*s & 0x0f) + int_; |
*s = (*s & 0xf0) | (temp >= 0x1f ? 0 : (temp >= 0x0f ? 0x0f : temp)); |
s++; |
} |
s += VGAScreen->pitch - 264; |
} |
} |
} |
void JE_checkSmoothies( void ) |
{ |
anySmoothies = (processorType > 2 && (smoothies[1-1] || smoothies[2-1])) || (processorType > 1 && (smoothies[3-1] || smoothies[4-1] || smoothies[5-1])); |
} |
void lava_filter( SDL_Surface *dst, SDL_Surface *src ) |
{ |
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8); |
/* we don't need to check for over-reading the pixel surfaces since we only |
* read from the top 185+1 scanlines, and there should be 320 */ |
const int dst_pitch = dst->pitch; |
Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch); |
const Uint8 * const dst_pixel_ll = (Uint8 *)dst->pixels; // lower limit |
const int src_pitch = src->pitch; |
const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch); |
const Uint8 * const src_pixel_ll = (Uint8 *)src->pixels; // lower limit |
int w = 320 * 185 - 1; |
for (int y = 185 - 1; y >= 0; --y) |
{ |
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320 |
src_pixel -= (src_pitch - 320); // in case pitch is not 320 |
for (int x = 320 - 1; x >= 0; x -= 8) |
{ |
int waver = abs(((w >> 9) & 0x0f) - 8) - 1; |
w -= 8; |
for (int xi = 8 - 1; xi >= 0; --xi) |
{ |
--dst_pixel; |
--src_pixel; |
// value is average value of source pixel (2x), destination pixel above, and destination pixel below (all with waver) |
// hue is red |
Uint8 value = 0; |
if (src_pixel + waver >= src_pixel_ll) |
value += (*(src_pixel + waver) & 0x0f) * 2; |
value += *(dst_pixel + waver + dst_pitch) & 0x0f; |
if (dst_pixel + waver - dst_pitch >= dst_pixel_ll) |
value += *(dst_pixel + waver - dst_pitch) & 0x0f; |
*dst_pixel = (value / 4) | 0x70; |
} |
} |
} |
} |
void water_filter( SDL_Surface *dst, SDL_Surface *src ) |
{ |
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8); |
Uint8 hue = smoothie_data[1] << 4; |
/* we don't need to check for over-reading the pixel surfaces since we only |
* read from the top 185+1 scanlines, and there should be 320 */ |
const int dst_pitch = dst->pitch; |
Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch); |
const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch); |
int w = 320 * 185 - 1; |
for (int y = 185 - 1; y >= 0; --y) |
{ |
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320 |
src_pixel -= (src->pitch - 320); // in case pitch is not 320 |
for (int x = 320 - 1; x >= 0; x -= 8) |
{ |
int waver = abs(((w >> 10) & 0x07) - 4) - 1; |
w -= 8; |
for (int xi = 8 - 1; xi >= 0; --xi) |
{ |
--dst_pixel; |
--src_pixel; |
// pixel is copied from source if not blue |
// otherwise, value is average of value of source pixel and destination pixel below (with waver) |
if ((*src_pixel & 0x30) == 0) |
{ |
*dst_pixel = *src_pixel; |
} |
else |
{ |
Uint8 value = *src_pixel & 0x0f; |
value += *(dst_pixel + waver + dst_pitch) & 0x0f; |
*dst_pixel = (value / 2) | hue; |
} |
} |
} |
} |
} |
void iced_blur_filter( SDL_Surface *dst, SDL_Surface *src ) |
{ |
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8); |
Uint8 *dst_pixel = dst->pixels; |
const Uint8 *src_pixel = src->pixels; |
for (int y = 0; y < 184; ++y) |
{ |
for (int x = 0; x < 320; ++x) |
{ |
// value is average value of source pixel and destination pixel |
// hue is icy blue |
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f); |
*dst_pixel = (value / 2) | 0x80; |
++dst_pixel; |
++src_pixel; |
} |
dst_pixel += (dst->pitch - 320); // in case pitch is not 320 |
src_pixel += (src->pitch - 320); // in case pitch is not 320 |
} |
} |
void blur_filter( SDL_Surface *dst, SDL_Surface *src ) |
{ |
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8); |
Uint8 *dst_pixel = dst->pixels; |
const Uint8 *src_pixel = src->pixels; |
for (int y = 0; y < 184; ++y) |
{ |
for (int x = 0; x < 320; ++x) |
{ |
// value is average value of source pixel and destination pixel |
// hue is source pixel hue |
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f); |
*dst_pixel = (value / 2) | (*src_pixel & 0xf0); |
++dst_pixel; |
++src_pixel; |
} |
dst_pixel += (dst->pitch - 320); // in case pitch is not 320 |
src_pixel += (src->pitch - 320); // in case pitch is not 320 |
} |
} |
/* Background Starfield */ |
typedef struct |
{ |
Uint8 color; |
JE_word position; // relies on overflow wrap-around |
int speed; |
} StarfieldStar; |
#define MAX_STARS 100 |
#define STARFIELD_HUE 0x90 |
static StarfieldStar starfield_stars[MAX_STARS]; |
int starfield_speed; |
void initialize_starfield( void ) |
{ |
for (int i = MAX_STARS-1; i >= 0; --i) |
{ |
starfield_stars[i].position = mt_rand() % 320 + mt_rand() % 200 * VGAScreen->pitch; |
starfield_stars[i].speed = mt_rand() % 3 + 2; |
starfield_stars[i].color = mt_rand() % 16 + STARFIELD_HUE; |
} |
} |
void update_and_draw_starfield( SDL_Surface* surface, int move_speed ) |
{ |
Uint8* p = (Uint8*)surface->pixels; |
for (int i = MAX_STARS-1; i >= 0; --i) |
{ |
StarfieldStar* star = &starfield_stars[i]; |
star->position += (star->speed + move_speed) * surface->pitch; |
if (star->position < 177 * surface->pitch) |
{ |
if (p[star->position] == 0) |
{ |
p[star->position] = star->color; |
} |
// If star is bright enough, draw surrounding pixels |
if (star->color - 4 >= STARFIELD_HUE) |
{ |
if (p[star->position + 1] == 0) |
p[star->position + 1] = star->color - 4; |
if (star->position > 0 && p[star->position - 1] == 0) |
p[star->position - 1] = star->color - 4; |
if (p[star->position + surface->pitch] == 0) |
p[star->position + surface->pitch] = star->color - 4; |
if (star->position >= surface->pitch && p[star->position - surface->pitch] == 0) |
p[star->position - surface->pitch] = star->color - 4; |
} |
} |
} |
} |
/contrib/games/opentyrian/src/backgrnd.h |
---|
0,0 → 1,64 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef BACKGRND_H |
#define BACKGRND_H |
#include "opentyr.h" |
#include "SDL.h" |
#include <stdint.h> |
extern JE_word backPos, backPos2, backPos3; |
extern JE_word backMove, backMove2, backMove3; |
extern JE_word mapX, mapY, mapX2, mapX3, mapY2, mapY3; |
extern JE_byte **mapYPos, **mapY2Pos, **mapY3Pos; |
extern JE_word mapXPos, oldMapXOfs, mapXOfs, mapX2Ofs, mapX2Pos, mapX3Pos, oldMapX3Ofs, mapX3Ofs, tempMapXOfs; |
extern intptr_t mapXbpPos, mapX2bpPos, mapX3bpPos; |
extern JE_byte map1YDelay, map1YDelayMax, map2YDelay, map2YDelayMax; |
extern JE_boolean anySmoothies; // if yes, I want one :D |
extern JE_byte smoothie_data[9]; |
extern int starfield_speed; |
void JE_darkenBackground( JE_word neat ); |
void blit_background_row( SDL_Surface *surface, int x, int y, Uint8 **map ); |
void blit_background_row_blend( SDL_Surface *surface, int x, int y, Uint8 **map ); |
void draw_background_1( SDL_Surface *surface ); |
void draw_background_2( SDL_Surface *surface ); |
void draw_background_2_blend( SDL_Surface *surface ); |
void draw_background_3( SDL_Surface *surface ); |
void JE_filterScreen( JE_shortint col, JE_shortint generic_int ); |
void JE_checkSmoothies( void ); |
void lava_filter( SDL_Surface *dst, SDL_Surface *src ); |
void water_filter( SDL_Surface *dst, SDL_Surface *src ); |
void iced_blur_filter( SDL_Surface *dst, SDL_Surface *src ); |
void blur_filter( SDL_Surface *dst, SDL_Surface *src ); |
/*smoothies #5 is used for 3*/ |
/*smoothies #9 is a vertical flip*/ |
void initialize_starfield( void ); |
void update_and_draw_starfield( SDL_Surface* surface, int move_speed ); |
#endif /* BACKGRND_H */ |
/contrib/games/opentyrian/src/config.c |
---|
0,0 → 1,1014 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "config.h" |
#include "episodes.h" |
#include "file.h" |
#include "joystick.h" |
#include "loudness.h" |
#include "mtrand.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "player.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include "video_scale.h" |
#include <stdio.h> |
#include <sys/stat.h> |
#ifdef _MSC_VER |
#include <direct.h> |
#define mkdir _mkdir |
#else |
#include <unistd.h> |
#endif |
/* Configuration Load/Save handler */ |
const JE_byte cryptKey[10] = /* [1..10] */ |
{ |
15, 50, 89, 240, 147, 34, 86, 9, 32, 208 |
}; |
const JE_KeySettingType defaultKeySettings = |
{ |
SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_SPACE, SDLK_RETURN, SDLK_LCTRL, SDLK_LALT |
/* 72, 80, 75, 77, 57, 28, 29, 56*/ |
}; |
const char defaultHighScoreNames[34][23] = /* [1..34] of string [22] */ |
{/*1P*/ |
/*TYR*/ "The Prime Chair", /*13*/ |
"Transon Lohk", |
"Javi Onukala", |
"Mantori", |
"Nortaneous", |
"Dougan", |
"Reid", |
"General Zinglon", |
"Late Gyges Phildren", |
"Vykromod", |
"Beppo", |
"Borogar", |
"ShipMaster Carlos", |
/*OTHER*/ "Jill", /*5*/ |
"Darcy", |
"Jake Stone", |
"Malvineous Havershim", |
"Marta Louise Velasquez", |
/*JAZZ*/ "Jazz Jackrabbit", /*3*/ |
"Eva Earlong", |
"Devan Shell", |
/*OMF*/ "Crystal Devroe", /*11*/ |
"Steffan Tommas", |
"Milano Angston", |
"Christian", |
"Shirro", |
"Jean-Paul", |
"Ibrahim Hothe", |
"Angel", |
"Cossette Akira", |
"Raven", |
"Hans Kreissack", |
/*DARE*/ "Tyler", /*2*/ |
"Rennis the Rat Guard" |
}; |
const char defaultTeamNames[22][25] = /* [1..22] of string [24] */ |
{ |
"Jackrabbits", |
"Team Tyrian", |
"The Elam Brothers", |
"Dare to Dream Team", |
"Pinball Freaks", |
"Extreme Pinball Freaks", |
"Team Vykromod", |
"Epic All-Stars", |
"Hans Keissack's WARriors", |
"Team Overkill", |
"Pied Pipers", |
"Gencore Growlers", |
"Microsol Masters", |
"Beta Warriors", |
"Team Loco", |
"The Shellians", |
"Jungle Jills", |
"Murderous Malvineous", |
"The Traffic Department", |
"Clan Mikal", |
"Clan Patrok", |
"Carlos' Crawlers" |
}; |
const JE_EditorItemAvailType initialItemAvail = |
{ |
1,1,1,0,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, /* Front/Rear Weapons 1-38 */ |
0,0,0,0,0,0,0,0,0,0,1, /* Fill */ |
1,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0,0, /* Sidekicks 51-68 */ |
0,0,0,0,0,0,0,0,0,0,0, /* Fill */ |
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* Special Weapons 81-93 */ |
0,0,0,0,0 /* Fill */ |
}; |
/* Last 2 bytes = Word |
* |
* Max Value = 1680 |
* X div 60 = Armor (1-28) |
* X div 168 = Shield (1-12) |
* X div 280 = Engine (1-06) |
*/ |
JE_boolean smoothies[9] = /* [1..9] */ |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
JE_byte starShowVGASpecialCode; |
/* CubeData */ |
JE_word lastCubeMax, cubeMax; |
JE_word cubeList[4]; /* [1..4] */ |
/* High-Score Stuff */ |
JE_boolean gameHasRepeated; // can only get highscore on first play-through |
/* Difficulty */ |
JE_shortint difficultyLevel, oldDifficultyLevel, |
initialDifficulty; // can only get highscore on initial episode |
/* Player Stuff */ |
uint power, lastPower, powerAdd; |
JE_byte shieldWait, shieldT; |
JE_byte shotRepeat[11], shotMultiPos[11]; |
JE_boolean portConfigChange, portConfigDone; |
/* Level Data */ |
char lastLevelName[11], levelName[11]; /* string [10] */ |
JE_byte mainLevel, nextLevel, saveLevel; /*Current Level #*/ |
/* Keyboard Junk */ |
JE_KeySettingType keySettings; |
/* Configuration */ |
JE_shortint levelFilter, levelFilterNew, levelBrightness, levelBrightnessChg; |
JE_boolean filtrationAvail, filterActive, filterFade, filterFadeStart; |
JE_boolean gameJustLoaded; |
JE_boolean galagaMode; |
JE_boolean extraGame; |
JE_boolean twoPlayerMode, twoPlayerLinked, onePlayerAction, superTyrian; |
JE_boolean trentWin = false; |
JE_byte superArcadeMode; |
JE_byte superArcadePowerUp; |
JE_real linkGunDirec; |
JE_byte inputDevice[2] = { 1, 2 }; // 0:any 1:keyboard 2:mouse 3+:joystick |
JE_byte secretHint; |
JE_byte background3over; |
JE_byte background2over; |
JE_byte gammaCorrection; |
JE_boolean superPause = false; |
JE_boolean explosionTransparent, |
youAreCheating, |
displayScore, |
background2, smoothScroll, wild, superWild, starActive, |
topEnemyOver, |
skyEnemyOverAll, |
background2notTransparent; |
JE_byte soundEffects; // dummy value for config |
JE_byte versionNum; /* SW 1.0 and SW/Reg 1.1 = 0 or 1 |
* EA 1.2 = 2 */ |
JE_byte fastPlay; |
JE_boolean pentiumMode; |
/* Savegame files */ |
JE_byte gameSpeed; |
JE_byte processorType; /* 1=386 2=486 3=Pentium Hyper */ |
JE_SaveFilesType saveFiles; /*array[1..saveLevelnum] of savefiletype;*/ |
JE_SaveGameTemp saveTemp; |
JE_word editorLevel; /*Initial value 800*/ |
Config opentyrian_config; // implicitly initialized |
bool load_opentyrian_config( void ) |
{ |
// defaults |
fullscreen_enabled = false; |
set_scaler_by_name("Scale2x"); |
Config *config = &opentyrian_config; |
FILE *file = dir_fopen_warn(get_user_directory(), "opentyrian.cfg", "r"); |
if (file == NULL) |
return false; |
if (!config_parse(config, file)) |
{ |
fclose(file); |
return false; |
} |
ConfigSection *section; |
section = config_find_section(config, "video", NULL); |
if (section != NULL) |
{ |
config_get_bool_option(section, "fullscreen", &fullscreen_enabled); |
const char *scaler; |
if (config_get_string_option(section, "scaler", &scaler)) |
set_scaler_by_name(scaler); |
} |
fclose(file); |
return true; |
} |
bool save_opentyrian_config( void ) |
{ |
Config *config = &opentyrian_config; |
ConfigSection *section; |
section = config_find_or_add_section(config, "video", NULL); |
if (section == NULL) |
exit(EXIT_FAILURE); // out of memory |
config_set_bool_option(section, "fullscreen", fullscreen_enabled, NO_YES); |
config_set_string_option(section, "scaler", scalers[scaler].name); |
#ifndef TARGET_WIN32 |
mkdir(get_user_directory(), 0700); |
#else |
mkdir(get_user_directory()); |
#endif |
FILE *file = dir_fopen(get_user_directory(), "opentyrian.cfg", "wb"); |
if (file == NULL) |
return false; |
config_write(config, file); |
printf("config write"); |
#if defined(TARGET_UNIX) |
fsync(fileno(file)); |
#endif |
fclose(file); |
return true; |
} |
static void playeritems_to_pitems( JE_PItemsType pItems, PlayerItems *items, JE_byte initial_episode_num ) |
{ |
pItems[0] = items->weapon[FRONT_WEAPON].id; |
pItems[1] = items->weapon[REAR_WEAPON].id; |
pItems[2] = items->super_arcade_mode; |
pItems[3] = items->sidekick[LEFT_SIDEKICK]; |
pItems[4] = items->sidekick[RIGHT_SIDEKICK]; |
pItems[5] = items->generator; |
pItems[6] = items->sidekick_level; |
pItems[7] = items->sidekick_series; |
pItems[8] = initial_episode_num; |
pItems[9] = items->shield; |
pItems[10] = items->special; |
pItems[11] = items->ship; |
} |
static void pitems_to_playeritems( PlayerItems *items, JE_PItemsType pItems, JE_byte *initial_episode_num ) |
{ |
items->weapon[FRONT_WEAPON].id = pItems[0]; |
items->weapon[REAR_WEAPON].id = pItems[1]; |
items->super_arcade_mode = pItems[2]; |
items->sidekick[LEFT_SIDEKICK] = pItems[3]; |
items->sidekick[RIGHT_SIDEKICK] = pItems[4]; |
items->generator = pItems[5]; |
items->sidekick_level = pItems[6]; |
items->sidekick_series = pItems[7]; |
if (initial_episode_num != NULL) |
*initial_episode_num = pItems[8]; |
items->shield = pItems[9]; |
items->special = pItems[10]; |
items->ship = pItems[11]; |
} |
void JE_saveGame( JE_byte slot, const char *name ) |
{ |
saveFiles[slot-1].initialDifficulty = initialDifficulty; |
saveFiles[slot-1].gameHasRepeated = gameHasRepeated; |
saveFiles[slot-1].level = saveLevel; |
if (superTyrian) |
player[0].items.super_arcade_mode = SA_SUPERTYRIAN; |
else if (superArcadeMode == SA_NONE && onePlayerAction) |
player[0].items.super_arcade_mode = SA_ARCADE; |
else |
player[0].items.super_arcade_mode = superArcadeMode; |
playeritems_to_pitems(saveFiles[slot-1].items, &player[0].items, initial_episode_num); |
if (twoPlayerMode) |
playeritems_to_pitems(saveFiles[slot-1].lastItems, &player[1].items, 0); |
else |
playeritems_to_pitems(saveFiles[slot-1].lastItems, &player[0].last_items, 0); |
saveFiles[slot-1].score = player[0].cash; |
saveFiles[slot-1].score2 = player[1].cash; |
memcpy(&saveFiles[slot-1].levelName, &lastLevelName, sizeof(lastLevelName)); |
saveFiles[slot-1].cubes = lastCubeMax; |
if (strcmp(lastLevelName, "Completed") == 0) |
{ |
temp = episodeNum - 1; |
if (temp < 1) |
{ |
temp = EPISODE_AVAILABLE; /* JE: {Episodemax is 4 for completion purposes} */ |
} |
saveFiles[slot-1].episode = temp; |
} |
else |
{ |
saveFiles[slot-1].episode = episodeNum; |
} |
saveFiles[slot-1].difficulty = difficultyLevel; |
saveFiles[slot-1].secretHint = secretHint; |
saveFiles[slot-1].input1 = inputDevice[0]; |
saveFiles[slot-1].input2 = inputDevice[1]; |
strcpy(saveFiles[slot-1].name, name); |
for (uint port = 0; port < 2; ++port) |
{ |
// if two-player, use first player's front and second player's rear weapon |
saveFiles[slot-1].power[port] = player[twoPlayerMode ? port : 0].items.weapon[port].power; |
} |
JE_saveConfiguration(); |
} |
void JE_loadGame( JE_byte slot ) |
{ |
superTyrian = false; |
onePlayerAction = false; |
twoPlayerMode = false; |
extraGame = false; |
galagaMode = false; |
initialDifficulty = saveFiles[slot-1].initialDifficulty; |
gameHasRepeated = saveFiles[slot-1].gameHasRepeated; |
twoPlayerMode = (slot-1) > 10; |
difficultyLevel = saveFiles[slot-1].difficulty; |
pitems_to_playeritems(&player[0].items, saveFiles[slot-1].items, &initial_episode_num); |
superArcadeMode = player[0].items.super_arcade_mode; |
if (superArcadeMode == SA_SUPERTYRIAN) |
superTyrian = true; |
if (superArcadeMode != SA_NONE) |
onePlayerAction = true; |
if (superArcadeMode > SA_NORTSHIPZ) |
superArcadeMode = SA_NONE; |
if (twoPlayerMode) |
{ |
onePlayerAction = false; |
pitems_to_playeritems(&player[1].items, saveFiles[slot-1].lastItems, NULL); |
} |
else |
{ |
pitems_to_playeritems(&player[0].last_items, saveFiles[slot-1].lastItems, NULL); |
} |
/* Compatibility with old version */ |
if (player[1].items.sidekick_level < 101) |
{ |
player[1].items.sidekick_level = 101; |
player[1].items.sidekick_series = player[1].items.sidekick[LEFT_SIDEKICK]; |
} |
player[0].cash = saveFiles[slot-1].score; |
player[1].cash = saveFiles[slot-1].score2; |
mainLevel = saveFiles[slot-1].level; |
cubeMax = saveFiles[slot-1].cubes; |
lastCubeMax = cubeMax; |
secretHint = saveFiles[slot-1].secretHint; |
inputDevice[0] = saveFiles[slot-1].input1; |
inputDevice[1] = saveFiles[slot-1].input2; |
for (uint port = 0; port < 2; ++port) |
{ |
// if two-player, use first player's front and second player's rear weapon |
player[twoPlayerMode ? port : 0].items.weapon[port].power = saveFiles[slot-1].power[port]; |
} |
int episode = saveFiles[slot-1].episode; |
memcpy(&levelName, &saveFiles[slot-1].levelName, sizeof(levelName)); |
if (strcmp(levelName, "Completed") == 0) |
{ |
if (episode == EPISODE_AVAILABLE) |
{ |
episode = 1; |
} else if (episode < EPISODE_AVAILABLE) { |
episode++; |
} |
/* Increment episode. Episode EPISODE_AVAILABLE goes to 1. */ |
} |
JE_initEpisode(episode); |
saveLevel = mainLevel; |
memcpy(&lastLevelName, &levelName, sizeof(levelName)); |
} |
void JE_initProcessorType( void ) |
{ |
/* SYN: Originally this proc looked at your hardware specs and chose appropriate options. We don't care, so I'll just set |
decent defaults here. */ |
wild = false; |
superWild = false; |
smoothScroll = true; |
explosionTransparent = true; |
filtrationAvail = false; |
background2 = true; |
displayScore = true; |
switch (processorType) |
{ |
case 1: /* 386 */ |
background2 = false; |
displayScore = false; |
explosionTransparent = false; |
break; |
case 2: /* 486 - Default */ |
break; |
case 3: /* High Detail */ |
smoothScroll = false; |
break; |
case 4: /* Pentium */ |
wild = true; |
filtrationAvail = true; |
break; |
case 5: /* Nonstandard VGA */ |
smoothScroll = false; |
break; |
case 6: /* SuperWild */ |
wild = true; |
superWild = true; |
filtrationAvail = true; |
break; |
} |
switch (gameSpeed) |
{ |
case 1: /* Slug Mode */ |
fastPlay = 3; |
break; |
case 2: /* Slower */ |
fastPlay = 4; |
break; |
case 3: /* Slow */ |
fastPlay = 5; |
break; |
case 4: /* Normal */ |
fastPlay = 0; |
break; |
case 5: /* Pentium Hyper */ |
fastPlay = 1; |
break; |
} |
} |
void JE_setNewGameSpeed( void ) |
{ |
pentiumMode = false; |
switch (fastPlay) |
{ |
case 0: |
speed = 0x4300; |
smoothScroll = true; |
frameCountMax = 2; |
break; |
case 1: |
speed = 0x3000; |
smoothScroll = true; |
frameCountMax = 2; |
break; |
case 2: |
speed = 0x2000; |
smoothScroll = false; |
frameCountMax = 2; |
break; |
case 3: |
speed = 0x5300; |
smoothScroll = true; |
frameCountMax = 4; |
break; |
case 4: |
speed = 0x4300; |
smoothScroll = true; |
frameCountMax = 3; |
break; |
case 5: |
speed = 0x4300; |
smoothScroll = true; |
frameCountMax = 2; |
pentiumMode = true; |
break; |
} |
frameCount = frameCountMax; |
JE_resetTimerInt(); |
JE_setTimerInt(); |
} |
void JE_encryptSaveTemp( void ) |
{ |
JE_SaveGameTemp s3; |
JE_word x; |
JE_byte y; |
memcpy(&s3, &saveTemp, sizeof(s3)); |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y += s3[x]; |
} |
saveTemp[SAVE_FILE_SIZE] = y; |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y -= s3[x]; |
} |
saveTemp[SAVE_FILE_SIZE+1] = y; |
y = 1; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y = (y * s3[x]) + 1; |
} |
saveTemp[SAVE_FILE_SIZE+2] = y; |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y = y ^ s3[x]; |
} |
saveTemp[SAVE_FILE_SIZE+3] = y; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
saveTemp[x] = saveTemp[x] ^ cryptKey[(x+1) % 10]; |
if (x > 0) |
{ |
saveTemp[x] = saveTemp[x] ^ saveTemp[x - 1]; |
} |
} |
} |
void JE_decryptSaveTemp( void ) |
{ |
JE_boolean correct = true; |
JE_SaveGameTemp s2; |
int x; |
JE_byte y; |
/* Decrypt save game file */ |
for (x = (SAVE_FILE_SIZE - 1); x >= 0; x--) |
{ |
s2[x] = (JE_byte)saveTemp[x] ^ (JE_byte)(cryptKey[(x+1) % 10]); |
if (x > 0) |
{ |
s2[x] ^= (JE_byte)saveTemp[x - 1]; |
} |
} |
/* for (x = 0; x < SAVE_FILE_SIZE; x++) printf("%c", s2[x]); */ |
/* Check save file for correctitude */ |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y += s2[x]; |
} |
if (saveTemp[SAVE_FILE_SIZE] != y) |
{ |
correct = false; |
printf("Failed additive checksum: %d vs %d\n", saveTemp[SAVE_FILE_SIZE], y); |
} |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y -= s2[x]; |
} |
if (saveTemp[SAVE_FILE_SIZE+1] != y) |
{ |
correct = false; |
printf("Failed subtractive checksum: %d vs %d\n", saveTemp[SAVE_FILE_SIZE+1], y); |
} |
y = 1; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y = (y * s2[x]) + 1; |
} |
if (saveTemp[SAVE_FILE_SIZE+2] != y) |
{ |
correct = false; |
printf("Failed multiplicative checksum: %d vs %d\n", saveTemp[SAVE_FILE_SIZE+2], y); |
} |
y = 0; |
for (x = 0; x < SAVE_FILE_SIZE; x++) |
{ |
y = y ^ s2[x]; |
} |
if (saveTemp[SAVE_FILE_SIZE+3] != y) |
{ |
correct = false; |
printf("Failed XOR'd checksum: %d vs %d\n", saveTemp[SAVE_FILE_SIZE+3], y); |
} |
/* Barf and die if save file doesn't validate */ |
if (!correct) |
{ |
fprintf(stderr, "Error reading save file!\n"); |
exit(255); |
} |
/* Keep decrypted version plz */ |
memcpy(&saveTemp, &s2, sizeof(s2)); |
} |
const char *get_user_directory( void ) |
{ |
static char user_dir[500] = ""; |
if (strlen(user_dir) == 0) |
{ |
#if defined(TARGET_UNIX) |
char *xdg_config_home = getenv("XDG_CONFIG_HOME"); |
if (xdg_config_home != NULL) |
{ |
snprintf(user_dir, sizeof(user_dir), "%s/opentyrian", xdg_config_home); |
} |
else |
{ |
char *home = getenv("HOME"); |
if (home != NULL) |
{ |
snprintf(user_dir, sizeof(user_dir), "%s/.config/opentyrian", home); |
} |
else |
{ |
strcpy(user_dir, "."); |
} |
} |
#else |
strcpy(user_dir, "."); |
#endif |
} |
return user_dir; |
} |
// for compatibility |
Uint8 joyButtonAssign[4] = {1, 4, 5, 5}; |
Uint8 inputDevice_ = 0, jConfigure = 0, midiPort = 1; |
void JE_loadConfiguration( void ) |
{ |
FILE *fi; |
int z; |
JE_byte *p; |
int y; |
fi = dir_fopen_warn(get_user_directory(), "tyrian.cfg", "rb"); |
if (fi && ftell_eof(fi) == 20 + sizeof(keySettings)) |
{ |
/* SYN: I've hardcoded the sizes here because the .CFG file format is fixed |
anyways, so it's not like they'll change. */ |
background2 = 0; |
efread(&background2, 1, 1, fi); |
efread(&gameSpeed, 1, 1, fi); |
efread(&inputDevice_, 1, 1, fi); |
efread(&jConfigure, 1, 1, fi); |
efread(&versionNum, 1, 1, fi); |
efread(&processorType, 1, 1, fi); |
efread(&midiPort, 1, 1, fi); |
efread(&soundEffects, 1, 1, fi); |
efread(&gammaCorrection, 1, 1, fi); |
efread(&difficultyLevel, 1, 1, fi); |
efread(joyButtonAssign, 1, 4, fi); |
efread(&tyrMusicVolume, 2, 1, fi); |
efread(&fxVolume, 2, 1, fi); |
efread(inputDevice, 1, 2, fi); |
efread(keySettings, sizeof(*keySettings), COUNTOF(keySettings), fi); |
fclose(fi); |
} |
else |
{ |
printf("\nInvalid or missing TYRIAN.CFG! Continuing using defaults.\n\n"); |
soundEffects = 1; |
memcpy(&keySettings, &defaultKeySettings, sizeof(keySettings)); |
background2 = true; |
tyrMusicVolume = fxVolume = 128; |
gammaCorrection = 0; |
processorType = 3; |
gameSpeed = 4; |
} |
load_opentyrian_config(); |
if (tyrMusicVolume > 255) |
tyrMusicVolume = 255; |
if (fxVolume > 255) |
fxVolume = 255; |
JE_calcFXVol(); |
set_volume(tyrMusicVolume, fxVolume); |
fi = dir_fopen_warn(get_user_directory(), "tyrian.sav", "rb"); |
if (fi) |
{ |
fseek(fi, 0, SEEK_SET); |
efread(saveTemp, 1, sizeof(saveTemp), fi); |
JE_decryptSaveTemp(); |
/* SYN: The original mostly blasted the save file into raw memory. However, our lives are not so |
easy, because the C struct is necessarily a different size. So instead we have to loop |
through each record and load fields manually. *emo tear* :'( */ |
p = saveTemp; |
for (z = 0; z < SAVE_FILES_NUM; z++) |
{ |
memcpy(&saveFiles[z].encode, p, sizeof(JE_word)); p += 2; |
saveFiles[z].encode = SDL_SwapLE16(saveFiles[z].encode); |
memcpy(&saveFiles[z].level, p, sizeof(JE_word)); p += 2; |
saveFiles[z].level = SDL_SwapLE16(saveFiles[z].level); |
memcpy(&saveFiles[z].items, p, sizeof(JE_PItemsType)); p += sizeof(JE_PItemsType); |
memcpy(&saveFiles[z].score, p, sizeof(JE_longint)); p += 4; |
saveFiles[z].score = SDL_SwapLE32(saveFiles[z].score); |
memcpy(&saveFiles[z].score2, p, sizeof(JE_longint)); p += 4; |
saveFiles[z].score2 = SDL_SwapLE32(saveFiles[z].score2); |
/* SYN: Pascal strings are prefixed by a byte holding the length! */ |
memset(&saveFiles[z].levelName, 0, sizeof(saveFiles[z].levelName)); |
memcpy(&saveFiles[z].levelName, &p[1], *p); |
p += 10; |
/* This was a BYTE array, not a STRING, in the original. Go fig. */ |
memcpy(&saveFiles[z].name, p, 14); |
p += 14; |
memcpy(&saveFiles[z].cubes, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].power, p, sizeof(JE_byte) * 2); p += 2; |
memcpy(&saveFiles[z].episode, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].lastItems, p, sizeof(JE_PItemsType)); p += sizeof(JE_PItemsType); |
memcpy(&saveFiles[z].difficulty, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].secretHint, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].input1, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].input2, p, sizeof(JE_byte)); p++; |
/* booleans were 1 byte in pascal -- working around it */ |
Uint8 temp; |
memcpy(&temp, p, 1); p++; |
saveFiles[z].gameHasRepeated = temp != 0; |
memcpy(&saveFiles[z].initialDifficulty, p, sizeof(JE_byte)); p++; |
memcpy(&saveFiles[z].highScore1, p, sizeof(JE_longint)); p += 4; |
saveFiles[z].highScore1 = SDL_SwapLE32(saveFiles[z].highScore1); |
memcpy(&saveFiles[z].highScore2, p, sizeof(JE_longint)); p += 4; |
saveFiles[z].highScore2 = SDL_SwapLE32(saveFiles[z].highScore2); |
memset(&saveFiles[z].highScoreName, 0, sizeof(saveFiles[z].highScoreName)); |
memcpy(&saveFiles[z].highScoreName, &p[1], *p); |
p += 30; |
memcpy(&saveFiles[z].highScoreDiff, p, sizeof(JE_byte)); p++; |
} |
/* SYN: This is truncating to bytes. I have no idea what this is doing or why. */ |
/* TODO: Figure out what this is about and make sure it isn't broked. */ |
editorLevel = (saveTemp[SIZEOF_SAVEGAMETEMP - 5] << 8) | saveTemp[SIZEOF_SAVEGAMETEMP - 6]; |
fclose(fi); |
} else { |
/* We didn't have a save file! Let's make up random stuff! */ |
editorLevel = 800; |
for (z = 0; z < 100; z++) |
{ |
saveTemp[SAVE_FILES_SIZE + z] = initialItemAvail[z]; |
} |
for (z = 0; z < SAVE_FILES_NUM; z++) |
{ |
saveFiles[z].level = 0; |
for (y = 0; y < 14; y++) |
{ |
saveFiles[z].name[y] = ' '; |
} |
saveFiles[z].name[14] = 0; |
saveFiles[z].highScore1 = ((mt_rand() % 20) + 1) * 1000; |
if (z % 6 > 2) |
{ |
saveFiles[z].highScore2 = ((mt_rand() % 20) + 1) * 1000; |
strcpy(saveFiles[z].highScoreName, defaultTeamNames[mt_rand() % 22]); |
} else { |
strcpy(saveFiles[z].highScoreName, defaultHighScoreNames[mt_rand() % 34]); |
} |
} |
} |
JE_initProcessorType(); |
} |
void JE_saveConfiguration( void ) |
{ |
FILE *f; |
JE_byte *p; |
int z; |
p = saveTemp; |
for (z = 0; z < SAVE_FILES_NUM; z++) |
{ |
JE_SaveFileType tempSaveFile; |
memcpy(&tempSaveFile, &saveFiles[z], sizeof(tempSaveFile)); |
tempSaveFile.encode = SDL_SwapLE16(tempSaveFile.encode); |
memcpy(p, &tempSaveFile.encode, sizeof(JE_word)); p += 2; |
tempSaveFile.level = SDL_SwapLE16(tempSaveFile.level); |
memcpy(p, &tempSaveFile.level, sizeof(JE_word)); p += 2; |
memcpy(p, &tempSaveFile.items, sizeof(JE_PItemsType)); p += sizeof(JE_PItemsType); |
tempSaveFile.score = SDL_SwapLE32(tempSaveFile.score); |
memcpy(p, &tempSaveFile.score, sizeof(JE_longint)); p += 4; |
tempSaveFile.score2 = SDL_SwapLE32(tempSaveFile.score2); |
memcpy(p, &tempSaveFile.score2, sizeof(JE_longint)); p += 4; |
/* SYN: Pascal strings are prefixed by a byte holding the length! */ |
memset(p, 0, sizeof(tempSaveFile.levelName)); |
*p = strlen(tempSaveFile.levelName); |
memcpy(&p[1], &tempSaveFile.levelName, *p); |
p += 10; |
/* This was a BYTE array, not a STRING, in the original. Go fig. */ |
memcpy(p, &tempSaveFile.name, 14); |
p += 14; |
memcpy(p, &tempSaveFile.cubes, sizeof(JE_byte)); p++; |
memcpy(p, &tempSaveFile.power, sizeof(JE_byte) * 2); p += 2; |
memcpy(p, &tempSaveFile.episode, sizeof(JE_byte)); p++; |
memcpy(p, &tempSaveFile.lastItems, sizeof(JE_PItemsType)); p += sizeof(JE_PItemsType); |
memcpy(p, &tempSaveFile.difficulty, sizeof(JE_byte)); p++; |
memcpy(p, &tempSaveFile.secretHint, sizeof(JE_byte)); p++; |
memcpy(p, &tempSaveFile.input1, sizeof(JE_byte)); p++; |
memcpy(p, &tempSaveFile.input2, sizeof(JE_byte)); p++; |
/* booleans were 1 byte in pascal -- working around it */ |
Uint8 temp = tempSaveFile.gameHasRepeated != false; |
memcpy(p, &temp, 1); p++; |
memcpy(p, &tempSaveFile.initialDifficulty, sizeof(JE_byte)); p++; |
tempSaveFile.highScore1 = SDL_SwapLE32(tempSaveFile.highScore1); |
memcpy(p, &tempSaveFile.highScore1, sizeof(JE_longint)); p += 4; |
tempSaveFile.highScore2 = SDL_SwapLE32(tempSaveFile.highScore2); |
memcpy(p, &tempSaveFile.highScore2, sizeof(JE_longint)); p += 4; |
memset(p, 0, sizeof(tempSaveFile.highScoreName)); |
*p = strlen(tempSaveFile.highScoreName); |
memcpy(&p[1], &tempSaveFile.highScoreName, *p); |
p += 30; |
memcpy(p, &tempSaveFile.highScoreDiff, sizeof(JE_byte)); p++; |
} |
saveTemp[SIZEOF_SAVEGAMETEMP - 6] = editorLevel >> 8; |
saveTemp[SIZEOF_SAVEGAMETEMP - 5] = editorLevel; |
JE_encryptSaveTemp(); |
#ifndef TARGET_WIN32 |
mkdir(get_user_directory(), 0700); |
#else |
mkdir(get_user_directory()); |
#endif |
f = dir_fopen_warn(get_user_directory(), "tyrian.sav", "wb"); |
if (f != NULL) |
{ |
efwrite(saveTemp, 1, sizeof(saveTemp), f); |
#if defined(TARGET_UNIX) |
fsync(fileno(f)); |
#endif |
fclose(f); |
} |
JE_decryptSaveTemp(); |
f = dir_fopen_warn(get_user_directory(), "tyrian.cfg", "wb"); |
if (f != NULL) |
{ |
efwrite(&background2, 1, 1, f); |
efwrite(&gameSpeed, 1, 1, f); |
efwrite(&inputDevice_, 1, 1, f); |
efwrite(&jConfigure, 1, 1, f); |
efwrite(&versionNum, 1, 1, f); |
efwrite(&processorType, 1, 1, f); |
efwrite(&midiPort, 1, 1, f); |
efwrite(&soundEffects, 1, 1, f); |
efwrite(&gammaCorrection, 1, 1, f); |
efwrite(&difficultyLevel, 1, 1, f); |
efwrite(joyButtonAssign, 1, 4, f); |
efwrite(&tyrMusicVolume, 2, 1, f); |
efwrite(&fxVolume, 2, 1, f); |
efwrite(inputDevice, 1, 2, f); |
efwrite(keySettings, sizeof(*keySettings), COUNTOF(keySettings), f); |
#if defined(TARGET_UNIX) |
fsync(fileno(f)); |
#endif |
fclose(f); |
} |
save_opentyrian_config(); |
} |
/contrib/games/opentyrian/src/config.h |
---|
0,0 → 1,148 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef CONFIG_H |
#define CONFIG_H |
#include "opentyr.h" |
#include "config_file.h" |
#include "SDL.h" |
#include <stdio.h> |
#define SAVE_FILES_NUM (11 * 2) |
/* These are necessary because the size of the structure has changed from the original, but we |
need to know the original sizes in order to find things in TYRIAN.SAV */ |
#define SAVE_FILES_SIZE 2398 |
#define SIZEOF_SAVEGAMETEMP SAVE_FILES_SIZE + 4 + 100 |
#define SAVE_FILE_SIZE (SIZEOF_SAVEGAMETEMP - 4) |
/*#define SAVE_FILES_SIZE (2502 - 4) |
#define SAVE_FILE_SIZE (SAVE_FILES_SIZE)*/ |
typedef SDLKey JE_KeySettingType[8]; /* [1..8] */ |
typedef JE_byte JE_PItemsType[12]; /* [1..12] */ |
typedef JE_byte JE_EditorItemAvailType[100]; /* [1..100] */ |
typedef struct |
{ |
JE_word encode; |
JE_word level; |
JE_PItemsType items; |
JE_longint score; |
JE_longint score2; |
char levelName[11]; /* string [9]; */ /* SYN: Added one more byte to match lastLevelName below */ |
JE_char name[15]; /* [1..14] */ /* SYN: Added extra byte for null */ |
JE_byte cubes; |
JE_byte power[2]; /* [1..2] */ |
JE_byte episode; |
JE_PItemsType lastItems; |
JE_byte difficulty; |
JE_byte secretHint; |
JE_byte input1; |
JE_byte input2; |
JE_boolean gameHasRepeated; /*See if you went from one episode to another*/ |
JE_byte initialDifficulty; |
/* High Scores - Each episode has both sets of 1&2 player selections - with 3 in each */ |
JE_longint highScore1, |
highScore2; |
char highScoreName[30]; /* string [29] */ |
JE_byte highScoreDiff; |
} JE_SaveFileType; |
typedef JE_SaveFileType JE_SaveFilesType[SAVE_FILES_NUM]; /* [1..savefilesnum] */ |
typedef JE_byte JE_SaveGameTemp[SAVE_FILES_SIZE + 4 + 100]; /* [1..sizeof(savefilestype) + 4 + 100] */ |
extern const JE_byte cryptKey[10]; |
extern const JE_KeySettingType defaultKeySettings; |
extern const char defaultHighScoreNames[34][23]; |
extern const char defaultTeamNames[22][25]; |
extern const JE_EditorItemAvailType initialItemAvail; |
extern JE_boolean smoothies[9]; |
extern JE_byte starShowVGASpecialCode; |
extern JE_word lastCubeMax, cubeMax; |
extern JE_word cubeList[4]; |
extern JE_boolean gameHasRepeated; |
extern JE_shortint difficultyLevel, oldDifficultyLevel, initialDifficulty; |
extern uint power, lastPower, powerAdd; |
extern JE_byte shieldWait, shieldT; |
enum |
{ |
SHOT_FRONT, |
SHOT_REAR, |
SHOT_LEFT_SIDEKICK, |
SHOT_RIGHT_SIDEKICK, |
SHOT_MISC, |
SHOT_P2_CHARGE, |
SHOT_P1_SUPERBOMB, |
SHOT_P2_SUPERBOMB, |
SHOT_SPECIAL, |
SHOT_NORTSPARKS, |
SHOT_SPECIAL2 |
}; |
extern JE_byte shotRepeat[11], shotMultiPos[11]; |
extern JE_boolean portConfigChange, portConfigDone; |
extern char lastLevelName[11], levelName[11]; |
extern JE_byte mainLevel, nextLevel, saveLevel; |
extern JE_KeySettingType keySettings; |
extern JE_shortint levelFilter, levelFilterNew, levelBrightness, levelBrightnessChg; |
extern JE_boolean filtrationAvail, filterActive, filterFade, filterFadeStart; |
extern JE_boolean gameJustLoaded; |
extern JE_boolean galagaMode; |
extern JE_boolean extraGame; |
extern JE_boolean twoPlayerMode, twoPlayerLinked, onePlayerAction, superTyrian, trentWin; |
extern JE_byte superArcadeMode; |
extern JE_byte superArcadePowerUp; |
extern JE_real linkGunDirec; |
extern JE_byte inputDevice[2]; |
extern JE_byte secretHint; |
extern JE_byte background3over; |
extern JE_byte background2over; |
extern JE_byte gammaCorrection; |
extern JE_boolean superPause, explosionTransparent, youAreCheating, displayScore, background2, smoothScroll, wild, superWild, starActive, topEnemyOver, skyEnemyOverAll, background2notTransparent; |
extern JE_byte versionNum; |
extern JE_byte fastPlay; |
extern JE_boolean pentiumMode; |
extern JE_byte gameSpeed; |
extern JE_byte processorType; |
extern JE_SaveFilesType saveFiles; |
extern JE_SaveGameTemp saveTemp; |
extern JE_word editorLevel; |
extern Config opentyrian_config; |
void JE_initProcessorType( void ); |
void JE_setNewGameSpeed( void ); |
const char *get_user_directory( void ); |
void JE_loadConfiguration( void ); |
void JE_saveConfiguration( void ); |
void JE_saveGame( JE_byte slot, const char *name ); |
void JE_loadGame( JE_byte slot ); |
void JE_encryptSaveTemp( void ); |
void JE_decryptSaveTemp( void ); |
#endif /* CONFIG_H */ |
/contrib/games/opentyrian/src/config_file.c |
---|
0,0 → 1,1033 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2015 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
/*! |
* \file config_file.c |
* \author Carl Reinke |
* \date 2015 |
* \copyright GNU General Public License v2+ or Mozilla Public License 2.0 |
*/ |
#include "config_file.h" |
#include <assert.h> |
#include <limits.h> |
#include <stdbool.h> |
#include <stddef.h> |
#include <string.h> |
/* potential size of decimal representation of type */ |
#define udecsizeof(t) ((CHAR_BIT * sizeof(t) / 3) + 1) |
#define sdecsizeof(t) (udecsizeof(t) + 1) |
extern void config_oom( void ); |
void config_oom( void ) |
{ |
fprintf(stderr, "out of memory\n"); |
exit(EXIT_FAILURE); |
} |
/* string manipulators */ |
static ConfigString string_init_len( const char *s, size_t n ) |
{ |
ConfigString string; |
if (s == NULL) |
{ |
CONFIG_STRING_LONG_TAG(string) = true; |
string.long_buf = NULL; |
} |
else |
{ |
char is_long = n >= COUNTOF(string.short_buf); |
CONFIG_STRING_LONG_TAG(string) = is_long; |
char *buffer = is_long ? |
string.long_buf = malloc((n + 1) * sizeof(char)) : |
string.short_buf; |
if (buffer == NULL) |
config_oom(); |
memcpy(buffer, s, n * sizeof(char)); |
buffer[n] = '\0'; |
} |
return string; |
} |
static void string_deinit( ConfigString *string ) |
{ |
char is_long = CONFIG_STRING_LONG_TAG(*string); |
if (is_long) |
{ |
free(string->long_buf); |
string->long_buf = NULL; |
} |
} |
static bool string_equal_len( ConfigString *string, const char *s, size_t n ) |
{ |
const char *cstr = config_string_to_cstr(string); |
return strncmp(cstr, s, n) == 0 && cstr[n] == '\0'; |
} |
/* config manipulators */ |
static void deinit_section( ConfigSection *section ); |
static void deinit_option( ConfigOption *option ); |
void config_init( Config *config ) |
{ |
assert(config != NULL); |
config->sections_count = 0; |
config->sections = NULL; |
} |
void config_deinit( Config *config ) |
{ |
assert(config != NULL); |
for (unsigned int s = 0; s < config->sections_count; ++s) |
{ |
ConfigSection *section = &config->sections[s]; |
deinit_section(section); |
} |
free(config->sections); |
config->sections = NULL; |
} |
/* config section manipulators -- internal */ |
static void init_section( ConfigSection *section, const char *type, size_t type_len, const char *name, size_t name_len ) |
{ |
section->type = string_init_len(type, type_len); |
section->name = string_init_len(name, name_len); |
section->options_count = 0; |
section->options = NULL; |
} |
static void deinit_section( ConfigSection *section ) |
{ |
for (unsigned int o = 0; o < section->options_count; ++o) |
{ |
ConfigOption *option = §ion->options[o]; |
deinit_option(option); |
} |
string_deinit(§ion->type); |
string_deinit(§ion->name); |
free(section->options); |
section->options = NULL; |
} |
/* config section accessors/manipulators -- by type, name */ |
ConfigSection *config_add_section_len( Config *config, const char *type, size_t type_len, const char *name, size_t name_len ) |
{ |
assert(config != NULL); |
assert(type != NULL); |
ConfigSection *sections = realloc(config->sections, (config->sections_count + 1) * sizeof(ConfigSection)); |
if (sections == NULL) |
return NULL; |
ConfigSection *section = §ions[config->sections_count]; |
config->sections_count += 1; |
config->sections = sections; |
init_section(section, type, type_len, name, name_len); |
return section; |
} |
ConfigSection *config_find_sections( Config *config, const char *type, ConfigSection **save ) |
{ |
assert(config != NULL); |
assert(type != NULL); |
ConfigSection *sections_end = &config->sections[config->sections_count]; |
ConfigSection *section = save != NULL && *save != NULL ? |
*save : |
&config->sections[0]; |
for (; section < sections_end; ++section) |
if (strcmp(config_string_to_cstr(§ion->type), type) == 0) |
break; |
if (save != NULL) |
*save = section; |
return section < sections_end ? section : NULL; |
} |
ConfigSection *config_find_section( Config *config, const char *type, const char *name ) |
{ |
assert(config != NULL); |
assert(type != NULL); |
ConfigSection *sections_end = &config->sections[config->sections_count]; |
for (ConfigSection *section = &config->sections[0]; section < sections_end; ++section) |
{ |
if (strcmp(config_string_to_cstr(§ion->type), type) == 0) |
{ |
const char *section_name = config_string_to_cstr(§ion->name); |
if ((section_name == NULL || name == NULL) ? section_name == name : strcmp(config_string_to_cstr(§ion->name), name) == 0) |
return section; |
} |
} |
return NULL; |
} |
ConfigSection *config_find_or_add_section( Config *config, const char *type, const char *name ) |
{ |
assert(config != NULL); |
assert(type != NULL); |
ConfigSection *section = config_find_section(config, type, name); |
if (section != NULL) |
return section; |
return config_add_section(config, type, name); |
} |
/* config option manipulators -- internal */ |
static void init_option_value( ConfigOption *option, const char *value, size_t value_len ) |
{ |
option->values_count = 0; |
option->v.value = string_init_len(value, value_len); |
} |
static void deinit_option_value( ConfigOption *option ) |
{ |
if (option->values_count != 0) |
{ |
ConfigString *values_end = &option->v.values[option->values_count]; |
for (ConfigString *value = &option->v.values[0]; value < values_end; ++value) |
string_deinit(value); |
free(option->v.values); |
option->v.values = NULL; |
} |
else |
{ |
string_deinit(&option->v.value); |
} |
} |
static void init_option( ConfigOption *option, const char *key, size_t key_len, const char *value, size_t value_len ) |
{ |
option->key = string_init_len(key, key_len); |
init_option_value(option, value, value_len); |
} |
static void deinit_option( ConfigOption *option ) |
{ |
string_deinit(&option->key); |
deinit_option_value(option); |
} |
static ConfigOption *append_option( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ) |
{ |
ConfigOption *options = realloc(section->options, (section->options_count + 1) * sizeof(ConfigSection)); |
if (options == NULL) |
return NULL; |
ConfigOption *option = &options[section->options_count]; |
section->options_count += 1; |
section->options = options; |
init_option(option, key, key_len, value, value_len); |
return option; |
} |
static ConfigOption *get_option_len( ConfigSection *section, const char *key, size_t key_len ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
ConfigOption *options_end = §ion->options[section->options_count]; |
for (ConfigOption *option = §ion->options[0]; option < options_end; ++option) |
if (string_equal_len(&option->key, key, key_len)) |
return option; |
return NULL; |
} |
/* config option accessors/manipulators -- by key */ |
ConfigOption *config_set_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
ConfigOption *option = get_option_len(section, key, key_len); |
if (option != NULL) |
return config_set_value_len(option, value, value_len); |
return append_option(section, key, key_len, value, value_len); |
} |
ConfigOption *config_get_option( const ConfigSection *section, const char *key ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
ConfigOption *options_end = §ion->options[section->options_count]; |
for (ConfigOption *option = §ion->options[0]; option < options_end; ++option) |
if (strcmp(config_string_to_cstr(&option->key), key) == 0) |
return option; |
return NULL; |
} |
ConfigOption *config_get_or_set_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
ConfigOption *option = get_option_len(section, key, key_len); |
if (option != NULL) |
return option; |
return append_option(section, key, key_len, value, value_len); |
} |
void config_set_string_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ) |
{ |
if (config_set_option_len(section, key, key_len, value, value_len) == NULL) |
config_oom(); |
} |
bool config_get_string_option( const ConfigSection *section, const char *key, const char **out_value ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
ConfigOption *option = config_get_option(section, key); |
if (option != NULL) |
{ |
const char *value = config_get_value(option); |
if (value != NULL) |
{ |
*out_value = value; |
return true; |
} |
} |
return false; |
} |
const char *config_get_or_set_string_option( ConfigSection *section, const char *key, const char *value ) |
{ |
if (!config_get_string_option(section, key, &value)) |
config_set_string_option_len(section, key, strlen(key), value, value == NULL ? 0 : strlen(value)); |
return value; |
} |
static const char *bool_values[][2] = |
{ |
{ "0", "1" }, |
{ "no", "yes" }, |
{ "off", "on" }, |
{ "false", "true" }, |
}; |
void config_set_bool_option( ConfigSection *section, const char *key, bool value, ConfigBoolStyle style ) |
{ |
if (config_set_option(section, key, bool_values[style][value ? 1 : 0]) == NULL) |
config_oom(); |
} |
bool config_get_bool_option( const ConfigSection *section, const char *key, bool *out_value ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
assert(out_value != NULL); |
const char *value; |
if (config_get_string_option(section, key, &value)) |
{ |
for (size_t i = 0; i < COUNTOF(bool_values); ++i) |
{ |
for (size_t j = 0; j < COUNTOF(bool_values[i]); ++j) |
{ |
if (strcmp(value, bool_values[i][j]) == 0) |
{ |
*out_value = j == 0 ? false : true; |
return true; |
} |
} |
} |
} |
return false; |
} |
bool config_get_or_set_bool_option( ConfigSection *section, const char *key, bool value, ConfigBoolStyle style ) |
{ |
if (!config_get_bool_option(section, key, &value)) |
config_set_bool_option(section, key, value, style); |
return value; |
} |
void config_set_int_option( ConfigSection *section, const char *key, int value ) |
{ |
assert(key != NULL); |
char buffer[sdecsizeof(int) + 1]; |
int buffer_len = snprintf(buffer, sizeof(buffer), "%i", value); |
if (config_set_option_len(section, key, strlen(key), buffer, buffer_len) == NULL) |
config_oom(); |
} |
bool config_get_int_option( const ConfigSection *section, const char *key, int *out_value ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
assert(out_value != NULL); |
const char *value; |
if (config_get_string_option(section, key, &value)) |
{ |
int i; |
int n; |
if (sscanf(value, "%i%n", &i, &n) > 0 && value[n] == '\0') /* must be entire string */ |
{ |
*out_value = i; |
return true; |
} |
} |
return false; |
} |
int config_get_or_set_int_option( ConfigSection *section, const char *key, int value ) |
{ |
if (!config_get_int_option(section, key, &value)) |
config_set_int_option(section, key, value); |
return value; |
} |
void config_set_uint_option( ConfigSection *section, const char *key, unsigned int value ) |
{ |
assert(key != NULL); |
char buffer[udecsizeof(unsigned int) + 1]; |
int buffer_len = snprintf(buffer, sizeof(buffer), "%u", value); |
if (config_set_option_len(section, key, strlen(key), buffer, buffer_len) == NULL) |
config_oom(); |
} |
bool config_get_uint_option( const ConfigSection *section, const char *key, unsigned int *out_value ) |
{ |
assert(section != NULL); |
assert(key != NULL); |
assert(out_value != NULL); |
const char *value; |
if (config_get_string_option(section, key, &value)) |
{ |
unsigned int u; |
int n; |
if (sscanf(value, "%u%n", &u, &n) > 0 && value[n] == '\0') /* must be entire string */ |
{ |
*out_value = u; |
return true; |
} |
} |
return false; |
} |
unsigned int config_get_or_set_uint_option( ConfigSection *section, const char *key, unsigned int value ) |
{ |
if (!config_get_uint_option(section, key, &value)) |
config_set_uint_option(section, key, value); |
return value; |
} |
/* config option accessors/manipulators -- by reference */ |
ConfigOption *config_set_value_len( ConfigOption *option, const char *value, size_t value_len ) |
{ |
assert(option != NULL); |
deinit_option_value(option); |
init_option_value(option, value, value_len); |
return option; |
} |
ConfigOption *config_add_value_len( ConfigOption *option, const char *value, size_t value_len ) |
{ |
assert(option != NULL); |
assert(value != NULL); |
/* convert 'item' to 'list' */ |
if (option->values_count == 0 && config_string_to_cstr(&option->v.value) != NULL) |
{ |
ConfigString option_value = option->v.value; |
ConfigString *values = malloc(2 * sizeof(ConfigString)); |
if (values == NULL) |
return NULL; |
option->v.values = values; |
option->v.values[0] = option_value; |
option->v.values[1] = string_init_len(value, value_len); |
option->values_count = 2; |
} |
else |
{ |
ConfigString *values = realloc(option->v.values, (option->values_count + 1) * sizeof(ConfigString)); |
if (values == NULL) |
return NULL; |
option->v.values = values; |
option->v.values[option->values_count] = string_init_len(value, value_len); |
option->values_count += 1; |
} |
return option; |
} |
ConfigOption *config_remove_value( ConfigOption *option, unsigned int i ) |
{ |
assert(option != NULL); |
if (!config_is_value_list(option)) |
{ |
if (i > 0) |
return NULL; |
config_set_value_len(option, NULL, 0); |
} |
else |
{ |
if (i >= option->values_count) |
return NULL; |
string_deinit(&option->v.values[i]); |
memmove(&option->v.values[i], &option->v.values[i + 1], (option->values_count - i - 1) * sizeof(ConfigString)); |
if (option->values_count - 1 == 0) |
{ |
option->v.value = string_init_len(NULL, 0); |
option->values_count = 0; |
} |
else |
{ |
ConfigString *values = realloc(option->v.values, (option->values_count - 1) * sizeof(ConfigString)); |
if (values == NULL) |
return NULL; |
option->v.values = values; |
option->values_count -= 1; |
} |
} |
return option; |
} |
const char *config_get_value( const ConfigOption *option ) |
{ |
if (option == NULL || option->values_count != 0) |
return NULL; |
return config_string_to_cstr(&option->v.value); |
} |
/* config parser */ |
static bool is_whitespace( char c ) |
{ |
return c == '\t' || c == ' '; |
} |
static bool is_end( char c ) |
{ |
return c == '\0' || c == '\n' || c == '\r'; |
} |
static bool is_whitespace_or_end( char c ) |
{ |
return is_whitespace(c) || is_end(c); |
} |
typedef enum |
{ |
INVALID_DIRECTIVE = 0, |
SECTION_DIRECTIVE, |
ITEM_DIRECTIVE, |
LIST_DIRECTIVE, |
} Directive; |
static Directive match_directive( const char *buffer, size_t *index ) |
{ |
size_t i = *index; |
while (is_whitespace(buffer[i])) |
++i; |
Directive directive; |
if (strncmp("section", &buffer[i], 7) == 0) |
{ |
directive = SECTION_DIRECTIVE; |
i += 7; |
} |
else if (strncmp("item", &buffer[i], 4) == 0) |
{ |
directive = ITEM_DIRECTIVE; |
i += 4; |
} |
else if (strncmp("list", &buffer[i], 4) == 0) |
{ |
directive = LIST_DIRECTIVE; |
i += 4; |
} |
else |
{ |
return INVALID_DIRECTIVE; |
} |
if (!is_whitespace_or_end(buffer[i])) |
return INVALID_DIRECTIVE; |
*index = i; |
return directive; |
} |
static bool match_nonquote_field( const char *buffer, size_t *index, size_t *length ) |
{ |
size_t i = *index; |
for (; ; ++i) |
{ |
char c = buffer[i]; |
if (is_whitespace_or_end(c)) |
{ |
break; |
} |
else if (c <= ' ' || c > '~' || c == '#' || c == '\'' || c == '"') |
{ |
return false; |
} |
} |
*length = i - *index; |
*index = i; |
return *length > 0; |
} |
static bool parse_quote_field( char *buffer, size_t *index, size_t *length ) |
{ |
size_t i = *index; |
size_t o = *index; |
char quote = buffer[i]; |
for (; ; ) |
{ |
char c = buffer[++i]; |
if (c == quote) |
{ |
++i; |
break; |
} |
else if (c == '\\') |
{ |
c = buffer[++i]; |
if (c == quote) |
{ |
buffer[o++] = quote; |
} |
else |
{ |
switch (c) |
{ |
case 't': |
buffer[o++] = '\t'; |
break; |
case 'n': |
buffer[o++] = '\n'; |
break; |
case 'r': |
buffer[o++] = '\r'; |
break; |
case '\\': |
buffer[o++] = '\\'; |
break; |
case 'x': |
/* parse two hex digits */ |
c = buffer[++i]; |
char m = (c >= '0' && c <= '9') ? '0' : |
(c >= 'a' && c <= 'f') ? 'a' - 10 : |
(c >= 'A' && c <= 'F') ? 'A' - 10 : 0; |
if (m == 0) |
return false; |
char h = c - m; |
c = buffer[++i]; |
m = (c >= '0' && c <= '9') ? '0' : |
(c >= 'a' && c <= 'f') ? 'a' - 10 : |
(c >= 'A' && c <= 'F') ? 'A' - 10 : 0; |
if (m == 0) |
return false; |
buffer[o++] = (h << 4) | (c - m); |
break; |
default: |
return false; |
} |
} |
} |
else if (c >= ' ' && c <= '~') |
{ |
buffer[o++] = c; |
} |
else |
{ |
return false; |
} |
} |
*length = o - *index; |
*index = i; |
return true; |
} |
static bool parse_field( char *buffer, size_t *index, size_t *start, size_t *length ) |
{ |
size_t i = *index; |
while (is_whitespace(buffer[i])) |
++i; |
*start = i; |
if (buffer[i] == '"' || buffer[i] == '\'') |
{ |
if (!parse_quote_field(buffer, &i, length)) |
return false; |
} |
else |
{ |
if (!match_nonquote_field(buffer, &i, length)) |
return false; |
} |
if (!is_whitespace_or_end(buffer[i])) |
return INVALID_DIRECTIVE; |
*index = i; |
return true; |
} |
bool config_parse( Config *config, FILE *file ) |
{ |
assert(config != NULL); |
assert(file != NULL); |
config_init(config); |
ConfigSection *section = NULL; |
ConfigOption *option = NULL; |
size_t buffer_cap = 128; |
char *buffer = malloc(buffer_cap * sizeof(char)); |
if (buffer == NULL) |
config_oom(); |
size_t buffer_end = 1; |
buffer[buffer_end - 1] = '\0'; |
for (size_t line = 0, next_line = 0; ; line = next_line) |
{ |
/* find begining of next line */ |
while (next_line < buffer_end) |
{ |
char c = buffer[next_line]; |
if (c == '\0' && next_line == buffer_end - 1) |
{ |
if (line > 0) |
{ |
/* shift to front */ |
memmove(&buffer[0], &buffer[line], buffer_end - line); |
buffer_end -= line; |
next_line -= line; |
line = 0; |
} |
else if (buffer_end > 1) |
{ |
/* need larger capacity */ |
buffer_cap *= 2; |
char *new_buffer = realloc(buffer, buffer_cap * sizeof(char)); |
if (new_buffer == NULL) |
config_oom(); |
buffer = new_buffer; |
} |
size_t read = fread(&buffer[buffer_end - 1], sizeof(char), buffer_cap - buffer_end, file); |
if (read == 0) |
break; |
buffer_end += read; |
buffer[buffer_end - 1] = '\0'; |
} |
else |
{ |
++next_line; |
if (c == '\n' || c == '\r') |
break; |
} |
} |
/* if at end of file */ |
if (next_line == line) |
break; |
size_t i = line; |
Directive directive = match_directive(buffer, &i); |
switch (directive) |
{ |
case INVALID_DIRECTIVE: |
continue; |
case SECTION_DIRECTIVE: |
{ |
size_t type_start; |
size_t type_length; |
if (!parse_field(buffer, &i, &type_start, &type_length)) |
continue; |
size_t name_start; |
size_t name_length; |
bool has_name = parse_field(buffer, &i, &name_start, &name_length); |
section = config_add_section_len(config, |
&buffer[type_start], type_length, |
has_name ? &buffer[name_start] : NULL, has_name ? name_length : 0); |
if (section == NULL) |
config_oom(); |
option = NULL; |
} |
break; |
case ITEM_DIRECTIVE: |
case LIST_DIRECTIVE: |
{ |
if (section == NULL) |
continue; |
size_t key_start; |
size_t key_length; |
if (!parse_field(buffer, &i, &key_start, &key_length)) |
continue; |
size_t value_start; |
size_t value_length; |
if (!parse_field(buffer, &i, &value_start, &value_length)) |
continue; |
if (directive == ITEM_DIRECTIVE) |
{ |
option = config_set_option_len(section, |
&buffer[key_start], key_length, |
&buffer[value_start], value_length); |
} |
else |
{ |
if (option == NULL || !string_equal_len(&option->key, &buffer[key_start], key_length)) |
option = config_get_or_set_option_len(section, |
&buffer[key_start], key_length, |
NULL, 0); |
if (option != NULL) |
option = config_add_value_len(option, |
&buffer[value_start], value_length); |
} |
if (option == NULL) |
config_oom(); |
} |
break; |
} |
assert(i <= next_line); |
} |
free(buffer); |
return config; |
} |
/* config writer */ |
static void write_field( const ConfigString *field, FILE *file ) |
{ |
fputc('\'', file); |
char buffer[128]; |
size_t o = 0; |
for (const char *ci = config_string_to_cstr(field); *ci != '\0'; ++ci) |
{ |
char c = *ci; |
size_t l; |
switch (c) |
{ |
case '\t': |
case '\n': |
case '\r': |
case '\'': |
case '\\': |
l = 2; |
break; |
default: |
l = (c >= ' ' && c <= '~') ? 1 : 4; |
break; |
} |
if (o + l > COUNTOF(buffer)) |
{ |
fwrite(buffer, sizeof(*buffer), o, file); |
o = 0; |
} |
switch (l) |
{ |
case 1: |
buffer[o++] = c; |
break; |
case 2: |
switch (c) |
{ |
case '\t': |
buffer[o++] = '\\'; |
buffer[o++] = 't'; |
break; |
case '\n': |
buffer[o++] = '\\'; |
buffer[o++] = 'n'; |
break; |
case '\r': |
buffer[o++] = '\\'; |
buffer[o++] = 'r'; |
break; |
case '\'': |
case '\\': |
buffer[o++] = '\\'; |
buffer[o++] = c; |
break; |
} |
break; |
case 4: |
buffer[o++] = '\\'; |
buffer[o++] = 'x'; |
char n = (c >> 4) & 0x0f; |
buffer[o++] = (n < 10 ? '0' : ('a' - 10)) + n; |
n = c & 0x0f; |
buffer[o++] = (n < 10 ? '0' : ('a' - 10)) + n; |
break; |
} |
} |
if (o > 0) |
fwrite(buffer, sizeof(*buffer), o, file); |
fputc('\'', file); |
} |
void config_write( const Config *config, FILE *file ) |
{ |
assert(config != NULL); |
assert(file != NULL); |
for (unsigned int s = 0; s < config->sections_count; ++s) |
{ |
ConfigSection *section = &config->sections[s]; |
fputs("section ", file); |
write_field(§ion->type, file); |
if (config_string_to_cstr(§ion->name) != NULL) |
{ |
fputc(' ', file); |
write_field(§ion->name, file); |
} |
fputc('\n', file); |
for (unsigned int o = 0; o < section->options_count; ++o) |
{ |
ConfigOption *option = §ion->options[o]; |
if (option->values_count == 0 && config_string_to_cstr(&option->v.value) != NULL) |
{ |
fputs("\titem ", file); |
write_field(&option->key, file); |
fputc(' ', file); |
write_field(&option->v.value, file); |
fputc('\n', file); |
} |
else |
{ |
ConfigString *values_end = &option->v.values[option->values_count]; |
for (ConfigString *value = &option->v.values[0]; value < values_end; ++value) |
{ |
fputs("\tlist ", file); |
write_field(&option->key, file); |
fputc(' ', file); |
write_field(value, file); |
fputc('\n', file); |
} |
} |
} |
fputc('\n', file); |
} |
} |
/contrib/games/opentyrian/src/config_file.h |
---|
0,0 → 1,596 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2015 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
/*! |
* \file config_file.h |
* \author Carl Reinke |
* \date 2015 |
* \copyright GNU General Public License v2+ or Mozilla Public License 2.0 |
*/ |
#ifndef CONFIG_FILE_H |
#define CONFIG_FILE_H |
#include <assert.h> |
#include <stdbool.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#ifndef COMPILE_TIME_ASSERT |
/*! |
* \brief Cause compile error if compile-time computable condition fails. |
* |
* \param[in] name the unique identifier of the assertion |
* \param[in] cond the condition |
*/ |
#define COMPILE_TIME_ASSERT(name, cond) typedef int assert_ ## name[(cond) * 2 - 1] |
#endif |
#ifndef COUNTOF |
/*! |
* \brief Calculate the number of elements in a fixed-length array. |
* |
* \param[in] a the fixed-length array |
* \return the number of elements in the array |
*/ |
#define COUNTOF(a) (sizeof(a) / sizeof(*(a))) |
#endif |
/* string type */ |
/*! |
* \brief A short-string-optimizing string type. |
* |
* This struct allows for storing up to 15 characters (plus a terminating \c '\0') inline. For |
* longer strings memory will be allocated. |
* |
* The tag for this union is the last character of \p short_buf: |
* \li if \c '\0' then \p short_buf is valid, |
* \li otherwise \p long_buf is valid. |
*/ |
typedef union |
{ |
/*! |
* \brief The inline buffer for short strings. |
*/ |
char short_buf[16]; |
/*! |
* \brief The buffer for long strings. |
* |
* May be \c NULL. |
*/ |
char *long_buf; |
} ConfigString; |
/*! \cond suppress_doxygen */ |
COMPILE_TIME_ASSERT(string_short_buf_sufficient, sizeof(char *) + 1 <= COUNTOF(((ConfigString *)NULL)->short_buf)); |
/*! \endcond */ |
/*! \cond suppress_doxygen */ |
#define CONFIG_STRING_LONG_TAG(s) ((s).short_buf[COUNTOF((s).short_buf) - 1]) |
/*! \endcond */ |
/*! |
* \brief Return a C-string backed by a string. |
* |
* \param[in] string the string |
* \return the C-string |
*/ |
static inline const char *config_string_to_cstr( const ConfigString *string ) |
{ |
assert(string != NULL); |
char is_long = CONFIG_STRING_LONG_TAG(*string); |
return is_long ? |
string->long_buf : |
string->short_buf; |
} |
/* config types */ |
/*! |
* \brief An option consisting of one (an item) or many (a list) values. |
*/ |
typedef struct |
{ |
/*! |
* \brief The key of the option. |
*/ |
ConfigString key; |
/*! |
* \brief The number of values in the option if it is a 'list' option. |
* |
* If \c 0 then the option \e may be an 'item' option. |
* |
* \see ::ConfigOption::value |
*/ |
unsigned int values_count; |
/*! |
* \brief The value or values. |
* |
* The tag for this union is \p value_count: |
* \li if \c 0 then \p value is valid, |
* \li otherwise \p values is valid. |
*/ |
union |
{ |
/*! |
* \brief The value of an 'item' option or an empty 'list' option. |
* |
* If this field is \c NULL then the option is an empty 'list' option. |
*/ |
ConfigString value; |
/*! |
* \brief The values of a non-empty 'list' option. |
*/ |
ConfigString *values; |
} v; |
} ConfigOption; |
/*! |
* \brief A section consisting of options. |
*/ |
typedef struct |
{ |
/*! |
* \brief The type of the section. |
*/ |
ConfigString type; |
/*! |
* \brief The optional name of the section. |
* |
* May be \c NULL. |
*/ |
ConfigString name; |
/*! |
* \brief The number of options in the section. |
*/ |
unsigned int options_count; |
/*! |
* \brief The options in the section. |
* |
* \c NULL if \p options_count is \c 0. |
*/ |
ConfigOption *options; |
} ConfigSection; |
/*! |
* \brief A configuration consisting of sections. |
*/ |
typedef struct |
{ |
/*! |
* \brief The number of sections in the configuration. |
*/ |
unsigned int sections_count; |
/*! |
* \brief The sections in the configuration. |
* |
* \c NULL if \p sections_count is \c 0. |
*/ |
ConfigSection *sections; |
} Config; |
/* config manipulators */ |
/*! |
* \brief Initialize a configuration. |
* |
* \param[in] config the configuration |
* \return void |
*/ |
extern void config_init( Config *config ); |
/*! |
* \brief Release any memory allocated inside a configuration. |
* |
* \param[in] config the configuration |
* \return void |
*/ |
extern void config_deinit( Config *config ); |
/*! |
* \brief Parse a configuration from a file. |
* |
* \param[in] config the uninitalized configuration |
* \param[in] file the file handle |
* \return whether parsing succeeded |
*/ |
extern bool config_parse( Config *config, FILE *file ); |
/*! |
* \brief Write a configuration to a file. |
* |
* \param[in] config the configuration |
* \param[in] file the file handle |
* \return void |
*/ |
extern void config_write( const Config *config, FILE *file ); |
/* config section accessors/manipulators -- by type, name */ |
/*! \see ::config_add_section() */ |
extern ConfigSection *config_add_section_len( Config *config, const char *type, size_t type_len, const char *name, size_t name_len ); |
/*! |
* \brief Add a section to a configuration. |
* |
* \param[in] config the configuration to contain the section |
* \param[in] type the type of the section |
* \param[in] name the name of the section; may be \c NULL |
* \return the added section; \c NULL if out of memory |
*/ |
static inline ConfigSection *config_add_section( Config *config, const char *type, const char *name) |
{ |
assert(type != NULL); |
return config_add_section_len(config, type, strlen(type), name, name == NULL ? 0 : strlen(name)); |
} |
// TODO: extern Config *config_remove_section( Config *config, unsigned int i ); |
/*! |
* \brief Iterate sections by type. |
* |
* \param[in] config the configuration containing the sections |
* \param[in] type the type of the section |
* \param[in,out] save the saved state of the iterator; initialize \c *save to \c NULL before |
* iteration |
* \return the section; \c NULL if iteration finished |
*/ |
extern ConfigSection *config_find_sections( Config *config, const char *type, ConfigSection **save ); |
/*! |
* \brief Find a section by type and name. |
* |
* \param[in] config the configuration containing the section |
* \param[in] type the type of the section |
* \param[in] name the name of the section |
* \return the section; \c NULL if it does not exist |
*/ |
extern ConfigSection *config_find_section( Config *config, const char *type, const char *name ); |
/*! |
* \brief Find a section by type and name, creating the section if it did not exist. |
* |
* \param[in] config the configuration containing the section |
* \param[in] type the type of the section |
* \param[in] name the name of the section; may be \c NULL |
* \return the section; \c NULL if out of memory |
*/ |
extern ConfigSection *config_find_or_add_section( Config *config, const char *type, const char *name ); |
/* config option accessors/manipulators -- by key */ |
/*! \see ::config_set_option() */ |
extern ConfigOption *config_set_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ); |
/*! |
* \brief Set a value of an 'item' option by key, creating the option if necessary. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the item value; \c NULL to set an emtpy 'list' option instead of an 'item' |
* option (can be used to delete an 'item' option) |
* \return the option; \c NULL if out of memory |
*/ |
static inline ConfigOption *config_set_option( ConfigSection *section, const char *key, const char *value) |
{ |
assert(key != NULL); |
return config_set_option_len(section, key, strlen(key), value, value == NULL ? 0 : strlen(value)); |
} |
/*! |
* \brief Get an option by key. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \return the option; \c NULL if it does not exist |
*/ |
extern ConfigOption *config_get_option( const ConfigSection *section, const char *key ); |
/*! \see ::config_get_or_set_option() */ |
extern ConfigOption *config_get_or_set_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ); |
/*! |
* \brief Get an option by key, creating an 'item' option if the option did not exist. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the default item value; \c NULL to set an empty 'list' option instead of an |
* 'item' option |
* \return the option; \c NULL if out of memory |
*/ |
static inline ConfigOption *config_get_or_set_option( ConfigSection *section, const char *key, const char *value ) |
{ |
assert(key != NULL); |
return config_get_or_set_option_len(section, key, strlen(key), value, value == NULL ? 0 : strlen(value)); |
} |
/*! \see ::config_set_string_option() */ |
extern void config_set_string_option_len( ConfigSection *section, const char *key, size_t key_len, const char *value, size_t value_len ); |
/*! |
* \brief Set a string value of an 'item' option by key, creating the option if necessary. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the item value |
* \return void |
*/ |
static inline void config_set_string_option( ConfigSection *section, const char *key, const char *value ) |
{ |
assert(key != NULL); |
config_set_string_option_len(section, key, strlen(key), value, value == NULL ? 0 : strlen(value)); |
} |
/*! |
* \brief Get a string value of an 'item' option by key. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[out] out_value the item value if a valid option exists; otherwise unset |
* \return whether \p out_value was set |
*/ |
extern bool config_get_string_option( const ConfigSection *section, const char *key, const char **out_value ); |
/*! |
* \brief Get a string value of an 'item' option by key, setting the option if it was invalid or |
* creating the option if it did not exist. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the default item value |
* \return the value |
*/ |
extern const char *config_get_or_set_string_option( ConfigSection *section, const char *key, const char *value ); |
/*! |
* \brief The styles of boolean values. |
*/ |
typedef enum |
{ |
ZERO_ONE = 0, |
NO_YES = 1, |
OFF_ON = 2, |
FALSE_TRUE = 3, |
} ConfigBoolStyle; |
/*! |
* \brief Set a boolean value of an 'item' option by key, creating the option if necessary. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the item value |
* \param[in] style the style of boolean value |
* \return void |
*/ |
extern void config_set_bool_option( ConfigSection *section, const char *key, bool value, ConfigBoolStyle style ); |
/*! |
* \brief Get a boolean value of an 'item' option by key. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[out] out_value the item value if a valid option exists; otherwise unset |
* \return whether \p out_value was set |
*/ |
extern bool config_get_bool_option( const ConfigSection *section, const char *key, bool *out_value ); |
/*! |
* \brief Get a boolean value of an 'item' option by key, setting the option if it was invalid or |
* creating the option if it did not exist. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the default item value |
* \param[in] style the style of boolean value |
* \return the value |
*/ |
extern bool config_get_or_set_bool_option( ConfigSection *section, const char *key, bool value, ConfigBoolStyle style ); |
/*! |
* \brief Set an integer value of an 'item' option by key, creating the option if necessary. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the item value |
* \return void |
*/ |
extern void config_set_int_option( ConfigSection *section, const char *key, int value ); |
/*! |
* \brief Get an integer value of an 'item' option by key. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[out] out_value the item value if a valid option exists; otherwise unset |
* \return whether \p out_value was set |
*/ |
extern bool config_get_int_option( const ConfigSection *section, const char *key, int *out_value ); |
/*! |
* \brief Get an integer value of an 'item' option by key, setting the option if it was invalid or |
* creating the option if it did not exist. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the default item value |
* \return the value |
*/ |
extern int config_get_or_set_int_option( ConfigSection *section, const char *key, int value ); |
/*! |
* \brief Set an unsigned integer value of an 'item' option by key, creating the option if |
* necessary. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the item value |
* \return void |
*/ |
extern void config_set_uint_option( ConfigSection *section, const char *key, unsigned int value ); |
/*! |
* \brief Get an unsigned integer value of an 'item' option by key. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[out] out_value the item value if a valid option exists; otherwise unset |
* \return whether \p out_value was set |
*/ |
extern bool config_get_uint_option( const ConfigSection *section, const char *key, unsigned int *out_value ); |
/*! |
* \brief Get an unsigned integer value of an 'item' option by key, setting the option if it was |
* invalid or creating the option if it did not exist. |
* |
* \param[in] section the section containing the option |
* \param[in] key the option key |
* \param[in] value the default item value |
* \return the value |
*/ |
extern unsigned int config_get_or_set_uint_option( ConfigSection *section, const char *key, unsigned int value ); |
/* config option accessors/manipulators -- by reference */ |
/*! \see ::config_set_value() */ |
extern ConfigOption *config_set_value_len( ConfigOption *option, const char *value, size_t value_len ); |
/*! |
* \brief Set the value of an 'item' option. |
* |
* \param[in] option the option |
* \param[in] value the value |
* \return the option; \c NULL if out of memory |
*/ |
static inline ConfigOption *config_set_value( ConfigOption *option, const char *value ) |
{ |
return config_set_value_len(option, value, value == NULL ? 0 : strlen(value)); |
} |
/*! \see ::config_add_value() */ |
extern ConfigOption *config_add_value_len( ConfigOption *option, const char *value, size_t value_len ); |
/*! |
* \brief Add a value to a 'list' option. |
* |
* \param[in] option the option |
* \param[in] value the value |
* \return the option; \c NULL if out of memory |
*/ |
static inline ConfigOption *config_add_value( ConfigOption *option, const char *value ) |
{ |
assert(value != NULL); |
return config_add_value_len(option, value, strlen(value)); |
} |
/*! |
* \brief Remove a value from a 'list' option. |
* |
* \param[in] option the option |
* \param[in] i the index of the value |
* \return the option; \c NULL if out of memory or invalid \p index |
*/ |
extern ConfigOption *config_remove_value( ConfigOption *option, unsigned int i ); |
/*! |
* \brief Get the value of an 'item' option. |
* |
* \param[in] option the option |
* \return the value; \c NULL if \p option was \c NULL or was a 'list' option |
*/ |
extern const char *config_get_value( const ConfigOption *option ); |
/*! |
* \brief Get the value that indicates whether the option is a 'list' option. |
* |
* \param[in] option the option |
* \return whether the option is a 'list' option |
*/ |
static inline bool config_is_value_list( const ConfigOption *option ) |
{ |
assert(option != NULL); |
return option->values_count > 0 || |
config_string_to_cstr(&option->v.value) == NULL; |
} |
/*! |
* \brief Get the number of values assigned to the option. |
* |
* \param[in] option the option |
* \return \c 1 if the option is an 'item' option; the number of elements if the option is a 'list' |
* option |
*/ |
static inline unsigned int config_get_value_count( const ConfigOption *option ) |
{ |
assert(option != NULL); |
return option->values_count == 0 ? |
(config_string_to_cstr(&option->v.value) == NULL ? 0 : 1) : |
option->values_count; |
} |
/*! |
* \brief Iterate over the values assigned to the option. |
* |
* \param[out] string_value the value variable to declare |
* \param[in] option the option |
*/ |
#define foreach_option_value( string_value, option ) \ |
for (ConfigOption *_option = (option); _option != NULL; _option = NULL) \ |
for (ConfigString *_values_begin = _option->values_count == 0 ? &_option->v.value : &_option->v.values[0], \ |
*_values_end = _option->values_count == 0 ? _values_begin + 1 : &_option->v.values[_option->values_count], \ |
*_value = _values_begin; _value < _values_end; ++_value) \ |
for (const char *(string_value) = config_string_to_cstr(_value); (string_value) != NULL; (string_value) = NULL) |
/*! |
* \brief Iterate over the values assigned to the option. |
* |
* \param[out] i the index variable to declare |
* \param[out] string_value the value variable to declare |
* \param[in] option the option |
*/ |
#define foreach_option_i_value( i, string_value, option ) \ |
for (unsigned int (i) = 0; (i) == 0; (i) = ~0) \ |
for (ConfigOption *_option = (option); _option != NULL; _option = NULL) \ |
for (ConfigString *_values_begin = _option->values_count == 0 ? &_option->v.value : &_option->v.values[0], \ |
*_values_end = _option->values_count == 0 ? _values_begin + 1 : &_option->v.values[_option->values_count], \ |
*_value = _values_begin; _value < _values_end; ++_value, (i) = _value - _values_begin) \ |
for (const char *(string_value) = config_string_to_cstr(_value); (string_value) != NULL; (string_value) = NULL) |
/*! |
* \brief Remove a value from an option during iteration. Should be followed by \c continue. |
*/ |
#define foreach_remove_option_value() \ |
{ \ |
extern void config_oom( void ); \ |
unsigned int _value_i = _value - _values_begin; \ |
if (config_remove_value(_option, _value_i) == NULL) \ |
config_oom(); \ |
_values_begin = _option->values_count == 0 ? &_option->v.value : &_option->v.values[0]; \ |
_values_end = _option->values_count == 0 ? _values_begin + 1 : &_option->v.values[_option->values_count]; \ |
_value = _values_begin + _value_i - 1; \ |
} |
#endif |
/contrib/games/opentyrian/src/destruct.c |
---|
0,0 → 1,2690 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
/* File notes: |
* Two players duke it out in a Scorched Earth style game. |
* Most of the variables referring to the players are global as |
* they are often edited and that's how the original was written. |
* |
* Currently this file is at its final stage for vanilla destruct. |
* Almost all of the left/right code duplications is gone. Most of the |
* functions have been examined and tightened up, none of the enums |
* start with '1', and the various large functions have been divided into |
* smaller chunks. |
* |
* Destruct also supports some 'hidden' configuration that's just too awesome |
* to not have available. Destruct has no configuration options in game, but |
* that doesn't stop us from changing various limiting vars and letting |
* people remap the keyboard. AIs may also be introduced here; fighting a |
* stateless AI isn't really challenging afterall. |
* |
* This hidden config also allows for a hidden game mode! Though as a custom |
* game mode wouldn't show up in the data files it forces us to distinguish |
* between the constant DESTRUCT_MODES (5) and MAX_MODES (6). DESTRUCT_MODES |
* is only used with loaded data. |
* |
* Things I wanted to do but can't: Remove references to VGAScreen. For |
* a multitude of reasons this just isn't feasable. It would have been nice |
* to increase the playing field though... |
*/ |
/*** Headers ***/ |
#include "destruct.h" |
#include "config.h" |
#include "config_file.h" |
#include "fonthand.h" |
#include "helptext.h" |
#include "keyboard.h" |
#include "loudness.h" |
#include "mtrand.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "picload.h" |
#include "sprite.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include <assert.h> |
/*** Defines ***/ |
#define UNIT_HEIGHT 12 |
#define MAX_KEY_OPTIONS 4 |
/*** Enums ***/ |
enum de_state_t { STATE_INIT, STATE_RELOAD, STATE_CONTINUE }; |
enum de_player_t { PLAYER_LEFT = 0, PLAYER_RIGHT = 1, MAX_PLAYERS = 2 }; |
enum de_team_t { TEAM_LEFT = 0, TEAM_RIGHT = 1, MAX_TEAMS = 2 }; |
enum de_mode_t { MODE_5CARDWAR = 0, MODE_TRADITIONAL, MODE_HELIASSAULT, |
MODE_HELIDEFENSE, MODE_OUTGUNNED, MODE_CUSTOM, |
MODE_FIRST = MODE_5CARDWAR, MODE_LAST = MODE_CUSTOM, |
MAX_MODES = 6, MODE_NONE = -1 }; |
enum de_unit_t { UNIT_TANK = 0, UNIT_NUKE, UNIT_DIRT, UNIT_SATELLITE, |
UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER, UNIT_HELI, |
UNIT_FIRST = UNIT_TANK, UNIT_LAST = UNIT_HELI, |
MAX_UNITS = 8, UNIT_NONE = -1 }; |
enum de_shot_t { SHOT_TRACER = 0, SHOT_SMALL, SHOT_LARGE, SHOT_MICRO, |
SHOT_SUPER, SHOT_DEMO, SHOT_SMALLNUKE, SHOT_LARGENUKE, |
SHOT_SMALLDIRT, SHOT_LARGEDIRT, SHOT_MAGNET, SHOT_MINILASER, |
SHOT_MEGALASER, SHOT_LASERTRACER, SHOT_MEGABLAST, SHOT_MINI, |
SHOT_BOMB, |
SHOT_FIRST = SHOT_TRACER, SHOT_LAST = SHOT_BOMB, |
MAX_SHOT_TYPES = 17, SHOT_INVALID = -1 }; |
enum de_expl_t { EXPL_NONE, EXPL_MAGNET, EXPL_DIRT, EXPL_NORMAL }; /* this needs a better name */ |
enum de_trails_t { TRAILS_NONE, TRAILS_NORMAL, TRAILS_FULL }; |
enum de_pixel_t { PIXEL_BLACK = 0, PIXEL_DIRT = 25 }; |
enum de_mapflags_t { MAP_NORMAL = 0x00, MAP_WALLS = 0x01, MAP_RINGS = 0x02, |
MAP_HOLES = 0x04, MAP_FUZZY = 0x08, MAP_TALL = 0x10 }; |
/* keys and moves should line up. */ |
enum de_keys_t { KEY_LEFT = 0, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_CHANGE, KEY_FIRE, KEY_CYUP, KEY_CYDN, MAX_KEY = 8}; |
enum de_move_t { MOVE_LEFT = 0, MOVE_RIGHT, MOVE_UP, MOVE_DOWN, MOVE_CHANGE, MOVE_FIRE, MOVE_CYUP, MOVE_CYDN, MAX_MOVE = 8}; |
/* The tracerlaser is dummied out. It works but (probably due to the low |
* MAX_SHOTS) is not assigned to anything. The bomb does not work. |
*/ |
/*** Structs ***/ |
struct destruct_config_s { |
unsigned int max_shots; |
unsigned int min_walls; |
unsigned int max_walls; |
unsigned int max_explosions; |
unsigned int max_installations; |
bool allow_custom; |
bool alwaysalias; |
bool jumper_straight[2]; |
bool ai[2]; |
}; |
struct destruct_unit_s { |
/* Positioning/movement */ |
unsigned int unitX; /* yep, one's an int and the other is a real */ |
float unitY; |
float unitYMov; |
bool isYInAir; |
/* What it is and what it fires */ |
enum de_unit_t unitType; |
enum de_shot_t shotType; |
/* What it's pointed */ |
float angle; |
float power; |
/* Misc */ |
int lastMove; |
unsigned int ani_frame; |
int health; |
}; |
struct destruct_shot_s { |
bool isAvailable; |
float x; |
float y; |
float xmov; |
float ymov; |
bool gravity; |
unsigned int shottype; |
//int shotdur; /* This looks to be unused */ |
unsigned int trailx[4], traily[4], trailc[4]; |
}; |
struct destruct_explo_s { |
bool isAvailable; |
unsigned int x, y; |
unsigned int explowidth; |
unsigned int explomax; |
unsigned int explofill; |
enum de_expl_t exploType; |
}; |
struct destruct_moves_s { |
bool actions[MAX_MOVE]; |
}; |
struct destruct_keys_s { |
SDLKey Config[MAX_KEY][MAX_KEY_OPTIONS]; |
}; |
struct destruct_ai_s { |
int c_Angle, c_Power, c_Fire; |
unsigned int c_noDown; |
}; |
struct destruct_player_s { |
bool is_cpu; |
struct destruct_ai_s aiMemory; |
struct destruct_unit_s * unit; |
struct destruct_moves_s moves; |
struct destruct_keys_s keys; |
enum de_team_t team; |
unsigned int unitsRemaining; |
unsigned int unitSelected; |
unsigned int shotDelay; |
unsigned int score; |
}; |
struct destruct_wall_s { |
bool wallExist; |
unsigned int wallX, wallY; |
}; |
struct destruct_world_s { |
/* Map data & screen pointer */ |
unsigned int baseMap[320]; |
SDL_Surface * VGAScreen; |
struct destruct_wall_s * mapWalls; |
/* Map configuration */ |
enum de_mode_t destructMode; |
unsigned int mapFlags; |
}; |
/*** Function decs ***/ |
//Prep functions |
static void JE_destructMain( void ); |
static void JE_introScreen( void ); |
static enum de_mode_t JE_modeSelect( void ); |
static void JE_helpScreen( void ); |
static void JE_pauseScreen( void ); |
//level generating functions |
static void JE_generateTerrain( void ); |
static void DE_generateBaseTerrain( unsigned int, unsigned int *); |
static void DE_drawBaseTerrain( unsigned int * ); |
static void DE_generateUnits( unsigned int * ); |
static void DE_generateWalls( struct destruct_world_s * ); |
static void DE_generateRings(SDL_Surface *, Uint8 ); |
static void DE_ResetLevel( void ); |
static unsigned int JE_placementPosition( unsigned int, unsigned int, unsigned int * ); |
//drawing functions |
static void JE_aliasDirt( SDL_Surface * ); |
static void DE_RunTickDrawCrosshairs( void ); |
static void DE_RunTickDrawHUD( void ); |
static void DE_GravityDrawUnit( enum de_player_t, struct destruct_unit_s * ); |
static void DE_RunTickAnimate( void ); |
static void DE_RunTickDrawWalls( void ); |
static void DE_DrawTrails( struct destruct_shot_s *, unsigned int, unsigned int, unsigned int ); |
static void JE_tempScreenChecking( void ); |
static void JE_superPixel( unsigned int, unsigned int ); |
static void JE_pixCool( unsigned int, unsigned int, Uint8 ); |
//player functions |
static void DE_RunTickGetInput( void ); |
static void DE_ProcessInput( void ); |
static void DE_ResetPlayers( void ); |
static void DE_ResetAI( void ); |
static void DE_ResetActions( void ); |
static void DE_RunTickAI( void ); |
//unit functions |
static void DE_RaiseAngle( struct destruct_unit_s * ); |
static void DE_LowerAngle( struct destruct_unit_s * ); |
static void DE_RaisePower( struct destruct_unit_s * ); |
static void DE_LowerPower( struct destruct_unit_s * ); |
static void DE_CycleWeaponUp( struct destruct_unit_s * ); |
static void DE_CycleWeaponDown( struct destruct_unit_s * ); |
static void DE_RunMagnet( enum de_player_t, struct destruct_unit_s * ); |
static void DE_GravityFlyUnit( struct destruct_unit_s * ); |
static void DE_GravityLowerUnit( struct destruct_unit_s * ); |
static void DE_DestroyUnit( enum de_player_t, struct destruct_unit_s * ); |
static void DE_ResetUnits( void ); |
static inline bool DE_isValidUnit( struct destruct_unit_s *); |
//weapon functions |
static void DE_ResetWeapons( void ); |
static void DE_RunTickShots( void ); |
static void DE_RunTickExplosions( void ); |
static void DE_TestExplosionCollision( unsigned int, unsigned int); |
static void JE_makeExplosion( unsigned int, unsigned int, enum de_shot_t ); |
static void DE_MakeShot( enum de_player_t, const struct destruct_unit_s *, int ); |
//gameplay functions |
static enum de_state_t DE_RunTick( void ); |
static void DE_RunTickCycleDeadUnits( void ); |
static void DE_RunTickGravity( void ); |
static bool DE_RunTickCheckEndgame( void ); |
static bool JE_stabilityCheck( unsigned int, unsigned int ); |
//sound |
static void DE_RunTickPlaySounds( void ); |
static void JE_eSound( unsigned int ); |
/*** Weapon configurations ***/ |
/* Part of me wants to leave these as bytes to save space. */ |
static const bool demolish[MAX_SHOT_TYPES] = {false, false, false, false, false, true, true, true, false, false, false, false, true, false, true, false, true}; |
//static const int shotGr[MAX_SHOT_TYPES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}; |
static const int shotTrail[MAX_SHOT_TYPES] = {TRAILS_NONE, TRAILS_NONE, TRAILS_NONE, TRAILS_NORMAL, TRAILS_NORMAL, TRAILS_NORMAL, TRAILS_FULL, TRAILS_FULL, TRAILS_NONE, TRAILS_NONE, TRAILS_NONE, TRAILS_NORMAL, TRAILS_FULL, TRAILS_NORMAL, TRAILS_FULL, TRAILS_NORMAL, TRAILS_NONE}; |
//static const int shotFuse[MAX_SHOT_TYPES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; |
static const int shotDelay[MAX_SHOT_TYPES] = {10, 30, 80, 20, 60, 100, 140, 200, 20, 60, 5, 15, 50, 5, 80, 16, 0}; |
static const int shotSound[MAX_SHOT_TYPES] = {S_SELECT, S_WEAPON_2, S_WEAPON_1, S_WEAPON_7, S_WEAPON_7, S_EXPLOSION_9, S_EXPLOSION_22, S_EXPLOSION_22, S_WEAPON_5, S_WEAPON_13, S_WEAPON_10, S_WEAPON_15, S_WEAPON_15, S_WEAPON_26, S_WEAPON_14, S_WEAPON_7, S_WEAPON_7}; |
static const int exploSize[MAX_SHOT_TYPES] = {4, 20, 30, 14, 22, 16, 40, 60, 10, 30, 0, 5, 10, 3, 15, 7, 0}; |
static const bool shotBounce[MAX_SHOT_TYPES] = {false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true}; |
static const int exploDensity[MAX_SHOT_TYPES] = { 2, 5, 10, 15, 20, 15, 25, 30, 40, 80, 0, 30, 30, 4, 30, 5, 0}; |
static const int shotDirt[MAX_SHOT_TYPES] = {EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_DIRT, EXPL_DIRT, EXPL_MAGNET, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NORMAL, EXPL_NONE}; |
static const int shotColor[MAX_SHOT_TYPES] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 10, 10, 10, 10, 16, 0}; |
static const int defaultWeapon[MAX_UNITS] = {SHOT_SMALL, SHOT_MICRO, SHOT_SMALLDIRT, SHOT_INVALID, SHOT_MAGNET, SHOT_MINILASER, SHOT_MICRO, SHOT_MINI}; |
static const int defaultCpuWeapon[MAX_UNITS] = {SHOT_SMALL, SHOT_MICRO, SHOT_DEMO, SHOT_INVALID, SHOT_MAGNET, SHOT_MINILASER, SHOT_MICRO, SHOT_MINI}; |
static const int defaultCpuWeaponB[MAX_UNITS] = {SHOT_DEMO, SHOT_SMALLNUKE, SHOT_DEMO, SHOT_INVALID, SHOT_MAGNET, SHOT_MEGALASER, SHOT_MICRO, SHOT_MINI}; |
static const int systemAngle[MAX_UNITS] = {true, true, true, false, false, true, false, false}; |
static const int baseDamage[MAX_UNITS] = {200, 120, 400, 300, 80, 150, 600, 40}; |
static const int systemAni[MAX_UNITS] = {false, false, false, true, false, false, false, true}; |
static bool weaponSystems[MAX_UNITS][MAX_SHOT_TYPES] = |
{ |
{1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // normal |
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // nuke |
{0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // dirt |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // worthless |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, // magnet |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, // laser |
{1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, // jumper |
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0} // helicopter |
}; |
/* More constant configuration settings. */ |
/* Music that destruct will play. You can check out musmast.c to see what is what. */ |
static const JE_byte goodsel[14] /*[1..14]*/ = {1, 2, 6, 12, 13, 14, 17, 23, 24, 26, 28, 29, 32, 33}; |
/* Unit creation. Need to move this later: Doesn't belong here */ |
static JE_byte basetypes[10][11] /*[1..8, 1..11]*/ = /* [0] is amount of units*/ |
{ |
{5, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_DIRT, UNIT_DIRT, UNIT_SATELLITE, UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER, UNIT_HELI}, /*Normal*/ |
{1, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK}, /*Traditional*/ |
{4, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI}, /*Weak Heli attack fleet*/ |
{8, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_NUKE, UNIT_NUKE, UNIT_DIRT, UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER}, /*Strong Heli defense fleet*/ |
{8, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI, UNIT_HELI}, /*Strong Heli attack fleet*/ |
{4, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_NUKE, UNIT_DIRT, UNIT_MAGNET, UNIT_JUMPER, UNIT_JUMPER}, /*Weak Heli defense fleet*/ |
{8, UNIT_TANK, UNIT_NUKE, UNIT_DIRT, UNIT_SATELLITE, UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER, UNIT_HELI, UNIT_TANK, UNIT_NUKE}, /*Overpowering fleet*/ |
{4, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_DIRT, UNIT_TANK, UNIT_LASER, UNIT_JUMPER, UNIT_HELI, UNIT_NUKE, UNIT_JUMPER}, /*Weak fleet*/ |
{5, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_DIRT, UNIT_DIRT, UNIT_SATELLITE, UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER, UNIT_HELI}, /*Left custom*/ |
{5, UNIT_TANK, UNIT_TANK, UNIT_NUKE, UNIT_DIRT, UNIT_DIRT, UNIT_SATELLITE, UNIT_MAGNET, UNIT_LASER, UNIT_JUMPER, UNIT_HELI}, /*Right custom*/ |
}; |
static const unsigned int baseLookup[MAX_PLAYERS][MAX_MODES] = |
{ |
{0, 1, 3, 4, 6, 8}, |
{0, 1, 2, 5, 7, 9} |
}; |
static const JE_byte GraphicBase[MAX_PLAYERS][MAX_UNITS] = |
{ |
{ 1, 6, 11, 58, 63, 68, 96, 153}, |
{ 20, 25, 30, 77, 82, 87, 115, 172} |
}; |
static const JE_byte ModeScore[MAX_PLAYERS][MAX_MODES] = |
{ |
{1, 0, 0, 5, 0, 1}, |
{1, 0, 5, 0, 1, 1} |
}; |
static SDLKey defaultKeyConfig[MAX_PLAYERS][MAX_KEY][MAX_KEY_OPTIONS] = |
{ |
{ {SDLK_c}, |
{SDLK_v}, |
{SDLK_a}, |
{SDLK_z}, |
{SDLK_LALT}, |
{SDLK_x, SDLK_LSHIFT}, |
{SDLK_LCTRL}, |
{SDLK_SPACE} |
}, |
{ {SDLK_LEFT, SDLK_KP4}, |
{SDLK_RIGHT, SDLK_KP6}, |
{SDLK_UP, SDLK_KP8}, |
{SDLK_DOWN, SDLK_KP2}, |
{SDLK_BACKSLASH, SDLK_KP5}, |
{SDLK_INSERT, SDLK_RETURN, SDLK_KP0, SDLK_KP_ENTER}, |
{SDLK_PAGEUP, SDLK_KP9}, |
{SDLK_PAGEDOWN, SDLK_KP3} |
} |
}; |
/*** Globals ***/ |
static SDL_Surface *destructTempScreen; |
static JE_boolean destructFirstTime; |
static struct destruct_config_s config = { 40, 20, 20, 40, 10, false, false, {true, false}, {true, false} }; |
static struct destruct_player_s destruct_player[MAX_PLAYERS]; |
static struct destruct_world_s world; |
static struct destruct_shot_s * shotRec; |
static struct destruct_explo_s * exploRec; |
static const char *player_names[] = |
{ |
"left", "right", |
}; |
static const char *key_names[] = |
{ |
"left", "right", "up", "down", |
"change", "fire", "previous weapon", "next weapon", |
}; |
static const char *unit_names[] = |
{ |
"tank", "nuke", "dirt", "satellite", |
"magnet", "laser", "jumper", "heli", |
}; |
static enum de_unit_t get_unit_by_name( const char *unit_name ) |
{ |
for (enum de_unit_t unit = UNIT_FIRST; unit < MAX_UNITS; ++unit) |
if (strcmp(unit_name, unit_names[unit]) == 0) |
return unit; |
return UNIT_NONE; |
} |
static SDLKey get_SDLKey_by_name( const char *key_name ) |
{ |
for (SDLKey key = SDLK_FIRST; key < SDLK_LAST; ++key) |
if (strcmp(key_name, SDL_GetKeyName(key)) == 0) |
return key; |
return SDLK_UNKNOWN; |
} |
static void load_destruct_config( Config *config_ ) |
{ |
ConfigSection *section; |
section = config_find_or_add_section(config_, "destruct", NULL); |
if (section == NULL) |
exit(EXIT_FAILURE); // out of memory |
config.alwaysalias = config_get_or_set_bool_option(section, "antialias craters", false, NO_YES); |
weaponSystems[UNIT_LASER][SHOT_LASERTRACER] = config_get_or_set_bool_option(section, "tracer laser", false, OFF_ON); |
config.max_shots = config_get_or_set_int_option(section, "max shots", 40); |
config.max_explosions = config_get_or_set_int_option(section, "max explosions", 40); |
config.min_walls = config_get_or_set_int_option(section, "min walls", 20); |
config.max_walls = config_get_or_set_int_option(section, "max walls", 20); |
config.ai[0] = config_get_or_set_bool_option(section, "left ai", true, NO_YES); |
config.jumper_straight[0] = config_get_or_set_bool_option(section, "left jumper fires straight", true, NO_YES); |
config.ai[1] = config_get_or_set_bool_option(section, "right ai", false, NO_YES); |
config.jumper_straight[1] = config_get_or_set_bool_option(section, "right jumper fires straight", false, NO_YES); |
// keyboard controls |
for (int p = 0; p < MAX_PLAYERS; ++p) |
{ |
section = config_find_section(config_, "destruct keyboard", player_names[p]); |
if (section == NULL) |
if ((section = config_add_section(config_, "destruct keyboard", player_names[p])) == NULL) |
exit(-1); |
ConfigOption *option; |
for (int k = 0; k < MAX_KEY; ++k) |
{ |
if ((option = config_get_or_set_option(section, key_names[k], NULL)) == NULL) |
exit(-1); |
foreach_option_i_value(i, value, option) |
{ |
SDLKey key = get_SDLKey_by_name(value); |
if (key != SDLK_LAST && i < COUNTOF(defaultKeyConfig[p][k])) |
{ |
defaultKeyConfig[p][k][i] = key; |
} |
else // invalid or excess |
{ |
foreach_remove_option_value(); |
continue; |
} |
} |
if (config_get_value_count(option) > 0) |
{ |
// unset remaining defaults |
for (unsigned int i = config_get_value_count(option); i < COUNTOF(defaultKeyConfig[p][k]); ++i) |
defaultKeyConfig[p][k][i] = SDLK_UNKNOWN; |
} |
else |
{ |
// set defaults |
for (unsigned int i = 0; i < COUNTOF(defaultKeyConfig[p][k]); ++i) |
if (defaultKeyConfig[p][k][i] != SDLK_UNKNOWN) |
config_add_value(option, SDL_GetKeyName(defaultKeyConfig[p][k][i])); |
} |
} |
} |
// custom destruct mode |
section = config_find_section(config_, "destruct custom", NULL); |
if (section == NULL) |
if ((section = config_add_section(config_, "destruct custom", NULL)) == NULL) |
exit(-1); |
config.allow_custom = config_get_or_set_bool_option(section, "enable", false, NO_YES); |
char buffer[15 + 1]; |
for (int p = 0; p < MAX_PLAYERS; ++p) |
{ |
snprintf(buffer, sizeof(buffer), "%s num units", player_names[p]); |
basetypes[8 + p][0] = config_get_or_set_int_option(section, buffer, basetypes[8 + p][0]); |
ConfigOption *option; |
snprintf(buffer, sizeof(buffer), "%s unit", player_names[p]); |
if ((option = config_get_or_set_option(section, buffer, NULL)) == NULL) |
exit(-1); |
foreach_option_i_value(i, value, option) |
{ |
enum de_unit_t unit = get_unit_by_name(value); |
if (unit != UNIT_NONE && 1 + i < COUNTOF(basetypes[8 + p])) |
{ |
basetypes[8 + p][1 + i] = unit; |
} |
else // invalid or excess |
{ |
foreach_remove_option_value(); |
continue; |
} |
} |
if (config_get_value_count(option) > 0) |
{ |
// set remaining units to tank |
for (unsigned int i = config_get_value_count(option); 1 + i < COUNTOF(basetypes[8 + p]); ++i) |
{ |
basetypes[8 + p][1 + i] = UNIT_TANK; |
config_add_value(option, unit_names[UNIT_TANK]); |
} |
} |
else |
{ |
// set defaults |
for (unsigned int i = 0; 1 + i < COUNTOF(basetypes[8 + p]); ++i) |
config_add_value(option, unit_names[basetypes[8 + p][1 + i]]); |
} |
} |
} |
/*** Startup ***/ |
void JE_destructGame( void ) |
{ |
unsigned int i; |
/* This is the entry function. Any one-time actions we need to |
* perform can go in here. */ |
JE_clr256(VGAScreen); |
JE_showVGA(); |
load_destruct_config(&opentyrian_config); |
//malloc things that have customizable sizes |
shotRec = malloc(sizeof(struct destruct_shot_s) * config.max_shots); |
exploRec = malloc(sizeof(struct destruct_explo_s) * config.max_explosions); |
world.mapWalls = malloc(sizeof(struct destruct_wall_s) * config.max_walls); |
//Malloc enough structures to cover all of this session's possible needs. |
for(i = 0; i < 10; i++) { |
config.max_installations = MAX(config.max_installations, basetypes[i][0]); |
} |
destruct_player[PLAYER_LEFT ].unit = malloc(sizeof(struct destruct_unit_s) * config.max_installations); |
destruct_player[PLAYER_RIGHT].unit = malloc(sizeof(struct destruct_unit_s) * config.max_installations); |
destructTempScreen = game_screen; |
world.VGAScreen = VGAScreen; |
JE_loadCompShapes(&eShapes[0], '~'); |
fade_black(1); |
JE_destructMain(); |
//and of course exit actions go here. |
free(shotRec); |
free(exploRec); |
free(world.mapWalls); |
free(destruct_player[PLAYER_LEFT ].unit); |
free(destruct_player[PLAYER_RIGHT].unit); |
} |
static void JE_destructMain( void ) |
{ |
enum de_state_t curState; |
JE_loadPic(VGAScreen, 11, false); |
JE_introScreen(); |
DE_ResetPlayers(); |
destruct_player[PLAYER_LEFT ].is_cpu = config.ai[PLAYER_LEFT]; |
destruct_player[PLAYER_RIGHT].is_cpu = config.ai[PLAYER_RIGHT]; |
while(1) |
{ |
world.destructMode = JE_modeSelect(); |
if(world.destructMode == MODE_NONE) { |
break; /* User is quitting */ |
} |
do |
{ |
destructFirstTime = true; |
JE_loadPic(VGAScreen, 11, false); |
DE_ResetUnits(); |
DE_ResetLevel(); |
do { |
curState = DE_RunTick(); |
} while(curState == STATE_CONTINUE); |
fade_black(25); |
} |
while (curState == STATE_RELOAD); |
} |
} |
static void JE_introScreen( void ) |
{ |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->h * VGAScreen2->pitch); |
JE_outText(VGAScreen, JE_fontCenter(specialName[7], TINY_FONT), 90, specialName[7], 12, 5); |
JE_outText(VGAScreen, JE_fontCenter(miscText[64], TINY_FONT), 180, miscText[64], 15, 2); |
JE_outText(VGAScreen, JE_fontCenter(miscText[65], TINY_FONT), 190, miscText[65], 15, 2); |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
newkey = false; |
while (!newkey) |
{ |
service_SDL_events(false); |
uSDL_Delay(16); |
} |
fade_black(15); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->h * VGAScreen->pitch); |
JE_showVGA(); |
} |
/* JE_modeSelect |
* |
* This function prints the DESTRUCT mode selection menu. |
* The return value is the selected mode, or -1 (MODE_NONE) |
* if the user quits. |
*/ |
static void DrawModeSelectMenu( enum de_mode_t mode ) { |
int i; |
/* Helper function of JE_modeSelect. Do not use elsewhere. */ |
for (i = 0; i < DESTRUCT_MODES; i++) |
{ /* What a large function call. */ |
JE_textShade(VGAScreen, JE_fontCenter(destructModeName[i], TINY_FONT), 82 + i * 12, destructModeName[i], 12, (i == mode) * 4, FULL_SHADE); |
} |
if (config.allow_custom == true) |
{ |
JE_textShade(VGAScreen, JE_fontCenter("Custom", TINY_FONT), 82 + i * 12, "Custom", 12, (i == mode) * 4, FULL_SHADE); |
} |
} |
static enum de_mode_t JE_modeSelect( void ) |
{ |
enum de_mode_t mode; |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->h * VGAScreen2->pitch); |
mode = MODE_5CARDWAR; |
// Draw the menu and fade us in |
DrawModeSelectMenu(mode); |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
/* Get input in a loop. */ |
while(1) |
{ |
/* Re-draw the menu every iteration */ |
DrawModeSelectMenu(mode); |
JE_showVGA(); |
/* Grab keys */ |
newkey = false; |
do { |
service_SDL_events(false); |
uSDL_Delay(16); |
} while(!newkey); |
/* See what was pressed */ |
if (keysactive[SDLK_ESCAPE]) |
{ |
mode = MODE_NONE; /* User is quitting, return failure */ |
break; |
} |
if (keysactive[SDLK_RETURN]) |
{ |
break; /* User has selected, return choice */ |
} |
if (keysactive[SDLK_UP]) |
{ |
if(mode == MODE_FIRST) |
{ |
if (config.allow_custom == true) |
{ |
mode = MODE_LAST; |
} else { |
mode = MODE_LAST-1; |
} |
} else { |
mode--; |
} |
} |
if (keysactive[SDLK_DOWN]) |
{ |
if(mode >= MODE_LAST-1) |
{ |
if (config.allow_custom == true && mode == MODE_LAST-1) |
{ |
mode++; |
} else { |
mode = MODE_FIRST; |
} |
} else { |
mode++; |
} |
} |
} |
fade_black(15); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->h * VGAScreen->pitch); |
JE_showVGA(); |
return(mode); |
} |
static void JE_generateTerrain( void ) |
{ |
/* The unique modifiers: |
Altered generation (really tall) |
Fuzzy hills |
Rings of dirt |
The non-unique ones;: |
Rings of not dirt (holes) |
Walls |
*/ |
world.mapFlags = MAP_NORMAL; |
if(mt_rand() % 2 == 0) |
{ |
world.mapFlags |= MAP_WALLS; |
} |
if(mt_rand() % 4 == 0) |
{ |
world.mapFlags |= MAP_HOLES; |
} |
switch(mt_rand() % 4) |
{ |
case 0: |
world.mapFlags |= MAP_FUZZY; |
break; |
case 1: |
world.mapFlags |= MAP_TALL; |
break; |
case 2: |
world.mapFlags |= MAP_RINGS; |
break; |
} |
play_song(goodsel[mt_rand() % 14] - 1); |
DE_generateBaseTerrain(world.mapFlags, world.baseMap); |
DE_generateUnits(world.baseMap); |
DE_generateWalls(&world); |
DE_drawBaseTerrain(world.baseMap); |
if (world.mapFlags & MAP_RINGS) |
{ |
DE_generateRings(world.VGAScreen, PIXEL_DIRT); |
} |
if (world.mapFlags & MAP_HOLES) |
{ |
DE_generateRings(world.VGAScreen, PIXEL_BLACK); |
} |
JE_aliasDirt(world.VGAScreen); |
JE_showVGA(); |
memcpy(destructTempScreen->pixels, VGAScreen->pixels, destructTempScreen->pitch * destructTempScreen->h); |
} |
static void DE_generateBaseTerrain( unsigned int mapFlags, unsigned int * baseWorld) |
{ |
unsigned int i; |
unsigned int newheight, HeightMul; |
float sinewave, sinewave2, cosinewave, cosinewave2; |
/* The 'terrain' is actually the video buffer :). If it's brown, flu... er, |
* brown pixels are what we check for collisions with. */ |
/* The ranges here are between .01 and roughly 0.07283...*/ |
sinewave = mt_rand_lt1() * M_PI / 50 + 0.01f; |
sinewave2 = mt_rand_lt1() * M_PI / 50 + 0.01f; |
cosinewave = mt_rand_lt1() * M_PI / 50 + 0.01f; |
cosinewave2 = mt_rand_lt1() * M_PI / 50 + 0.01f; |
HeightMul = 20; |
/* This block just exists to mix things up. */ |
if(mapFlags & MAP_FUZZY) |
{ |
sinewave = M_PI - mt_rand_lt1() * 0.3f; |
sinewave2 = M_PI - mt_rand_lt1() * 0.3f; |
} |
if(mapFlags & MAP_TALL) |
{ |
HeightMul = 100; |
} |
/* Now compute a height for each of our lines. */ |
for (i = 1; i <= 318; i++) |
{ |
newheight = roundf(sinf(sinewave * i) * HeightMul + sinf(sinewave2 * i) * 15 + |
cosf(cosinewave * i) * 10 + sinf(cosinewave2 * i) * 15) + 130; |
/* Bind it; we have mins and maxs */ |
if (newheight < 40) |
{ |
newheight = 40; |
} |
else if (newheight > 195) { |
newheight = 195; |
} |
baseWorld[i] = newheight; |
} |
/* The base world has been created. */ |
} |
static void DE_drawBaseTerrain( unsigned int * baseWorld) |
{ |
unsigned int i; |
for (i = 1; i <= 318; i++) |
{ |
JE_rectangle(VGAScreen, i, baseWorld[i], i, 199, PIXEL_DIRT); |
} |
} |
static void DE_generateUnits( unsigned int * baseWorld ) |
{ |
unsigned int i, j, numSatellites; |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
numSatellites = 0; |
destruct_player[i].unitsRemaining = 0; |
for (j = 0; j < basetypes[baseLookup[i][world.destructMode]][0]; j++) |
{ |
/* Not everything is the same between players */ |
if(i == PLAYER_LEFT) |
{ |
destruct_player[i].unit[j].unitX = (mt_rand() % 120) + 10; |
} |
else |
{ |
destruct_player[i].unit[j].unitX = 320 - ((mt_rand() % 120) + 22); |
} |
destruct_player[i].unit[j].unitY = JE_placementPosition(destruct_player[i].unit[j].unitX - 1, 14, baseWorld); |
destruct_player[i].unit[j].unitType = basetypes[baseLookup[i][world.destructMode]][(mt_rand() % 10) + 1]; |
/* Sats are special cases since they are useless. They don't count |
* as active units and we can't have a team of all sats */ |
if (destruct_player[i].unit[j].unitType == UNIT_SATELLITE) |
{ |
if (numSatellites == basetypes[baseLookup[i][world.destructMode]][0]) |
{ |
destruct_player[i].unit[j].unitType = UNIT_TANK; |
destruct_player[i].unitsRemaining++; |
} else { |
/* Place the satellite. Note: Earlier we cleared |
* space with JE_placementPosition. Now we are randomly |
* placing the sat's Y. It can be generated in hills |
* and there is a clearing underneath it. This CAN |
* be fixed but won't be for classic. |
*/ |
destruct_player[i].unit[j].unitY = 30 + (mt_rand() % 40); |
numSatellites++; |
} |
} |
else |
{ |
destruct_player[i].unitsRemaining++; |
} |
/* Now just fill in the rest of the unit's values. */ |
destruct_player[i].unit[j].lastMove = 0; |
destruct_player[i].unit[j].unitYMov = 0; |
destruct_player[i].unit[j].isYInAir = false; |
destruct_player[i].unit[j].angle = 0; |
destruct_player[i].unit[j].power = (destruct_player[i].unit[j].unitType == UNIT_LASER) ? 6 : 3; |
destruct_player[i].unit[j].shotType = defaultWeapon[destruct_player[i].unit[j].unitType]; |
destruct_player[i].unit[j].health = baseDamage[destruct_player[i].unit[j].unitType]; |
destruct_player[i].unit[j].ani_frame = 0; |
} |
} |
} |
static void DE_generateWalls( struct destruct_world_s * gameWorld ) |
{ |
unsigned int i, j, wallX; |
unsigned int wallHeight, remainWalls; |
unsigned int tries; |
bool isGood; |
if ((world.mapFlags & MAP_WALLS) == false) |
{ |
/* Just clear them out */ |
for (i = 0; i < config.max_walls; i++) |
{ |
gameWorld->mapWalls[i].wallExist = false; |
} |
return; |
} |
remainWalls = (rand() % (config.max_walls - config.min_walls + 1)) + config.min_walls; |
do { |
/* Create a wall. Decide how tall the wall will be */ |
wallHeight = (mt_rand() % 5) + 1; |
if(wallHeight > remainWalls) |
{ |
wallHeight = remainWalls; |
} |
/* Now find a good place to put the wall. */ |
tries = 0; |
do { |
isGood = true; |
wallX = (mt_rand() % 300) + 10; |
/* Is this X already occupied? In the original Tyrian we only |
* checked to make sure four units on each side were unobscured. |
* That's not very scalable; instead I will check every unit, |
* but I'll only try plotting an unobstructed X four times. |
* After that we'll cover up what may; having a few units |
* stuck behind walls makes things mildly interesting. |
*/ |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
for (j = 0; j < config.max_installations; j++) |
{ |
if ((wallX > destruct_player[i].unit[j].unitX - 12) |
&& (wallX < destruct_player[i].unit[j].unitX + 13)) |
{ |
isGood = false; |
goto label_outer_break; /* I do feel that outer breaking is a legitimate goto use. */ |
} |
} |
} |
label_outer_break: |
tries++; |
} while(isGood == false && tries < 5); |
/* We now have a valid X. Create the wall. */ |
for (i = 1; i <= wallHeight; i++) |
{ |
gameWorld->mapWalls[remainWalls - i].wallExist = true; |
gameWorld->mapWalls[remainWalls - i].wallX = wallX; |
gameWorld->mapWalls[remainWalls - i].wallY = JE_placementPosition(wallX, 12, gameWorld->baseMap) - 14 * i; |
} |
remainWalls -= wallHeight; |
} while (remainWalls != 0); |
} |
static void DE_generateRings( SDL_Surface * screen, Uint8 pixel ) |
{ |
unsigned int i, j, tempSize, rings; |
int tempPosX1, tempPosY1, tempPosX2, tempPosY2; |
float tempRadian; |
rings = mt_rand() % 6 + 1; |
for (i = 1; i <= rings; i++) |
{ |
tempPosX1 = (mt_rand() % 320); |
tempPosY1 = (mt_rand() % 160) + 20; |
tempSize = (mt_rand() % 40) + 10; /*Size*/ |
for (j = 1; j <= tempSize * tempSize * 2; j++) |
{ |
tempRadian = mt_rand_lt1() * (2 * M_PI); |
tempPosY2 = tempPosY1 + roundf(cosf(tempRadian) * (mt_rand_lt1() * 0.1f + 0.9f) * tempSize); |
tempPosX2 = tempPosX1 + roundf(sinf(tempRadian) * (mt_rand_lt1() * 0.1f + 0.9f) * tempSize); |
if ((tempPosY2 > 12) && (tempPosY2 < 200) |
&& (tempPosX2 > 0) && (tempPosX2 < 319)) |
{ |
((Uint8 *)screen->pixels)[tempPosX2 + tempPosY2 * screen->pitch] = pixel; |
} |
} |
} |
} |
static unsigned int aliasDirtPixel(const SDL_Surface * screen, unsigned int x, unsigned int y, const Uint8 * s) { |
//A helper function used when aliasing dirt. That's a messy process; |
//let's contain the mess here. |
unsigned int newColor = PIXEL_BLACK; |
if ((y > 0) && (*(s - screen->pitch) == PIXEL_DIRT)) { // look up |
newColor += 1; |
} |
if ((y < screen->h - 1u) && (*(s + screen->pitch) == PIXEL_DIRT)) { // look down |
newColor += 3; |
} |
if ((x > 0) && (*(s - 1) == PIXEL_DIRT)) { // look left |
newColor += 2; |
} |
if ((x < screen->pitch - 1u) && (*(s + 1) == PIXEL_DIRT)) { // look right |
newColor += 2; |
} |
if (newColor != PIXEL_BLACK) { |
return(newColor + 16); // 16 must be the start of the brown pixels. |
} |
return(PIXEL_BLACK); |
} |
static void JE_aliasDirt( SDL_Surface * screen ) |
{ |
/* This complicated looking function goes through the whole screen |
* looking for brown pixels which just happen to be next to non-brown |
* pixels. It's an aliaser, just like it says. */ |
unsigned int x, y; |
/* This is a pointer to a screen. If you don't like pointer arithmetic, |
* you won't like this function. */ |
Uint8 *s = screen->pixels; |
s += 12 * screen->pitch; |
for (y = 12; y < (unsigned)screen->h; y++) { |
for (x = 0; x < screen->pitch; x++) { |
if (*s == PIXEL_BLACK) { |
*s = aliasDirtPixel(screen, x, y, s); |
} |
s++; |
} |
} |
} |
static unsigned int JE_placementPosition( unsigned int passed_x, unsigned int width, unsigned int * world ) |
{ |
unsigned int i, new_y; |
/* This is the function responsible for carving out chunks of land. |
* There's a bug here, but it's a pretty major gameplay altering one: |
* areas can be carved out for units that are aerial or in mountains. |
* This can result in huge caverns. Ergo, it's a feature :) |
* |
* I wondered if it might be better to not carve out land at all. |
* On testing I determined that was distracting and added nothing. */ |
new_y = 0; |
for (i = passed_x; i <= passed_x + width - 1; i++) |
{ |
if (new_y < world[i]) |
new_y = world[i]; |
} |
for (i = passed_x; i <= passed_x + width - 1; i++) |
{ |
world[i] = new_y; |
} |
return new_y; |
} |
static bool JE_stabilityCheck( unsigned int x, unsigned int y ) |
{ |
unsigned int i, numDirtPixels; |
Uint8 * s; |
numDirtPixels = 0; |
s = destructTempScreen->pixels; |
s += x + (y * destructTempScreen->pitch) - 1; |
/* Check the 12 pixels on the bottom border of our object */ |
for (i = 0; i < 12; i++) |
{ |
if (*s == PIXEL_DIRT) |
numDirtPixels++; |
s++; |
} |
/* If there are fewer than 10 brown pixels we don't consider it a solid base */ |
return (numDirtPixels < 10); |
} |
static void JE_tempScreenChecking( void ) /*and copy to vgascreen*/ |
{ |
Uint8 *s = VGAScreen->pixels; |
s += 12 * VGAScreen->pitch; |
Uint8 *temps = destructTempScreen->pixels; |
temps += 12 * destructTempScreen->pitch; |
for (int y = 12; y < VGAScreen->h; y++) |
{ |
for (int x = 0; x < VGAScreen->pitch; x++) |
{ |
// This block is what fades out explosions. The palette from 241 |
// to 255 fades from a very dark red to a very bright yellow. |
if (*temps >= 241) |
{ |
if (*temps == 241) |
*temps = PIXEL_BLACK; |
else |
(*temps)--; |
} |
// This block is for aliasing dirt. Computers are fast these days, |
// and it's fun. |
if (config.alwaysalias == true && *temps == PIXEL_BLACK) { |
*temps = aliasDirtPixel(VGAScreen, x, y, temps); |
} |
/* This is copying from our temp screen to VGAScreen */ |
*s = *temps; |
s++; |
temps++; |
} |
} |
} |
static void JE_makeExplosion( unsigned int tempPosX, unsigned int tempPosY, enum de_shot_t shottype ) |
{ |
unsigned int i, tempExploSize; |
/* First find an open explosion. If we can't find one, return.*/ |
for (i = 0; i < config.max_explosions; i++) |
{ |
if (exploRec[i].isAvailable == true) |
break; |
} |
if (i == config.max_explosions) /* No empty slots */ |
{ |
return; |
} |
exploRec[i].isAvailable = false; |
exploRec[i].x = tempPosX; |
exploRec[i].y = tempPosY; |
exploRec[i].explowidth = 2; |
if(shottype != SHOT_INVALID) |
{ |
tempExploSize = exploSize[shottype]; |
if (tempExploSize < 5) |
JE_eSound(3); |
else if (tempExploSize < 15) |
JE_eSound(4); |
else if (tempExploSize < 20) |
JE_eSound(12); |
else if (tempExploSize < 40) |
JE_eSound(11); |
else |
{ |
JE_eSound(12); |
JE_eSound(11); |
} |
exploRec[i].explomax = tempExploSize; |
exploRec[i].explofill = exploDensity[shottype]; |
exploRec[i].exploType = shotDirt[shottype]; |
} |
else |
{ |
JE_eSound(4); |
exploRec[i].explomax = (mt_rand() % 40) + 10; |
exploRec[i].explofill = (mt_rand() % 60) + 20; |
exploRec[i].exploType = EXPL_NORMAL; |
} |
} |
static void JE_eSound( unsigned int sound ) |
{ |
static int exploSoundChannel = 0; |
if (++exploSoundChannel > 5) |
{ |
exploSoundChannel = 1; |
} |
soundQueue[exploSoundChannel] = sound; |
} |
static void JE_superPixel( unsigned int tempPosX, unsigned int tempPosY ) |
{ |
const unsigned int starPattern[5][5] = { |
{ 0, 0, 246, 0, 0 }, |
{ 0, 247, 249, 247, 0 }, |
{ 246, 249, 252, 249, 246 }, |
{ 0, 247, 249, 247, 0 }, |
{ 0, 0, 246, 0, 0 } |
}; |
const unsigned int starIntensity[5][5] = { |
{ 0, 0, 1, 0, 0 }, |
{ 0, 1, 2, 1, 0 }, |
{ 1, 2, 4, 2, 1 }, |
{ 0, 1, 2, 1, 0 }, |
{ 0, 0, 1, 0, 0 } |
}; |
int x, y, maxX, maxY; |
unsigned int rowLen; |
Uint8 *s; |
maxX = destructTempScreen->pitch; |
maxY = destructTempScreen->h; |
rowLen = destructTempScreen->pitch; |
s = destructTempScreen->pixels; |
s += (rowLen * (tempPosY - 2)) + (tempPosX - 2); |
for (y = 0; y < 5; y++, s += rowLen - 5) |
{ |
if ((signed)tempPosY + y - 2 < 0 /* would be out of bounds */ |
|| (signed)tempPosY + y - 2 >= maxY) { continue; } |
for (x = 0; x < 5; x++, s++) |
{ |
if ((signed)tempPosX + x - 2 < 0 |
|| (signed)tempPosX + x - 2 >= maxX) { continue; } |
if (starPattern[y][x] == 0) { continue; } /* this is just to speed it up */ |
/* at this point *s is our pixel. Our constant arrays tell us what |
* to do with it. */ |
if (*s < starPattern[y][x]) |
{ |
*s = starPattern[y][x]; |
} |
else if (*s + starIntensity[y][x] > 255) |
{ |
*s = 255; |
} |
else |
{ |
*s += starIntensity[y][x]; |
} |
} |
} |
} |
static void JE_helpScreen( void ) |
{ |
unsigned int i, j; |
//JE_getVGA(); didn't do anything anyway? |
fade_black(15); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->h * VGAScreen2->pitch); |
JE_clr256(VGAScreen); |
for(i = 0; i < 2; i++) |
{ |
JE_outText(VGAScreen, 100, 5 + i * 90, destructHelp[i * 12 + 0], 2, 4); |
JE_outText(VGAScreen, 100, 15 + i * 90, destructHelp[i * 12 + 1], 2, 1); |
for (j = 3; j <= 12; j++) |
{ |
JE_outText(VGAScreen, ((j - 1) % 2) * 160 + 10, 15 + ((j - 1) / 2) * 12 + i * 90, destructHelp[i * 12 + j-1], 1, 3); |
} |
} |
JE_outText(VGAScreen, 30, 190, destructHelp[24], 3, 4); |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
do /* wait until user hits a key */ |
{ |
service_SDL_events(true); |
uSDL_Delay(16); |
} |
while (!newkey); |
fade_black(15); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->h * VGAScreen->pitch); |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
} |
static void JE_pauseScreen( void ) |
{ |
set_volume(tyrMusicVolume / 2, fxVolume); |
/* Save our current screen/game world. We don't want to screw it up while paused. */ |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->h * VGAScreen2->pitch); |
JE_outText(VGAScreen, JE_fontCenter(miscText[22], TINY_FONT), 90, miscText[22], 12, 5); |
JE_showVGA(); |
do /* wait until user hits a key */ |
{ |
service_SDL_events(true); |
uSDL_Delay(16); |
} |
while (!newkey); |
/* Restore current screen & volume*/ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->h * VGAScreen->pitch); |
JE_showVGA(); |
set_volume(tyrMusicVolume, fxVolume); |
} |
/* DE_ResetX |
* |
* The reset functions clear the state of whatefer they are assigned to. |
*/ |
static void DE_ResetUnits( void ) |
{ |
unsigned int p, u; |
for (p = 0; p < MAX_PLAYERS; ++p) |
for (u = 0; u < config.max_installations; ++u) |
destruct_player[p].unit[u].health = 0; |
} |
static void DE_ResetPlayers( void ) |
{ |
unsigned int i; |
for (i = 0; i < MAX_PLAYERS; ++i) |
{ |
destruct_player[i].is_cpu = false; |
destruct_player[i].unitSelected = 0; |
destruct_player[i].shotDelay = 0; |
destruct_player[i].score = 0; |
destruct_player[i].aiMemory.c_Angle = 0; |
destruct_player[i].aiMemory.c_Power = 0; |
destruct_player[i].aiMemory.c_Fire = 0; |
destruct_player[i].aiMemory.c_noDown = 0; |
memcpy(destruct_player[i].keys.Config, defaultKeyConfig[i], sizeof(destruct_player[i].keys.Config)); |
} |
} |
static void DE_ResetWeapons( void ) |
{ |
unsigned int i; |
for (i = 0; i < config.max_shots; i++) |
shotRec[i].isAvailable = true; |
for (i = 0; i < config.max_explosions; i++) |
exploRec[i].isAvailable = true; |
} |
static void DE_ResetLevel( void ) |
{ |
/* Okay, let's prep the arena */ |
DE_ResetWeapons(); |
JE_generateTerrain(); |
DE_ResetAI(); |
} |
static void DE_ResetAI( void ) |
{ |
unsigned int i, j; |
struct destruct_unit_s * ptr; |
for (i = PLAYER_LEFT; i < MAX_PLAYERS; i++) |
{ |
if (destruct_player[i].is_cpu == false) { continue; } |
ptr = destruct_player[i].unit; |
for( j = 0; j < config.max_installations; j++, ptr++) |
{ |
if(DE_isValidUnit(ptr) == false) |
continue; |
if (systemAngle[ptr->unitType] || ptr->unitType == UNIT_HELI) |
ptr->angle = M_PI_4; |
else |
ptr->angle = 0; |
ptr->power = (ptr->unitType == UNIT_LASER) ? 6 : 4; |
if (world.mapFlags & MAP_WALLS) |
ptr->shotType = defaultCpuWeaponB[ptr->unitType]; |
else |
ptr->shotType = defaultCpuWeapon[ptr->unitType]; |
} |
} |
} |
static void DE_ResetActions( void ) |
{ |
unsigned int i; |
for(i = 0; i < MAX_PLAYERS; i++) |
{ /* Zero it all. A memset would do the trick */ |
memset(&(destruct_player[i].moves), 0, sizeof(destruct_player[i].moves)); |
} |
} |
/* DE_RunTick |
* |
* Runs one tick. One tick involves handling physics, drawing crap, |
* moving projectiles and explosions, and getting input. |
* Returns true while the game is running or false if the game is |
* to be terminated. |
*/ |
static enum de_state_t DE_RunTick( void ) |
{ |
static unsigned int endDelay; |
setjasondelay(1); |
memset(soundQueue, 0, sizeof(soundQueue)); |
JE_tempScreenChecking(); |
DE_ResetActions(); |
DE_RunTickCycleDeadUnits(); |
DE_RunTickGravity(); |
DE_RunTickAnimate(); |
DE_RunTickDrawWalls(); |
DE_RunTickExplosions(); |
DE_RunTickShots(); |
DE_RunTickAI(); |
DE_RunTickDrawCrosshairs(); |
DE_RunTickDrawHUD(); |
JE_showVGA(); |
if (destructFirstTime) |
{ |
fade_palette(colors, 25, 0, 255); |
destructFirstTime = false; |
endDelay = 0; |
} |
DE_RunTickGetInput(); |
DE_ProcessInput(); |
if (endDelay > 0) |
{ |
if(--endDelay == 0) |
{ |
return(STATE_RELOAD); |
} |
} |
else if ( DE_RunTickCheckEndgame() == true) |
{ |
endDelay = 80; |
} |
DE_RunTickPlaySounds(); |
/* The rest of this cruft needs to be put in appropriate sections */ |
if (keysactive[SDLK_F10]) |
{ |
destruct_player[PLAYER_LEFT].is_cpu = !destruct_player[PLAYER_LEFT].is_cpu; |
keysactive[SDLK_F10] = false; |
} |
if (keysactive[SDLK_F11]) |
{ |
destruct_player[PLAYER_RIGHT].is_cpu = !destruct_player[PLAYER_RIGHT].is_cpu; |
keysactive[SDLK_F11] = false; |
} |
if (keysactive[SDLK_p]) |
{ |
JE_pauseScreen(); |
keysactive[lastkey_sym] = false; |
} |
if (keysactive[SDLK_F1]) |
{ |
JE_helpScreen(); |
keysactive[lastkey_sym] = false; |
} |
wait_delay(); |
if (keysactive[SDLK_ESCAPE]) |
{ |
keysactive[SDLK_ESCAPE] = false; |
return(STATE_INIT); /* STATE_INIT drops us to the mode select */ |
} |
if (keysactive[SDLK_BACKSPACE]) |
{ |
keysactive[SDLK_BACKSPACE] = false; |
return(STATE_RELOAD); /* STATE_RELOAD creates a new map */ |
} |
return(STATE_CONTINUE); |
} |
/* DE_RunTickX |
* |
* Handles something that we do once per tick, such as |
* track ammo and move asplosions. |
*/ |
static void DE_RunTickCycleDeadUnits( void ) |
{ |
unsigned int i; |
struct destruct_unit_s * unit; |
/* This code automatically switches the active unit if it is destroyed |
* and skips over the useless satellite */ |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
if (destruct_player[i].unitsRemaining == 0) { continue; } |
unit = &(destruct_player[i].unit[destruct_player[i].unitSelected]); |
while(DE_isValidUnit(unit) == false |
|| unit->shotType == SHOT_INVALID) |
{ |
destruct_player[i].unitSelected++; |
unit++; |
if (destruct_player[i].unitSelected >= config.max_installations) |
{ |
destruct_player[i].unitSelected = 0; |
unit = destruct_player[i].unit; |
} |
} |
} |
} |
static void DE_RunTickGravity( void ) |
{ |
unsigned int i, j; |
struct destruct_unit_s * unit; |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
unit = destruct_player[i].unit; |
for (j = 0; j < config.max_installations; j++, unit++) |
{ |
if (DE_isValidUnit(unit) == false) /* invalid unit */ |
continue; |
switch(unit->unitType) |
{ |
case UNIT_SATELLITE: /* satellites don't fall down */ |
break; |
case UNIT_HELI: |
case UNIT_JUMPER: |
if (unit->isYInAir == true) /* unit is falling down, at least in theory */ |
{ |
DE_GravityFlyUnit(unit); |
break; |
} |
/* else treat as a normal unit */ |
/* fall through */ |
default: |
DE_GravityLowerUnit(unit); |
} |
/* Draw the unit. */ |
DE_GravityDrawUnit(i, unit); |
} |
} |
} |
static void DE_GravityDrawUnit( enum de_player_t team, struct destruct_unit_s * unit ) |
{ |
unsigned int anim_index; |
anim_index = GraphicBase[team][unit->unitType] + unit->ani_frame; |
if (unit->unitType == UNIT_HELI) |
{ |
/* Adjust animation index if we are travelling right or left. */ |
if (unit->lastMove < -2) |
anim_index += 5; |
else if (unit->lastMove > 2) |
anim_index += 10; |
} |
else /* This handles our cannons and the like */ |
{ |
anim_index += floorf(unit->angle * 9.99f / M_PI); |
} |
blit_sprite2(VGAScreen, unit->unitX, roundf(unit->unitY) - 13, eShapes[0], anim_index); |
} |
static void DE_GravityLowerUnit( struct destruct_unit_s * unit ) |
{ |
/* units fall at a constant speed. The heli is an odd case though; |
* we simply give it a downward velocity, but due to a buggy implementation |
* the chopper didn't lower until you tried to fly it up. Tyrian 2000 fixes |
* this by not making the chopper a special case. I've decided to actually |
* mix both; the chopper is given a slight downward acceleration (simulating |
* a 'rocky' takeoff), and it is lowered like a regular unit, but not as |
* quickly. |
*/ |
if(unit->unitY < 199) { /* checking takes time, don't check if it's at the bottom */ |
if (JE_stabilityCheck(unit->unitX, roundf(unit->unitY))) |
{ |
switch(unit->unitType) |
{ |
case UNIT_HELI: |
unit->unitYMov = 1.5f; |
unit->unitY += 0.2f; |
break; |
default: |
unit->unitY += 1; |
} |
if (unit->unitY > 199) /* could be possible */ |
unit->unitY = 199; |
} |
} |
} |
static void DE_GravityFlyUnit( struct destruct_unit_s * unit ) |
{ |
if (unit->unitY + unit->unitYMov > 199) /* would hit bottom of screen */ |
{ |
unit->unitY = 199; |
unit->unitYMov = 0; |
unit->isYInAir = false; |
return; |
} |
/* move the unit and alter acceleration */ |
unit->unitY += unit->unitYMov; |
if (unit->unitY < 24) /* This stops units from going above the screen */ |
{ |
unit->unitYMov = 0; |
unit->unitY = 24; |
} |
if (unit->unitType == UNIT_HELI) /* helicopters fall more slowly */ |
unit->unitYMov += 0.0001f; |
else |
unit->unitYMov += 0.03f; |
if (!JE_stabilityCheck(unit->unitX, roundf(unit->unitY))) |
{ |
unit->unitYMov = 0; |
unit->isYInAir = false; |
} |
} |
static void DE_RunTickAnimate( void ) |
{ |
unsigned int p, u; |
struct destruct_unit_s * ptr; |
for (p = 0; p < MAX_PLAYERS; ++p) |
{ |
ptr = destruct_player[p].unit; |
for (u = 0; u < config.max_installations; ++u, ++ptr) |
{ |
/* Don't mess with any unit that is unallocated |
* or doesn't animate and is set to frame 0 */ |
if(DE_isValidUnit(ptr) == false) { continue; } |
if(systemAni[ptr->unitType] == false && ptr->ani_frame == 0) { continue; } |
if (++(ptr->ani_frame) > 3) |
{ |
ptr->ani_frame = 0; |
} |
} |
} |
} |
static void DE_RunTickDrawWalls( void ) |
{ |
unsigned int i; |
for (i = 0; i < config.max_walls; i++) |
{ |
if (world.mapWalls[i].wallExist) |
{ |
blit_sprite2(VGAScreen, world.mapWalls[i].wallX, world.mapWalls[i].wallY, eShapes[0], 42); |
} |
} |
} |
static void DE_RunTickExplosions( void ) |
{ |
unsigned int i, j; |
int tempPosX, tempPosY; |
float tempRadian; |
/* Run through all open explosions. They are not sorted in any way */ |
for (i = 0; i < config.max_explosions; i++) |
{ |
if (exploRec[i].isAvailable == true) { continue; } /* Nothing to do */ |
for (j = 0; j < exploRec[i].explofill; j++) |
{ |
/* An explosion is comprised of multiple 'flares' that fan out. |
Calculate where this 'flare' will end up */ |
tempRadian = mt_rand_lt1() * (2 * M_PI); |
tempPosY = exploRec[i].y + roundf(cosf(tempRadian) * mt_rand_lt1() * exploRec[i].explowidth); |
tempPosX = exploRec[i].x + roundf(sinf(tempRadian) * mt_rand_lt1() * exploRec[i].explowidth); |
/* Our game allows explosions to wrap around. This looks to have |
* originally been a bug that was left in as being fun, but we are |
* going to replicate it w/o risking out of bound arrays. */ |
while(tempPosX < 0) { tempPosX += 320; } |
while(tempPosX > 320) { tempPosX -= 320; } |
/* We don't draw our explosion if it's out of bounds vertically */ |
if (tempPosY >= 200 || tempPosY <= 15) { continue; } |
/* And now the drawing. There are only two types of explosions |
* right now; dirt and flares. Dirt simply draws a brown pixel; |
* flares explode and have a star formation. */ |
switch(exploRec[i].exploType) |
{ |
case EXPL_DIRT: |
((Uint8 *)destructTempScreen->pixels)[tempPosX + tempPosY * destructTempScreen->pitch] = PIXEL_DIRT; |
break; |
case EXPL_NORMAL: |
JE_superPixel(tempPosX, tempPosY); |
DE_TestExplosionCollision(tempPosX, tempPosY); |
break; |
default: |
assert(false); |
break; |
} |
} |
/* Widen the explosion and delete it if necessary. */ |
exploRec[i].explowidth++; |
if (exploRec[i].explowidth == exploRec[i].explomax) |
{ |
exploRec[i].isAvailable = true; |
} |
} |
} |
static void DE_TestExplosionCollision( unsigned int PosX, unsigned int PosY) |
{ |
unsigned int i, j; |
struct destruct_unit_s * unit; |
for (i = PLAYER_LEFT; i < MAX_PLAYERS; i++) |
{ |
unit = destruct_player[i].unit; |
for (j = 0; j < config.max_installations; j++, unit++) |
{ |
if (DE_isValidUnit(unit) == true |
&& PosX > unit->unitX && PosX < unit->unitX + 11 |
&& PosY < unit->unitY && PosY > unit->unitY - 11) |
{ |
unit->health--; |
if (unit->health <= 0) |
{ |
DE_DestroyUnit(i, unit); |
} |
} |
} |
} |
} |
static void DE_DestroyUnit( enum de_player_t playerID, struct destruct_unit_s * unit ) |
{ |
/* This function call was an evil evil piece of brilliance before. Go on. |
* Look at the older revisions. It passed the result of a comparison. |
* MULTIPLIED. This is at least a little clearer... */ |
JE_makeExplosion(unit->unitX + 5, roundf(unit->unitY) - 5, (unit->unitType == UNIT_HELI) ? SHOT_SMALL : SHOT_INVALID); /* Helicopters explode like small shots do. Invalids are their own special case. */ |
if (unit->unitType != UNIT_SATELLITE) /* increment score */ |
{ /* todo: change when teams are created. Hacky kludge for now.*/ |
destruct_player[playerID].unitsRemaining--; |
destruct_player[((playerID == PLAYER_LEFT) ? PLAYER_RIGHT : PLAYER_LEFT)].score++; |
} |
} |
static void DE_RunTickShots( void ) |
{ |
unsigned int i, j, k; |
unsigned int tempTrails; |
unsigned int tempPosX, tempPosY; |
struct destruct_unit_s * unit; |
for (i = 0; i < config.max_shots; i++) |
{ |
if (shotRec[i].isAvailable == true) { continue; } /* Nothing to do */ |
/* Move the shot. Simple displacement */ |
shotRec[i].x += shotRec[i].xmov; |
shotRec[i].y += shotRec[i].ymov; |
/* If the shot can bounce off the map, bounce it */ |
if (shotBounce[shotRec[i].shottype]) |
{ |
if (shotRec[i].y > 199 || shotRec[i].y < 14) |
{ |
shotRec[i].y -= shotRec[i].ymov; |
shotRec[i].ymov = -shotRec[i].ymov; |
} |
if (shotRec[i].x < 1 || shotRec[i].x > 318) |
{ |
shotRec[i].x -= shotRec[i].xmov; |
shotRec[i].xmov = -shotRec[i].xmov; |
} |
} |
else /* If it cannot, apply normal physics */ |
{ |
shotRec[i].ymov += 0.05f; /* add gravity */ |
if (shotRec[i].y > 199) /* We hit the floor */ |
{ |
shotRec[i].y -= shotRec[i].ymov; |
shotRec[i].ymov = -shotRec[i].ymov * 0.8f; /* bounce at reduced velocity */ |
/* Don't allow a bouncing shot to bounce straight up and down */ |
if (shotRec[i].xmov == 0) |
{ |
shotRec[i].xmov += mt_rand_lt1() - 0.5f; |
} |
} |
} |
/* Shot has gone out of bounds. Eliminate it. */ |
if (shotRec[i].x > 318 || shotRec[i].x < 1) |
{ |
shotRec[i].isAvailable = true; |
continue; |
} |
/* Now check for collisions. */ |
/* Don't bother checking for collisions above the map :) */ |
if (shotRec[i].y <= 14) |
continue; |
tempPosX = roundf(shotRec[i].x); |
tempPosY = roundf(shotRec[i].y); |
/*Check building hits*/ |
for(j = 0; j < MAX_PLAYERS; j++) |
{ |
unit = destruct_player[j].unit; |
for(k = 0; k < config.max_installations; k++, unit++) |
{ |
if (DE_isValidUnit(unit) == false) |
continue; |
if (tempPosX > unit->unitX && tempPosX < unit->unitX + 11 |
&& tempPosY < unit->unitY && tempPosY > unit->unitY - 13) |
{ |
shotRec[i].isAvailable = true; |
JE_makeExplosion(tempPosX, tempPosY, shotRec[i].shottype); |
} |
} |
} |
tempTrails = (shotColor[shotRec[i].shottype] << 4) - 3; |
JE_pixCool(tempPosX, tempPosY, tempTrails); |
/*Draw the shot trail (if applicable) */ |
switch (shotTrail[shotRec[i].shottype]) |
{ |
case TRAILS_NONE: |
break; |
case TRAILS_NORMAL: |
DE_DrawTrails( &(shotRec[i]), 2, 4, tempTrails - 3 ); |
break; |
case TRAILS_FULL: |
DE_DrawTrails( &(shotRec[i]), 4, 3, tempTrails - 1 ); |
break; |
} |
/* Bounce off of or destroy walls */ |
for (j = 0; j < config.max_walls; j++) |
{ |
if (world.mapWalls[j].wallExist == true |
&& tempPosX >= world.mapWalls[j].wallX && tempPosX <= world.mapWalls[j].wallX + 11 |
&& tempPosY >= world.mapWalls[j].wallY && tempPosY <= world.mapWalls[j].wallY + 14) |
{ |
if (demolish[shotRec[i].shottype]) |
{ |
/* Blow up the wall and remove the shot. */ |
world.mapWalls[j].wallExist = false; |
shotRec[i].isAvailable = true; |
JE_makeExplosion(tempPosX, tempPosY, shotRec[i].shottype); |
continue; |
} |
else |
{ |
/* Otherwise, bounce. */ |
if (shotRec[i].x - shotRec[i].xmov < world.mapWalls[j].wallX |
|| shotRec[i].x - shotRec[i].xmov > world.mapWalls[j].wallX + 11) |
{ |
shotRec[i].xmov = -shotRec[i].xmov; |
} |
if (shotRec[i].y - shotRec[i].ymov < world.mapWalls[j].wallY |
|| shotRec[i].y - shotRec[i].ymov > world.mapWalls[j].wallY + 14) |
{ |
if (shotRec[i].ymov < 0) |
shotRec[i].ymov = -shotRec[i].ymov; |
else |
shotRec[i].ymov = -shotRec[i].ymov * 0.8f; |
} |
tempPosX = roundf(shotRec[i].x); |
tempPosY = roundf(shotRec[i].y); |
} |
} |
} |
/* Our last collision check, at least for now. We hit dirt. */ |
if((((Uint8 *)destructTempScreen->pixels)[tempPosX + tempPosY * destructTempScreen->pitch]) == PIXEL_DIRT) |
{ |
shotRec[i].isAvailable = true; |
JE_makeExplosion(tempPosX, tempPosY, shotRec[i].shottype); |
continue; |
} |
} |
} |
static void DE_DrawTrails( struct destruct_shot_s * shot, unsigned int count, unsigned int decay, unsigned int startColor ) |
{ |
int i; |
for (i = count-1; i >= 0; i--) /* going in reverse is important as it affects how we draw */ |
{ |
if (shot->trailc[i] > 0 && shot->traily[i] > 12) /* If it exists and if it's not out of bounds, draw it. */ |
{ |
JE_pixCool(shot->trailx[i], shot->traily[i], shot->trailc[i]); |
} |
if (i == 0) /* The first trail we create. */ |
{ |
shot->trailx[i] = roundf(shot->x); |
shot->traily[i] = roundf(shot->y); |
shot->trailc[i] = startColor; |
} |
else /* The newer trails decay into the older trails.*/ |
{ |
shot->trailx[i] = shot->trailx[i-1]; |
shot->traily[i] = shot->traily[i-1]; |
if (shot->trailc[i-1] > 0) |
{ |
shot->trailc[i] = shot->trailc[i-1] - decay; |
} |
} |
} |
} |
static void DE_RunTickAI( void ) |
{ |
unsigned int i, j; |
struct destruct_player_s * ptrPlayer, * ptrTarget; |
struct destruct_unit_s * ptrUnit, * ptrCurUnit; |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
ptrPlayer = &(destruct_player[i]); |
if (ptrPlayer->is_cpu == false) |
{ |
continue; |
} |
/* I've been thinking, purely hypothetically, about what it would take |
* to have multiple computer opponents. The answer? A lot of crap |
* and a 'target' variable in the destruct_player struct. */ |
j = i + 1; |
if (j >= MAX_PLAYERS) |
{ |
j = 0; |
} |
ptrTarget = &(destruct_player[j]); |
ptrCurUnit = &(ptrPlayer->unit[ptrPlayer->unitSelected]); |
/* This is the start of the original AI. Heh. AI. */ |
if (ptrPlayer->aiMemory.c_noDown > 0) |
ptrPlayer->aiMemory.c_noDown--; |
/* Until all structs are properly divvied up this must only apply to player1 */ |
if (mt_rand() % 100 > 80) |
{ |
ptrPlayer->aiMemory.c_Angle += (mt_rand() % 3) - 1; |
if (ptrPlayer->aiMemory.c_Angle > 1) |
ptrPlayer->aiMemory.c_Angle = 1; |
else |
if (ptrPlayer->aiMemory.c_Angle < -1) |
ptrPlayer->aiMemory.c_Angle = -1; |
} |
if (mt_rand() % 100 > 90) |
{ |
if (ptrPlayer->aiMemory.c_Angle > 0 && ptrCurUnit->angle > (M_PI_2) - (M_PI / 9)) |
ptrPlayer->aiMemory.c_Angle = 0; |
else |
if (ptrPlayer->aiMemory.c_Angle < 0 && ptrCurUnit->angle < M_PI / 8) |
ptrPlayer->aiMemory.c_Angle = 0; |
} |
if (mt_rand() % 100 > 93) |
{ |
ptrPlayer->aiMemory.c_Power += (mt_rand() % 3) - 1; |
if (ptrPlayer->aiMemory.c_Power > 1) |
ptrPlayer->aiMemory.c_Power = 1; |
else |
if (ptrPlayer->aiMemory.c_Power < -1) |
ptrPlayer->aiMemory.c_Power = -1; |
} |
if (mt_rand() % 100 > 90) |
{ |
if (ptrPlayer->aiMemory.c_Power > 0 && ptrCurUnit->power > 4) |
ptrPlayer->aiMemory.c_Power = 0; |
else |
if (ptrPlayer->aiMemory.c_Power < 0 && ptrCurUnit->power < 3) |
ptrPlayer->aiMemory.c_Power = 0; |
else |
if (ptrCurUnit->power < 2) |
ptrPlayer->aiMemory.c_Power = 1; |
} |
// prefer helicopter |
ptrUnit = ptrPlayer->unit; |
for (j = 0; j < config.max_installations; j++, ptrUnit++) |
{ |
if (DE_isValidUnit(ptrUnit) && ptrUnit->unitType == UNIT_HELI) |
{ |
ptrPlayer->unitSelected = j; |
break; |
} |
} |
if (ptrCurUnit->unitType == UNIT_HELI) |
{ |
if (ptrCurUnit->isYInAir == false) |
{ |
ptrPlayer->aiMemory.c_Power = 1; |
} |
if (mt_rand() % ptrCurUnit->unitX > 100) |
{ |
ptrPlayer->aiMemory.c_Power = 1; |
} |
if (mt_rand() % 240 > ptrCurUnit->unitX) |
{ |
ptrPlayer->moves.actions[MOVE_RIGHT] = true; |
} |
else if ((mt_rand() % 20) + 300 < ptrCurUnit->unitX) |
{ |
ptrPlayer->moves.actions[MOVE_LEFT] = true; |
} |
else if (mt_rand() % 30 == 1) |
{ |
ptrPlayer->aiMemory.c_Angle = (mt_rand() % 3) - 1; |
} |
if (ptrCurUnit->unitX > 295 && ptrCurUnit->lastMove > 1) |
{ |
ptrPlayer->moves.actions[MOVE_LEFT] = true; |
ptrPlayer->moves.actions[MOVE_RIGHT] = false; |
} |
if (ptrCurUnit->unitType != UNIT_HELI || ptrCurUnit->lastMove > 3 || (ptrCurUnit->unitX > 160 && ptrCurUnit->lastMove > -3)) |
{ |
if (mt_rand() % (int)roundf(ptrCurUnit->unitY) < 150 && ptrCurUnit->unitYMov < 0.01f && (ptrCurUnit->unitX < 160 || ptrCurUnit->lastMove < 2)) |
{ |
ptrPlayer->moves.actions[MOVE_FIRE] = true; |
} |
ptrPlayer->aiMemory.c_noDown = (5 - abs(ptrCurUnit->lastMove)) * (5 - abs(ptrCurUnit->lastMove)) + 3; |
ptrPlayer->aiMemory.c_Power = 1; |
} else { |
ptrPlayer->moves.actions[MOVE_FIRE] = false; |
} |
ptrUnit = ptrTarget->unit; |
for (j = 0; j < config.max_installations; j++, ptrUnit++) |
{ |
if (abs(ptrUnit->unitX - ptrCurUnit->unitX) < 8) |
{ |
/* I get it. This makes helicoptors hover over |
* their enemies. */ |
if (ptrUnit->unitType == UNIT_SATELLITE) |
{ |
ptrPlayer->moves.actions[MOVE_FIRE] = false; |
} |
else |
{ |
ptrPlayer->moves.actions[MOVE_LEFT] = false; |
ptrPlayer->moves.actions[MOVE_RIGHT] = false; |
if (ptrCurUnit->lastMove < -1) |
{ |
ptrCurUnit->lastMove++; |
} |
else if (ptrCurUnit->lastMove > 1) |
{ |
ptrCurUnit->lastMove--; |
} |
} |
} |
} |
} else { |
ptrPlayer->moves.actions[MOVE_FIRE] = 1; |
} |
if (mt_rand() % 200 > 198) |
{ |
ptrPlayer->moves.actions[MOVE_CHANGE] = true; |
ptrPlayer->aiMemory.c_Angle = 0; |
ptrPlayer->aiMemory.c_Power = 0; |
ptrPlayer->aiMemory.c_Fire = 0; |
} |
if (mt_rand() % 100 > 98 || ptrCurUnit->shotType == SHOT_TRACER) |
{ /* Clearly the CPU doesn't like the tracer :) */ |
ptrPlayer->moves.actions[MOVE_CYDN] = true; |
} |
if (ptrPlayer->aiMemory.c_Angle > 0) |
{ |
ptrPlayer->moves.actions[MOVE_LEFT] = true; |
} |
if (ptrPlayer->aiMemory.c_Angle < 0) |
{ |
ptrPlayer->moves.actions[MOVE_RIGHT] = true; |
} |
if (ptrPlayer->aiMemory.c_Power > 0) |
{ |
ptrPlayer->moves.actions[MOVE_UP] = true; |
} |
if (ptrPlayer->aiMemory.c_Power < 0 && ptrPlayer->aiMemory.c_noDown == 0) |
{ |
ptrPlayer->moves.actions[MOVE_DOWN] = true; |
} |
if (ptrPlayer->aiMemory.c_Fire > 0) |
{ |
ptrPlayer->moves.actions[MOVE_FIRE] = true; |
} |
if (ptrCurUnit->unitYMov < -0.1f && ptrCurUnit->unitType == UNIT_HELI) |
{ |
ptrPlayer->moves.actions[MOVE_FIRE] = false; |
} |
/* This last hack was down in the processing section. |
* What exactly it was doing there I do not know */ |
if(ptrCurUnit->unitType == UNIT_LASER || ptrCurUnit->isYInAir == true) { |
ptrPlayer->aiMemory.c_Power = 0; |
} |
} |
} |
static void DE_RunTickDrawCrosshairs( void ) |
{ |
unsigned int i; |
int tempPosX, tempPosY; |
int direction; |
struct destruct_unit_s * curUnit; |
/* Draw the crosshairs. Most vehicles aim left or right. Helis can aim |
* either way and this must be accounted for. |
*/ |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
direction = (i == PLAYER_LEFT) ? -1 : 1; |
curUnit = &(destruct_player[i].unit[destruct_player[i].unitSelected]); |
if (curUnit->unitType == UNIT_HELI) |
{ |
tempPosX = curUnit->unitX + roundf(0.1f * curUnit->lastMove * curUnit->lastMove * curUnit->lastMove) + 5; |
tempPosY = roundf(curUnit->unitY) + 1; |
} else { |
tempPosX = roundf(curUnit->unitX + 6 - cosf(curUnit->angle) * (curUnit->power * 8 + 7) * direction); |
tempPosY = roundf(curUnit->unitY - 7 - sinf(curUnit->angle) * (curUnit->power * 8 + 7)); |
} |
/* Draw it. Clip away from the HUD though. */ |
if(tempPosY > 9) |
{ |
if(tempPosY > 11) |
{ |
if(tempPosY > 13) |
{ |
/* Top pixel */ |
JE_pix(VGAScreen, tempPosX, tempPosY - 2, 3); |
} |
/* Middle three pixels */ |
JE_pix(VGAScreen, tempPosX + 3, tempPosY, 3); |
JE_pix(VGAScreen, tempPosX, tempPosY, 14); |
JE_pix(VGAScreen, tempPosX - 3, tempPosY, 3); |
} |
/* Bottom pixel */ |
JE_pix(VGAScreen, tempPosX, tempPosY + 2, 3); |
} |
} |
} |
static void DE_RunTickDrawHUD( void ) |
{ |
unsigned int i; |
unsigned int startX; |
char tempstr[16]; /* Max size needed: 16 assuming 10 digit int max. */ |
struct destruct_unit_s * curUnit; |
for (i = 0; i < MAX_PLAYERS; i++) |
{ |
curUnit = &(destruct_player[i].unit[destruct_player[i].unitSelected]); |
startX = ((i == PLAYER_LEFT) ? 0 : 320 - 150); |
fill_rectangle_xy(VGAScreen, startX + 5, 3, startX + 14, 8, 241); |
JE_rectangle(VGAScreen, startX + 4, 2, startX + 15, 9, 242); |
JE_rectangle(VGAScreen, startX + 3, 1, startX + 16, 10, 240); |
fill_rectangle_xy(VGAScreen, startX + 18, 3, startX + 140, 8, 241); |
JE_rectangle(VGAScreen, startX + 17, 2, startX + 143, 9, 242); |
JE_rectangle(VGAScreen, startX + 16, 1, startX + 144, 10, 240); |
blit_sprite2(VGAScreen, startX + 4, 0, eShapes[0], 191 + curUnit->shotType); |
JE_outText (VGAScreen, startX + 20, 3, weaponNames[curUnit->shotType], 15, 2); |
sprintf (tempstr, "dmg~%d~", curUnit->health); |
JE_outText (VGAScreen, startX + 75, 3, tempstr, 15, 0); |
sprintf (tempstr, "pts~%d~", destruct_player[i].score); |
JE_outText (VGAScreen, startX + 110, 3, tempstr, 15, 0); |
} |
} |
static void DE_RunTickGetInput( void ) |
{ |
unsigned int player_index, key_index, slot_index; |
SDLKey key; |
/* destruct_player.keys holds our key config. Players will eventually be |
* allowed to can change their key mappings. destruct_player.moves and |
* destruct_player.keys line up; rather than manually checking left and |
* right we can just loop through the indexes and set the actions as |
* needed. */ |
service_SDL_events(true); |
for(player_index = 0; player_index < MAX_PLAYERS; player_index++) |
{ |
for(key_index = 0; key_index < MAX_KEY; key_index++) |
{ |
for(slot_index = 0; slot_index < MAX_KEY_OPTIONS; slot_index++) |
{ |
key = destruct_player[player_index].keys.Config[key_index][slot_index]; |
if(key == SDLK_UNKNOWN) { break; } |
if(keysactive[key] == true) |
{ |
/* The right key was clearly pressed */ |
destruct_player[player_index].moves.actions[key_index] = true; |
/* Some keys we want to toggle afterwards */ |
if(key_index == KEY_CHANGE || |
key_index == KEY_CYUP || |
key_index == KEY_CYDN) |
{ |
keysactive[key] = false; |
} |
break; |
} |
} |
} |
} |
} |
static void DE_ProcessInput( void ) |
{ |
int direction; |
unsigned int player_index; |
struct destruct_unit_s * curUnit; |
for (player_index = 0; player_index < MAX_PLAYERS; player_index++) |
{ |
if (destruct_player[player_index].unitsRemaining <= 0) { continue; } |
direction = (player_index == PLAYER_LEFT) ? -1 : 1; |
curUnit = &(destruct_player[player_index].unit[destruct_player[player_index].unitSelected]); |
if (systemAngle[curUnit->unitType] == true) /* selected unit may change shot angle */ |
{ |
if (destruct_player[player_index].moves.actions[MOVE_LEFT] == true) |
{ |
(player_index == PLAYER_LEFT) ? DE_RaiseAngle(curUnit) : DE_LowerAngle(curUnit); |
} |
if (destruct_player[player_index].moves.actions[MOVE_RIGHT] == true) |
{ |
(player_index == PLAYER_LEFT) ? DE_LowerAngle(curUnit) : DE_RaiseAngle(curUnit); |
} |
} else if (curUnit->unitType == UNIT_HELI) { |
if (destruct_player[player_index].moves.actions[MOVE_LEFT] == true && curUnit->unitX > 5) |
if (JE_stabilityCheck(curUnit->unitX - 5, roundf(curUnit->unitY))) |
{ |
if (curUnit->lastMove > -5) |
{ |
curUnit->lastMove--; |
} |
curUnit->unitX--; |
if (JE_stabilityCheck(curUnit->unitX, roundf(curUnit->unitY))) |
{ |
curUnit->isYInAir = true; |
} |
} |
if (destruct_player[player_index].moves.actions[MOVE_RIGHT] == true && curUnit->unitX < 305) |
{ |
if (JE_stabilityCheck(curUnit->unitX + 5, roundf(curUnit->unitY))) |
{ |
if (curUnit->lastMove < 5) |
{ |
curUnit->lastMove++; |
} |
curUnit->unitX++; |
if (JE_stabilityCheck(curUnit->unitX, roundf(curUnit->unitY))) |
{ |
curUnit->isYInAir = true; |
} |
} |
} |
} |
if (curUnit->unitType != UNIT_LASER) |
{ /*increasepower*/ |
if (destruct_player[player_index].moves.actions[MOVE_UP] == true) |
{ |
if (curUnit->unitType == UNIT_HELI) |
{ |
curUnit->isYInAir = true; |
curUnit->unitYMov -= 0.1f; |
} |
else if (curUnit->unitType == UNIT_JUMPER |
&& curUnit->isYInAir == false) { |
curUnit->unitYMov = -3; |
curUnit->isYInAir = true; |
} |
else { |
DE_RaisePower(curUnit); |
} |
} |
/*decreasepower*/ |
if (destruct_player[player_index].moves.actions[MOVE_DOWN] == true) |
{ |
if (curUnit->unitType == UNIT_HELI && curUnit->isYInAir == true) |
{ |
curUnit->unitYMov += 0.1f; |
} else { |
DE_LowerPower(curUnit); |
} |
} |
} |
/*up/down weapon. These just cycle until a valid weapon is found */ |
if (destruct_player[player_index].moves.actions[MOVE_CYUP] == true) |
{ |
DE_CycleWeaponUp(curUnit); |
} |
if (destruct_player[player_index].moves.actions[MOVE_CYDN] == true) |
{ |
DE_CycleWeaponDown(curUnit); |
} |
/* Change. Since change would change out curUnit pointer, let's just do it last. |
* Validity checking is performed at the beginning of the tick. */ |
if (destruct_player[player_index].moves.actions[MOVE_CHANGE] == true) |
{ |
destruct_player[player_index].unitSelected++; |
if (destruct_player[player_index].unitSelected >= config.max_installations) |
{ |
destruct_player[player_index].unitSelected = 0; |
} |
} |
/*Newshot*/ |
if (destruct_player[player_index].shotDelay > 0) |
{ |
destruct_player[player_index].shotDelay--; |
} |
if (destruct_player[player_index].moves.actions[MOVE_FIRE] == true |
&& (destruct_player[player_index].shotDelay == 0)) |
{ |
destruct_player[player_index].shotDelay = shotDelay[curUnit->shotType]; |
switch(shotDirt[curUnit->shotType]) |
{ |
case EXPL_NONE: |
break; |
case EXPL_MAGNET: |
DE_RunMagnet(player_index, curUnit); |
break; |
case EXPL_DIRT: |
case EXPL_NORMAL: |
DE_MakeShot(player_index, curUnit, direction); |
break; |
default: |
assert(false); |
} |
} |
} |
} |
static void DE_CycleWeaponUp( struct destruct_unit_s * unit ) |
{ |
do |
{ |
unit->shotType++; |
if (unit->shotType > SHOT_LAST) |
{ |
unit->shotType = SHOT_FIRST; |
} |
} while (weaponSystems[unit->unitType][unit->shotType] == 0); |
} |
static void DE_CycleWeaponDown( struct destruct_unit_s * unit ) |
{ |
do |
{ |
unit->shotType--; |
if (unit->shotType < SHOT_FIRST) |
{ |
unit->shotType = SHOT_LAST; |
} |
} while (weaponSystems[unit->unitType][unit->shotType] == 0); |
} |
static void DE_MakeShot( enum de_player_t curPlayer, const struct destruct_unit_s * curUnit, int direction ) |
{ |
unsigned int i; |
unsigned int shotIndex; |
/* First, find an empty shot struct we can use */ |
for (i = 0; ; i++) |
{ |
if (i >= config.max_shots) { return; } /* no empty slots. Do nothing. */ |
if (shotRec[i].isAvailable) |
{ |
shotIndex = i; |
break; |
} |
} |
if (curUnit->unitType == UNIT_HELI && curUnit->isYInAir == false) |
{ /* Helis can't fire when they are on the ground. */ |
return; |
} |
/* Play the firing sound */ |
soundQueue[curPlayer] = shotSound[curUnit->shotType]; |
/* Create our shot. Some units have differing logic here */ |
switch (curUnit->unitType) |
{ |
case UNIT_HELI: |
shotRec[shotIndex].x = curUnit->unitX + curUnit->lastMove * 2 + 5; |
shotRec[shotIndex].xmov = 0.02f * curUnit->lastMove * curUnit->lastMove * curUnit->lastMove; |
/* If we are trying in vain to move up off the screen, act differently.*/ |
if (destruct_player[curPlayer].moves.actions[MOVE_UP] && curUnit->unitY < 30) |
{ |
shotRec[shotIndex].y = curUnit->unitY; |
shotRec[shotIndex].ymov = 0.1f; |
if (shotRec[shotIndex].xmov < 0) |
{ |
shotRec[shotIndex].xmov += 0.1f; |
} |
else if (shotRec[shotIndex].xmov > 0) |
{ |
shotRec[shotIndex].xmov -= 0.1f; |
} |
} |
else |
{ |
shotRec[shotIndex].y = curUnit->unitY + 1; |
shotRec[shotIndex].ymov = 0.5f + curUnit->unitYMov * 0.1f; |
} |
break; |
case UNIT_JUMPER: /* Jumpers are normally only special for the left hand player. Bug? Or feature? */ |
if(config.jumper_straight[curPlayer]) |
{ |
/* This is identical to the default case. |
* I considered letting the switch fall through |
* but that's more confusing to people who aren't used |
* to that quirk of switch. */ |
shotRec[shotIndex].x = curUnit->unitX + 6 - cosf(curUnit->angle) * 10 * direction; |
shotRec[shotIndex].y = curUnit->unitY - 7 - sinf(curUnit->angle) * 10; |
shotRec[shotIndex].xmov = -cosf(curUnit->angle) * curUnit->power * direction; |
shotRec[shotIndex].ymov = -sinf(curUnit->angle) * curUnit->power; |
} |
else |
{ |
/* This is not identical to the default case. */ |
shotRec[shotIndex].x = curUnit->unitX + 2; |
shotRec[shotIndex].xmov = -cosf(curUnit->angle) * curUnit->power * direction; |
if (curUnit->isYInAir == true) |
{ |
shotRec[shotIndex].ymov = 1; |
shotRec[shotIndex].y = curUnit->unitY + 2; |
} else { |
shotRec[shotIndex].ymov = -2; |
shotRec[shotIndex].y = curUnit->unitY - 12; |
} |
} |
break; |
default: |
shotRec[shotIndex].x = curUnit->unitX + 6 - cosf(curUnit->angle) * 10 * direction; |
shotRec[shotIndex].y = curUnit->unitY - 7 - sinf(curUnit->angle) * 10; |
shotRec[shotIndex].xmov = -cosf(curUnit->angle) * curUnit->power * direction; |
shotRec[shotIndex].ymov = -sinf(curUnit->angle) * curUnit->power; |
break; |
} |
/* Now set/clear out a few last details. */ |
shotRec[shotIndex].isAvailable = false; |
shotRec[shotIndex].shottype = curUnit->shotType; |
//shotRec[shotIndex].shotdur = shotFuse[shotRec[shotIndex].shottype]; |
shotRec[shotIndex].trailc[0] = 0; |
shotRec[shotIndex].trailc[1] = 0; |
shotRec[shotIndex].trailc[2] = 0; |
shotRec[shotIndex].trailc[3] = 0; |
} |
static void DE_RunMagnet( enum de_player_t curPlayer, struct destruct_unit_s * magnet ) |
{ |
unsigned int i; |
enum de_player_t curEnemy; |
int direction; |
struct destruct_unit_s * enemyUnit; |
curEnemy = (curPlayer == PLAYER_LEFT) ? PLAYER_RIGHT : PLAYER_LEFT; |
direction = (curPlayer == PLAYER_LEFT) ? -1 : 1; |
/* Push all shots that are in front of the magnet */ |
for (i = 0; i < config.max_shots; i++) |
{ |
if (shotRec[i].isAvailable == false) |
{ |
if ((curPlayer == PLAYER_LEFT && shotRec[i].x > magnet->unitX) |
|| (curPlayer == PLAYER_RIGHT && shotRec[i].x < magnet->unitX)) |
{ |
shotRec[i].xmov += magnet->power * 0.1f * -direction; |
} |
} |
} |
enemyUnit = destruct_player[curEnemy].unit; |
for (i = 0; i < config.max_installations; i++, enemyUnit++) /* magnets push coptors */ |
{ |
if (DE_isValidUnit(enemyUnit) |
&& enemyUnit->unitType == UNIT_HELI |
&& enemyUnit->isYInAir == true) |
{ |
if ((curEnemy == PLAYER_RIGHT && destruct_player[curEnemy].unit[i].unitX + 11 < 318) |
|| (curEnemy == PLAYER_LEFT && destruct_player[curEnemy].unit[i].unitX > 1)) |
{ |
enemyUnit->unitX -= 2 * direction; |
} |
} |
} |
magnet->ani_frame = 1; |
} |
static void DE_RaiseAngle( struct destruct_unit_s * unit ) |
{ |
unit->angle += 0.01f; |
if (unit->angle > M_PI_2 - 0.01f) |
{ |
unit->angle = M_PI_2 - 0.01f; |
} |
} |
static void DE_LowerAngle( struct destruct_unit_s * unit ) |
{ |
unit->angle -= 0.01f; |
if (unit->angle < 0) |
{ |
unit->angle = 0; |
} |
} |
static void DE_RaisePower( struct destruct_unit_s * unit ) |
{ |
unit->power += 0.05f; |
if (unit->power > 5) |
{ |
unit->power = 5; |
} |
} |
static void DE_LowerPower( struct destruct_unit_s * unit ) |
{ |
unit->power -= 0.05f; |
if (unit->power < 1) |
{ |
unit->power = 1; |
} |
} |
/* DE_isValidUnit |
* |
* Returns true if the unit's health is above 0 and false |
* otherwise. This mainly exists because the 'health' var |
* serves two roles and that can get confusing. |
*/ |
static inline bool DE_isValidUnit( struct destruct_unit_s * unit ) |
{ |
return(unit->health > 0); |
} |
static bool DE_RunTickCheckEndgame( void ) |
{ |
if (destruct_player[PLAYER_LEFT].unitsRemaining == 0) |
{ |
destruct_player[PLAYER_RIGHT].score += ModeScore[PLAYER_LEFT][world.destructMode]; |
soundQueue[7] = V_CLEARED_PLATFORM; |
return(true); |
} |
if (destruct_player[PLAYER_RIGHT].unitsRemaining == 0) |
{ |
destruct_player[PLAYER_LEFT].score += ModeScore[PLAYER_RIGHT][world.destructMode]; |
soundQueue[7] = V_CLEARED_PLATFORM; |
return(true); |
} |
return(false); |
} |
static void DE_RunTickPlaySounds( void ) |
{ |
unsigned int i, tempSampleIndex, tempVolume; |
for (i = 0; i < COUNTOF(soundQueue); i++) |
{ |
if (soundQueue[i] != S_NONE) |
{ |
tempSampleIndex = soundQueue[i]; |
if (i == 7) |
{ |
tempVolume = fxPlayVol; |
} |
else |
{ |
tempVolume = fxPlayVol / 2; |
} |
JE_multiSamplePlay(digiFx[tempSampleIndex-1], fxSize[tempSampleIndex-1], i, tempVolume); |
soundQueue[i] = S_NONE; |
} |
} |
} |
static void JE_pixCool( unsigned int x, unsigned int y, Uint8 c ) |
{ |
JE_pix(VGAScreen, x, y, c); |
JE_pix(VGAScreen, x - 1, y, c - 2); |
JE_pix(VGAScreen, x + 1, y, c - 2); |
JE_pix(VGAScreen, x, y - 1, c - 2); |
JE_pix(VGAScreen, x, y + 1, c - 2); |
} |
/contrib/games/opentyrian/src/destruct.h |
---|
0,0 → 1,27 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef DESTRUCT_H |
#define DESTRUCT_H |
#include "opentyr.h" |
void JE_destructGame( void ); |
#endif /* DESTRUCT_H */ |
/contrib/games/opentyrian/src/editship.c |
---|
0,0 → 1,92 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "editship.h" |
#include "config.h" |
#include "file.h" |
#include "opentyr.h" |
#define SAS (sizeof(JE_ShipsType) - 4) |
const JE_byte extraCryptKey[10] = { 58, 23, 16, 192, 254, 82, 113, 147, 62, 99 }; |
JE_boolean extraAvail; |
JE_ShipsType extraShips; |
void *extraShapes; |
JE_word extraShapeSize; |
void JE_decryptShips( void ) |
{ |
JE_boolean correct = true; |
JE_ShipsType s2; |
JE_byte y; |
for (int x = SAS - 1; x >= 0; x--) |
{ |
s2[x] = extraShips[x] ^ extraCryptKey[(x + 1) % 10]; |
if (x > 0) |
s2[x] ^= extraShips[x - 1]; |
} /* <= Key Decryption Test (Reversed key) */ |
y = 0; |
for (uint x = 0; x < SAS; x++) |
y += s2[x]; |
if (extraShips[SAS + 0] != y) |
correct = false; |
y = 0; |
for (uint x = 0; x < SAS; x++) |
y -= s2[x]; |
if (extraShips[SAS + 1] != y) |
correct = false; |
y = 1; |
for (uint x = 0; x < SAS; x++) |
y = y * s2[x] + 1; |
if (extraShips[SAS + 2] != y) |
correct = false; |
y = 0; |
for (uint x = 0; x < SAS; x++) |
y ^= s2[x]; |
if (extraShips[SAS + 3] != y) |
correct = false; |
if (!correct) |
exit(255); |
memcpy(extraShips, s2, sizeof(extraShips)); |
} |
void JE_loadExtraShapes( void ) |
{ |
FILE *f = dir_fopen(get_user_directory(), "newsh$.shp", "rb"); |
if (f) |
{ |
extraAvail = true; |
extraShapeSize = ftell_eof(f) - sizeof(extraShips); |
extraShapes = malloc(extraShapeSize); |
efread(extraShapes, extraShapeSize, 1, f); |
efread(extraShips, sizeof(extraShips), 1, f); |
JE_decryptShips(); |
fclose(f); |
} |
} |
/contrib/games/opentyrian/src/editship.h |
---|
0,0 → 1,36 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef EDITSHIP_H |
#define EDITSHIP_H |
#include "opentyr.h" |
typedef JE_byte JE_ShipsType[154]; /* [1..154] */ |
extern JE_boolean extraAvail; |
extern JE_ShipsType extraShips; |
extern void *extraShapes; |
extern JE_word extraShapeSize; |
void JE_decryptShips( void ); |
void JE_loadExtraShapes( void ); |
#endif /* EDITSHIP_H */ |
/contrib/games/opentyrian/src/episodes.c |
---|
0,0 → 1,267 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "episodes.h" |
#include "config.h" |
#include "file.h" |
#include "lvllib.h" |
#include "lvlmast.h" |
#include "opentyr.h" |
/* MAIN Weapons Data */ |
JE_WeaponPortType weaponPort; |
JE_WeaponType weapons[WEAP_NUM + 1]; /* [0..weapnum] */ |
/* Items */ |
JE_PowerType powerSys; |
JE_ShipType ships; |
JE_OptionType options[OPTION_NUM + 1]; /* [0..optionnum] */ |
JE_ShieldType shields; |
JE_SpecialType special; |
/* Enemy data */ |
JE_EnemyDatType enemyDat; |
/* EPISODE variables */ |
JE_byte initial_episode_num, episodeNum = 0; |
JE_boolean episodeAvail[EPISODE_MAX]; /* [1..episodemax] */ |
char episode_file[13], cube_file[13]; |
JE_longint episode1DataLoc; |
/* Tells the game whether the level currently loaded is a bonus level. */ |
JE_boolean bonusLevel; |
/* Tells if the game jumped back to Episode 1 */ |
JE_boolean jumpBackToEpisode1; |
void JE_loadItemDat( void ) |
{ |
FILE *f = NULL; |
if (episodeNum <= 3) |
{ |
f = dir_fopen_die(data_dir(), "tyrian.hdt", "rb"); |
efread(&episode1DataLoc, sizeof(JE_longint), 1, f); |
fseek(f, episode1DataLoc, SEEK_SET); |
} |
else |
{ |
// episode 4 stores item data in the level file |
f = dir_fopen_die(data_dir(), levelFile, "rb"); |
fseek(f, lvlPos[lvlNum-1], SEEK_SET); |
} |
JE_word itemNum[7]; /* [1..7] */ |
efread(&itemNum, sizeof(JE_word), 7, f); |
for (int i = 0; i < WEAP_NUM + 1; ++i) |
{ |
efread(&weapons[i].drain, sizeof(JE_word), 1, f); |
efread(&weapons[i].shotrepeat, sizeof(JE_byte), 1, f); |
efread(&weapons[i].multi, sizeof(JE_byte), 1, f); |
efread(&weapons[i].weapani, sizeof(JE_word), 1, f); |
efread(&weapons[i].max, sizeof(JE_byte), 1, f); |
efread(&weapons[i].tx, sizeof(JE_byte), 1, f); |
efread(&weapons[i].ty, sizeof(JE_byte), 1, f); |
efread(&weapons[i].aim, sizeof(JE_byte), 1, f); |
efread(&weapons[i].attack, sizeof(JE_byte), 8, f); |
efread(&weapons[i].del, sizeof(JE_byte), 8, f); |
efread(&weapons[i].sx, sizeof(JE_shortint), 8, f); |
efread(&weapons[i].sy, sizeof(JE_shortint), 8, f); |
efread(&weapons[i].bx, sizeof(JE_shortint), 8, f); |
efread(&weapons[i].by, sizeof(JE_shortint), 8, f); |
efread(&weapons[i].sg, sizeof(JE_word), 8, f); |
efread(&weapons[i].acceleration, sizeof(JE_shortint), 1, f); |
efread(&weapons[i].accelerationx, sizeof(JE_shortint), 1, f); |
efread(&weapons[i].circlesize, sizeof(JE_byte), 1, f); |
efread(&weapons[i].sound, sizeof(JE_byte), 1, f); |
efread(&weapons[i].trail, sizeof(JE_byte), 1, f); |
efread(&weapons[i].shipblastfilter, sizeof(JE_byte), 1, f); |
} |
for (int i = 0; i < PORT_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&weaponPort[i].name, 1, 30, f); |
weaponPort[i].name[30] = '\0'; |
efread(&weaponPort[i].opnum, sizeof(JE_byte), 1, f); |
for (int j = 0; j < 2; ++j) |
{ |
efread(&weaponPort[i].op[j], sizeof(JE_word), 11, f); |
} |
efread(&weaponPort[i].cost, sizeof(JE_word), 1, f); |
efread(&weaponPort[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&weaponPort[i].poweruse, sizeof(JE_word), 1, f); |
} |
for (int i = 0; i < SPECIAL_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&special[i].name, 1, 30, f); |
special[i].name[30] = '\0'; |
efread(&special[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&special[i].pwr, sizeof(JE_byte), 1, f); |
efread(&special[i].stype, sizeof(JE_byte), 1, f); |
efread(&special[i].wpn, sizeof(JE_word), 1, f); |
} |
for (int i = 0; i < POWER_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&powerSys[i].name, 1, 30, f); |
powerSys[i].name[30] = '\0'; |
efread(&powerSys[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&powerSys[i].power, sizeof(JE_shortint), 1, f); |
efread(&powerSys[i].speed, sizeof(JE_byte), 1, f); |
efread(&powerSys[i].cost, sizeof(JE_word), 1, f); |
} |
for (int i = 0; i < SHIP_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&ships[i].name, 1, 30, f); |
ships[i].name[30] = '\0'; |
efread(&ships[i].shipgraphic, sizeof(JE_word), 1, f); |
efread(&ships[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&ships[i].ani, sizeof(JE_byte), 1, f); |
efread(&ships[i].spd, sizeof(JE_shortint), 1, f); |
efread(&ships[i].dmg, sizeof(JE_byte), 1, f); |
efread(&ships[i].cost, sizeof(JE_word), 1, f); |
efread(&ships[i].bigshipgraphic, sizeof(JE_byte), 1, f); |
} |
for (int i = 0; i < OPTION_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&options[i].name, 1, 30, f); |
options[i].name[30] = '\0'; |
efread(&options[i].pwr, sizeof(JE_byte), 1, f); |
efread(&options[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&options[i].cost, sizeof(JE_word), 1, f); |
efread(&options[i].tr, sizeof(JE_byte), 1, f); |
efread(&options[i].option, sizeof(JE_byte), 1, f); |
efread(&options[i].opspd, sizeof(JE_shortint), 1, f); |
efread(&options[i].ani, sizeof(JE_byte), 1, f); |
efread(&options[i].gr, sizeof(JE_word), 20, f); |
efread(&options[i].wport, sizeof(JE_byte), 1, f); |
efread(&options[i].wpnum, sizeof(JE_word), 1, f); |
efread(&options[i].ammo, sizeof(JE_byte), 1, f); |
efread(&options[i].stop, 1, 1, f); /* override sizeof(JE_boolean) */ |
efread(&options[i].icongr, sizeof(JE_byte), 1, f); |
} |
for (int i = 0; i < SHIELD_NUM + 1; ++i) |
{ |
fseek(f, 1, SEEK_CUR); /* skip string length */ |
efread(&shields[i].name, 1, 30, f); |
shields[i].name[30] = '\0'; |
efread(&shields[i].tpwr, sizeof(JE_byte), 1, f); |
efread(&shields[i].mpwr, sizeof(JE_byte), 1, f); |
efread(&shields[i].itemgraphic, sizeof(JE_word), 1, f); |
efread(&shields[i].cost, sizeof(JE_word), 1, f); |
} |
for (int i = 0; i < ENEMY_NUM + 1; ++i) |
{ |
efread(&enemyDat[i].ani, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].tur, sizeof(JE_byte), 3, f); |
efread(&enemyDat[i].freq, sizeof(JE_byte), 3, f); |
efread(&enemyDat[i].xmove, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].ymove, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].xaccel, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].yaccel, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].xcaccel, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].ycaccel, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].startx, sizeof(JE_integer), 1, f); |
efread(&enemyDat[i].starty, sizeof(JE_integer), 1, f); |
efread(&enemyDat[i].startxc, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].startyc, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].armor, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].esize, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].egraphic, sizeof(JE_word), 20, f); |
efread(&enemyDat[i].explosiontype, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].animate, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].shapebank, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].xrev, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].yrev, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].dgr, sizeof(JE_word), 1, f); |
efread(&enemyDat[i].dlevel, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].dani, sizeof(JE_shortint), 1, f); |
efread(&enemyDat[i].elaunchfreq, sizeof(JE_byte), 1, f); |
efread(&enemyDat[i].elaunchtype, sizeof(JE_word), 1, f); |
efread(&enemyDat[i].value, sizeof(JE_integer), 1, f); |
efread(&enemyDat[i].eenemydie, sizeof(JE_word), 1, f); |
} |
fclose(f); |
} |
void JE_initEpisode( JE_byte newEpisode ) |
{ |
if (newEpisode == episodeNum) |
return; |
episodeNum = newEpisode; |
sprintf(levelFile, "tyrian%d.lvl", episodeNum); |
sprintf(cube_file, "cubetxt%d.dat", episodeNum); |
sprintf(episode_file, "levels%d.dat", episodeNum); |
JE_analyzeLevel(); |
JE_loadItemDat(); |
} |
void JE_scanForEpisodes( void ) |
{ |
for (int i = 0; i < EPISODE_MAX; ++i) |
{ |
char ep_file[20]; |
snprintf(ep_file, sizeof(ep_file), "tyrian%d.lvl", i + 1); |
episodeAvail[i] = dir_file_exists(data_dir(), ep_file); |
} |
} |
unsigned int JE_findNextEpisode( void ) |
{ |
unsigned int newEpisode = episodeNum; |
jumpBackToEpisode1 = false; |
while (true) |
{ |
newEpisode++; |
if (newEpisode > EPISODE_MAX) |
{ |
newEpisode = 1; |
jumpBackToEpisode1 = true; |
gameHasRepeated = true; |
} |
if (episodeAvail[newEpisode-1] || newEpisode == episodeNum) |
{ |
break; |
} |
} |
return newEpisode; |
} |
/contrib/games/opentyrian/src/episodes.h |
---|
0,0 → 1,173 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef EPISODES_H |
#define EPISODES_H |
#include "opentyr.h" |
#include "lvlmast.h" |
/* Episodes and general data */ |
#define FIRST_LEVEL 1 |
#define EPISODE_MAX 5 |
#define EPISODE_AVAILABLE 4 |
typedef struct |
{ |
JE_word drain; |
JE_byte shotrepeat; |
JE_byte multi; |
JE_word weapani; |
JE_byte max; |
JE_byte tx, ty, aim; |
JE_byte attack[8], del[8]; /* [1..8] */ |
JE_shortint sx[8], sy[8]; /* [1..8] */ |
JE_shortint bx[8], by[8]; /* [1..8] */ |
JE_word sg[8]; /* [1..8] */ |
JE_shortint acceleration, accelerationx; |
JE_byte circlesize; |
JE_byte sound; |
JE_byte trail; |
JE_byte shipblastfilter; |
} JE_WeaponType; |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_byte opnum; |
JE_word op[2][11]; /* [1..2, 1..11] */ |
JE_word cost; |
JE_word itemgraphic; |
JE_word poweruse; |
} JE_WeaponPortType[PORT_NUM + 1]; /* [0..portnum] */ |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_word itemgraphic; |
JE_byte power; |
JE_shortint speed; |
JE_word cost; |
} JE_PowerType[POWER_NUM + 1]; /* [0..powernum] */ |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_word itemgraphic; |
JE_byte pwr; |
JE_byte stype; |
JE_word wpn; |
} JE_SpecialType[SPECIAL_NUM + 1]; /* [0..specialnum] */ |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_byte pwr; |
JE_word itemgraphic; |
JE_word cost; |
JE_byte tr, option; |
JE_shortint opspd; |
JE_byte ani; |
JE_word gr[20]; /* [1..20] */ |
JE_byte wport; |
JE_word wpnum; |
JE_byte ammo; |
JE_boolean stop; |
JE_byte icongr; |
} JE_OptionType; |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_byte tpwr; |
JE_byte mpwr; |
JE_word itemgraphic; |
JE_word cost; |
} JE_ShieldType[SHIELD_NUM + 1]; /* [0..shieldnum] */ |
typedef struct |
{ |
char name[31]; /* string [30] */ |
JE_word shipgraphic; |
JE_word itemgraphic; |
JE_byte ani; |
JE_shortint spd; |
JE_byte dmg; |
JE_word cost; |
JE_byte bigshipgraphic; |
} JE_ShipType[SHIP_NUM + 1]; /* [0..shipnum] */ |
/* EnemyData */ |
typedef struct |
{ |
JE_byte ani; |
JE_byte tur[3]; /* [1..3] */ |
JE_byte freq[3]; /* [1..3] */ |
JE_shortint xmove; |
JE_shortint ymove; |
JE_shortint xaccel; |
JE_shortint yaccel; |
JE_shortint xcaccel; |
JE_shortint ycaccel; |
JE_integer startx; |
JE_integer starty; |
JE_shortint startxc; |
JE_shortint startyc; |
JE_byte armor; |
JE_byte esize; |
JE_word egraphic[20]; /* [1..20] */ |
JE_byte explosiontype; |
JE_byte animate; /* 0:Not Yet 1:Always 2:When Firing Only */ |
JE_byte shapebank; /* See LEVELMAK.DOC */ |
JE_shortint xrev, yrev; |
JE_word dgr; |
JE_shortint dlevel; |
JE_shortint dani; |
JE_byte elaunchfreq; |
JE_word elaunchtype; |
JE_integer value; |
JE_word eenemydie; |
} JE_EnemyDatType[ENEMY_NUM + 1]; /* [0..enemynum] */ |
extern JE_WeaponPortType weaponPort; |
extern JE_WeaponType weapons[WEAP_NUM + 1]; /* [0..weapnum] */ |
extern JE_PowerType powerSys; |
extern JE_ShipType ships; |
extern JE_OptionType options[OPTION_NUM + 1]; /* [0..optionnum] */ |
extern JE_ShieldType shields; |
extern JE_SpecialType special; |
extern JE_EnemyDatType enemyDat; |
extern JE_byte initial_episode_num, episodeNum; |
extern JE_boolean episodeAvail[EPISODE_MAX]; |
extern char episode_file[13], cube_file[13]; |
extern JE_longint episode1DataLoc; |
extern JE_boolean bonusLevel; |
extern JE_boolean jumpBackToEpisode1; |
void JE_loadItemDat( void ); |
void JE_initEpisode( JE_byte newEpisode ); |
unsigned int JE_findNextEpisode( void ); |
void JE_scanForEpisodes( void ); |
#endif /* EPISODES_H */ |
/contrib/games/opentyrian/src/file.c |
---|
0,0 → 1,208 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "file.h" |
#include "opentyr.h" |
#include "varz.h" |
#include "SDL.h" |
#include <errno.h> |
#include <stdio.h> |
#include <string.h> |
const char *custom_data_dir = NULL; |
// finds the Tyrian data directory |
const char *data_dir( void ) |
{ |
const char *dirs[] = |
{ |
custom_data_dir, |
TYRIAN_DIR, |
"data", |
".", |
}; |
static const char *dir = NULL; |
if (dir != NULL) |
return dir; |
for (uint i = 0; i < COUNTOF(dirs); ++i) |
{ |
if (dirs[i] == NULL) |
continue; |
FILE *f = dir_fopen(dirs[i], "tyrian1.lvl", "rb"); |
if (f) |
{ |
fclose(f); |
dir = dirs[i]; |
break; |
} |
} |
if (dir == NULL) // data not found |
dir = ""; |
return dir; |
} |
// prepend directory and fopen |
FILE *dir_fopen( const char *dir, const char *file, const char *mode ) |
{ |
char *path = malloc(strlen(dir) + 1 + strlen(file) + 1); |
sprintf(path, "%s/%s", dir, file); |
FILE *f = fopen(path, mode); |
fprintf(stderr, "%s\n", path); |
free(path); |
return f; |
} |
// warn when dir_fopen fails |
FILE *dir_fopen_warn( const char *dir, const char *file, const char *mode ) |
{ |
FILE *f = dir_fopen(dir, file, mode); |
if (f == NULL) |
fprintf(stderr, "warning: failed to open '%s': %s\n", file, strerror(errno)); |
return f; |
} |
// die when dir_fopen fails |
FILE *dir_fopen_die( const char *dir, const char *file, const char *mode ) |
{ |
FILE *f = dir_fopen(dir, file, mode); |
if (f == NULL) |
{ |
fprintf(stderr, "error: failed to open '%s': %s\n", file, strerror(errno)); |
fprintf(stderr, "error: One or more of the required Tyrian " TYRIAN_VERSION " data files could not be found.\n" |
" Please read the README file.\n"); |
JE_tyrianHalt(1); |
} |
return f; |
} |
// check if file can be opened for reading |
bool dir_file_exists( const char *dir, const char *file ) |
{ |
FILE *f = dir_fopen(dir, file, "rb"); |
if (f != NULL) |
fclose(f); |
return (f != NULL); |
} |
// returns end-of-file position |
long ftell_eof( FILE *f ) |
{ |
long pos = ftell(f); |
fseek(f, 0, SEEK_END); |
long size = ftell(f); |
fseek(f, pos, SEEK_SET); |
return size; |
} |
// endian-swapping fread that dies if the expected amount cannot be read |
size_t efread( void *buffer, size_t size, size_t num, FILE *stream ) |
{ |
size_t num_read = fread(buffer, size, num, stream); |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
switch (size) |
{ |
case 2: |
for (size_t i = 0; i < num; i++) |
((Uint16 *)buffer)[i] = SDL_Swap16(((Uint16 *)buffer)[i]); |
break; |
case 4: |
for (size_t i = 0; i < num; i++) |
((Uint32 *)buffer)[i] = SDL_Swap32(((Uint32 *)buffer)[i]); |
break; |
case 8: |
for (size_t i = 0; i < num; i++) |
((Uint64 *)buffer)[i] = SDL_Swap64(((Uint64 *)buffer)[i]); |
break; |
default: |
break; |
} |
#endif |
if (num_read != num) |
{ |
fprintf(stderr, "error: An unexpected problem occurred while reading from a file.\n"); |
JE_tyrianHalt(1); |
} |
return num_read; |
} |
// endian-swapping fwrite that dies if the expected amount cannot be written |
size_t efwrite( const void *buffer, size_t size, size_t num, FILE *stream ) |
{ |
void *swap_buffer = NULL; |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
switch (size) |
{ |
case 2: |
swap_buffer = malloc(size * num); |
for (size_t i = 0; i < num; i++) |
((Uint16 *)swap_buffer)[i] = SDL_SwapLE16(((Uint16 *)buffer)[i]); |
buffer = swap_buffer; |
break; |
case 4: |
swap_buffer = malloc(size * num); |
for (size_t i = 0; i < num; i++) |
((Uint32 *)swap_buffer)[i] = SDL_SwapLE32(((Uint32 *)buffer)[i]); |
buffer = swap_buffer; |
break; |
case 8: |
swap_buffer = malloc(size * num); |
for (size_t i = 0; i < num; i++) |
((Uint64 *)swap_buffer)[i] = SDL_SwapLE64(((Uint64 *)buffer)[i]); |
buffer = swap_buffer; |
break; |
default: |
break; |
} |
#endif |
size_t num_written = fwrite(buffer, size, num, stream); |
if (swap_buffer != NULL) |
free(swap_buffer); |
if (num_written != num) |
{ |
fprintf(stderr, "error: An unexpected problem occurred while writing to a file.\n"); |
JE_tyrianHalt(1); |
} |
return num_written; |
} |
/contrib/games/opentyrian/src/file.h |
---|
0,0 → 1,44 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef FILE_H |
#define FILE_H |
#include "SDL_endian.h" |
#include <stdbool.h> |
#include <stdio.h> |
extern const char *custom_data_dir; |
const char *data_dir( void ); |
FILE *dir_fopen( const char *dir, const char *file, const char *mode ); |
FILE *dir_fopen_warn( const char *dir, const char *file, const char *mode ); |
FILE *dir_fopen_die( const char *dir, const char *file, const char *mode ); |
bool dir_file_exists( const char *dir, const char *file ); |
long ftell_eof( FILE *f ); |
// endian-swapping fread/fwrite that die if the expected amount cannot be read/written |
size_t efread( void *buffer, size_t size, size_t num, FILE *stream ); |
size_t efwrite( const void *buffer, size_t size, size_t num, FILE *stream ); |
#endif // FILE_H |
/contrib/games/opentyrian/src/font.c |
---|
0,0 → 1,275 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "font.h" |
#include "fonthand.h" |
#include "sprite.h" |
/** |
* \file font.c |
* \brief Text drawing routines. |
*/ |
/** |
* \brief Draws text in a color specified by hue and value and with a drop |
* shadow. |
* |
* A '~' in the text is not drawn but instead toggles highlighting which |
* increases \c value by 4. |
* |
* \li like JE_dString() if (black == false && shadow_dist == 2 && hue == 15) |
* \li like JE_textShade() with PART_SHADE if (black == true && shadow_dist == 1) |
* \li like JE_outTextAndDarken() if (black == false && shadow_dist == 1) |
* \li like JE_outTextAdjust() with shadow if (black == false && shadow_dist == 2) |
* |
* @param surface destination surface |
* @param x initial x-position in pixels; which direction(s) the text is drawn |
* from this position depends on the alignment |
* @param y initial upper y-position in pixels |
* @param text text to be drawn |
* @param font style/size of text |
* @param alignment left_aligned, centered, or right_aligned |
* @param hue hue component of text color |
* @param value value component of text color |
* @param black if true the shadow is drawn as solid black, if false the shadow |
* is drawn by darkening the pixels of the destination surface |
* @param shadow_dist distance in pixels that the shadow will be drawn away from |
* the text. (This is added to both the x and y positions, so a value of |
* 1 causes the shadow to be drawn 1 pixel right and 1 pixel lower than |
* the text.) |
*/ |
void draw_font_hv_shadow( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value, bool black, int shadow_dist ) |
{ |
draw_font_dark(surface, x + shadow_dist, y + shadow_dist, text, font, alignment, black); |
draw_font_hv(surface, x, y, text, font, alignment, hue, value); |
} |
/** |
* \brief Draws text in a color specified by hue and value and with a |
* surrounding shadow. |
* |
* A '~' in the text is not drawn but instead toggles highlighting which |
* increases \c value by 4. |
* |
* \li like JE_textShade() with FULL_SHADE if (black == true && shadow_dist == 1) |
* |
* @param surface destination surface |
* @param x initial x-position in pixels; which direction(s) the text is drawn |
* from this position depends on the alignment |
* @param y initial upper y-position in pixels |
* @param text text to be drawn |
* @param font style/size of text |
* @param alignment left_aligned, centered, or right_aligned |
* @param hue hue component of text color |
* @param value value component of text color |
* @param black if true the shadow is drawn as solid black, if false the shadow |
* is drawn by darkening the pixels of the destination surface |
* @param shadow_dist distance in pixels that the shadows will be drawn away |
* from the text. (This distance is separately added to and subtracted |
* from the x position and y position, resulting in four shadows -- one |
* in each cardinal direction. If this shadow distance is small enough, |
* this produces a shadow that outlines the text.) |
*/ |
void draw_font_hv_full_shadow( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value, bool black, int shadow_dist ) |
{ |
draw_font_dark(surface, x, y - shadow_dist, text, font, alignment, black); |
draw_font_dark(surface, x + shadow_dist, y, text, font, alignment, black); |
draw_font_dark(surface, x, y + shadow_dist, text, font, alignment, black); |
draw_font_dark(surface, x - shadow_dist, y, text, font, alignment, black); |
draw_font_hv(surface, x, y, text, font, alignment, hue, value); |
} |
/** |
* \brief Draws text in a color specified by hue and value. |
* |
* A '~' in the text is not drawn but instead toggles highlighting which |
* increases \c value by 4. |
* |
* \li like JE_outText() with (brightness >= 0) |
* \li like JE_outTextAdjust() without shadow |
* |
* @param surface destination surface |
* @param x initial x-position in pixels; which direction(s) the text is drawn |
* from this position depends on the alignment |
* @param y initial upper y-position in pixels |
* @param text text to be drawn |
* @param font style/size of text |
* @param alignment left_aligned, centered, or right_aligned |
* @param hue hue component of text color |
* @param value value component of text color |
*/ |
void draw_font_hv( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value ) |
{ |
switch (alignment) |
{ |
case left_aligned: |
break; |
case centered: |
x -= JE_textWidth(text, font) / 2; |
break; |
case right_aligned: |
x -= JE_textWidth(text, font); |
break; |
} |
bool highlight = false; |
for (; *text != '\0'; ++text) |
{ |
int sprite_id = font_ascii[(unsigned char)*text]; |
switch (*text) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
highlight = !highlight; |
if (highlight) |
value += 4; |
else |
value -= 4; |
break; |
default: |
if (sprite_id != -1 && sprite_exists(font, sprite_id)) |
{ |
blit_sprite_hv(surface, x, y, font, sprite_id, hue, value); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
/** |
* \brief Draws blended text in a color specified by hue and value. |
* |
* Corresponds to blit_sprite_hv_blend() |
* |
* \li like JE_outTextModify() |
* |
* @param surface destination surface |
* @param x initial x-position in pixels; which direction(s) the text is drawn |
* from this position depends on the alignment |
* @param y initial upper y-position in pixels |
* @param text text to be drawn |
* @param font style/size of text |
* @param alignment left_aligned, centered, or right_aligned |
* @param hue hue component of text color |
* @param value value component of text color |
*/ |
void draw_font_hv_blend( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value ) |
{ |
switch (alignment) |
{ |
case left_aligned: |
break; |
case centered: |
x -= JE_textWidth(text, font) / 2; |
break; |
case right_aligned: |
x -= JE_textWidth(text, font); |
break; |
} |
for (; *text != '\0'; ++text) |
{ |
int sprite_id = font_ascii[(unsigned char)*text]; |
switch (*text) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
break; |
default: |
if (sprite_id != -1 && sprite_exists(font, sprite_id)) |
{ |
blit_sprite_hv_blend(surface, x, y, font, sprite_id, hue, value); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
/** |
* \brief Draws darkened text. |
* |
* Corresponds to blit_sprite_dark() |
* |
* \li like JE_outText() with (brightness < 0) if (black == true) |
* |
* @param surface destination surface |
* @param x initial x-position in pixels; which direction(s) the text is drawn |
* from this position depends on the alignment |
* @param y initial upper y-position in pixels |
* @param text text to be drawn |
* @param font style/size of text |
* @param alignment left_aligned, centered, or right_aligned |
* @param black if true text is drawn as solid black, if false text is drawn by |
* darkening the pixels of the destination surface |
*/ |
void draw_font_dark( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, bool black ) |
{ |
switch (alignment) |
{ |
case left_aligned: |
break; |
case centered: |
x -= JE_textWidth(text, font) / 2; |
break; |
case right_aligned: |
x -= JE_textWidth(text, font); |
break; |
} |
for (; *text != '\0'; ++text) |
{ |
int sprite_id = font_ascii[(unsigned char)*text]; |
switch (*text) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
break; |
default: |
if (sprite_id != -1 && sprite_exists(font, sprite_id)) |
{ |
blit_sprite_dark(surface, x, y, font, sprite_id, black); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
/contrib/games/opentyrian/src/font.h |
---|
0,0 → 1,49 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef FONT_H |
#define FONT_H |
#include "SDL.h" |
#include <stdbool.h> |
typedef enum |
{ |
large_font = 0, |
normal_font = 1, |
small_font = 2 |
} |
Font; |
typedef enum |
{ |
left_aligned, |
centered, |
right_aligned |
} |
FontAlignment; |
void draw_font_hv_shadow( SDL_Surface *, int x, int y, const char *text, Font, FontAlignment, Uint8 hue, Sint8 value, bool black, int shadow_dist ); |
void draw_font_hv_full_shadow( SDL_Surface *, int x, int y, const char *text, Font, FontAlignment, Uint8 hue, Sint8 value, bool black, int shadow_dist ); |
void draw_font_hv( SDL_Surface *, int x, int y, const char *text, Font, FontAlignment, Uint8 hue, Sint8 value ); |
void draw_font_hv_blend( SDL_Surface *, int x, int y, const char *text, Font, FontAlignment, Uint8 hue, Sint8 value ); |
void draw_font_dark( SDL_Surface *, int x, int y, const char *text, Font, FontAlignment, bool black ); |
#endif // FONT_H |
/contrib/games/opentyrian/src/fonthand.c |
---|
0,0 → 1,334 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "fonthand.h" |
#include "network.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "params.h" |
#include "sprite.h" |
#include "vga256d.h" |
#include "video.h" |
const int font_ascii[256] = |
{ |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, 26, 33, 60, 61, 62, -1, 32, 64, 65, 63, 84, 29, 83, 28, 80, // !"#$%&'()*+,-./ |
79, 70, 71, 72, 73, 74, 75, 76, 77, 78, 31, 30, -1, 85, -1, 27, // 0123456789:;<=>? |
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // @ABCDEFGHIJKLMNO |
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 68, 82, 69, -1, -1, // PQRSTUVWXYZ[\]^_ |
-1, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // `abcdefghijklmno |
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 66, 81, 67, -1, -1, // pqrstuvwxyz{|}~⌂ |
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, // Çüéâäà åçêëèïîìÄÅ |
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, // ÉæÆôöòûùÿÖÜ¢£¥₧ƒ |
118, 119, 120, 121, 122, 123, 124, 125, 126, -1, -1, -1, -1, -1, -1, -1, // áÃóúñѪº¿ |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
}; |
/* shape constants included in newshape.h */ |
JE_byte textGlowFont, textGlowBrightness = 6; |
JE_boolean levelWarningDisplay; |
JE_byte levelWarningLines; |
char levelWarningText[10][61]; /* [1..10] of string [60] */ |
JE_boolean warningRed; |
JE_byte warningSoundDelay; |
JE_word armorShipDelay; |
JE_byte warningCol; |
JE_shortint warningColChange; |
void JE_dString( SDL_Surface * screen, int x, int y, const char *s, unsigned int font ) |
{ |
const int defaultBrightness = -3; |
int bright = 0; |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
switch (s[i]) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
bright = (bright == 0) ? 2 : 0; |
break; |
default: |
if (sprite_id != -1) |
{ |
blit_sprite_dark(screen, x + 2, y + 2, font, sprite_id, false); |
blit_sprite_hv_unsafe(screen, x, y, font, sprite_id, 0xf, defaultBrightness + bright); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
int JE_fontCenter( const char *s, unsigned int font ) |
{ |
return 160 - (JE_textWidth(s, font) / 2); |
} |
int JE_textWidth( const char *s, unsigned int font ) |
{ |
int x = 0; |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
if (s[i] == ' ') |
x += 6; |
else if (sprite_id != -1) |
x += sprite(font, sprite_id)->width + 1; |
} |
return x; |
} |
void JE_textShade( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, int brightness, unsigned int shadetype ) |
{ |
switch (shadetype) |
{ |
case PART_SHADE: |
JE_outText(screen, x+1, y+1, s, 0, -1); |
JE_outText(screen, x, y, s, colorbank, brightness); |
break; |
case FULL_SHADE: |
JE_outText(screen, x-1, y, s, 0, -1); |
JE_outText(screen, x+1, y, s, 0, -1); |
JE_outText(screen, x, y-1, s, 0, -1); |
JE_outText(screen, x, y+1, s, 0, -1); |
JE_outText(screen, x, y, s, colorbank, brightness); |
break; |
case DARKEN: |
JE_outTextAndDarken(screen, x+1, y+1, s, colorbank, brightness, TINY_FONT); |
break; |
case TRICK: |
JE_outTextModify(screen, x, y, s, colorbank, brightness, TINY_FONT); |
break; |
} |
} |
void JE_outText( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, int brightness ) |
{ |
int bright = 0; |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
switch (s[i]) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
bright = (bright == 0) ? 4 : 0; |
break; |
default: |
if (sprite_id != -1 && sprite_exists(TINY_FONT, sprite_id)) |
{ |
if (brightness >= 0) |
blit_sprite_hv_unsafe(screen, x, y, TINY_FONT, sprite_id, colorbank, brightness + bright); |
else |
blit_sprite_dark(screen, x, y, TINY_FONT, sprite_id, true); |
x += sprite(TINY_FONT, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
void JE_outTextModify( SDL_Surface * screen, int x, int y, const char *s, unsigned int filter, unsigned int brightness, unsigned int font ) |
{ |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
if (s[i] == ' ') |
{ |
x += 6; |
} |
else if (sprite_id != -1) |
{ |
blit_sprite_hv_blend(screen, x, y, font, sprite_id, filter, brightness); |
x += sprite(font, sprite_id)->width + 1; |
} |
} |
} |
void JE_outTextAdjust( SDL_Surface * screen, int x, int y, const char *s, unsigned int filter, int brightness, unsigned int font, JE_boolean shadow ) |
{ |
int bright = 0; |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
switch (s[i]) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
bright = (bright == 0) ? 4 : 0; |
break; |
default: |
if (sprite_id != -1 && sprite_exists(TINY_FONT, sprite_id)) |
{ |
if (shadow) |
blit_sprite_dark(screen, x + 2, y + 2, font, sprite_id, false); |
blit_sprite_hv(screen, x, y, font, sprite_id, filter, brightness + bright); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
void JE_outTextAndDarken( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, unsigned int brightness, unsigned int font ) |
{ |
int bright = 0; |
for (int i = 0; s[i] != '\0'; ++i) |
{ |
int sprite_id = font_ascii[(unsigned char)s[i]]; |
switch (s[i]) |
{ |
case ' ': |
x += 6; |
break; |
case '~': |
bright = (bright == 0) ? 4 : 0; |
break; |
default: |
if (sprite_id != -1 && sprite_exists(TINY_FONT, sprite_id)) |
{ |
blit_sprite_dark(screen, x + 1, y + 1, font, sprite_id, false); |
blit_sprite_hv_unsafe(screen, x, y, font, sprite_id, colorbank, brightness + bright); |
x += sprite(font, sprite_id)->width + 1; |
} |
break; |
} |
} |
} |
void JE_updateWarning( SDL_Surface * screen ) |
{ |
if (delaycount2() == 0) |
{ /*Update Color Bars*/ |
warningCol += warningColChange; |
if (warningCol > 14 * 16 + 10 || warningCol < 14 * 16 + 4) |
{ |
warningColChange = -warningColChange; |
} |
fill_rectangle_xy(screen, 0, 0, 319, 5, warningCol); |
fill_rectangle_xy(screen, 0, 194, 319, 199, warningCol); |
JE_showVGA(); |
setjasondelay2(6); |
if (warningSoundDelay > 0) |
{ |
warningSoundDelay--; |
} |
else |
{ |
warningSoundDelay = 14; |
JE_playSampleNum(S_WARNING); |
} |
} |
} |
void JE_outTextGlow( SDL_Surface * screen, int x, int y, const char *s ) |
{ |
JE_integer z; |
JE_byte c = 15; |
if (warningRed) |
{ |
c = 7; |
} |
JE_outTextAdjust(screen, x - 1, y, s, 0, -12, textGlowFont, false); |
JE_outTextAdjust(screen, x, y - 1, s, 0, -12, textGlowFont, false); |
JE_outTextAdjust(screen, x + 1, y, s, 0, -12, textGlowFont, false); |
JE_outTextAdjust(screen, x, y + 1, s, 0, -12, textGlowFont, false); |
if (frameCountMax > 0) |
for (z = 1; z <= 12; z++) |
{ |
setjasondelay(frameCountMax); |
JE_outTextAdjust(screen, x, y, s, c, z - 10, textGlowFont, false); |
if (JE_anyButton()) |
{ |
frameCountMax = 0; |
} |
NETWORK_KEEP_ALIVE(); |
JE_showVGA(); |
wait_delay(); |
} |
for (z = (frameCountMax == 0) ? 6 : 12; z >= textGlowBrightness; z--) |
{ |
setjasondelay(frameCountMax); |
JE_outTextAdjust(screen, x, y, s, c, z - 10, textGlowFont, false); |
if (JE_anyButton()) |
{ |
frameCountMax = 0; |
} |
NETWORK_KEEP_ALIVE(); |
JE_showVGA(); |
wait_delay(); |
} |
textGlowBrightness = 6; |
} |
/contrib/games/opentyrian/src/fonthand.h |
---|
0,0 → 1,58 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef FONTHAND_H |
#define FONTHAND_H |
#include "opentyr.h" |
#include "SDL.h" |
#define PART_SHADE 0 |
#define FULL_SHADE 1 |
#define DARKEN 2 |
#define TRICK 3 |
#define NO_SHADE 255 |
extern const int font_ascii[256]; |
extern JE_byte textGlowFont, textGlowBrightness; |
extern JE_boolean levelWarningDisplay; |
extern JE_byte levelWarningLines; |
extern char levelWarningText[10][61]; |
extern JE_boolean warningRed; |
extern JE_byte warningSoundDelay; |
extern JE_word armorShipDelay; |
extern JE_byte warningCol; |
extern JE_shortint warningColChange; |
void JE_dString( SDL_Surface * screen, int x, int y, const char *s, unsigned int font ); |
int JE_fontCenter( const char *s, unsigned int font ); |
int JE_textWidth( const char *s, unsigned int font ); |
void JE_textShade( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, int brightness, unsigned int shadetype ); |
void JE_outText( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, int brightness ); |
void JE_outTextModify( SDL_Surface * screen, int x, int y, const char *s, unsigned int filter, unsigned int brightness, unsigned int font ); |
void JE_outTextAdjust( SDL_Surface * screen, int x, int y, const char *s, unsigned int filter, int brightness, unsigned int font, bool shadow ); |
void JE_outTextAndDarken( SDL_Surface * screen, int x, int y, const char *s, unsigned int colorbank, unsigned int brightness, unsigned int font ); |
void JE_updateWarning( SDL_Surface * screen ); |
void JE_outTextGlow( SDL_Surface * screen, int x, int y, const char *s ); |
#endif /* FONTHAND_H */ |
/contrib/games/opentyrian/src/game_menu.c |
---|
0,0 → 1,3243 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "game_menu.h" |
#include "backgrnd.h" |
#include "config.h" |
#include "file.h" |
#include "fonthand.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "loudness.h" |
#include "mainint.h" |
#include "mouse.h" |
#include "musmast.h" |
#include "network.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "params.h" |
#include "pcxmast.h" |
#include "picload.h" |
#include "player.h" |
#include "shots.h" |
#include "sprite.h" |
#include "tyrian2.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include <assert.h> |
/*** Structs ***/ |
struct cube_struct |
{ |
char title[81]; |
char header[13]; |
int face_sprite; |
char text[90][36]; |
int last_line; |
}; |
/*** Globals ***/ |
static int joystick_config = 0; // which joystick is being configured in menu |
static JE_word yLoc; |
static JE_shortint yChg; |
static int newPal, curPal, oldPal; |
static JE_boolean quikSave; |
static JE_byte oldMenu; |
static JE_boolean backFromHelp; |
static JE_integer lastDirection; |
static JE_boolean firstMenu9, paletteChanged; |
static JE_MenuChoiceType menuChoices; |
static JE_integer col, colC; |
static JE_byte lastCurSel; |
static JE_integer curMenu; |
static JE_byte curSel[MENU_MAX]; /* [1..maxmenu] */ |
static JE_byte curItemType, curItem, cursor; |
static JE_boolean leftPower, rightPower, rightPowerAfford; |
static JE_byte currentCube; |
static JE_boolean keyboardUsed; |
static JE_byte planetAni, planetAniWait; |
static JE_byte currentDotNum, currentDotWait; |
static JE_real navX, navY, newNavX, newNavY; |
static JE_integer tempNavX, tempNavY; |
static JE_byte planetDots[5]; /* [1..5] */ |
static JE_integer planetDotX[5][10], planetDotY[5][10]; /* [1..5, 1..10] */ |
static PlayerItems old_items[2]; // TODO: should not be global if possible |
static struct cube_struct cube[4]; |
static const JE_MenuChoiceType menuChoicesDefault = { 7, 9, 8, 0, 0, 11, (SAVE_FILES_NUM / 2) + 2, 0, 0, 6, 4, 6, 7, 5 }; |
static const JE_byte menuEsc[MENU_MAX] = { 0, 1, 1, 1, 2, 3, 3, 1, 8, 0, 0, 11, 3, 0 }; |
static const JE_byte itemAvailMap[7] = { 1, 2, 3, 9, 4, 6, 7 }; |
static const JE_word planetX[21] = { 200, 150, 240, 300, 270, 280, 320, 260, 220, 150, 160, 210, 80, 240, 220, 180, 310, 330, 150, 240, 200 }; |
static const JE_word planetY[21] = { 40, 90, 90, 80, 170, 30, 50, 130, 120, 150, 220, 200, 80, 50, 160, 10, 55, 55, 90, 90, 40 }; |
static const uint cube_line_chars = sizeof(*cube->text) - 1; |
static const uint cube_line_width = 150; |
/*** Functions ***/ |
static uint *playeritem_map( PlayerItems *items, uint i ) |
{ |
uint * const map[] = { &items->ship, &items->weapon[FRONT_WEAPON].id, &items->weapon[REAR_WEAPON].id, &items->shield, &items->generator, &items->sidekick[LEFT_SIDEKICK], &items->sidekick[RIGHT_SIDEKICK] }; |
assert(i < COUNTOF(map)); |
return map[i]; |
} |
JE_longint JE_cashLeft( void ) |
{ |
JE_longint tempL = player[0].cash; |
JE_word itemNum = *playeritem_map(&player[0].items, curSel[1] - 2); |
tempL -= JE_getCost(curSel[1], itemNum); |
tempW = 0; |
switch (curSel[1]) |
{ |
case 3: |
case 4: |
for (uint i = 1; i < player[0].items.weapon[curSel[1]-3].power; ++i) |
{ |
tempW += weaponPort[itemNum].cost * i; |
tempL -= tempW; |
} |
break; |
} |
return tempL; |
} |
void JE_itemScreen( void ) |
{ |
bool quit = false; |
/* SYN: Okay, here's the menu numbers. All are reindexed by -1 from the original code. |
0: full game menu |
1: upgrade ship main |
2: full game options |
3: play next level |
4: upgrade ship submenus |
5: keyboard settings |
6: load/save menu |
7: data cube menu |
8: read data cube |
9: 2 player arcade game menu |
10: 1 player arcade game menu |
11: network game options |
12: joystick settings |
13: super tyrian |
*/ |
free_sprite2s(&shapes6); |
JE_loadCompShapes(&shapes6, '1'); // item sprites |
load_cubes(); |
VGAScreen = VGAScreenSeg; |
memcpy(menuChoices, menuChoicesDefault, sizeof(menuChoices)); |
play_song(songBuy); |
JE_loadPic(VGAScreen, 1, false); |
curPal = 1; |
newPal = 0; |
JE_showVGA(); |
set_palette(colors, 0, 255); |
col = 1; |
gameLoaded = false; |
curItemType = 1; |
cursor = 1; |
curItem = 0; |
for (unsigned int i = 0; i < COUNTOF(curSel); ++i) |
curSel[i] = 2; |
curMenu = 0; |
int temp_weapon_power[7]; // assumes there'll never be more than 6 weapons to choose from, 7th is "Done" |
/* JE: (* Check for where Pitems and Select match up - if no match then add to the itemavail list *) */ |
for (int i = 0; i < 7; i++) |
{ |
int item = *playeritem_map(&player[0].last_items, i); |
int slot = 0; |
for ( ; slot < itemAvailMax[itemAvailMap[i]-1]; ++slot) |
{ |
if (itemAvail[itemAvailMap[i]-1][slot] == item) |
break; |
} |
if (slot == itemAvailMax[itemAvailMap[i]-1]) |
{ |
itemAvail[itemAvailMap[i]-1][slot] = item; |
itemAvailMax[itemAvailMap[i]-1]++; |
} |
} |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
keyboardUsed = false; |
firstMenu9 = false; |
backFromHelp = false; |
/* JE: Sort items in merchant inventory */ |
for (int x = 0; x < 9; x++) |
{ |
if (itemAvailMax[x] > 1) |
{ |
for (temp = 0; temp < itemAvailMax[x] - 1; temp++) |
{ |
for (temp2 = temp; temp2 < itemAvailMax[x]; temp2++) |
{ |
if (itemAvail[x][temp] == 0 || (itemAvail[x][temp] > itemAvail[x][temp2] && itemAvail[x][temp2] != 0)) |
{ |
temp3 = itemAvail[x][temp]; |
itemAvail[x][temp] = itemAvail[x][temp2]; |
itemAvail[x][temp2] = temp3; |
} |
} |
} |
} |
} |
do |
{ |
quit = false; |
JE_getShipInfo(); |
/* JE: If curMenu==1 and twoPlayerMode is on, then force move to menu 10 */ |
if (curMenu == 0) |
{ |
if (twoPlayerMode) |
curMenu = 9; |
if (isNetworkGame || onePlayerAction) |
curMenu = 10; |
if (superTyrian) |
curMenu = 13; |
} |
paletteChanged = false; |
leftPower = false; |
rightPower = false; |
/* SYN: note reindexing... "firstMenu9" refers to Menu 8 here :( */ |
if (curMenu != 8 || firstMenu9) |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
} |
if (curMenu == 1 && (curSel[curMenu] == 3 || curSel[curMenu] == 4)) |
{ |
// reset temp_weapon_power[] every time we select upgrading front or back |
const uint item = player[0].items.weapon[curSel[1] - 3].id, |
item_power = player[0].items.weapon[curSel[1] - 3].power, |
i = curSel[1] - 2; // 1 or 2 (front or rear) |
// set power level of owned weapon |
for (int slot = 0; slot < itemAvailMax[itemAvailMap[i]-1]; ++slot) |
{ |
if (itemAvail[itemAvailMap[i]-1][slot] == item) |
temp_weapon_power[slot] = item_power; |
else |
temp_weapon_power[slot] = 1; |
} |
// set power level for "Done" |
temp_weapon_power[itemAvailMax[itemAvailMap[i]-1]] = item_power; |
} |
/* play next level menu */ |
if (curMenu == 3) |
{ |
planetAni = 0; |
keyboardUsed = false; |
currentDotNum = 0; |
currentDotWait = 8; |
planetAniWait = 3; |
JE_updateNavScreen(); |
} |
/* Draw menu title for everything but upgrade ship submenus */ |
if (curMenu != 4) |
{ |
JE_drawMenuHeader(); |
} |
/* Draw menu choices for simple menus */ |
if ((curMenu >= 0 && curMenu <= 3) || (curMenu >= 9 && curMenu <= 11) || curMenu == 13) |
{ |
JE_drawMenuChoices(); |
} |
/* Data cube icons */ |
if (curMenu == 0) |
{ |
for (int i = 1; i <= cubeMax; i++) |
{ |
blit_sprite_dark(VGAScreen, 190 + i * 18 + 2, 37 + 1, OPTION_SHAPES, 34, false); |
blit_sprite(VGAScreen, 190 + i * 18, 37, OPTION_SHAPES, 34); // data cube |
} |
} |
/* load/save menu */ |
if (curMenu == 6) |
{ |
int min, max; |
if (twoPlayerMode) |
{ |
min = 13; |
max = 24; |
} |
else |
{ |
min = 2; |
max = 13; |
} |
for (int x = min; x <= max; x++) |
{ |
/* Highlight if current selection */ |
temp2 = (x - min + 2 == curSel[curMenu]) ? 15 : 28; |
/* Write save game slot */ |
if (x == max) |
strcpy(tempStr, miscText[6-1]); |
else if (saveFiles[x-2].level == 0) |
strcpy(tempStr, miscText[3-1]); |
else |
strcpy(tempStr, saveFiles[x-2].name); |
int tempY = 38 + (x - min)*11; |
JE_textShade(VGAScreen, 163, tempY, tempStr, temp2 / 16, temp2 % 16 - 8, DARKEN); |
/* If selected with keyboard, move mouse pointer to match? Or something. */ |
if (x - min + 2 == curSel[curMenu]) |
{ |
if (keyboardUsed) |
set_mouse_position(305, 38 + (x - min) * 11); |
} |
if (x < max) /* x == max isn't a save slot */ |
{ |
/* Highlight if current selection */ |
temp2 = (x - min + 2 == curSel[curMenu]) ? 252 : 250; |
if (saveFiles[x-2].level == 0) |
{ |
strcpy(tempStr, "-----"); /* Empty save slot */ |
} |
else |
{ |
char buf[20]; |
strcpy(tempStr, saveFiles[x-2].levelName); |
snprintf(buf, sizeof buf, "%s%d", miscTextB[1-1], saveFiles[x-2].episode); |
JE_textShade(VGAScreen, 297, tempY, buf, temp2 / 16, temp2 % 16 - 8, DARKEN); |
} |
JE_textShade(VGAScreen, 245, tempY, tempStr, temp2 / 16, temp2 % 16 - 8, DARKEN); |
} |
JE_drawMenuHeader(); |
} |
} |
/* keyboard settings menu */ |
if (curMenu == 5) |
{ |
for (int x = 2; x <= 11; x++) |
{ |
if (x == curSel[curMenu]) |
{ |
temp2 = 15; |
if (keyboardUsed) |
set_mouse_position(305, 38 + (x - 2) * 12); |
} |
else |
{ |
temp2 = 28; |
} |
JE_textShade(VGAScreen, 166, 38 + (x - 2)*12, menuInt[curMenu + 1][x-1], temp2 / 16, temp2 % 16 - 8, DARKEN); |
if (x < 10) /* 10 = reset to defaults, 11 = done */ |
{ |
temp2 = (x == curSel[curMenu]) ? 252 : 250; |
JE_textShade(VGAScreen, 236, 38 + (x - 2)*12, SDL_GetKeyName(keySettings[x-2]), temp2 / 16, temp2 % 16 - 8, DARKEN); |
} |
} |
menuChoices[5] = 11; |
} |
/* Joystick settings menu */ |
if (curMenu == 12) |
{ |
const char *menu_item[] = |
{ |
"JOYSTICK", |
"ANALOG AXES", |
" SENSITIVITY", |
" THRESHOLD", |
menuInt[6][1], |
menuInt[6][4], |
menuInt[6][2], |
menuInt[6][3], |
menuInt[6][5], |
menuInt[6][6], |
menuInt[6][7], |
menuInt[6][8], |
"MENU", |
"PAUSE", |
menuInt[6][9], |
menuInt[6][10] |
}; |
for (uint i = 0; i < COUNTOF(menu_item); i++) |
{ |
int temp = (i == curSel[curMenu] - 2u) ? 15 : 28; |
JE_textShade(VGAScreen, 166, 38 + i * 8, menu_item[i], temp / 16, temp % 16 - 8, DARKEN); |
temp = (i == curSel[curMenu] - 2u) ? 252 : 250; |
char value[30] = ""; |
if (joysticks == 0 && i < 14) // no joysticks, everything disabled |
{ |
sprintf(value, "-"); |
} |
else if (i == 0) // joystick number |
{ |
sprintf(value, "%d", joystick_config + 1); |
} |
else if (i == 1) // joystick is analog |
{ |
sprintf(value, "%s", joystick[joystick_config].analog ? "TRUE" : "FALSE"); |
} |
else if (i < 4) // joystick analog settings |
{ |
if (!joystick[joystick_config].analog) |
temp -= 3; |
sprintf(value, "%d", i == 2 ? joystick[joystick_config].sensitivity : joystick[joystick_config].threshold); |
} |
else if (i < 14) // assignments |
{ |
joystick_assignments_to_string(value, sizeof(value), joystick[joystick_config].assignment[i - 4]); |
} |
JE_textShade(VGAScreen, 236, 38 + i * 8, value, temp / 16, temp % 16 - 8, DARKEN); |
} |
menuChoices[curMenu] = COUNTOF(menu_item) + 1; |
} |
/* Upgrade weapon submenus, with weapon sim */ |
if (curMenu == 4) |
{ |
/* Move cursor until we hit either "Done" or a weapon the player can afford */ |
while (curSel[4] < menuChoices[4] && JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[4]-2]) > player[0].cash) |
{ |
curSel[4] += lastDirection; |
if (curSel[4] < 2) |
curSel[4] = menuChoices[4]; |
else if (curSel[4] > menuChoices[4]) |
curSel[4] = 2; |
} |
if (curSel[4] == menuChoices[4]) |
{ |
/* If cursor on "Done", use previous weapon */ |
*playeritem_map(&player[0].items, curSel[1] - 2) = *playeritem_map(&old_items[0], curSel[1] - 2); |
} |
else |
{ |
/* Otherwise display the selected weapon */ |
*playeritem_map(&player[0].items, curSel[1] - 2) = itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[4]-2]; |
} |
/* Get power level info for front and rear weapons */ |
if ((curSel[1] == 3 && curSel[4] < menuChoices[4]) || (curSel[1] == 4 && curSel[4] < menuChoices[4]-1)) |
{ |
const uint port = curSel[1] - 3, // 0 or 1 (front or back) |
item_level = player[0].items.weapon[port].power; |
// calculate upgradeCost |
JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[5]-2]); |
leftPower = item_level > 1; // can downgrade |
rightPower = item_level < 11; // can upgrade |
if (rightPower) |
rightPowerAfford = JE_cashLeft() >= upgradeCost; // can afford upgrade |
} |
else |
{ |
/* Nothing else can be upgraded / downgraded */ |
leftPower = false; |
rightPower = false; |
} |
/* submenu title e.g., "Left Sidekick" */ |
JE_dString(VGAScreen, 74 + JE_fontCenter(menuInt[2][curSel[1]-1], FONT_SHAPES), 10, menuInt[2][curSel[1]-1], FONT_SHAPES); |
/* Iterate through all submenu options */ |
for (tempW = 1; tempW < menuChoices[curMenu]; tempW++) |
{ |
int tempY = 40 + (tempW-1) * 26; /* Calculate y position */ |
uint temp_cost; |
/* Is this a item or None/DONE? */ |
if (tempW < menuChoices[4] - 1) |
{ |
/* Get base cost for choice */ |
temp_cost = JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][tempW-1]); |
} |
else |
{ |
/* "None" is free :) */ |
temp_cost = 0; |
} |
int afford_shade = (temp_cost > player[0].cash) ? 4 : 0; // can player afford current weapon at all |
temp = itemAvail[itemAvailMap[curSel[1]-2]-1][tempW-1]; /* Item ID */ |
switch (curSel[1]-1) |
{ |
case 1: /* ship */ |
if (temp > 90) |
{ |
snprintf(tempStr, sizeof(tempStr), "Custom Ship %d", temp - 90); |
} else { |
strcpy(tempStr, ships[temp].name); |
} |
break; |
case 2: /* front and rear weapon */ |
case 3: |
strcpy(tempStr, weaponPort[temp].name); |
break; |
case 4: /* shields */ |
strcpy(tempStr, shields[temp].name); |
break; |
case 5: /* generator */ |
strcpy(tempStr, powerSys[temp].name); |
break; |
case 6: /* sidekicks */ |
case 7: |
strcpy(tempStr, options[temp].name); |
break; |
} |
if (tempW == curSel[curMenu]-1) |
{ |
if (keyboardUsed) |
{ |
set_mouse_position(305, tempY + 10); |
} |
temp2 = 15; |
} else { |
temp2 = 28; |
} |
JE_getShipInfo(); |
/* item-owned marker */ |
if (temp == *playeritem_map(&old_items[0], curSel[1] - 2) && temp != 0 && tempW != menuChoices[curMenu]-1) |
{ |
fill_rectangle_xy(VGAScreen, 160, tempY+7, 300, tempY+11, 227); |
blit_sprite2(VGAScreen, 298, tempY+2, shapes6, 247); |
} |
/* Draw DONE */ |
if (tempW == menuChoices[curMenu]-1) |
{ |
strcpy(tempStr, miscText[13]); |
} |
JE_textShade(VGAScreen, 185, tempY, tempStr, temp2 / 16, temp2 % 16 - 8 - afford_shade, DARKEN); |
/* Draw icon if not DONE. NOTE: None is a normal item with a blank icon. */ |
if (tempW < menuChoices[curMenu]-1) |
{ |
JE_drawItem(curSel[1]-1, temp, 160, tempY-4); |
} |
/* Make selected text brigther */ |
temp2 = (tempW == curSel[curMenu]-1) ? 15 : 28; |
/* Draw Cost: if it's not the DONE option */ |
if (tempW != menuChoices[curMenu]-1) |
{ |
char buf[20]; |
snprintf(buf, sizeof buf, "Cost: %d", temp_cost); |
JE_textShade(VGAScreen, 187, tempY+10, buf, temp2 / 16, temp2 % 16 - 8 - afford_shade, DARKEN); |
} |
} |
} /* /weapon upgrade */ |
/* Draw current money and shield/armor bars, when appropriate */ |
/* YKS: Ouch */ |
if (((curMenu <= 2 || curMenu == 5 || curMenu == 6 || curMenu >= 10) && !twoPlayerMode) || (curMenu == 4 && (curSel[1] >= 1 && curSel[1] <= 6))) |
{ |
if (curMenu != 4) |
{ |
char buf[20]; |
snprintf(buf, sizeof buf, "%lu", player[0].cash); |
JE_textShade(VGAScreen, 65, 173, buf, 1, 6, DARKEN); |
} |
JE_barDrawShadow(VGAScreen, 42, 152, 3, 14, player[0].armor, 2, 13); |
JE_barDrawShadow(VGAScreen, 104, 152, 2, 14, shields[player[0].items.shield].mpwr * 2, 2, 13); |
} |
/* Draw crap on the left side of the screen, i.e. two player scores, ship graphic, etc. */ |
if (((curMenu >= 0 && curMenu <= 2) || curMenu == 5 || curMenu == 6 || curMenu >= 9) || (curMenu == 4 && (curSel[1] == 2 || curSel[1] == 5))) |
{ |
if (twoPlayerMode) |
{ |
char buf[50]; |
for (uint i = 0; i < 2; ++i) |
{ |
snprintf(buf, sizeof(buf), "%s %lu", miscText[40 + i], player[i].cash); |
JE_textShade(VGAScreen, 25, 50 + 10 * i, buf, 15, 0, FULL_SHADE); |
} |
} |
else if (superArcadeMode != SA_NONE || superTyrian) |
{ |
helpBoxColor = 15; |
helpBoxBrightness = 4; |
if (!superTyrian) |
JE_helpBox(VGAScreen, 35, 25, superShips[superArcadeMode], 18); |
else |
JE_helpBox(VGAScreen, 35, 25, superShips[SA+3], 18); |
helpBoxBrightness = 1; |
JE_textShade(VGAScreen, 25, 50, superShips[SA+1], 15, 0, FULL_SHADE); |
JE_helpBox(VGAScreen, 25, 60, weaponPort[player[0].items.weapon[FRONT_WEAPON].id].name, 22); |
JE_textShade(VGAScreen, 25, 120, superShips[SA+2], 15, 0, FULL_SHADE); |
JE_helpBox(VGAScreen, 25, 130, special[player[0].items.special].name, 22); |
} |
else |
{ |
draw_ship_illustration(); |
} |
} |
/* Changing the volume? */ |
if ((curMenu == 2) || (curMenu == 11)) |
{ |
JE_barDrawShadow(VGAScreen, 225, 70, 1, music_disabled ? 12 : 16, tyrMusicVolume / 12, 3, 13); |
JE_barDrawShadow(VGAScreen, 225, 86, 1, samples_disabled ? 12 : 16, fxVolume / 12, 3, 13); |
} |
/* 7 is data cubes menu, 8 is reading a data cube, "firstmenu9" refers to menu 8 because of reindexing */ |
if (curMenu == 7 || ( curMenu == 8 && (firstMenu9 || backFromHelp) ) ) |
{ |
firstMenu9 = false; |
menuChoices[7] = cubeMax + 2; |
fill_rectangle_xy(VGAScreen, 1, 1, 145, 170, 0); |
blit_sprite(VGAScreenSeg, 1, 1, OPTION_SHAPES, 20); /* Portrait area background */ |
if (curMenu == 7) |
{ |
if (cubeMax == 0) |
{ |
JE_helpBox(VGAScreen, 166, 80, miscText[16 - 1], 30); |
tempW = 160; |
temp2 = 252; |
} |
else |
{ |
for (int x = 1; x <= cubeMax; x++) |
{ |
JE_drawCube(VGAScreenSeg, 166, 38 + (x - 1) * 28, 13, 0); |
if (x + 1 == curSel[curMenu]) |
{ |
if (keyboardUsed) |
set_mouse_position(305, 38 + (x - 1) * 28 + 6); |
temp2 = 252; |
} |
else |
{ |
temp2 = 250; |
} |
helpBoxColor = temp2 / 16; |
helpBoxBrightness = (temp2 % 16) - 8; |
helpBoxShadeType = DARKEN; |
JE_helpBox(VGAScreen, 192, 44 + (x - 1) * 28, cube[x - 1].title, 24); |
} |
int x = cubeMax + 1; |
if (x + 1 == curSel[curMenu]) |
{ |
if (keyboardUsed) |
set_mouse_position(305, 38 + (x - 1) * 28 + 6); |
temp2 = 252; |
} |
else |
{ |
temp2 = 250; |
} |
tempW = 44 + (x - 1) * 28; |
} |
JE_textShade(VGAScreen, 172, tempW, miscText[6 - 1], temp2 / 16, (temp2 % 16) - 8, DARKEN); |
} |
if (curSel[7] < menuChoices[7]) |
{ |
const int face_sprite = cube[curSel[7] - 2].face_sprite; |
if (face_sprite != -1) |
{ |
const int face_x = 77 - (sprite(FACE_SHAPES, face_sprite)->width / 2), |
face_y = 92 - (sprite(FACE_SHAPES, face_sprite)->height / 2); |
blit_sprite(VGAScreenSeg, face_x, face_y, FACE_SHAPES, face_sprite); // datacube face |
// modify pallete for face |
paletteChanged = true; |
temp2 = facepal[face_sprite]; |
newPal = 0; |
for (temp = 1; temp <= 255 - (3 * 16); temp++) |
colors[temp] = palettes[temp2][temp]; |
} |
} |
} |
/* 2 player input devices */ |
if (curMenu == 9) |
{ |
for (uint i = 0; i < COUNTOF(inputDevice); i++) |
{ |
if (inputDevice[i] > 2 + joysticks) |
inputDevice[i] = inputDevice[i == 0 ? 1 : 0] == 1 ? 2 : 1; |
char temp[64]; |
if (joysticks > 1 && inputDevice[i] > 2) |
sprintf(temp, "%s %d", inputDevices[2], inputDevice[i] - 2); |
else |
sprintf(temp, "%s", inputDevices[inputDevice[i] - 1]); |
JE_dString(VGAScreen, 186, 38 + 2 * (i + 1) * 16, temp, SMALL_FONT_SHAPES); |
} |
} |
/* JE: { - Step VI - Help text for current cursor location } */ |
flash = false; |
/* JE: {Reset player weapons} */ |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
JE_drawScore(); |
JE_drawMainMenuHelpText(); |
if (newPal > 0) /* can't reindex this :( */ |
{ |
curPal = newPal; |
memcpy(colors, palettes[newPal - 1], sizeof(colors)); |
set_palette(palettes[newPal - 1], 0, 255); |
newPal = 0; |
} |
/* datacube title under face */ |
if ( ( (curMenu == 7) || (curMenu == 8) ) && (curSel[7] < menuChoices[7]) ) |
JE_textShade (VGAScreen, 75 - JE_textWidth(cube[curSel[7] - 2].header, TINY_FONT) / 2, 173, cube[curSel[7] - 2].header, 14, 3, DARKEN); |
/* SYN: Everything above was just drawing the screen. In the rest of it, we process |
any user input (and do a few other things) */ |
/* SYN: Let's start by getting fresh events from SDL */ |
service_SDL_events(true); |
if (constantPlay) |
{ |
mainLevel = mapSection[mapPNum-1]; |
jumpSection = true; |
} |
else |
{ |
do |
{ |
/* Inner loop -- this handles animations on menus that need them and handles |
some keyboard events. Events it can't handle end the loop and fall through |
to the main keyboard handler below. |
Also, I think all timing is handled in here. Somehow. */ |
NETWORK_KEEP_ALIVE(); |
mouseCursor = 0; |
col += colC; |
if (col < -2 || col > 6) |
{ |
colC = (-1 * colC); |
} |
// data cube reading |
if (curMenu == 8) |
{ |
if (mouseX > 164 && mouseX < 299 && mouseY > 47 && mouseY < 153) |
{ |
if (mouseY > 100) |
mouseCursor = 2; |
else |
mouseCursor = 1; |
} |
fill_rectangle_xy(VGAScreen, 160, 49, 310, 158, 228); |
if (yLoc + yChg < 0) |
{ |
yChg = 0; |
yLoc = 0; |
} |
yLoc += yChg; |
temp = yLoc / 12; |
temp2 = yLoc % 12; |
tempW = 38 + 12 - temp2; |
temp3 = cube[curSel[7] - 2].last_line; |
for (int x = temp + 1; x <= temp + 10; x++) |
{ |
if (x <= temp3) |
{ |
JE_outTextAndDarken(VGAScreen, 161, tempW, cube[curSel[7] - 2].text[x-1], 14, 3, TINY_FONT); |
tempW += 12; |
} |
} |
fill_rectangle_xy(VGAScreen, 160, 39, 310, 48, 228); |
fill_rectangle_xy(VGAScreen, 160, 157, 310, 166, 228); |
int percent_read = (cube[currentCube].last_line <= 9) |
? 100 |
: (yLoc * 100) / ((cube[currentCube].last_line - 9) * 12); |
char buf[20]; |
snprintf(buf, sizeof(buf), "%s %d%%", miscText[11], percent_read); |
JE_outTextAndDarken(VGAScreen, 176, 160, buf, 14, 1, TINY_FONT); |
JE_dString(VGAScreen, 260, 160, miscText[12], SMALL_FONT_SHAPES); |
if (temp2 == 0) |
yChg = 0; |
JE_mouseStart(); |
JE_showVGA(); |
if (backFromHelp) |
{ |
fade_palette(colors, 10, 0, 255); |
backFromHelp = false; |
} |
JE_mouseReplace(); |
setjasondelay(1); |
} |
else |
{ |
/* current menu is not 8 (read data cube) */ |
if (curMenu == 3) |
{ |
JE_updateNavScreen(); |
JE_drawMainMenuHelpText(); |
JE_drawMenuHeader(); |
JE_drawMenuChoices(); |
if (extraGame) |
JE_dString(VGAScreen, 170, 140, miscText[68 - 1], FONT_SHAPES); |
} |
if (curMenu == 7 && curSel[7] < menuChoices[7]) |
{ |
/* Draw flashy cube */ |
blit_sprite_hv_blend(VGAScreenSeg, 166, 38 + (curSel[7] - 2) * 28, OPTION_SHAPES, 25, 13, col); |
} |
/* IF (curmenu = 5) AND (cursel [2] IN [3, 4, 6, 7, 8]) */ |
if (curMenu == 4 && ( curSel[1] == 3 || curSel[1] == 4 || ( curSel[1] >= 6 && curSel[1] <= 8) ) ) |
{ |
setjasondelay(3); |
JE_weaponSimUpdate(); |
JE_drawScore(); |
service_SDL_events(false); |
if (newPal > 0) |
{ |
curPal = newPal; |
set_palette(palettes[newPal - 1], 0, 255); |
newPal = 0; |
} |
JE_mouseStart(); |
if (paletteChanged) |
{ |
set_palette(colors, 0, 255); |
paletteChanged = false; |
} |
JE_showVGA(); /* SYN: This is where it updates the screen for the weapon sim */ |
if (backFromHelp) |
{ |
fade_palette(colors, 10, 0, 255); |
backFromHelp = false; |
} |
JE_mouseReplace(); |
} else { /* current menu is anything but weapon sim or datacube */ |
setjasondelay(2); |
JE_drawScore(); |
//JE_waitRetrace(); didn't do anything anyway? |
if (newPal > 0) |
{ |
curPal = newPal; |
set_palette(palettes[newPal - 1], 0, 255); |
newPal = 0; |
} |
JE_mouseStart(); |
if (paletteChanged) |
{ |
set_palette(colors, 0, 255); |
paletteChanged = false; |
} |
JE_showVGA(); /* SYN: This is the where the screen updates for most menus */ |
JE_mouseReplace(); |
if (backFromHelp) |
{ |
fade_palette(colors, 10, 0, 255); |
backFromHelp = false; |
} |
} |
} |
wait_delay(); |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
mouseButton = JE_mousePosition(&mouseX, &mouseY); |
inputDetected = newkey || mouseButton > 0; |
if (curMenu != 6) |
{ |
if (keysactive[SDLK_s] && (keysactive[SDLK_LALT] || keysactive[SDLK_RALT]) ) |
{ |
if (curMenu == 8 || curMenu == 7) |
{ |
curMenu = 0; |
} |
quikSave = true; |
oldMenu = curMenu; |
curMenu = 6; |
performSave = true; |
newPal = 1; |
oldPal = curPal; |
} |
if (keysactive[SDLK_l] && (keysactive[SDLK_LALT] || keysactive[SDLK_RALT]) ) |
{ |
if (curMenu == 8 || curMenu == 7) |
{ |
curMenu = 0; |
} |
quikSave = true; |
oldMenu = curMenu; |
curMenu = 6; |
performSave = false; |
newPal = 1; |
oldPal = curPal; |
} |
} |
if (curMenu == 8) |
{ |
if (mouseButton > 0 && mouseCursor >= 1) |
{ |
inputDetected = false; |
if (mouseCursor == 1) |
{ |
yChg = -1; |
} else { |
yChg = 1; |
} |
} |
if (keysactive[SDLK_PAGEUP]) |
{ |
yChg = -2; |
inputDetected = false; |
} |
if (keysactive[SDLK_PAGEDOWN]) |
{ |
yChg = 2; |
inputDetected = false; |
} |
bool joystick_up = false, joystick_down = false; |
for (int j = 0; j < joysticks; j++) |
{ |
joystick_up |= joystick[j].direction[0]; |
joystick_down |= joystick[j].direction[2]; |
} |
if (keysactive[SDLK_UP] || joystick_up) |
{ |
yChg = -1; |
inputDetected = false; |
} |
if (keysactive[SDLK_DOWN] || joystick_down) |
{ |
yChg = 1; |
inputDetected = false; |
} |
if (yChg < 0 && yLoc == 0) |
{ |
yChg = 0; |
} |
if (yChg > 0 && (yLoc / 12) > cube[currentCube].last_line - 10) |
{ |
yChg = 0; |
} |
} |
} while (!inputDetected); |
} |
keyboardUsed = false; |
/* The rest of this just grabs input events, handles them, then proceeds on. */ |
if (mouseButton > 0) |
{ |
lastDirection = 1; |
mouseButton = JE_mousePosition(&mouseX, &mouseY); |
if (curMenu == 7 && cubeMax == 0) |
{ |
curMenu = 0; |
JE_playSampleNum(S_SPRING); |
newPal = 1; |
JE_wipeKey(); |
} |
if (curMenu == 8) |
{ |
if ((mouseX > 258) && (mouseX < 290) && (mouseY > 159) && (mouseY < 171)) |
{ |
curMenu = 7; |
JE_playSampleNum(S_SPRING); |
} |
} |
if (curMenu == 2 || curMenu == 11) |
{ |
if ((mouseX >= (225 - 4)) && (mouseY >= 70) && (mouseY <= 82)) |
{ |
if (music_disabled) |
{ |
music_disabled = false; |
restart_song(); |
} |
curSel[2] = 4; |
tyrMusicVolume = (mouseX - (225 - 4)) / 4 * 12; |
if (tyrMusicVolume > 255) |
tyrMusicVolume = 255; |
} |
if ((mouseX >= (225 - 4)) && (mouseY >= 86) && (mouseY <= 98)) |
{ |
samples_disabled = false; |
curSel[2] = 5; |
fxVolume = (mouseX - (225 - 4)) / 4 * 12; |
if (fxVolume > 255) |
fxVolume = 255; |
} |
JE_calcFXVol(); |
set_volume(tyrMusicVolume, fxVolume); |
JE_playSampleNum(S_CURSOR); |
} |
if ((mouseY > 20) && (mouseX > 170) && (mouseX < 308) && (curMenu != 8)) |
{ |
const JE_byte mouseSelectionY[MENU_MAX] = { 16, 16, 16, 16, 26, 12, 11, 28, 0, 16, 16, 16, 8, 16 }; |
int selection = (mouseY - 38) / mouseSelectionY[curMenu]+2; |
if (curMenu == 9) |
{ |
if (selection > 5) |
selection--; |
if (selection > 3) |
selection--; |
} |
if (curMenu == 0) |
{ |
if (selection > 7) |
selection = 7; |
} |
// is play next level screen? |
if (curMenu == 3) |
{ |
if (selection == menuChoices[curMenu] + 1) |
selection = menuChoices[curMenu]; |
} |
if (selection <= menuChoices[curMenu]) |
{ |
if ((curMenu == 4) && (selection == menuChoices[4])) |
{ |
player[0].cash = JE_cashLeft(); |
curMenu = 1; |
JE_playSampleNum(S_ITEM); |
} |
else |
{ |
JE_playSampleNum(S_CLICK); |
if (curSel[curMenu] == selection) |
{ |
JE_menuFunction(curSel[curMenu]); |
} |
else |
{ |
if ((curMenu == 4) && (JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][selection-2]) > player[0].cash)) |
{ |
JE_playSampleNum(S_CLINK); |
} |
else |
{ |
if (curSel[1] == 4) |
player[0].weapon_mode = 1; |
curSel[curMenu] = selection; |
} |
// in front or rear weapon upgrade screen? |
if ((curMenu == 4) && ((curSel[1] == 3) || (curSel[1] == 4))) |
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2]; |
} |
} |
} |
wait_noinput(false, true, false); |
} |
if ((curMenu == 4) && ((curSel[1] == 3) || (curSel[1] == 4))) |
{ |
if ((mouseX >= 23) && (mouseX <= 36) && (mouseY >= 149) && (mouseY <= 168)) |
{ |
JE_playSampleNum(S_CURSOR); |
switch (curSel[1]) |
{ |
case 3: |
case 4: |
if (leftPower) |
player[0].items.weapon[curSel[1]-3].power = --temp_weapon_power[curSel[4]-2]; |
else |
JE_playSampleNum(S_CLINK); |
break; |
} |
wait_noinput(false, true, false); |
} |
if ((mouseX >= 119) && (mouseX <= 131) && (mouseY >= 149) && (mouseY <= 168)) |
{ |
JE_playSampleNum(S_CURSOR); |
switch (curSel[1]) |
{ |
case 3: |
case 4: |
if (rightPower && rightPowerAfford) |
player[0].items.weapon[curSel[1]-3].power = ++temp_weapon_power[curSel[4]-2]; |
else |
JE_playSampleNum(S_CLINK); |
break; |
} |
wait_noinput(false, true, false); |
} |
} |
} |
else if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_SLASH: |
// if in rear weapon upgrade screen |
if ( (curMenu == 4) && (curSel[1] == 4)) |
{ |
// cycle weapon modes |
if (++player[0].weapon_mode > weaponPort[player[0].items.weapon[REAR_WEAPON].id].opnum) |
player[0].weapon_mode = 1; |
} |
break; |
case SDLK_SPACE: |
case SDLK_RETURN: |
keyboardUsed = true; |
// if front or rear weapon, update "Done" power level |
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4)) |
temp_weapon_power[itemAvailMax[itemAvailMap[curSel[1]-2]-1]] = player[0].items.weapon[curSel[1]-3].power; |
JE_menuFunction(curSel[curMenu]); |
break; |
case SDLK_ESCAPE: |
keyboardUsed = true; |
JE_playSampleNum(S_SPRING); |
if ( (curMenu == 6) && quikSave) |
{ |
curMenu = oldMenu; |
newPal = oldPal; |
} |
else if (menuEsc[curMenu] == 0) |
{ |
if (JE_quitRequest()) |
{ |
gameLoaded = true; |
mainLevel = 0; |
} |
} |
else |
{ |
if (curMenu == 4) // leaving upgrade menu without buying |
{ |
player[0].items = old_items[0]; |
curSel[4] = lastCurSel; |
player[0].cash = JE_cashLeft(); |
} |
if (curMenu != 8) // not data cube |
newPal = 1; |
curMenu = menuEsc[curMenu] - 1; |
} |
break; |
case SDLK_F1: |
if (!isNetworkGame) |
{ |
JE_helpSystem(2); |
fade_black(10); |
play_song(songBuy); |
JE_loadPic(VGAScreen, 1, false); |
newPal = 1; |
switch (curMenu) |
{ |
case 3: |
newPal = 18; |
break; |
case 7: |
case 8: |
break; |
} |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
curPal = newPal; |
memcpy(colors, palettes[newPal-1], sizeof(colors)); |
JE_showVGA(); |
newPal = 0; |
backFromHelp = true; |
} |
break; |
case SDLK_UP: |
keyboardUsed = true; |
lastDirection = -1; |
if (curMenu != 8) // not data cube |
JE_playSampleNum(S_CURSOR); |
curSel[curMenu]--; |
if (curSel[curMenu] < 2) |
curSel[curMenu] = menuChoices[curMenu]; |
// if in front or rear weapon upgrade screen |
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4)) |
{ |
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2]; |
if (curSel[curMenu] == 4) |
player[0].weapon_mode = 1; |
} |
// if joystick config, skip disabled items when digital |
if (curMenu == 12 && joysticks > 0 && !joystick[joystick_config].analog && curSel[curMenu] == 5) |
curSel[curMenu] = 3; |
break; |
case SDLK_DOWN: |
keyboardUsed = true; |
lastDirection = 1; |
if (curMenu != 8) // not data cube |
JE_playSampleNum(S_CURSOR); |
curSel[curMenu]++; |
if (curSel[curMenu] > menuChoices[curMenu]) |
curSel[curMenu] = 2; |
// if in front or rear weapon upgrade screen |
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4)) |
{ |
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2]; |
if (curSel[curMenu] == 4) |
player[0].weapon_mode = 1; |
} |
// if in joystick config, skip disabled items when digital |
if (curMenu == 12 && joysticks > 0 && !joystick[joystick_config].analog && curSel[curMenu] == 4) |
curSel[curMenu] = 6; |
break; |
case SDLK_HOME: |
if (curMenu == 8) // data cube |
yLoc = 0; |
break; |
case SDLK_END: |
if (curMenu == 8) // data cube |
yLoc = (cube[currentCube].last_line - 9) * 12; |
break; |
case SDLK_LEFT: |
if (curMenu == 12) // joystick settings menu |
{ |
if (joysticks > 0) |
{ |
switch (curSel[curMenu]) |
{ |
case 2: |
if (joystick_config == 0) |
joystick_config = joysticks; |
joystick_config--; |
break; |
case 3: |
joystick[joystick_config].analog = !joystick[joystick_config].analog; |
break; |
case 4: |
if (joystick[joystick_config].sensitivity == 0) |
joystick[joystick_config].sensitivity = 10; |
else |
joystick[joystick_config].sensitivity--; |
break; |
case 5: |
if (joystick[joystick_config].threshold == 0) |
joystick[joystick_config].threshold = 10; |
else |
joystick[joystick_config].threshold--; |
break; |
default: |
break; |
} |
} |
} |
if (curMenu == 9) |
{ |
switch (curSel[curMenu]) |
{ |
case 3: |
case 4: |
JE_playSampleNum(S_CURSOR); |
int temp = curSel[curMenu] - 3; |
do { |
if (joysticks == 0) |
{ |
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers |
} |
if (inputDevice[temp] <= 1) |
{ |
inputDevice[temp] = 2 + joysticks; |
} else { |
inputDevice[temp]--; |
} |
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]); |
break; |
} |
} |
if (curMenu == 2 || curMenu == 4 || curMenu == 11) |
{ |
JE_playSampleNum(S_CURSOR); |
} |
switch (curMenu) |
{ |
case 2: |
case 11: |
switch (curSel[curMenu]) |
{ |
case 4: |
JE_changeVolume(&tyrMusicVolume, -12, &fxVolume, 0); |
if (music_disabled) |
{ |
music_disabled = false; |
restart_song(); |
} |
break; |
case 5: |
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, -12); |
samples_disabled = false; |
break; |
} |
break; |
case 4: |
switch (curSel[1]) |
{ |
case 3: |
case 4: |
if (leftPower) |
player[0].items.weapon[curSel[1]-3].power = --temp_weapon_power[curSel[4]-2]; |
else |
JE_playSampleNum(S_CLINK); |
break; |
} |
break; |
} |
break; |
case SDLK_RIGHT: |
if (curMenu == 12) // joystick settings menu |
{ |
if (joysticks > 0) |
{ |
switch (curSel[curMenu]) |
{ |
case 2: |
joystick_config++; |
joystick_config %= joysticks; |
break; |
case 3: |
joystick[joystick_config].analog = !joystick[joystick_config].analog; |
break; |
case 4: |
joystick[joystick_config].sensitivity++; |
joystick[joystick_config].sensitivity %= 11; |
break; |
case 5: |
joystick[joystick_config].threshold++; |
joystick[joystick_config].threshold %= 11; |
break; |
default: |
break; |
} |
} |
} |
if (curMenu == 9) |
{ |
switch (curSel[curMenu]) |
{ |
case 3: |
case 4: |
JE_playSampleNum(S_CURSOR); |
int temp = curSel[curMenu] - 3; |
do { |
if (joysticks == 0) |
{ |
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers |
} |
if (inputDevice[temp] >= 2 + joysticks) |
{ |
inputDevice[temp] = 1; |
} else { |
inputDevice[temp]++; |
} |
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]); |
break; |
} |
} |
if (curMenu == 2 || curMenu == 4 || curMenu == 11) |
{ |
JE_playSampleNum(S_CURSOR); |
} |
switch (curMenu) |
{ |
case 2: |
case 11: |
switch (curSel[curMenu]) |
{ |
case 4: |
JE_changeVolume(&tyrMusicVolume, 12, &fxVolume, 0); |
if (music_disabled) |
{ |
music_disabled = false; |
restart_song(); |
} |
break; |
case 5: |
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, 12); |
samples_disabled = false; |
break; |
} |
break; |
case 4: |
switch (curSel[1]) |
{ |
case 3: |
case 4: |
if (rightPower && rightPowerAfford) |
player[0].items.weapon[curSel[1]-3].power = ++temp_weapon_power[curSel[4]-2]; |
else |
JE_playSampleNum(S_CLINK); |
break; |
} |
break; |
} |
break; |
default: |
break; |
} |
} |
} while (!(quit || gameLoaded || jumpSection)); |
#ifdef WITH_NETWORK |
if (!quit && isNetworkGame) |
{ |
JE_barShade(VGAScreen, 3, 3, 316, 196); |
JE_barShade(VGAScreen, 1, 1, 318, 198); |
JE_dString(VGAScreen, 10, 160, "Waiting for other player.", SMALL_FONT_SHAPES); |
network_prepare(PACKET_WAITING); |
network_send(4); // PACKET_WAITING |
while (true) |
{ |
service_SDL_events(false); |
JE_showVGA(); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_WAITING) |
{ |
network_update(); |
break; |
} |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
network_state_reset(); |
} |
if (isNetworkGame) |
{ |
while (!network_is_sync()) |
{ |
service_SDL_events(false); |
JE_showVGA(); |
network_check(); |
uSDL_Delay(16); |
} |
} |
#endif |
if (gameLoaded) |
fade_black(10); |
} |
void draw_ship_illustration( void ) |
{ |
// full of evil hardcoding |
// ship |
{ |
assert(player[0].items.ship > 0); |
const int sprite_id = (player[0].items.ship < COUNTOF(ships)) // shipedit ships get a default |
? ships[player[0].items.ship].bigshipgraphic - 1 |
: 31; |
const int ship_x[6] = { 31, 0, 0, 0, 35, 31 }, |
ship_y[6] = { 36, 0, 0, 0, 33, 35 }; |
const int x = ship_x[sprite_id - 27], |
y = ship_y[sprite_id - 27]; |
blit_sprite(VGAScreenSeg, x, y, OPTION_SHAPES, sprite_id); |
} |
// generator |
{ |
assert(player[0].items.generator > 0 && player[0].items.generator < 7); |
const int sprite_id = (player[0].items.generator == 1) // generator 1 and generator 2 have the same sprite |
? player[0].items.generator + 15 |
: player[0].items.generator + 14; |
const int generator_x[5] = { 62, 64, 67, 66, 63 }, |
generator_y[5] = { 84, 85, 86, 84, 97 }; |
const int x = generator_x[sprite_id - 16], |
y = generator_y[sprite_id - 16]; |
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, sprite_id); |
} |
const int weapon_sprites[43] = |
{ |
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, |
9, 10, 11, 21, 5, 13, -1, 14, 15, 0, |
14, 9, 8, 2, 15, 0, 13, 0, 8, 8, |
11, 1, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 2, 1 |
}; |
// front weapon |
if (player[0].items.weapon[FRONT_WEAPON].id > 0) |
{ |
const int front_weapon_xy_list[43] = |
{ |
-1, 4, 9, 3, 8, 2, 5, 10, 1, -1, |
-1, -1, -1, 7, 8, -1, -1, 0, -1, 4, |
0, -1, -1, 3, -1, 4, -1, 4, -1, -1, |
-1, 9, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 3, 9 |
}; |
const int front_weapon_x[12] = { 59, 66, 66, 54, 61, 51, 58, 51, 61, 52, 53, 58 }; |
const int front_weapon_y[12] = { 38, 53, 41, 36, 48, 35, 41, 35, 53, 41, 39, 31 }; |
const int x = front_weapon_x[front_weapon_xy_list[player[0].items.weapon[FRONT_WEAPON].id]], |
y = front_weapon_y[front_weapon_xy_list[player[0].items.weapon[FRONT_WEAPON].id]]; |
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, weapon_sprites[player[0].items.weapon[FRONT_WEAPON].id]); // ship illustration: front weapon |
} |
// rear weapon |
if (player[0].items.weapon[REAR_WEAPON].id > 0) |
{ |
const int rear_weapon_xy_list[43] = |
{ |
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, |
1, 2, 3, -1, 4, 5, -1, -1, 6, -1, |
-1, 1, 0, -1, 6, -1, 5, -1, 0, 0, |
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, -1, -1 |
}; |
const int rear_weapon_x[7] = { 41, 27, 49, 43, 51, 39, 41 }; |
const int rear_weapon_y[7] = { 92, 92, 113, 102, 97, 96, 76 }; |
const int x = rear_weapon_x[rear_weapon_xy_list[player[0].items.weapon[REAR_WEAPON].id]], |
y = rear_weapon_y[rear_weapon_xy_list[player[0].items.weapon[REAR_WEAPON].id]]; |
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, weapon_sprites[player[0].items.weapon[REAR_WEAPON].id]); |
} |
// sidekicks |
JE_drawItem(6, player[0].items.sidekick[LEFT_SIDEKICK], 3, 84); |
JE_drawItem(7, player[0].items.sidekick[RIGHT_SIDEKICK], 129, 84); |
// shield |
blit_sprite_hv(VGAScreenSeg, 28, 23, OPTION_SHAPES, 26, 15, shields[player[0].items.shield].mpwr - 10); |
} |
void load_cubes( void ) |
{ |
for (int cube_slot = 0; cube_slot < cubeMax; ++cube_slot) |
{ |
memset(cube[cube_slot].text, 0, sizeof(cube->text)); |
load_cube(cube_slot, cubeList[cube_slot]); |
} |
} |
bool load_cube( int cube_slot, int cube_index ) |
{ |
FILE *f = dir_fopen_die(data_dir(), cube_file, "rb"); |
char buf[256]; |
// seek to the cube |
while (cube_index > 0) |
{ |
read_encrypted_pascal_string(buf, sizeof(buf), f); |
if (buf[0] == '*') |
--cube_index; |
if (feof(f)) |
{ |
fclose(f); |
return false; |
} |
} |
str_pop_int(&buf[4], &cube[cube_slot].face_sprite); |
--cube[cube_slot].face_sprite; |
read_encrypted_pascal_string(cube[cube_slot].title, sizeof(cube[cube_slot].title), f); |
read_encrypted_pascal_string(cube[cube_slot].header, sizeof(cube[cube_slot].header), f); |
uint line = 0, line_chars = 0, line_width = 0; |
// for each line of decrypted text, split the line into words |
// and add them individually to the lines of wrapped text |
for (; ; ) |
{ |
read_encrypted_pascal_string(buf, sizeof(buf), f); |
// end of data |
if (feof(f) || buf[0] == '*') |
break; |
// new paragraph |
if (strlen(buf) == 0) |
{ |
if (line_chars == 0) |
line += 4; // subsequent new paragaphs indicate 4-line break |
else |
++line; |
line_chars = 0; |
line_width = 0; |
continue; |
} |
uint word_start = 0; |
for (uint i = 0; ; ++i) |
{ |
bool end_of_line = (buf[i] == '\0'), |
end_of_word = end_of_line || (buf[i] == ' '); |
if (end_of_word) |
{ |
buf[i] = '\0'; |
char *word = &buf[word_start]; |
word_start = i + 1; |
uint word_chars = strlen(word), |
word_width = JE_textWidth(word, TINY_FONT); |
// word won't fit; no can do |
if (word_chars > cube_line_chars || word_width > cube_line_width) |
break; |
bool prepend_space = true; |
line_chars += word_chars + (prepend_space ? 1 : 0); |
line_width += word_width + (prepend_space ? 6 : 0); |
// word won't fit on current line; use next |
if (line_chars > cube_line_chars || line_width > cube_line_width) |
{ |
++line; |
line_chars = word_chars; |
line_width = word_width; |
prepend_space = false; |
} |
// append word |
if (line < COUNTOF(cube->text)) |
{ |
if (prepend_space) |
strcat(cube[cube_slot].text[line], " "); |
strcat(cube[cube_slot].text[line], word); |
// track last line with text |
cube[cube_slot].last_line = line + 1; |
} |
} |
if (end_of_line) |
break; |
} |
} |
fclose(f); |
return true; |
} |
void JE_drawItem( JE_byte itemType, JE_word itemNum, JE_word x, JE_word y ) |
{ |
JE_word tempW = 0; |
if (itemNum > 0) |
{ |
switch (itemType) |
{ |
case 2: |
case 3: |
tempW = weaponPort[itemNum].itemgraphic; |
break; |
case 5: |
tempW = powerSys[itemNum].itemgraphic; |
break; |
case 6: |
case 7: |
tempW = options[itemNum].itemgraphic; |
break; |
case 4: |
tempW = shields[itemNum].itemgraphic; |
break; |
} |
if (itemType == 1) |
{ |
if (itemNum > 90) |
{ |
shipGrPtr = &shapes9; |
shipGr = JE_SGr(itemNum - 90, &shipGrPtr); |
blit_sprite2x2(VGAScreen, x, y, *shipGrPtr, shipGr); |
} |
else |
{ |
blit_sprite2x2(VGAScreen, x, y, shapes9, ships[itemNum].shipgraphic); |
} |
} |
else if (tempW > 0) |
{ |
blit_sprite2x2(VGAScreen, x, y, shapes6, tempW); |
} |
} |
} |
void JE_drawMenuHeader( void ) |
{ |
switch (curMenu) |
{ |
case 8: |
strcpy(tempStr, cube[curSel[7]-2].header); |
break; |
case 7: |
strcpy(tempStr, menuInt[1][1]); |
break; |
case 6: |
strcpy(tempStr, menuInt[3][performSave + 1]); |
break; |
default: |
strcpy(tempStr, menuInt[curMenu + 1][0]); |
break; |
} |
JE_dString(VGAScreen, 74 + JE_fontCenter(tempStr, FONT_SHAPES), 10, tempStr, FONT_SHAPES); |
} |
void JE_drawMenuChoices( void ) |
{ |
JE_byte x; |
char *str; |
for (x = 2; x <= menuChoices[curMenu]; x++) |
{ |
int tempY = 38 + (x-1) * 16; |
if (curMenu == 0) |
{ |
if (x == 7) |
{ |
tempY += 16; |
} |
} |
if (curMenu == 9) |
{ |
if (x > 3) |
{ |
tempY += 16; |
} |
if (x > 4) |
{ |
tempY += 16; |
} |
} |
if (!(curMenu == 3 && x == menuChoices[curMenu])) |
{ |
tempY -= 16; |
} |
str = malloc(strlen(menuInt[curMenu + 1][x-1])+2); |
if (curSel[curMenu] == x) |
{ |
str[0] = '~'; |
strcpy(str+1, menuInt[curMenu + 1][x-1]); |
} else { |
strcpy(str, menuInt[curMenu + 1][x-1]); |
} |
JE_dString(VGAScreen, 166, tempY, str, SMALL_FONT_SHAPES); |
free(str); |
if (keyboardUsed && curSel[curMenu] == x) |
{ |
set_mouse_position(305, tempY + 6); |
} |
} |
} |
void JE_updateNavScreen( void ) |
{ |
JE_byte x; |
/* minor issues: */ |
/* TODO: The scroll to the new planet is too fast, I think */ |
/* TODO: The starting coordinates for the scrolling effect may be wrong, the |
yellowish planet below Tyrian isn't visible for as many frames as in the |
original. */ |
tempNavX = roundf(navX); |
tempNavY = roundf(navY); |
fill_rectangle_xy(VGAScreen, 19, 16, 135, 169, 2); |
JE_drawNavLines(true); |
JE_drawNavLines(false); |
JE_drawDots(); |
for (x = 0; x < 11; x++) |
JE_drawPlanet(x); |
for (x = 0; x < menuChoices[3]-1; x++) |
{ |
if (mapPlanet[x] > 11) |
JE_drawPlanet(mapPlanet[x] - 1); |
} |
if (mapOrigin > 11) |
JE_drawPlanet(mapOrigin - 1); |
blit_sprite(VGAScreenSeg, 0, 0, OPTION_SHAPES, 28); // navigation screen interface |
if (curSel[3] < menuChoices[3]) |
{ |
const unsigned int origin_x_offset = sprite(PLANET_SHAPES, PGR[mapOrigin-1]-1)->width / 2, |
origin_y_offset = sprite(PLANET_SHAPES, PGR[mapOrigin-1]-1)->height / 2, |
dest_x_offset = sprite(PLANET_SHAPES, PGR[mapPlanet[curSel[3]-2] - 1]-1)->width / 2, |
dest_y_offset = sprite(PLANET_SHAPES, PGR[mapPlanet[curSel[3]-2] - 1]-1)->height / 2; |
newNavX = (planetX[mapOrigin-1] - origin_x_offset |
+ planetX[mapPlanet[curSel[3]-2] - 1] - dest_x_offset) / 2.0f; |
newNavY = (planetY[mapOrigin-1] - origin_y_offset |
+ planetY[mapPlanet[curSel[3]-2] - 1] - dest_y_offset) / 2.0f; |
} |
navX = navX + (newNavX - navX) / 2.0f; |
navY = navY + (newNavY - navY) / 2.0f; |
if (fabsf(newNavX - navX) < 1) |
navX = newNavX; |
if (fabsf(newNavY - navY) < 1) |
navY = newNavY; |
fill_rectangle_xy(VGAScreen, 314, 0, 319, 199, 230); |
if (planetAniWait > 0) |
{ |
planetAniWait--; |
} |
else |
{ |
planetAni++; |
if (planetAni > 14) |
planetAni = 0; |
planetAniWait = 3; |
} |
if (currentDotWait > 0) |
{ |
currentDotWait--; |
} |
else |
{ |
if (currentDotNum < planetDots[curSel[3]-2]) |
currentDotNum++; |
currentDotWait = 5; |
} |
} |
void JE_drawLines( SDL_Surface *surface, JE_boolean dark ) |
{ |
JE_byte x, y; |
JE_integer tempX, tempY; |
JE_integer tempX2, tempY2; |
JE_word tempW, tempW2; |
tempX2 = -10; |
tempY2 = 0; |
tempW = 0; |
for (x = 0; x < 20; x++) |
{ |
tempW += 15; |
tempX = tempW - tempX2; |
if (tempX > 18 && tempX < 135) |
{ |
if (dark) |
{ |
JE_rectangle(surface, tempX + 1, 0, tempX + 1, 199, 32+3); |
} else { |
JE_rectangle(surface, tempX, 0, tempX, 199, 32+5); |
} |
} |
} |
tempW = 0; |
for (y = 0; y < 20; y++) |
{ |
tempW += 15; |
tempY = tempW - tempY2; |
if (tempY > 15 && tempY < 169) |
{ |
if (dark) |
{ |
JE_rectangle(surface, 0, tempY + 1, 319, tempY + 1, 32+3); |
} else { |
JE_rectangle(surface, 0, tempY, 319, tempY, 32+5); |
} |
tempW2 = 0; |
for (x = 0; x < 20; x++) |
{ |
tempW2 += 15; |
tempX = tempW2 - tempX2; |
if (tempX > 18 && tempX < 135) |
{ |
JE_pix3(surface, tempX, tempY, 32+6); |
} |
} |
} |
} |
} |
/* SYN: This was originally PROC drawlines... yes, there were two different procs called |
drawlines in different scopes in the same file. Dammit, Jason, why do you do this to me? */ |
void JE_drawNavLines( JE_boolean dark ) |
{ |
JE_byte x, y; |
JE_integer tempX, tempY; |
JE_integer tempX2, tempY2; |
JE_word tempW, tempW2; |
tempX2 = tempNavX >> 1; |
tempY2 = tempNavY >> 1; |
tempW = 0; |
for (x = 1; x <= 20; x++) |
{ |
tempW += 15; |
tempX = tempW - tempX2; |
if (tempX > 18 && tempX < 135) |
{ |
if (dark) |
JE_rectangle(VGAScreen, tempX + 1, 16, tempX + 1, 169, 1); |
else |
JE_rectangle(VGAScreen, tempX, 16, tempX, 169, 5); |
} |
} |
tempW = 0; |
for (y = 1; y <= 20; y++) |
{ |
tempW += 15; |
tempY = tempW - tempY2; |
if (tempY > 15 && tempY < 169) |
{ |
if (dark) |
JE_rectangle(VGAScreen, 19, tempY + 1, 135, tempY + 1, 1); |
else |
JE_rectangle(VGAScreen, 8, tempY, 160, tempY, 5); |
tempW2 = 0; |
for (x = 0; x < 20; x++) |
{ |
tempW2 += 15; |
tempX = tempW2 - tempX2; |
if (tempX > 18 && tempX < 135) |
JE_pix3(VGAScreen, tempX, tempY, 7); |
} |
} |
} |
} |
void JE_drawDots( void ) |
{ |
JE_byte x, y; |
JE_integer tempX, tempY; |
for (x = 0; x < mapPNum; x++) |
{ |
for (y = 0; y < planetDots[x]; y++) |
{ |
tempX = planetDotX[x][y] - tempNavX + 66 - 2; |
tempY = planetDotY[x][y] - tempNavY + 85 - 2; |
if (tempX > 0 && tempX < 140 && tempY > 0 && tempY < 168) |
blit_sprite(VGAScreenSeg, tempX, tempY, OPTION_SHAPES, (x == curSel[3]-2 && y < currentDotNum) ? 30 : 29); // navigation dots |
} |
} |
} |
void JE_drawPlanet( JE_byte planetNum ) |
{ |
JE_integer tempZ = PGR[planetNum]-1, |
tempX = planetX[planetNum] + 66 - tempNavX - sprite(PLANET_SHAPES, tempZ)->width / 2, |
tempY = planetY[planetNum] + 85 - tempNavY - sprite(PLANET_SHAPES, tempZ)->height / 2; |
if (tempX > -7 && tempX + sprite(PLANET_SHAPES, tempZ)->width < 170 && tempY > 0 && tempY < 160) |
{ |
if (PAni[planetNum]) |
tempZ += planetAni; |
blit_sprite_dark(VGAScreenSeg, tempX + 3, tempY + 3, PLANET_SHAPES, tempZ, false); |
blit_sprite(VGAScreenSeg, tempX, tempY, PLANET_SHAPES, tempZ); // planets |
} |
} |
void JE_scaleBitmap( SDL_Surface *dst_bitmap, const SDL_Surface *src_bitmap, int x1, int y1, int x2, int y2 ) |
{ |
/* This function scales one screen and writes the result to another. |
* The only code that calls it is the code run when you select 'ship |
* specs' from the main menu. |
* |
* Originally this used fixed point math. I haven't seen that in ages :). |
* But we're well past the point of needing that.*/ |
assert(src_bitmap != NULL && dst_bitmap != NULL); |
assert(x1 >= 0 && y1 >= 0 && x2 < src_bitmap->pitch && y2 < src_bitmap->h); |
int w = x2 - x1 + 1, |
h = y2 - y1 + 1; |
float base_skip_w = src_bitmap->pitch / (float)w, |
base_skip_h = src_bitmap->h / (float)h; |
float cumulative_skip_w, cumulative_skip_h; |
//Okay, it's time to loop through and add bits of A to a rectangle in B |
Uint8 *dst = dst_bitmap->pixels; /* 8-bit specific */ |
const Uint8 *src, *src_w; /* 8-bit specific */ |
dst += y1 * dst_bitmap->pitch + x1; |
cumulative_skip_h = 0; |
for (int i = 0; i < h; i++) |
{ |
//this sets src to the beginning of our desired line |
src = src_w = (Uint8 *)(src_bitmap->pixels) + (src_bitmap->w * ((unsigned int)cumulative_skip_h)); |
cumulative_skip_h += base_skip_h; |
cumulative_skip_w = 0; |
for (int j = 0; j < w; j++) |
{ |
//copy and move pointers |
*dst = *src; |
dst++; |
cumulative_skip_w += base_skip_w; |
src = src_w + ((unsigned int)cumulative_skip_w); //value is floored |
} |
dst += dst_bitmap->pitch - w; |
} |
} |
void JE_initWeaponView( void ) |
{ |
fill_rectangle_xy(VGAScreen, 8, 8, 144, 177, 0); |
player[0].sidekick[LEFT_SIDEKICK].x = 72 - 15; |
player[0].sidekick[LEFT_SIDEKICK].y = 120; |
player[0].sidekick[RIGHT_SIDEKICK].x = 72 + 15; |
player[0].sidekick[RIGHT_SIDEKICK].y = 120; |
player[0].x = 72; |
player[0].y = 110; |
player[0].delta_x_shot_move = 0; |
player[0].delta_y_shot_move = 0; |
player[0].last_x_explosion_follow = 72; |
player[0].last_y_explosion_follow = 110; |
power = 500; |
lastPower = 500; |
memset(shotAvail, 0, sizeof(shotAvail)); |
memset(shotRepeat, 1, sizeof(shotRepeat)); |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
initialize_starfield(); |
} |
void JE_computeDots( void ) |
{ |
JE_integer tempX, tempY; |
JE_longint distX, distY; |
JE_byte x, y; |
for (x = 0; x < mapPNum; x++) |
{ |
distX = (int)(planetX[mapPlanet[x]-1]) - (int)(planetX[mapOrigin-1]); |
distY = (int)(planetY[mapPlanet[x]-1]) - (int)(planetY[mapOrigin-1]); |
tempX = abs(distX) + abs(distY); |
if (tempX != 0) |
{ |
planetDots[x] = roundf(sqrtf(sqrtf((distX * distX) + (distY * distY)))) - 1; |
} else { |
planetDots[x] = 0; |
} |
if (planetDots[x] > 10) |
{ |
planetDots[x] = 10; |
} |
for (y = 0; y < planetDots[x]; y++) |
{ |
tempX = JE_partWay(planetX[mapOrigin-1], planetX[mapPlanet[x]-1], planetDots[x], y); |
tempY = JE_partWay(planetY[mapOrigin-1], planetY[mapPlanet[x]-1], planetDots[x], y); |
/* ??? Why does it use temp? =P */ |
planetDotX[x][y] = tempX; |
planetDotY[x][y] = tempY; |
} |
} |
} |
JE_integer JE_partWay( JE_integer start, JE_integer finish, JE_byte dots, JE_byte dist ) |
{ |
return (finish - start) / (dots + 2) * (dist + 1) + start; |
} |
void JE_doShipSpecs( void ) |
{ |
/* This function is called whenever you select 'ship specs' in the |
* game menu. It draws the nice green tech screen and scales it onto |
* the main window. To do this we need two temp buffers, so we're going |
* to use VGAScreen and game_screen for the purpose (making things more |
* complex than they would be if we just malloc'd, but faster) |
* |
* Originally the whole system was pretty oddly designed. So I changed it. |
* Currently drawFunkyScreen creates the image, scaleInPicture draws it, |
* and doFunkyScreen ties everything together. Before it was more like |
* an oddly designed, unreusable, global sharing hierarchy. */ |
//create the image we want |
wait_noinput(true, true, true); |
JE_drawShipSpecs(game_screen, VGAScreen2); |
//reset VGAScreen2, which we clobbered |
JE_loadPic(VGAScreen2, 1, false); |
//draw it |
JE_playSampleNum(S_SPRING); |
JE_scaleInPicture(VGAScreen, game_screen); |
wait_input(true, true, true); |
} |
void JE_drawMainMenuHelpText( void ) |
{ |
char tempStr[67]; |
JE_byte temp; |
temp = curSel[curMenu] - 2; |
if (curMenu == 12) // joystick settings menu help |
{ |
int help[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 11 }; |
memcpy(tempStr, mainMenuHelp[help[curSel[curMenu] - 2]], sizeof(tempStr)); |
} |
else if (curMenu < 3 || curMenu == 9 || curMenu > 10) |
{ |
memcpy(tempStr, mainMenuHelp[(menuHelp[curMenu][temp])-1], sizeof(tempStr)); |
} |
else if (curMenu == 5 && curSel[5] == 10) |
{ |
memcpy(tempStr, mainMenuHelp[25-1], sizeof(tempStr)); |
} |
else if (leftPower || rightPower) |
{ |
memcpy(tempStr, mainMenuHelp[24-1], sizeof(tempStr)); |
} |
else if ( (temp == menuChoices[curMenu] - 1) || ( (curMenu == 7) && (cubeMax == 0) ) ) |
{ |
memcpy(tempStr, mainMenuHelp[12-1], sizeof(tempStr)); |
} |
else |
{ |
memcpy(tempStr, mainMenuHelp[17 + curMenu - 3], sizeof(tempStr)); |
} |
JE_textShade(VGAScreen, 10, 187, tempStr, 14, 1, DARKEN); |
} |
JE_boolean JE_quitRequest( void ) |
{ |
bool quit_selected = true, done = false; |
JE_clearKeyboard(); |
JE_wipeKey(); |
wait_noinput(true, true, true); |
JE_barShade(VGAScreen, 65, 55, 255, 155); |
while (!done) |
{ |
Uint8 col = 8; |
int colC = 1; |
do |
{ |
service_SDL_events(true); |
setjasondelay(4); |
blit_sprite(VGAScreen, 50, 50, OPTION_SHAPES, 35); // message box |
JE_textShade(VGAScreen, 70, 60, miscText[28], 0, 5, FULL_SHADE); |
JE_helpBox(VGAScreen, 70, 90, miscText[30], 30); |
col += colC; |
if (col > 8 || col < 2) |
colC = -colC; |
int temp_x, temp_c; |
temp_x = 54 + 45 - (JE_textWidth(miscText[9], FONT_SHAPES) / 2); |
temp_c = quit_selected ? col - 12 : -5; |
JE_outTextAdjust(VGAScreen, temp_x, 128, miscText[9], 15, temp_c, FONT_SHAPES, true); |
temp_x = 149 + 45 - (JE_textWidth(miscText[10], FONT_SHAPES) / 2); |
temp_c = !quit_selected ? col - 12 : -5; |
JE_outTextAdjust(VGAScreen, temp_x, 128, miscText[10], 15, temp_c, FONT_SHAPES, true); |
if (has_mouse) |
{ |
JE_mouseStart(); |
JE_showVGA(); |
JE_mouseReplace(); |
} |
else |
{ |
JE_showVGA(); |
} |
wait_delay(); |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
} while (!newkey && !mousedown); |
if (mousedown) |
{ |
if (lastmouse_y > 123 && lastmouse_y < 149) |
{ |
if (lastmouse_x > 56 && lastmouse_x < 142) |
{ |
quit_selected = true; |
done = true; |
} |
else if (lastmouse_x > 151 && lastmouse_x < 237) |
{ |
quit_selected = false; |
done = true; |
} |
} |
mousedown = false; |
} |
else if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_LEFT: |
case SDLK_RIGHT: |
case SDLK_TAB: |
quit_selected = !quit_selected; |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_RETURN: |
case SDLK_SPACE: |
done = true; |
break; |
case SDLK_ESCAPE: |
quit_selected = false; |
done = true; |
break; |
default: |
break; |
} |
} |
} |
JE_playSampleNum(quit_selected ? S_SPRING : S_CLICK); |
#ifdef WITH_NETWORK |
if (isNetworkGame && quit_selected) |
{ |
network_prepare(PACKET_QUIT); |
network_send(4); // PACKET QUIT |
network_tyrian_halt(0, true); |
} |
#endif |
return quit_selected; |
} |
void JE_genItemMenu( JE_byte itemNum ) |
{ |
menuChoices[4] = itemAvailMax[itemAvailMap[itemNum - 2] - 1] + 2; |
temp3 = 2; |
temp2 = *playeritem_map(&player[0].items, itemNum - 2); |
strcpy(menuInt[5][0], menuInt[2][itemNum - 1]); |
for (tempW = 0; tempW < itemAvailMax[itemAvailMap[itemNum - 2] - 1]; tempW++) |
{ |
temp = itemAvail[itemAvailMap[itemNum - 2] - 1][tempW]; |
switch (itemNum) |
{ |
case 2: |
strcpy(tempStr, ships[temp].name); |
break; |
case 3: |
case 4: |
strcpy(tempStr, weaponPort[temp].name); |
break; |
case 5: |
strcpy(tempStr, shields[temp].name); |
break; |
case 6: |
strcpy(tempStr, powerSys[temp].name); |
break; |
case 7: |
case 8: |
strcpy(tempStr, options[temp].name); |
break; |
} |
if (temp == temp2) |
{ |
temp3 = tempW + 2; |
} |
strcpy(menuInt[5][tempW], tempStr); |
} |
strcpy(menuInt[5][tempW], miscText[13]); |
curSel[4] = temp3; |
} |
void JE_scaleInPicture( SDL_Surface *dst, const SDL_Surface *src ) |
{ |
for (int i = 2; i <= 160; i += 2) |
{ |
if (JE_anyButton()) { break; } |
JE_scaleBitmap(dst, src, 160 - i, 0, 160 + i - 1, 100 + roundf(i * 0.625f) - 1); |
JE_showVGA(); |
uSDL_Delay(1); |
} |
} |
void JE_drawScore( void ) |
{ |
char cl[24]; |
if (curMenu == 4) |
{ |
sprintf(cl, "%d", JE_cashLeft()); |
JE_textShade(VGAScreen, 65, 173, cl, 1, 6, DARKEN); |
} |
} |
void JE_menuFunction( JE_byte select ) |
{ |
JE_byte x; |
JE_word curSelect; |
col = 0; |
colC = -1; |
JE_playSampleNum(S_CLICK); |
curSelect = curSel[curMenu]; |
switch (curMenu) |
{ |
case 0: //root menu |
switch (select) |
{ |
case 2: //cubes |
curMenu = 7; |
curSel[7] = 2; |
break; |
case 3: //shipspecs |
JE_doShipSpecs(); |
break; |
case 4://upgradeship |
curMenu = 1; |
break; |
case 5: //options |
curMenu = 2; |
break; |
case 6: //nextlevel |
curMenu = 3; |
newPal = 18; |
JE_computeDots(); |
navX = planetX[mapOrigin - 1]; |
navY = planetY[mapOrigin - 1]; |
newNavX = navX; |
newNavY = navY; |
menuChoices[3] = mapPNum + 2; |
curSel[3] = 2; |
strcpy(menuInt[4][0], "Next Level"); |
for (x = 0; x < mapPNum; x++) |
{ |
temp = mapPlanet[x]; |
strcpy(menuInt[4][x + 1], pName[temp - 1]); |
} |
strcpy(menuInt[4][x + 1], miscText[5]); |
break; |
case 7: //quit |
if (JE_quitRequest()) |
{ |
gameLoaded = true; |
mainLevel = 0; |
} |
break; |
} |
break; |
case 1: //upgradeship |
if (select == 9) //done |
{ |
curMenu = 0; |
} |
else // selected item to upgrade |
{ |
old_items[0] = player[0].items; |
lastDirection = 1; |
JE_genItemMenu(select); |
JE_initWeaponView(); |
curMenu = 4; |
lastCurSel = curSel[4]; |
player[0].cash = player[0].cash * 2 - JE_cashLeft(); |
} |
break; |
case 2: //options |
switch (select) |
{ |
case 2: |
curMenu = 6; |
performSave = false; |
quikSave = false; |
break; |
case 3: |
curMenu = 6; |
performSave = true; |
quikSave = false; |
break; |
case 6: |
curMenu = 12; |
break; |
case 7: |
curMenu = 5; |
break; |
case 8: |
curMenu = 0; |
break; |
} |
break; |
case 3: //nextlevel |
if (select == menuChoices[3]) //exit |
{ |
curMenu = 0; |
newPal = 1; |
} else { |
mainLevel = mapSection[curSelect - 2]; |
jumpSection = true; |
} |
break; |
case 4: //buying |
if (curSel[4] < menuChoices[4]) |
{ |
// select done |
curSel[4] = menuChoices[4]; |
} |
else // if done is selected |
{ |
JE_playSampleNum(S_ITEM); |
player[0].cash = JE_cashLeft(); |
curMenu = 1; |
} |
break; |
case 5: /* keyboard settings */ |
if (curSelect == 10) /* reset to defaults */ |
{ |
memcpy(keySettings, defaultKeySettings, sizeof(keySettings)); |
} |
else if (curSelect == 11) /* done */ |
{ |
if (isNetworkGame || onePlayerAction) |
{ |
curMenu = 11; |
} else { |
curMenu = 2; |
} |
} |
else /* change key */ |
{ |
temp2 = 254; |
int tempY = 38 + (curSelect - 2) * 12; |
JE_textShade(VGAScreen, 236, tempY, SDL_GetKeyName(keySettings[curSelect-2]), (temp2 / 16), (temp2 % 16) - 8, DARKEN); |
JE_showVGA(); |
wait_noinput(true, true, true); |
col = 248; |
colC = 1; |
do { |
setjasondelay(1); |
col += colC; |
if (col < 243 || col > 248) |
{ |
colC *= -1; |
} |
JE_rectangle(VGAScreen, 230, tempY - 2, 300, tempY + 7, col); |
poll_joysticks(); |
service_SDL_events(true); |
JE_showVGA(); |
wait_delay(); |
} while (!newkey && !mousedown && !joydown); |
if (newkey) |
{ |
// already used? then swap |
for (uint i = 0; i < COUNTOF(keySettings); ++i) |
{ |
if (keySettings[i] == lastkey_sym) |
{ |
keySettings[i] = keySettings[curSelect-2]; |
break; |
} |
} |
if (lastkey_sym != SDLK_ESCAPE && // reserved for menu |
lastkey_sym != SDLK_F11 && // reserved for gamma |
lastkey_sym != SDLK_p) // reserved for pause |
{ |
JE_playSampleNum(S_CLICK); |
keySettings[curSelect-2] = lastkey_sym; |
++curSelect; |
} |
JE_wipeKey(); |
} |
} |
break; |
case 6: //save |
if (curSelect == 13) |
{ |
if (quikSave) |
{ |
curMenu = oldMenu; |
newPal = oldPal; |
} else { |
curMenu = 2; |
} |
} else { |
if (twoPlayerMode) |
{ |
temp = 11; |
} else { |
temp = 0; |
} |
JE_operation(curSelect - 1 + temp); |
if (quikSave) |
{ |
curMenu = oldMenu; |
newPal = oldPal; |
} |
} |
break; |
case 7: //cubes |
if (curSelect == menuChoices[curMenu]) |
{ |
curMenu = 0; |
newPal = 1; |
} else { |
if (cubeMax > 0) |
{ |
firstMenu9 = true; |
curMenu = 8; |
yLoc = 0; |
yChg = 0; |
currentCube = curSel[7] - 2; |
} else { |
curMenu = 0; |
newPal = 1; |
} |
} |
break; |
case 8: //cubes 2 |
curMenu = 7; |
break; |
case 9: //2player |
switch (curSel[curMenu]) |
{ |
case 2: |
mainLevel = mapSection[mapPNum-1]; |
jumpSection = true; |
break; |
case 3: |
case 4: |
JE_playSampleNum(S_CURSOR); |
int temp = curSel[curMenu] - 3; |
do { |
if (joysticks == 0) |
{ |
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers |
} |
if (inputDevice[temp] >= 2 + joysticks) |
{ |
inputDevice[temp] = 1; |
} else { |
inputDevice[temp]++; |
} |
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]); |
break; |
case 5: |
curMenu = 2; |
break; |
case 6: |
if (JE_quitRequest()) |
{ |
gameLoaded = true; |
mainLevel = 0; |
} |
break; |
} |
break; |
case 10: //arcade |
switch (curSel[curMenu]) |
{ |
case 2: |
mainLevel = mapSection[mapPNum-1]; |
jumpSection = true; |
break; |
case 3: |
curMenu = 2; |
break; |
case 4: |
if (JE_quitRequest()) |
{ |
gameLoaded = true; |
mainLevel = 0; |
} |
break; |
} |
break; |
case 11: //dunno, possibly online multiplayer |
switch (select) |
{ |
case 2: |
curMenu = 12; |
break; |
case 3: |
curMenu = 5; |
break; |
case 6: |
curMenu = 10; |
break; |
} |
break; |
case 12: //joy |
if (joysticks == 0 && select != 17) |
break; |
switch (select) |
{ |
case 2: |
joystick_config++; |
joystick_config %= joysticks; |
break; |
case 3: |
joystick[joystick_config].analog = !joystick[joystick_config].analog; |
break; |
case 4: |
if (joystick[joystick_config].analog) |
{ |
joystick[joystick_config].sensitivity++; |
joystick[joystick_config].sensitivity %= 11; |
} |
break; |
case 5: |
if (joystick[joystick_config].analog) |
{ |
joystick[joystick_config].threshold++; |
joystick[joystick_config].threshold %= 11; |
} |
break; |
case 16: |
reset_joystick_assignments(joystick_config); |
break; |
case 17: |
if (isNetworkGame || onePlayerAction) |
{ |
curMenu = 11; |
} else { |
curMenu = 2; |
} |
break; |
default: |
if (joysticks == 0) |
break; |
// int temp = 254; |
// JE_textShade(VGAScreen, 236, 38 + i * 8, value, temp / 16, temp % 16 - 8, DARKEN); |
JE_rectangle(VGAScreen, 235, 21 + select * 8, 310, 30 + select * 8, 248); |
Joystick_assignment temp; |
if (detect_joystick_assignment(joystick_config, &temp)) |
{ |
// if the detected assignment was already set, unset it |
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++) |
{ |
if (joystick_assignment_cmp(&temp, &joystick[joystick_config].assignment[select - 6][i])) |
{ |
joystick[joystick_config].assignment[select - 6][i].type = NONE; |
goto joystick_assign_done; |
} |
} |
// if there is an empty assignment, set it |
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++) |
{ |
if (joystick[joystick_config].assignment[select - 6][i].type == NONE) |
{ |
joystick[joystick_config].assignment[select - 6][i] = temp; |
goto joystick_assign_done; |
} |
} |
// if no assignments are empty, shift them all forward and set the last one |
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++) |
{ |
if (i == COUNTOF(*joystick->assignment) - 1) |
joystick[joystick_config].assignment[select - 6][i] = temp; |
else |
joystick[joystick_config].assignment[select - 6][i] = joystick[joystick_config].assignment[select - 6][i + 1]; |
} |
joystick_assign_done: |
curSelect++; |
poll_joysticks(); |
} |
} |
break; |
case 13: //engage |
switch (curSel[curMenu]) |
{ |
case 2: |
mainLevel = mapSection[mapPNum-1]; |
jumpSection = true; |
break; |
case 3: |
JE_doShipSpecs(); |
break; |
case 4: |
curMenu = 2; |
break; |
case 5: |
if (JE_quitRequest()) |
{ |
if (isNetworkGame) |
{ |
JE_tyrianHalt(0); |
} |
gameLoaded = true; |
mainLevel = 0; |
} |
} |
break; |
} |
old_items[0] = player[0].items; |
} |
void JE_drawShipSpecs( SDL_Surface * screen, SDL_Surface * temp_screen ) |
{ |
/* In this function we create our ship description image. |
* |
* We use a temp screen for convenience. Bad design maybe (Jason!), |
* but it'll be okay (and the alternative is malloc/a large stack) */ |
int temp_x = 0, temp_y = 0, temp_index; |
Uint8 *src, *dst; |
//first, draw the text and other assorted flavoring. |
JE_clr256(screen); |
JE_drawLines(screen, true); |
JE_drawLines(screen, false); |
JE_rectangle(screen, 0, 0, 319, 199, 37); |
JE_rectangle(screen, 1, 1, 318, 198, 35); |
verticalHeight = 9; |
JE_outText(screen, 10, 2, ships[player[0].items.ship].name, 12, 3); |
JE_helpBox(screen, 100, 20, shipInfo[player[0].items.ship-1][0], 40); |
JE_helpBox(screen, 100, 100, shipInfo[player[0].items.ship-1][1], 40); |
verticalHeight = 7; |
JE_outText(screen, JE_fontCenter(miscText[4], TINY_FONT), 190, miscText[4], 12, 2); |
//now draw the green ship over that. |
//This hardcoded stuff is for positioning our little ship graphic |
if (player[0].items.ship > 90) |
{ |
temp_index = 32; |
} |
else if (player[0].items.ship > 0) |
{ |
temp_index = ships[player[0].items.ship].bigshipgraphic; |
} |
else |
{ |
temp_index = ships[old_items[0].ship].bigshipgraphic; |
} |
switch (temp_index) |
{ |
case 32: |
temp_x = 35; |
temp_y = 33; |
break; |
case 28: |
temp_x = 31; |
temp_y = 36; |
break; |
case 33: |
temp_x = 31; |
temp_y = 35; |
break; |
default: |
assert(0); |
} |
temp_x -= 30; |
//draw the ship into our temp buffer. |
JE_clr256(temp_screen); |
blit_sprite(temp_screen, temp_x, temp_y, OPTION_SHAPES, temp_index - 1); // ship illustration |
/* But wait! Our ship is fully colored, not green! |
* With a little work we could get the sprite dimensions and greenify |
* the area it resides in. For now, let's just greenify the (almost |
* entirely) black screen. |
* We can't work in place. In fact we'll need to overlay the result |
* To avoid our temp screen dependence this has been rewritten to |
* only write one line at a time.*/ |
dst = screen->pixels; |
src = temp_screen->pixels; |
for (int y = 0; y < screen->h; y++) |
{ |
for (int x = 0; x < screen->pitch; x++) |
{ |
int avg = 0; |
if (y > 0) |
avg += *(src - screen->pitch) & 0x0f; |
if (y < screen->h - 1) |
avg += *(src + screen->pitch) & 0x0f; |
if (x > 0) |
avg += *(src - 1) & 0x0f; |
if (x < screen->pitch - 1) |
avg += *(src + 1) & 0x0f; |
avg /= 4; |
if ((*src & 0x0f) > avg) |
{ |
*dst = (*src & 0x0f) | 0xc0; |
//} else { |
// *dst = 0; |
} |
src++; |
dst++; |
} |
} |
} |
void JE_weaponSimUpdate( void ) |
{ |
char buf[32]; |
JE_weaponViewFrame(); |
if ( (curSel[1] == 3 && curSel[4] < menuChoices[4]) || (curSel[1] == 4 && curSel[4] < menuChoices[4] - 1) ) |
{ |
if (leftPower) |
{ |
sprintf(buf, "%d", downgradeCost); |
JE_outText(VGAScreen, 26, 137, buf, 1, 4); |
} |
else |
{ |
blit_sprite(VGAScreenSeg, 24, 149, OPTION_SHAPES, 13); // downgrade disabled |
} |
if (rightPower) |
{ |
if (!rightPowerAfford) |
{ |
sprintf(buf, "%d", upgradeCost); |
JE_outText(VGAScreen, 108, 137, buf, 7, 4); |
blit_sprite(VGAScreenSeg, 119, 149, OPTION_SHAPES, 14); // upgrade disabled |
} |
else |
{ |
sprintf(buf, "%d", upgradeCost); |
JE_outText(VGAScreen, 108, 137, buf, 1, 4); |
} |
} |
else |
{ |
blit_sprite(VGAScreenSeg, 119, 149, OPTION_SHAPES, 14); // upgrade disabled |
} |
temp = player[0].items.weapon[curSel[1]-3].power; |
for (int x = 1; x <= temp; x++) |
{ |
fill_rectangle_xy(VGAScreen, 39 + x * 6, 151, 39 + x * 6 + 4, 151, 251); |
JE_pix(VGAScreen, 39 + x * 6, 151, 252); |
fill_rectangle_xy(VGAScreen, 39 + x * 6, 152, 39 + x * 6 + 4, 164, 250); |
fill_rectangle_xy(VGAScreen, 39 + x * 6, 165, 39 + x * 6 + 4, 165, 249); |
} |
sprintf(buf, "POWER: %d", temp); |
JE_outText(VGAScreen, 58, 137, buf, 15, 4); |
} |
else |
{ |
leftPower = false; |
rightPower = false; |
blit_sprite(VGAScreenSeg, 20, 146, OPTION_SHAPES, 17); // hide power level interface |
} |
JE_drawItem(1, player[0].items.ship, player[0].x - 5, player[0].y - 7); |
} |
void JE_weaponViewFrame( void ) |
{ |
fill_rectangle_xy(VGAScreen, 8, 8, 143, 182, 0); |
/* JE: (* Port Configuration Display *) |
(* drawportconfigbuttons;*/ |
update_and_draw_starfield(VGAScreen, 1); |
mouseX = player[0].x; |
mouseY = player[0].y; |
// create shots in weapon simulator |
for (uint i = 0; i < 2; ++i) |
{ |
if (shotRepeat[i] > 0) |
{ |
--shotRepeat[i]; |
} |
else |
{ |
const uint item = player[0].items.weapon[i].id, |
item_power = player[0].items.weapon[i].power - 1, |
item_mode = (i == REAR_WEAPON) ? player[0].weapon_mode - 1 : 0; |
b = player_shot_create(item, i, player[0].x, player[0].y, mouseX, mouseY, weaponPort[item].op[item_mode][item_power], 1); |
} |
} |
if (options[player[0].items.sidekick[LEFT_SIDEKICK]].wport > 0) |
{ |
if (shotRepeat[SHOT_LEFT_SIDEKICK] > 0) |
{ |
--shotRepeat[SHOT_LEFT_SIDEKICK]; |
} |
else |
{ |
const uint item = player[0].items.sidekick[LEFT_SIDEKICK]; |
const int x = player[0].sidekick[LEFT_SIDEKICK].x, |
y = player[0].sidekick[LEFT_SIDEKICK].y; |
b = player_shot_create(options[item].wport, SHOT_LEFT_SIDEKICK, x, y, mouseX, mouseY, options[item].wpnum, 1); |
} |
} |
if (options[player[0].items.sidekick[RIGHT_SIDEKICK]].tr == 2) |
{ |
player[0].sidekick[RIGHT_SIDEKICK].x = player[0].x; |
player[0].sidekick[RIGHT_SIDEKICK].y = MAX(10, player[0].y - 20); |
} |
else |
{ |
player[0].sidekick[RIGHT_SIDEKICK].x = 72 + 15; |
player[0].sidekick[RIGHT_SIDEKICK].y = 120; |
} |
if (options[player[0].items.sidekick[RIGHT_SIDEKICK]].wport > 0) |
{ |
if (shotRepeat[SHOT_RIGHT_SIDEKICK] > 0) |
{ |
--shotRepeat[SHOT_RIGHT_SIDEKICK]; |
} |
else |
{ |
const uint item = player[0].items.sidekick[RIGHT_SIDEKICK]; |
const int x = player[0].sidekick[RIGHT_SIDEKICK].x, |
y = player[0].sidekick[RIGHT_SIDEKICK].y; |
b = player_shot_create(options[item].wport, SHOT_RIGHT_SIDEKICK, x, y, mouseX, mouseY, options[item].wpnum, 1); |
} |
} |
simulate_player_shots(); |
blit_sprite(VGAScreenSeg, 0, 0, OPTION_SHAPES, 12); // upgrade interface |
/*========================Power Bar=========================*/ |
power += powerAdd; |
if (power > 900) |
power = 900; |
temp = power / 10; |
for (temp = 147 - temp; temp <= 146; temp++) |
{ |
temp2 = 113 + (146 - temp) / 9 + 2; |
temp3 = (temp + 1) % 6; |
if (temp3 == 1) |
temp2 += 3; |
else if (temp3 != 0) |
temp2 += 2; |
JE_pix(VGAScreen, 141, temp, temp2 - 3); |
JE_pix(VGAScreen, 142, temp, temp2 - 3); |
JE_pix(VGAScreen, 143, temp, temp2 - 2); |
JE_pix(VGAScreen, 144, temp, temp2 - 1); |
fill_rectangle_xy(VGAScreen, 145, temp, 149, temp, temp2); |
if (temp2 - 3 < 112) |
temp2++; |
} |
temp = 147 - (power / 10); |
temp2 = 113 + (146 - temp) / 9 + 4; |
JE_pix(VGAScreen, 141, temp - 1, temp2 - 1); |
JE_pix(VGAScreen, 142, temp - 1, temp2 - 1); |
JE_pix(VGAScreen, 143, temp - 1, temp2 - 1); |
JE_pix(VGAScreen, 144, temp - 1, temp2 - 1); |
fill_rectangle_xy(VGAScreen, 145, temp-1, 149, temp-1, temp2); |
lastPower = temp; |
//JE_waitFrameCount(); TODO: didn't do anything? |
} |
/contrib/games/opentyrian/src/game_menu.h |
---|
0,0 → 1,58 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef GAME_MENU_H |
#define GAME_MENU_H |
#include "helptext.h" |
#include "opentyr.h" |
typedef JE_byte JE_MenuChoiceType[MENU_MAX]; |
JE_longint JE_cashLeft( void ); |
void JE_itemScreen( void ); |
void load_cubes( void ); |
bool load_cube( int cube_slot, int cube_index ); |
void JE_drawItem( JE_byte itemType, JE_word itemNum, JE_word x, JE_word y ); |
void JE_drawMenuHeader( void ); |
void JE_drawMenuChoices( void ); |
void JE_updateNavScreen( void ); |
void JE_drawNavLines( JE_boolean dark ); |
void JE_drawLines( SDL_Surface *surface, JE_boolean dark ); |
void JE_drawDots( void ); |
void JE_drawPlanet( JE_byte planetNum ); |
void draw_ship_illustration( void ); |
void JE_scaleBitmap( SDL_Surface *dst, const SDL_Surface *src, int x1, int y1, int x2, int y2 ); |
void JE_initWeaponView( void ); |
void JE_computeDots( void ); |
JE_integer JE_partWay( JE_integer start, JE_integer finish, JE_byte dots, JE_byte dist ); |
void JE_doShipSpecs( void ); |
void JE_drawMainMenuHelpText( void ); |
JE_boolean JE_quitRequest( void ); |
void JE_genItemMenu( JE_byte itemnum ); |
void JE_scaleInPicture( SDL_Surface *dst, const SDL_Surface *src ); |
void JE_drawScore( void ); |
void JE_menuFunction( JE_byte select ); |
void JE_drawShipSpecs( SDL_Surface *, SDL_Surface * ); |
void JE_weaponSimUpdate( void ); |
void JE_weaponViewFrame( void ); |
#endif // GAME_MENU_H |
/contrib/games/opentyrian/src/helptext.c |
---|
0,0 → 1,381 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "helptext.h" |
#include "config.h" |
#include "episodes.h" |
#include "file.h" |
#include "fonthand.h" |
#include "menus.h" |
#include "opentyr.h" |
#include "video.h" |
#include <assert.h> |
#include <string.h> |
const JE_byte menuHelp[MENU_MAX][11] = /* [1..maxmenu, 1..11] */ |
{ |
{ 1, 34, 2, 3, 4, 5, 0, 0, 0, 0, 0 }, |
{ 6, 7, 8, 9, 10, 11, 11, 12, 0, 0, 0 }, |
{ 13, 14, 15, 15, 16, 17, 12, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 4, 30, 30, 3, 5, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 16, 17, 15, 15, 12, 0, 0, 0, 0, 0, 0 }, |
{ 31, 31, 31, 31, 32, 12, 0, 0, 0, 0, 0 }, |
{ 4, 34, 3, 5, 0, 0, 0, 0, 0, 0, 0 } |
}; |
JE_byte verticalHeight = 7; |
JE_byte helpBoxColor = 12; |
JE_byte helpBoxBrightness = 1; |
JE_byte helpBoxShadeType = FULL_SHADE; |
char helpTxt[39][231]; /* [1..39] of string [230] */ |
char pName[21][16]; /* [1..21] of string [15] */ |
char miscText[HELPTEXT_MISCTEXT_COUNT][42]; /* [1..68] of string [41] */ |
char miscTextB[HELPTEXT_MISCTEXTB_COUNT][HELPTEXT_MISCTEXTB_SIZE]; /* [1..5] of string [10] */ |
char keyName[8][18]; /* [1..8] of string [17] */ |
char menuText[7][HELPTEXT_MENUTEXT_SIZE]; /* [1..7] of string [20] */ |
char outputs[9][31]; /* [1..9] of string [30] */ |
char topicName[6][21]; /* [1..6] of string [20] */ |
char mainMenuHelp[HELPTEXT_MAINMENUHELP_COUNT][66]; /* [1..34] of string [65] */ |
char inGameText[6][21]; /* [1..6] of string [20] */ |
char detailLevel[6][13]; /* [1..6] of string [12] */ |
char gameSpeedText[5][13]; /* [1..5] of string [12] */ |
char inputDevices[3][13]; /* [1..3] of string [12] */ |
char networkText[HELPTEXT_NETWORKTEXT_COUNT][HELPTEXT_NETWORKTEXT_SIZE]; /* [1..4] of string [20] */ |
char difficultyNameB[11][21]; /* [0..9] of string [20] */ |
char joyButtonNames[5][21]; /* [1..5] of string [20] */ |
char superShips[HELPTEXT_SUPERSHIPS_COUNT][26]; /* [0..10] of string [25] */ |
char specialName[HELPTEXT_SPECIALNAME_COUNT][10]; /* [1..9] of string [9] */ |
char destructHelp[25][22]; /* [1..25] of string [21] */ |
char weaponNames[17][17]; /* [1..17] of string [16] */ |
char destructModeName[DESTRUCT_MODES][13]; /* [1..destructmodes] of string [12] */ |
char shipInfo[HELPTEXT_SHIPINFO_COUNT][2][256]; /* [1..13, 1..2] of string */ |
char menuInt[MENU_MAX+1][11][18]; /* [0..14, 1..11] of string [17] */ |
void decrypt_pascal_string( char *s, int len ) |
{ |
static const unsigned char crypt_key[] = { 204, 129, 63, 255, 71, 19, 25, 62, 1, 99 }; |
for (int i = len - 1; i >= 0; --i) |
{ |
s[i] ^= crypt_key[i % sizeof(crypt_key)]; |
if (i > 0) |
s[i] ^= s[i - 1]; |
} |
} |
void read_encrypted_pascal_string( char *s, int size, FILE *f ) |
{ |
int len = getc(f); |
if (len != EOF) |
{ |
int skip = MAX((len + 1) - size, 0); |
assert(skip == 0); |
len -= skip; |
efread(s, 1, len, f); |
if (size > 0) |
s[len] = '\0'; |
fseek(f, skip, SEEK_CUR); |
decrypt_pascal_string(s, len); |
} |
} |
void skip_pascal_string( FILE *f ) |
{ |
int len = getc(f); |
fseek(f, len, SEEK_CUR); |
} |
void JE_helpBox( SDL_Surface *screen, int x, int y, const char *message, unsigned int boxwidth ) |
{ |
JE_byte startpos, endpos, pos; |
JE_boolean endstring; |
char substring[256]; |
if (strlen(message) == 0) |
{ |
return; |
} |
pos = 1; |
endpos = 0; |
endstring = false; |
do |
{ |
startpos = endpos + 1; |
do |
{ |
endpos = pos; |
do |
{ |
pos++; |
if (pos == strlen(message)) |
{ |
endstring = true; |
if ((unsigned)(pos - startpos) < boxwidth) |
{ |
endpos = pos + 1; |
} |
} |
} while (!(message[pos-1] == ' ' || endstring)); |
} while (!((unsigned)(pos - startpos) > boxwidth || endstring)); |
SDL_strlcpy(substring, message + startpos - 1, MIN((size_t)(endpos - startpos + 1), sizeof(substring))); |
JE_textShade(screen, x, y, substring, helpBoxColor, helpBoxBrightness, helpBoxShadeType); |
y += verticalHeight; |
} while (!endstring); |
if (endpos != pos + 1) |
{ |
JE_textShade(screen, x, y, message + endpos, helpBoxColor, helpBoxBrightness, helpBoxShadeType); |
} |
helpBoxColor = 12; |
helpBoxShadeType = FULL_SHADE; |
} |
void JE_HBox( SDL_Surface *screen, int x, int y, unsigned int messagenum, unsigned int boxwidth ) |
{ |
JE_helpBox(screen, x, y, helpTxt[messagenum-1], boxwidth); |
} |
void JE_loadHelpText( void ) |
{ |
const unsigned int menuInt_entries[MENU_MAX + 1] = { -1, 7, 9, 8, -1, -1, 11, -1, -1, -1, 6, 4, 6, 7, 5 }; |
FILE *f = dir_fopen_die(data_dir(), "tyrian.hdt", "rb"); |
efread(&episode1DataLoc, sizeof(JE_longint), 1, f); |
/*Online Help*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(helpTxt); ++i) |
read_encrypted_pascal_string(helpTxt[i], sizeof(helpTxt[i]), f); |
skip_pascal_string(f); |
/*Planet names*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(pName); ++i) |
read_encrypted_pascal_string(pName[i], sizeof(pName[i]), f); |
skip_pascal_string(f); |
/*Miscellaneous text*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(miscText); ++i) |
read_encrypted_pascal_string(miscText[i], sizeof(miscText[i]), f); |
skip_pascal_string(f); |
/*Little Miscellaneous text*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(miscTextB); ++i) |
read_encrypted_pascal_string(miscTextB[i], sizeof(miscTextB[i]), f); |
skip_pascal_string(f); |
/*Key names*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[6]; ++i) |
read_encrypted_pascal_string(menuInt[6][i], sizeof(menuInt[6][i]), f); |
skip_pascal_string(f); |
/*Main Menu*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(menuText); ++i) |
read_encrypted_pascal_string(menuText[i], sizeof(menuText[i]), f); |
skip_pascal_string(f); |
/*Event text*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(outputs); ++i) |
read_encrypted_pascal_string(outputs[i], sizeof(outputs[i]), f); |
skip_pascal_string(f); |
/*Help topics*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(topicName); ++i) |
read_encrypted_pascal_string(topicName[i], sizeof(topicName[i]), f); |
skip_pascal_string(f); |
/*Main Menu Help*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(mainMenuHelp); ++i) |
read_encrypted_pascal_string(mainMenuHelp[i], sizeof(mainMenuHelp[i]), f); |
skip_pascal_string(f); |
/*Menu 1 - Main*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[1]; ++i) |
read_encrypted_pascal_string(menuInt[1][i], sizeof(menuInt[1][i]), f); |
skip_pascal_string(f); |
/*Menu 2 - Items*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[2]; ++i) |
read_encrypted_pascal_string(menuInt[2][i], sizeof(menuInt[2][i]), f); |
skip_pascal_string(f); |
/*Menu 3 - Options*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[3]; ++i) |
read_encrypted_pascal_string(menuInt[3][i], sizeof(menuInt[3][i]), f); |
skip_pascal_string(f); |
/*InGame Menu*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(inGameText); ++i) |
read_encrypted_pascal_string(inGameText[i], sizeof(inGameText[i]), f); |
skip_pascal_string(f); |
/*Detail Level*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(detailLevel); ++i) |
read_encrypted_pascal_string(detailLevel[i], sizeof(detailLevel[i]), f); |
skip_pascal_string(f); |
/*Game speed text*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(gameSpeedText); ++i) |
read_encrypted_pascal_string(gameSpeedText[i], sizeof(gameSpeedText[i]), f); |
skip_pascal_string(f); |
// episode names |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(episode_name); ++i) |
read_encrypted_pascal_string(episode_name[i], sizeof(episode_name[i]), f); |
skip_pascal_string(f); |
// difficulty names |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(difficulty_name); ++i) |
read_encrypted_pascal_string(difficulty_name[i], sizeof(difficulty_name[i]), f); |
skip_pascal_string(f); |
// gameplay mode names |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(gameplay_name); ++i) |
read_encrypted_pascal_string(gameplay_name[i], sizeof(gameplay_name[i]), f); |
skip_pascal_string(f); |
/*Menu 10 - 2Player Main*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[10]; ++i) |
read_encrypted_pascal_string(menuInt[10][i], sizeof(menuInt[10][i]), f); |
skip_pascal_string(f); |
/*Input Devices*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(inputDevices); ++i) |
read_encrypted_pascal_string(inputDevices[i], sizeof(inputDevices[i]), f); |
skip_pascal_string(f); |
/*Network text*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(networkText); ++i) |
read_encrypted_pascal_string(networkText[i], sizeof(networkText[i]), f); |
skip_pascal_string(f); |
/*Menu 11 - 2Player Network*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[11]; ++i) |
read_encrypted_pascal_string(menuInt[11][i], sizeof(menuInt[11][i]), f); |
skip_pascal_string(f); |
/*HighScore Difficulty Names*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(difficultyNameB); ++i) |
read_encrypted_pascal_string(difficultyNameB[i], sizeof(difficultyNameB[i]), f); |
skip_pascal_string(f); |
/*Menu 12 - Network Options*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[12]; ++i) |
read_encrypted_pascal_string(menuInt[12][i], sizeof(menuInt[12][i]), f); |
skip_pascal_string(f); |
/*Menu 13 - Joystick*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < menuInt_entries[13]; ++i) |
read_encrypted_pascal_string(menuInt[13][i], sizeof(menuInt[13][i]), f); |
skip_pascal_string(f); |
/*Joystick Button Assignments*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(joyButtonNames); ++i) |
read_encrypted_pascal_string(joyButtonNames[i], sizeof(joyButtonNames[i]), f); |
skip_pascal_string(f); |
/*SuperShips - For Super Arcade Mode*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(superShips); ++i) |
read_encrypted_pascal_string(superShips[i], sizeof(superShips[i]), f); |
skip_pascal_string(f); |
/*SuperShips - For Super Arcade Mode*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(specialName); ++i) |
read_encrypted_pascal_string(specialName[i], sizeof(specialName[i]), f); |
skip_pascal_string(f); |
/*Secret DESTRUCT game*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(destructHelp); ++i) |
read_encrypted_pascal_string(destructHelp[i], sizeof(destructHelp[i]), f); |
skip_pascal_string(f); |
/*Secret DESTRUCT weapons*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(weaponNames); ++i) |
read_encrypted_pascal_string(weaponNames[i], sizeof(weaponNames[i]), f); |
skip_pascal_string(f); |
/*Secret DESTRUCT modes*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(destructModeName); ++i) |
read_encrypted_pascal_string(destructModeName[i], sizeof(destructModeName[i]), f); |
skip_pascal_string(f); |
/*NEW: Ship Info*/ |
skip_pascal_string(f); |
for (unsigned int i = 0; i < COUNTOF(shipInfo); ++i) |
{ |
read_encrypted_pascal_string(shipInfo[i][0], sizeof(shipInfo[i][0]), f); |
read_encrypted_pascal_string(shipInfo[i][1], sizeof(shipInfo[i][1]), f); |
} |
skip_pascal_string(f); |
fclose(f); |
} |
/contrib/games/opentyrian/src/helptext.h |
---|
0,0 → 1,80 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef HELPTEXT_H |
#define HELPTEXT_H |
#include "opentyr.h" |
#include "SDL.h" |
#include <stdio.h> |
#define MENU_MAX 14 |
#define DESTRUCT_MODES 5 |
extern const JE_byte menuHelp[MENU_MAX][11]; /* [1..14, 1..11] */ |
extern JE_byte verticalHeight; |
extern JE_byte helpBoxColor, helpBoxBrightness, helpBoxShadeType; |
#define HELPTEXT_MISCTEXT_COUNT 68 |
#define HELPTEXT_MISCTEXTB_COUNT 5 |
#define HELPTEXT_MISCTEXTB_SIZE 11 |
#define HELPTEXT_MENUTEXT_SIZE 21 |
#define HELPTEXT_MAINMENUHELP_COUNT 34 |
#define HELPTEXT_NETWORKTEXT_COUNT 4 |
#define HELPTEXT_NETWORKTEXT_SIZE 22 |
#define HELPTEXT_SUPERSHIPS_COUNT 11 |
#define HELPTEXT_SPECIALNAME_COUNT 9 |
#define HELPTEXT_SHIPINFO_COUNT 13 |
extern char helpTxt[39][231]; |
extern char pName[21][16]; |
extern char miscText[HELPTEXT_MISCTEXT_COUNT][42]; |
extern char miscTextB[HELPTEXT_MISCTEXTB_COUNT][HELPTEXT_MISCTEXTB_SIZE]; |
extern char keyName[8][18]; |
extern char menuText[7][HELPTEXT_MENUTEXT_SIZE]; |
extern char outputs[9][31]; |
extern char topicName[6][21]; |
extern char mainMenuHelp[HELPTEXT_MAINMENUHELP_COUNT][66]; |
extern char inGameText[6][21]; |
extern char detailLevel[6][13]; |
extern char gameSpeedText[5][13]; |
extern char inputDevices[3][13]; |
extern char networkText[HELPTEXT_NETWORKTEXT_COUNT][HELPTEXT_NETWORKTEXT_SIZE]; |
extern char difficultyNameB[11][21]; |
extern char joyButtonNames[5][21]; |
extern char superShips[HELPTEXT_SUPERSHIPS_COUNT][26]; |
extern char specialName[HELPTEXT_SPECIALNAME_COUNT][10]; |
extern char destructHelp[25][22]; |
extern char weaponNames[17][17]; |
extern char destructModeName[DESTRUCT_MODES][13]; |
extern char shipInfo[HELPTEXT_SHIPINFO_COUNT][2][256]; |
extern char menuInt[MENU_MAX+1][11][18]; |
void read_encrypted_pascal_string( char *s, int size, FILE *f ); |
void skip_pascal_string( FILE *f ); |
void JE_helpBox( SDL_Surface *screen, int x, int y, const char *message, unsigned int boxwidth ); |
void JE_HBox( SDL_Surface *screen, int x, int y, unsigned int messagenum, unsigned int boxwidth ); |
void JE_loadHelpText( void ); |
#endif /* HELPTEXT_H */ |
/contrib/games/opentyrian/src/joystick.c |
---|
0,0 → 1,653 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "joystick.h" |
#include "config.h" |
#include "config_file.h" |
#include "file.h" |
#include "keyboard.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "params.h" |
#include "varz.h" |
#include "video.h" |
#include <assert.h> |
#include <ctype.h> |
#include <string.h> |
int joystick_axis_threshold( int j, int value ); |
int check_assigned( SDL_Joystick *joystick_handle, const Joystick_assignment assignment[2] ); |
const char *assignment_to_code( const Joystick_assignment *assignment ); |
void code_to_assignment( Joystick_assignment *assignment, const char *buffer ); |
int joystick_repeat_delay = 300; // milliseconds, repeat delay for buttons |
bool joydown = false; // any joystick buttons down, updated by poll_joysticks() |
bool ignore_joystick = false; |
int joysticks = 0; |
Joystick *joystick = NULL; |
static const int joystick_analog_max = 32767; |
// eliminates axis movement below the threshold |
int joystick_axis_threshold( int j, int value ) |
{ |
assert(j < joysticks); |
bool negative = value < 0; |
if (negative) |
value = -value; |
if (value <= joystick[j].threshold * 1000) |
return 0; |
value -= joystick[j].threshold * 1000; |
return negative ? -value : value; |
} |
// converts joystick axis to sane Tyrian-usable value (based on sensitivity) |
int joystick_axis_reduce( int j, int value ) |
{ |
assert(j < joysticks); |
value = joystick_axis_threshold(j, value); |
if (value == 0) |
return 0; |
return value / (3000 - 200 * joystick[j].sensitivity); |
} |
// converts analog joystick axes to an angle |
// returns false if axes are centered (there is no angle) |
bool joystick_analog_angle( int j, float *angle ) |
{ |
assert(j < joysticks); |
float x = joystick_axis_threshold(j, joystick[j].x), y = joystick_axis_threshold(j, joystick[j].y); |
if (x != 0) |
{ |
*angle += atanf(-y / x); |
*angle += (x < 0) ? -M_PI_2 : M_PI_2; |
return true; |
} |
else if (y != 0) |
{ |
*angle += y < 0 ? M_PI : 0; |
return true; |
} |
return false; |
} |
/* gives back value 0..joystick_analog_max indicating that one of the assigned |
* buttons has been pressed or that one of the assigned axes/hats has been moved |
* in the assigned direction |
*/ |
int check_assigned( SDL_Joystick *joystick_handle, const Joystick_assignment assignment[2] ) |
{ |
int result = 0; |
for (int i = 0; i < 2; i++) |
{ |
int temp = 0; |
switch (assignment[i].type) |
{ |
case NONE: |
continue; |
case AXIS: |
temp = SDL_JoystickGetAxis(joystick_handle, assignment[i].num); |
if (assignment[i].negative_axis) |
temp = -temp; |
break; |
case BUTTON: |
temp = SDL_JoystickGetButton(joystick_handle, assignment[i].num) == 1 ? joystick_analog_max : 0; |
break; |
case HAT: |
temp = SDL_JoystickGetHat(joystick_handle, assignment[i].num); |
if (assignment[i].x_axis) |
temp &= SDL_HAT_LEFT | SDL_HAT_RIGHT; |
else |
temp &= SDL_HAT_UP | SDL_HAT_DOWN; |
if (assignment[i].negative_axis) |
temp &= SDL_HAT_LEFT | SDL_HAT_UP; |
else |
temp &= SDL_HAT_RIGHT | SDL_HAT_DOWN; |
temp = temp ? joystick_analog_max : 0; |
break; |
} |
if (temp > result) |
result = temp; |
} |
return result; |
} |
// updates joystick state |
void poll_joystick( int j ) |
{ |
assert(j < joysticks); |
if (joystick[j].handle == NULL) |
return; |
SDL_JoystickUpdate(); |
// indicates that a direction/action was pressed since last poll |
joystick[j].input_pressed = false; |
// indicates that an direction/action has been held long enough to fake a repeat press |
bool repeat = joystick[j].joystick_delay < SDL_GetTicks(); |
// update direction state |
for (uint d = 0; d < COUNTOF(joystick[j].direction); d++) |
{ |
bool old = joystick[j].direction[d]; |
joystick[j].analog_direction[d] = check_assigned(joystick[j].handle, joystick[j].assignment[d]); |
joystick[j].direction[d] = joystick[j].analog_direction[d] > (joystick_analog_max / 2); |
joydown |= joystick[j].direction[d]; |
joystick[j].direction_pressed[d] = joystick[j].direction[d] && (!old || repeat); |
joystick[j].input_pressed |= joystick[j].direction_pressed[d]; |
} |
joystick[j].x = -joystick[j].analog_direction[3] + joystick[j].analog_direction[1]; |
joystick[j].y = -joystick[j].analog_direction[0] + joystick[j].analog_direction[2]; |
// update action state |
for (uint d = 0; d < COUNTOF(joystick[j].action); d++) |
{ |
bool old = joystick[j].action[d]; |
joystick[j].action[d] = check_assigned(joystick[j].handle, joystick[j].assignment[d + COUNTOF(joystick[j].direction)]) > (joystick_analog_max / 2); |
joydown |= joystick[j].action[d]; |
joystick[j].action_pressed[d] = joystick[j].action[d] && (!old || repeat); |
joystick[j].input_pressed |= joystick[j].action_pressed[d]; |
} |
joystick[j].confirm = joystick[j].action[0] || joystick[j].action[4]; |
joystick[j].cancel = joystick[j].action[1] || joystick[j].action[5]; |
// if new input, reset press-repeat delay |
if (joystick[j].input_pressed) |
joystick[j].joystick_delay = SDL_GetTicks() + joystick_repeat_delay; |
} |
// updates all joystick states |
void poll_joysticks( void ) |
{ |
joydown = false; |
for (int j = 0; j < joysticks; j++) |
poll_joystick(j); |
} |
// sends SDL KEYDOWN and KEYUP events for a key |
void push_key( SDLKey key ) |
{ |
SDL_Event e; |
memset(&e.key.keysym, 0, sizeof(e.key.keysym)); |
e.key.keysym.sym = key; |
e.key.keysym.unicode = key; |
e.key.state = SDL_RELEASED; |
e.type = SDL_KEYDOWN; |
SDL_PushEvent(&e); |
e.type = SDL_KEYUP; |
SDL_PushEvent(&e); |
} |
// helps us be lazy by pretending joysticks are a keyboard (useful for menus) |
void push_joysticks_as_keyboard( void ) |
{ |
const SDLKey confirm = SDLK_RETURN, cancel = SDLK_ESCAPE; |
const SDLKey direction[4] = { SDLK_UP, SDLK_RIGHT, SDLK_DOWN, SDLK_LEFT }; |
poll_joysticks(); |
for (int j = 0; j < joysticks; j++) |
{ |
if (!joystick[j].input_pressed) |
continue; |
if (joystick[j].confirm) |
push_key(confirm); |
if (joystick[j].cancel) |
push_key(cancel); |
for (uint d = 0; d < COUNTOF(joystick[j].direction_pressed); d++) |
{ |
if (joystick[j].direction_pressed[d]) |
push_key(direction[d]); |
} |
} |
} |
// initializes SDL joystick system and loads assignments for joysticks found |
void init_joysticks( void ) |
{ |
if (ignore_joystick) |
return; |
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK)) |
{ |
fprintf(stderr, "warning: failed to initialize joystick system: %s\n", SDL_GetError()); |
ignore_joystick = true; |
return; |
} |
SDL_JoystickEventState(SDL_IGNORE); |
joysticks = SDL_NumJoysticks(); |
joystick = malloc(joysticks * sizeof(*joystick)); |
for (int j = 0; j < joysticks; j++) |
{ |
memset(&joystick[j], 0, sizeof(*joystick)); |
joystick[j].handle = SDL_JoystickOpen(j); |
if (joystick[j].handle != NULL) |
{ |
printf("joystick detected: %s ", SDL_JoystickName(j)); |
printf("(%d axes, %d buttons, %d hats)\n", |
SDL_JoystickNumAxes(joystick[j].handle), |
SDL_JoystickNumButtons(joystick[j].handle), |
SDL_JoystickNumHats(joystick[j].handle)); |
if (!load_joystick_assignments(&opentyrian_config, j)) |
reset_joystick_assignments(j); |
} |
} |
if (joysticks == 0) |
printf("no joysticks detected\n"); |
} |
// deinitializes SDL joystick system and saves joystick assignments |
void deinit_joysticks( void ) |
{ |
if (ignore_joystick) |
return; |
for (int j = 0; j < joysticks; j++) |
{ |
if (joystick[j].handle != NULL) |
{ |
save_joystick_assignments(&opentyrian_config, j); |
SDL_JoystickClose(joystick[j].handle); |
} |
} |
free(joystick); |
SDL_QuitSubSystem(SDL_INIT_JOYSTICK); |
} |
void reset_joystick_assignments( int j ) |
{ |
assert(j < joysticks); |
// defaults: first 2 axes, first hat, first 6 buttons |
for (uint a = 0; a < COUNTOF(joystick[j].assignment); a++) |
{ |
// clear assignments |
for (uint i = 0; i < COUNTOF(joystick[j].assignment[a]); i++) |
joystick[j].assignment[a][i].type = NONE; |
if (a < 4) |
{ |
if (SDL_JoystickNumAxes(joystick[j].handle) >= 2) |
{ |
joystick[j].assignment[a][0].type = AXIS; |
joystick[j].assignment[a][0].num = (a + 1) % 2; |
joystick[j].assignment[a][0].negative_axis = (a == 0 || a == 3); |
} |
if (SDL_JoystickNumHats(joystick[j].handle) >= 1) |
{ |
joystick[j].assignment[a][1].type = HAT; |
joystick[j].assignment[a][1].num = 0; |
joystick[j].assignment[a][1].x_axis = (a == 1 || a == 3); |
joystick[j].assignment[a][1].negative_axis = (a == 0 || a == 3); |
} |
} |
else |
{ |
if (a - 4 < (unsigned)SDL_JoystickNumButtons(joystick[j].handle)) |
{ |
joystick[j].assignment[a][0].type = BUTTON; |
joystick[j].assignment[a][0].num = a - 4; |
} |
} |
} |
joystick[j].analog = false; |
joystick[j].sensitivity = 5; |
joystick[j].threshold = 5; |
} |
static const char* const assignment_names[] = |
{ |
"up", |
"right", |
"down", |
"left", |
"fire", |
"change fire", |
"left sidekick", |
"right sidekick", |
"menu", |
"pause", |
}; |
bool load_joystick_assignments( Config *config, int j ) |
{ |
ConfigSection *section = config_find_section(config, "joystick", SDL_JoystickName(j)); |
if (section == NULL) |
return false; |
if (!config_get_bool_option(section, "analog", &joystick[j].analog)) |
joystick[j].analog = false; |
joystick[j].sensitivity = config_get_or_set_int_option(section, "sensitivity", 5); |
joystick[j].threshold = config_get_or_set_int_option(section, "threshold", 5); |
for (size_t a = 0; a < COUNTOF(assignment_names); ++a) |
{ |
for (unsigned int i = 0; i < COUNTOF(joystick[j].assignment[a]); ++i) |
joystick[j].assignment[a][i].type = NONE; |
ConfigOption *option = config_get_option(section, assignment_names[a]); |
if (option == NULL) |
continue; |
foreach_option_i_value(i, value, option) |
{ |
if (i >= COUNTOF(joystick[j].assignment[a])) |
break; |
code_to_assignment(&joystick[j].assignment[a][i], value); |
} |
} |
return true; |
} |
bool save_joystick_assignments( Config *config, int j ) |
{ |
ConfigSection *section = config_find_or_add_section(config, "joystick", SDL_JoystickName(j)); |
if (section == NULL) |
exit(EXIT_FAILURE); // out of memory |
config_set_bool_option(section, "analog", joystick[j].analog, NO_YES); |
config_set_int_option(section, "sensitivity", joystick[j].sensitivity); |
config_set_int_option(section, "threshold", joystick[j].threshold); |
for (size_t a = 0; a < COUNTOF(assignment_names); ++a) |
{ |
ConfigOption *option = config_set_option(section, assignment_names[a], NULL); |
if (option == NULL) |
exit(EXIT_FAILURE); // out of memory |
option = config_set_value(option, NULL); |
if (option == NULL) |
exit(EXIT_FAILURE); // out of memory |
for (size_t i = 0; i < COUNTOF(joystick[j].assignment[a]); ++i) |
{ |
if (joystick[j].assignment[a][i].type == NONE) |
continue; |
option = config_add_value(option, assignment_to_code(&joystick[j].assignment[a][i])); |
if (option == NULL) |
exit(EXIT_FAILURE); // out of memory |
} |
} |
return true; |
} |
// fills buffer with comma separated list of assigned joystick functions |
void joystick_assignments_to_string( char *buffer, size_t buffer_len, const Joystick_assignment *assignments ) |
{ |
strncpy(buffer, "", buffer_len); |
bool comma = false; |
for (uint i = 0; i < COUNTOF(*joystick->assignment); ++i) |
{ |
if (assignments[i].type == NONE) |
continue; |
size_t len = snprintf(buffer, buffer_len, "%s%s", |
comma ? ", " : "", |
assignment_to_code(&assignments[i])); |
buffer += len; |
buffer_len -= len; |
comma = true; |
} |
} |
// reverse of assignment_to_code() |
void code_to_assignment( Joystick_assignment *assignment, const char *buffer ) |
{ |
memset(assignment, 0, sizeof(*assignment)); |
char axis = 0, direction = 0; |
if (sscanf(buffer, " AX %d%c", &assignment->num, &direction) == 2) |
assignment->type = AXIS; |
else if (sscanf(buffer, " BTN %d", &assignment->num) == 1) |
assignment->type = BUTTON; |
else if (sscanf(buffer, " H %d%c%c", &assignment->num, &axis, &direction) == 3) |
assignment->type = HAT; |
if (assignment->num == 0) |
assignment->type = NONE; |
else |
--assignment->num; |
assignment->x_axis = (toupper(axis) == 'X'); |
assignment->negative_axis = (toupper(direction) == '-'); |
} |
/* gives the short (6 or less characters) identifier for a joystick assignment |
* |
* two of these per direction/action is all that can fit on the joystick config screen, |
* assuming two digits for the axis/button/hat number |
*/ |
const char *assignment_to_code( const Joystick_assignment *assignment ) |
{ |
static char name[7]; |
switch (assignment->type) |
{ |
case NONE: |
strcpy(name, ""); |
break; |
case AXIS: |
snprintf(name, sizeof(name), "AX %d%c", |
assignment->num + 1, |
assignment->negative_axis ? '-' : '+'); |
break; |
case BUTTON: |
snprintf(name, sizeof(name), "BTN %d", |
assignment->num + 1); |
break; |
case HAT: |
snprintf(name, sizeof(name), "H %d%c%c", |
assignment->num + 1, |
assignment->x_axis ? 'X' : 'Y', |
assignment->negative_axis ? '-' : '+'); |
break; |
} |
return name; |
} |
// captures joystick input for configuring assignments |
// returns false if non-joystick input was detected |
// TODO: input from joystick other than the one being configured probably should not be ignored |
bool detect_joystick_assignment( int j, Joystick_assignment *assignment ) |
{ |
// get initial joystick state to compare against to see if anything was pressed |
const int axes = SDL_JoystickNumAxes(joystick[j].handle); |
Sint16 *axis = malloc(axes * sizeof(*axis)); |
for (int i = 0; i < axes; i++) |
axis[i] = SDL_JoystickGetAxis(joystick[j].handle, i); |
const int buttons = SDL_JoystickNumButtons(joystick[j].handle); |
Uint8 *button = malloc(buttons * sizeof(*button)); |
for (int i = 0; i < buttons; i++) |
button[i] = SDL_JoystickGetButton(joystick[j].handle, i); |
const int hats = SDL_JoystickNumHats(joystick[j].handle); |
Uint8 *hat = malloc(hats * sizeof(*hat)); |
for (int i = 0; i < hats; i++) |
hat[i] = SDL_JoystickGetHat(joystick[j].handle, i); |
bool detected = false; |
do |
{ |
setjasondelay(1); |
SDL_JoystickUpdate(); |
for (int i = 0; i < axes; ++i) |
{ |
Sint16 temp = SDL_JoystickGetAxis(joystick[j].handle, i); |
if (abs(temp - axis[i]) > joystick_analog_max * 2 / 3) |
{ |
assignment->type = AXIS; |
assignment->num = i; |
assignment->negative_axis = temp < axis[i]; |
detected = true; |
break; |
} |
} |
for (int i = 0; i < buttons; ++i) |
{ |
Uint8 new_button = SDL_JoystickGetButton(joystick[j].handle, i), |
changed = button[i] ^ new_button; |
if (!changed) |
continue; |
if (new_button == 0) // button was released |
{ |
button[i] = new_button; |
} |
else // button was pressed |
{ |
assignment->type = BUTTON; |
assignment->num = i; |
detected = true; |
break; |
} |
} |
for (int i = 0; i < hats; ++i) |
{ |
Uint8 new_hat = SDL_JoystickGetHat(joystick[j].handle, i), |
changed = hat[i] ^ new_hat; |
if (!changed) |
continue; |
if ((new_hat & changed) == SDL_HAT_CENTERED) // hat was centered |
{ |
hat[i] = new_hat; |
} |
else |
{ |
assignment->type = HAT; |
assignment->num = i; |
assignment->x_axis = changed & (SDL_HAT_LEFT | SDL_HAT_RIGHT); |
assignment->negative_axis = changed & (SDL_HAT_LEFT | SDL_HAT_UP); |
detected = true; |
} |
} |
service_SDL_events(true); |
JE_showVGA(); |
wait_delay(); |
} |
while (!detected && !newkey && !newmouse); |
free(axis); |
free(button); |
free(hat); |
return detected; |
} |
// compares relevant parts of joystick assignments for equality |
bool joystick_assignment_cmp( const Joystick_assignment *a, const Joystick_assignment *b ) |
{ |
if (a->type == b->type) |
{ |
switch (a->type) |
{ |
case NONE: |
return true; |
case AXIS: |
return (a->num == b->num) && |
(a->negative_axis == b->negative_axis); |
case BUTTON: |
return (a->num == b->num); |
case HAT: |
return (a->num == b->num) && |
(a->x_axis == b->x_axis) && |
(a->negative_axis == b->negative_axis); |
} |
} |
return false; |
} |
/contrib/games/opentyrian/src/joystick.h |
---|
0,0 → 1,98 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef JOYSTICK_H |
#define JOYSTICK_H |
#include "opentyr.h" |
#include "config_file.h" |
#include "SDL.h" |
typedef enum |
{ |
NONE, |
AXIS, |
BUTTON, |
HAT |
} |
Joystick_assignment_types; |
typedef struct |
{ |
Joystick_assignment_types type; |
int num; |
// if hat |
bool x_axis; // else y_axis |
// if hat or axis |
bool negative_axis; // else positive |
} |
Joystick_assignment; |
typedef struct |
{ |
SDL_Joystick *handle; |
Joystick_assignment assignment[10][2]; // 0-3: directions, 4-9: actions |
bool analog; |
int sensitivity, threshold; |
signed int x, y; |
int analog_direction[4]; |
bool direction[4], direction_pressed[4]; // up, right, down, left (_pressed, for emulating key presses) |
bool confirm, cancel; |
bool action[6], action_pressed[6]; // fire, mode swap, left fire, right fire, menu, pause |
Uint32 joystick_delay; |
bool input_pressed; |
} |
Joystick; |
extern int joystick_repeat_delay; |
extern bool joydown; |
extern bool ignore_joystick; |
extern int joysticks; |
extern Joystick *joystick; |
int joystick_axis_reduce( int j, int value ); |
bool joystick_analog_angle( int j, float *angle ); |
void poll_joystick( int j ); |
void poll_joysticks( void ); |
void push_key( SDLKey key ); |
void push_joysticks_as_keyboard( void ); |
void init_joysticks( void ); |
void deinit_joysticks( void ); |
void reset_joystick_assignments( int j ); |
bool load_joystick_assignments( Config* config, int j ); |
bool save_joystick_assignments( Config* config, int j ); |
void joystick_assignments_to_string( char *buffer, size_t buffer_len, const Joystick_assignment *assignments ); |
bool detect_joystick_assignment( int j, Joystick_assignment *assignment ); |
bool joystick_assignment_cmp( const Joystick_assignment *, const Joystick_assignment * ); |
#endif /* JOYSTICK_H */ |
/contrib/games/opentyrian/src/jukebox.c |
---|
0,0 → 1,203 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "jukebox.h" |
#include "font.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "lds_play.h" |
#include "loudness.h" |
#include "mtrand.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "sprite.h" |
#include "starlib.h" |
#include "vga_palette.h" |
#include "video.h" |
#include <stdio.h> |
void jukebox( void ) |
{ |
bool trigger_quit = false, // true when user wants to quit |
quitting = false; |
bool hide_text = false; |
bool fade_looped_songs = true, fading_song = false; |
bool stopped = false; |
bool fx = false; |
int fx_num = 0; |
int palette_fade_steps = 15; |
int diff[256][3]; |
init_step_fade_palette(diff, vga_palette, 0, 255); |
JE_starlib_init(); |
int fade_volume = tyrMusicVolume; |
for (; ; ) |
{ |
if (!stopped && !audio_disabled) |
{ |
if (songlooped && fade_looped_songs) |
fading_song = true; |
if (fading_song) |
{ |
if (fade_volume > 5) |
{ |
fade_volume -= 2; |
} |
else |
{ |
fade_volume = tyrMusicVolume; |
fading_song = false; |
} |
set_volume(fade_volume, fxVolume); |
} |
if (!playing || (songlooped && fade_looped_songs && !fading_song)) |
play_song(mt_rand() % MUSIC_NUM); |
} |
setdelay(1); |
SDL_FillRect(VGAScreenSeg, NULL, 0); |
// starlib input needs to be rewritten |
JE_starlib_main(); |
push_joysticks_as_keyboard(); |
service_SDL_events(true); |
if (!hide_text) |
{ |
char buffer[60]; |
if (fx) |
snprintf(buffer, sizeof(buffer), "%d %s", fx_num + 1, soundTitle[fx_num]); |
else |
snprintf(buffer, sizeof(buffer), "%d %s", song_playing + 1, musicTitle[song_playing]); |
const int x = VGAScreen->w / 2; |
draw_font_hv(VGAScreen, x, 170, "Press ESC to quit the jukebox.", small_font, centered, 1, 0); |
draw_font_hv(VGAScreen, x, 180, "Arrow keys change the song being played.", small_font, centered, 1, 0); |
draw_font_hv(VGAScreen, x, 190, buffer, small_font, centered, 1, 4); |
} |
if (palette_fade_steps > 0) |
step_fade_palette(diff, palette_fade_steps--, 0, 255); |
JE_showVGA(); |
wait_delay(); |
// quit on mouse click |
Uint16 x, y; |
if (JE_mousePosition(&x, &y) > 0) |
trigger_quit = true; |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_ESCAPE: // quit jukebox |
case SDLK_q: |
trigger_quit = true; |
break; |
case SDLK_SPACE: |
hide_text = !hide_text; |
break; |
case SDLK_f: |
fading_song = !fading_song; |
break; |
case SDLK_n: |
fade_looped_songs = !fade_looped_songs; |
break; |
case SDLK_SLASH: // switch to sfx mode |
fx = !fx; |
break; |
case SDLK_COMMA: |
if (fx && --fx_num < 0) |
fx_num = SAMPLE_COUNT - 1; |
break; |
case SDLK_PERIOD: |
if (fx && ++fx_num >= SAMPLE_COUNT) |
fx_num = 0; |
break; |
case SDLK_SEMICOLON: |
if (fx) |
JE_playSampleNum(fx_num + 1); |
break; |
case SDLK_LEFT: |
case SDLK_UP: |
play_song((song_playing > 0 ? song_playing : MUSIC_NUM) - 1); |
stopped = false; |
break; |
case SDLK_RETURN: |
case SDLK_RIGHT: |
case SDLK_DOWN: |
play_song((song_playing + 1) % MUSIC_NUM); |
stopped = false; |
break; |
case SDLK_s: // stop song |
stop_song(); |
stopped = true; |
break; |
case SDLK_r: // restart song |
restart_song(); |
stopped = false; |
break; |
default: |
break; |
} |
} |
// user wants to quit, start fade-out |
if (trigger_quit && !quitting) |
{ |
palette_fade_steps = 15; |
SDL_Color black = { 0, 0, 0 }; |
init_step_fade_solid(diff, black, 0, 255); |
quitting = true; |
} |
// if fade-out finished, we can finally quit |
if (quitting && palette_fade_steps == 0) |
break; |
} |
set_volume(tyrMusicVolume, fxVolume); |
} |
/contrib/games/opentyrian/src/jukebox.h |
---|
0,0 → 1,27 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef JUKEBOX_H |
#define JUKEBOX_H |
#include "opentyr.h" |
void jukebox( void ); |
#endif /* JUKEBOX_H */ |
/contrib/games/opentyrian/src/keyboard.c |
---|
0,0 → 1,255 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "keyboard.h" |
#include "joystick.h" |
#include "network.h" |
#include "opentyr.h" |
#include "video.h" |
#include "video_scale.h" |
#include "SDL.h" |
#include <stdio.h> |
JE_boolean ESCPressed; |
JE_boolean newkey, newmouse, keydown, mousedown; |
SDLKey lastkey_sym; |
SDLMod lastkey_mod; |
unsigned char lastkey_char; |
Uint8 lastmouse_but; |
Uint16 lastmouse_x, lastmouse_y; |
JE_boolean mouse_pressed[3] = {false, false, false}; |
Uint16 mouse_x, mouse_y; |
Uint8 keysactive[SDLK_LAST]; |
#ifdef NDEBUG |
bool input_grab_enabled = true; |
#else |
bool input_grab_enabled = false; |
#endif |
void flush_events_buffer( void ) |
{ |
SDL_Event ev; |
while (SDL_PollEvent(&ev)); |
} |
void wait_input( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) |
{ |
service_SDL_events(false); |
while (!((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown))) |
{ |
uSDL_Delay(SDL_POLL_INTERVAL); |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
network_check(); |
#endif |
} |
} |
void wait_noinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) |
{ |
service_SDL_events(false); |
while ((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown)) |
{ |
uSDL_Delay(SDL_POLL_INTERVAL); |
poll_joysticks(); |
service_SDL_events(false); |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
network_check(); |
#endif |
} |
} |
void init_keyboard( void ) |
{ |
SDL_EnableKeyRepeat(500, 60); |
newkey = newmouse = false; |
keydown = mousedown = false; |
SDL_EnableUNICODE(1); |
} |
void input_grab( bool enable ) |
{ |
#if defined(TARGET_GP2X) || defined(TARGET_DINGUX) |
enable = true; |
#endif |
input_grab_enabled = enable || fullscreen_enabled; |
SDL_ShowCursor(input_grab_enabled ? SDL_DISABLE : SDL_ENABLE); |
#ifdef NDEBUG |
SDL_WM_GrabInput(input_grab_enabled ? SDL_GRAB_ON : SDL_GRAB_OFF); |
#endif |
} |
JE_word JE_mousePosition( JE_word *mouseX, JE_word *mouseY ) |
{ |
service_SDL_events(false); |
*mouseX = mouse_x; |
*mouseY = mouse_y; |
return mousedown ? lastmouse_but : 0; |
} |
void set_mouse_position( int x, int y ) |
{ |
if (input_grab_enabled) |
{ |
SDL_WarpMouse(x * scalers[scaler].width / vga_width, y * scalers[scaler].height / vga_height); |
mouse_x = x; |
mouse_y = y; |
} |
} |
void service_SDL_events( JE_boolean clear_new ) |
{ |
SDL_Event ev; |
if (clear_new) |
newkey = newmouse = false; |
while (SDL_PollEvent(&ev)) |
{ |
switch (ev.type) |
{ |
case SDL_ACTIVEEVENT: |
if (ev.active.state == SDL_APPINPUTFOCUS && !ev.active.gain) |
input_grab(false); |
break; |
case SDL_MOUSEMOTION: |
mouse_x = ev.motion.x * vga_width / scalers[scaler].width; |
mouse_y = ev.motion.y * vga_height / scalers[scaler].height; |
break; |
case SDL_KEYDOWN: |
if (ev.key.keysym.mod & KMOD_CTRL) |
{ |
/* <ctrl><bksp> emergency kill */ |
if (ev.key.keysym.sym == SDLK_BACKSPACE) |
{ |
puts("\n\n\nCtrl+Backspace pressed. Doing emergency quit.\n"); |
SDL_Quit(); |
exit(1); |
} |
/* <ctrl><f10> toggle input grab */ |
if (ev.key.keysym.sym == SDLK_F10) |
{ |
input_grab(!input_grab_enabled); |
break; |
} |
} |
if (ev.key.keysym.mod & KMOD_ALT) |
{ |
/* <alt><enter> toggle fullscreen */ |
if (ev.key.keysym.sym == SDLK_RETURN) |
{ |
if (!init_scaler(scaler, !fullscreen_enabled) && // try new fullscreen state |
!init_any_scaler(!fullscreen_enabled) && // try any scaler in new fullscreen state |
!init_scaler(scaler, fullscreen_enabled)) // revert on fail |
{ |
exit(EXIT_FAILURE); |
} |
break; |
} |
/* <alt><tab> disable input grab and fullscreen */ |
if (ev.key.keysym.sym == SDLK_TAB) |
{ |
if (!init_scaler(scaler, false) && // try windowed |
!init_any_scaler(false) && // try any scaler windowed |
!init_scaler(scaler, fullscreen_enabled)) // revert on fail |
{ |
exit(EXIT_FAILURE); |
} |
input_grab(false); |
break; |
} |
} |
keysactive[ev.key.keysym.sym] = 1; |
newkey = true; |
lastkey_sym = ev.key.keysym.sym; |
lastkey_mod = ev.key.keysym.mod; |
lastkey_char = ev.key.keysym.unicode; |
keydown = true; |
return; |
case SDL_KEYUP: |
keysactive[ev.key.keysym.sym] = 0; |
keydown = false; |
return; |
case SDL_MOUSEBUTTONDOWN: |
if (!input_grab_enabled) |
{ |
input_grab(true); |
break; |
} |
// fall through |
case SDL_MOUSEBUTTONUP: |
if (ev.type == SDL_MOUSEBUTTONDOWN) |
{ |
newmouse = true; |
lastmouse_but = ev.button.button; |
lastmouse_x = ev.button.x * vga_width / scalers[scaler].width; |
lastmouse_y = ev.button.y * vga_height / scalers[scaler].height; |
mousedown = true; |
} |
else |
{ |
mousedown = false; |
} |
switch (ev.button.button) |
{ |
case SDL_BUTTON_LEFT: |
mouse_pressed[0] = mousedown; break; |
case SDL_BUTTON_RIGHT: |
mouse_pressed[1] = mousedown; break; |
case SDL_BUTTON_MIDDLE: |
mouse_pressed[2] = mousedown; break; |
} |
break; |
case SDL_QUIT: |
/* TODO: Call the cleanup code here. */ |
exit(0); |
break; |
} |
} |
} |
void JE_clearKeyboard( void ) |
{ |
// /!\ Doesn't seems important. I think. D: |
} |
/contrib/games/opentyrian/src/keyboard.h |
---|
0,0 → 1,57 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef KEYBOARD_H |
#define KEYBOARD_H |
#include "opentyr.h" |
#include "SDL.h" |
#define SDL_POLL_INTERVAL 5 |
extern JE_boolean ESCPressed; |
extern JE_boolean newkey, newmouse, keydown, mousedown; |
extern SDLKey lastkey_sym; |
extern SDLMod lastkey_mod; |
extern unsigned char lastkey_char; |
extern Uint8 lastmouse_but; |
extern Uint16 lastmouse_x, lastmouse_y; |
extern JE_boolean mouse_pressed[3]; |
extern Uint16 mouse_x, mouse_y; |
extern Uint8 keysactive[SDLK_LAST]; |
extern bool input_grab_enabled; |
void flush_events_buffer( void ); |
void wait_input( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ); |
void wait_noinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ); |
void init_keyboard( void ); |
void input_grab( bool enable ); |
JE_word JE_mousePosition( JE_word *mouseX, JE_word *mouseY ); |
void set_mouse_position( int x, int y ); |
void service_SDL_events( JE_boolean clear_new ); |
void sleep_game( void ); |
void JE_clearKeyboard( void ); |
#endif /* KEYBOARD_H */ |
/contrib/games/opentyrian/src/lds_play.c |
---|
0,0 → 1,769 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "lds_play.h" |
#include "file.h" |
#include "loudness.h" |
#include "opentyr.h" |
#include <assert.h> |
const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; |
/* A substantial amount of this code has been copied and adapted from adplug. |
Thanks, guys! Adplug is awesome! :D */ |
/* Note frequency table (16 notes / octave) */ |
static const Uint16 frequency[(13 * 15) - 3] = { |
343, 344, 345, 347, 348, 349, 350, 352, 353, 354, 356, 357, 358, |
359, 361, 362, 363, 365, 366, 367, 369, 370, 371, 373, 374, 375, |
377, 378, 379, 381, 382, 384, 385, 386, 388, 389, 391, 392, 393, |
395, 396, 398, 399, 401, 402, 403, 405, 406, 408, 409, 411, 412, |
414, 415, 417, 418, 420, 421, 423, 424, 426, 427, 429, 430, 432, |
434, 435, 437, 438, 440, 442, 443, 445, 446, 448, 450, 451, 453, |
454, 456, 458, 459, 461, 463, 464, 466, 468, 469, 471, 473, 475, |
476, 478, 480, 481, 483, 485, 487, 488, 490, 492, 494, 496, 497, |
499, 501, 503, 505, 506, 508, 510, 512, 514, 516, 518, 519, 521, |
523, 525, 527, 529, 531, 533, 535, 537, 538, 540, 542, 544, 546, |
548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 571, 573, |
575, 577, 579, 581, 583, 585, 587, 589, 591, 594, 596, 598, 600, |
602, 604, 607, 609, 611, 613, 615, 618, 620, 622, 624, 627, 629, |
631, 633, 636, 638, 640, 643, 645, 647, 650, 652, 654, 657, 659, |
662, 664, 666, 669, 671, 674, 676, 678, 681, 683 |
}; |
/* Vibrato (sine) table */ |
static const Uint8 vibtab[25 + (13 * 3)] = { |
0, 13, 25, 37, 50, 62, 74, 86, 98, 109, 120, 131, 142, 152, 162, |
171, 180, 189, 197, 205, 212, 219, 225, 231, 236, 240, 244, 247, |
250, 252, 254, 255, 255, 255, 254, 252, 250, 247, 244, 240, 236, |
231, 225, 219, 212, 205, 197, 189, 180, 171, 162, 152, 142, 131, |
120, 109, 98, 86, 74, 62, 50, 37, 25, 13 |
}; |
/* Tremolo (sine * sine) table */ |
static const Uint8 tremtab[128] = { |
0, 0, 1, 1, 2, 4, 5, 7, 10, 12, 15, 18, 21, 25, 29, 33, 37, 42, 47, |
52, 57, 62, 67, 73, 79, 85, 90, 97, 103, 109, 115, 121, 128, 134, |
140, 146, 152, 158, 165, 170, 176, 182, 188, 193, 198, 203, 208, |
213, 218, 222, 226, 230, 234, 237, 240, 243, 245, 248, 250, 251, |
253, 254, 254, 255, 255, 255, 254, 254, 253, 251, 250, 248, 245, |
243, 240, 237, 234, 230, 226, 222, 218, 213, 208, 203, 198, 193, |
188, 182, 176, 170, 165, 158, 152, 146, 140, 134, 127, 121, 115, |
109, 103, 97, 90, 85, 79, 73, 67, 62, 57, 52, 47, 42, 37, 33, 29, |
25, 21, 18, 15, 12, 10, 7, 5, 4, 2, 1, 1, 0 |
}; |
static const Uint16 maxsound = 0x3f, maxpos = 0xff; |
static SoundBank *soundbank = NULL; |
static Channel channel[9]; |
static Position *positions = NULL; |
static Uint8 fmchip[0xff], jumping, fadeonoff, allvolume, hardfade, tempo_now, pattplay, tempo, regbd, chandelay[9], mode, pattlen; |
static Uint16 posplay, jumppos, speed; |
static Uint16 *patterns = NULL; |
static Uint16 numpatch, numposi, mainvolume; |
bool playing, songlooped; |
bool lds_load( FILE *f, unsigned int music_offset, unsigned int music_size ) |
{ |
SoundBank *sb; |
fseek(f, music_offset, SEEK_SET); |
/* load header */ |
mode = fgetc(f); |
if (mode > 2) |
{ |
fprintf(stderr, "error: failed to load music\n"); |
return false; |
} |
efread(&speed, 2, 1, f); |
tempo = fgetc(f); |
pattlen = fgetc(f); |
for (unsigned int i = 0; i < 9; i++) |
chandelay[i] = fgetc(f); |
regbd = fgetc(f); |
/* load patches */ |
efread(&numpatch, 2, 1, f); |
free(soundbank); |
soundbank = malloc(sizeof(SoundBank) * numpatch); |
for (unsigned int i = 0; i < numpatch; i++) |
{ |
sb = &soundbank[i]; |
sb->mod_misc = fgetc(f); |
sb->mod_vol = fgetc(f); |
sb->mod_ad = fgetc(f); |
sb->mod_sr = fgetc(f); |
sb->mod_wave = fgetc(f); |
sb->car_misc = fgetc(f); |
sb->car_vol = fgetc(f); |
sb->car_ad = fgetc(f); |
sb->car_sr = fgetc(f); |
sb->car_wave = fgetc(f); |
sb->feedback = fgetc(f); |
sb->keyoff = fgetc(f); |
sb->portamento = fgetc(f); |
sb->glide = fgetc(f); |
sb->finetune = fgetc(f); |
sb->vibrato = fgetc(f); |
sb->vibdelay = fgetc(f); |
sb->mod_trem = fgetc(f); |
sb->car_trem = fgetc(f); |
sb->tremwait = fgetc(f); |
sb->arpeggio = fgetc(f); |
for (unsigned int j = 0; j < 12; j++) |
sb->arp_tab[j] = fgetc(f); |
efread(&sb->start, 2, 1, f); |
efread(&sb->size, 2, 1, f); |
sb->fms = fgetc(f); |
efread(&sb->transp, 2, 1, f); |
sb->midinst = fgetc(f); |
sb->midvelo = fgetc(f); |
sb->midkey = fgetc(f); |
sb->midtrans = fgetc(f); |
sb->middum1 = fgetc(f); |
sb->middum2 = fgetc(f); |
} |
/* load positions */ |
efread(&numposi, 2, 1, f); |
free(positions); |
positions = malloc(sizeof(Position) * 9 * numposi); |
for (unsigned int i = 0; i < numposi; i++) |
{ |
for (unsigned int j = 0; j < 9; j++) |
{ |
/* |
* patnum is a pointer inside the pattern space, but patterns are 16bit |
* word fields anyway, so it ought to be an even number (hopefully) and |
* we can just divide it by 2 to get our array index of 16bit words. |
*/ |
Uint16 temp; |
efread(&temp, 2, 1, f); |
positions[i * 9 + j].patnum = temp / 2; |
positions[i * 9 + j].transpose = fgetc(f); |
} |
} |
/* load patterns */ |
fseek(f, 2, SEEK_CUR); /* ignore # of digital sounds (dunno what this is for) */ |
unsigned int remaining = music_size - (ftell(f) - music_offset); |
free(patterns); |
patterns = malloc(sizeof(Uint16) * (remaining / 2)); |
for (unsigned int i = 0; i < remaining / 2; i++) |
efread(&patterns[i], 2, 1, f); |
lds_rewind(); |
return true; |
} |
void lds_free( void ) |
{ |
free(soundbank); |
soundbank = NULL; |
free(positions); |
positions = NULL; |
free(patterns); |
patterns = NULL; |
} |
void lds_rewind( void ) |
{ |
int i; |
/* init all with 0 */ |
tempo_now = 3; |
playing = true; songlooped = false; |
jumping = fadeonoff = allvolume = hardfade = pattplay = posplay = jumppos = mainvolume = 0; |
memset(channel, 0, sizeof(channel)); |
memset(fmchip, 0, sizeof(fmchip)); |
/* OPL2 init */ |
opl_init(); /* Reset OPL chip */ |
opl_write(1, 0x20); |
opl_write(8, 0); |
opl_write(0xbd, regbd); |
for(i = 0; i < 9; i++) { |
opl_write(0x20 + op_table[i], 0); |
opl_write(0x23 + op_table[i], 0); |
opl_write(0x40 + op_table[i], 0x3f); |
opl_write(0x43 + op_table[i], 0x3f); |
opl_write(0x60 + op_table[i], 0xff); |
opl_write(0x63 + op_table[i], 0xff); |
opl_write(0x80 + op_table[i], 0xff); |
opl_write(0x83 + op_table[i], 0xff); |
opl_write(0xe0 + op_table[i], 0); |
opl_write(0xe3 + op_table[i], 0); |
opl_write(0xa0 + i, 0); |
opl_write(0xb0 + i, 0); |
opl_write(0xc0 + i, 0); |
} |
} |
void lds_setregs(Uint8 reg, Uint8 val) |
{ |
if(fmchip[reg] == val) return; |
fmchip[reg] = val; |
opl_write(reg, val); |
} |
void lds_setregs_adv(Uint8 reg, Uint8 mask, Uint8 val) |
{ |
lds_setregs(reg, (fmchip[reg] & mask) | val); |
} |
int lds_update( void ) |
{ |
Uint16 comword, freq, octave, chan, tune, wibc, tremc, arpreg; |
int vbreak; |
Uint8 level, regnum, comhi, comlo; |
int i; |
Channel *c; |
if(!playing) return false; |
/* handle fading */ |
if(fadeonoff) |
{ |
if(fadeonoff <= 128) { |
if(allvolume > fadeonoff || allvolume == 0) |
{ |
allvolume -= fadeonoff; |
} else { |
allvolume = 1; |
fadeonoff = 0; |
if(hardfade != 0) { |
playing = false; |
hardfade = 0; |
for(i = 0; i < 9; i++) |
{ |
channel[i].keycount = 1; |
} |
} |
} |
} else { |
if( (Uint8) ((allvolume + (0x100 - fadeonoff)) & 0xff) <= mainvolume) |
{ |
allvolume += 0x100 - fadeonoff; |
} else { |
allvolume = mainvolume; |
fadeonoff = 0; |
} |
} |
} |
/* handle channel delay */ |
for(chan = 0; chan < 9; chan++) { |
c = &channel[chan]; |
if(c->chancheat.chandelay) { |
if(!(--c->chancheat.chandelay)) { |
lds_playsound(c->chancheat.sound, chan, c->chancheat.high); |
} |
} |
} |
/* handle notes */ |
if(!tempo_now && positions) |
{ |
vbreak = false; |
for(chan = 0; chan < 9; chan++) |
{ |
c = &channel[chan]; |
if(!c->packwait) { |
Uint16 patnum = positions[posplay * 9 + chan].patnum; |
Uint8 transpose = positions[posplay * 9 + chan].transpose; |
/*printf("> %p", positions);*/ |
comword = patterns[patnum + c->packpos]; |
comhi = comword >> 8; comlo = comword & 0xff; |
if(comword) { |
if(comhi == 0x80) |
{ |
c->packwait = comlo; |
} else { |
if(comhi >= 0x80) |
{ |
switch(comhi) |
{ |
case 0xff: |
c->volcar = (((c->volcar & 0x3f) * comlo) >> 6) & 0x3f; |
if(fmchip[0xc0 + chan] & 1) |
c->volmod = (((c->volmod & 0x3f) * comlo) >> 6) & 0x3f; |
break; |
case 0xfe: |
tempo = comword & 0x3f; |
break; |
case 0xfd: |
c->nextvol = comlo; |
break; |
case 0xfc: |
playing = false; |
/* in real player there's also full keyoff here, but we don't need it */ |
break; |
case 0xfb: |
c->keycount = 1; |
break; |
case 0xfa: |
vbreak = true; |
jumppos = (posplay + 1) & maxpos; |
break; |
case 0xf9: |
vbreak = true; |
jumppos = comlo & maxpos; |
jumping = 1; |
if(jumppos < posplay) |
{ |
songlooped = true; |
} |
break; |
case 0xf8: |
c->lasttune = 0; |
break; |
case 0xf7: |
c->vibwait = 0; |
/* PASCAL: c->vibspeed = ((comlo >> 4) & 15) + 2; */ |
c->vibspeed = (comlo >> 4) + 2; |
c->vibrate = (comlo & 15) + 1; |
break; |
case 0xf6: |
c->glideto = comlo; |
break; |
case 0xf5: |
c->finetune = comlo; |
break; |
case 0xf4: |
if(!hardfade) |
{ |
allvolume = mainvolume = comlo; |
fadeonoff = 0; |
} |
break; |
case 0xf3: |
if(!hardfade) |
{ |
fadeonoff = comlo; |
} |
break; |
case 0xf2: |
c->trmstay = comlo; |
break; |
case 0xf1: /* panorama */ |
case 0xf0: /* progch */ |
/* MIDI commands (unhandled) */ |
/*AdPlug_LogWrite("CldsPlayer(): not handling MIDI command 0x%x, " |
"value = 0x%x\n", comhi);*/ |
break; |
default: |
if(comhi < 0xa0) |
{ |
c->glideto = comhi & 0x1f; |
} else { |
/*AdPlug_LogWrite("CldsPlayer(): unknown command 0x%x encountered!" |
" value = 0x%x\n", comhi, comlo);*/ |
} |
break; |
} |
} else { |
Uint8 sound; |
Uint16 high; |
Sint8 transp = transpose & 127; |
/* |
* Originally, in assembler code, the player first shifted |
* logically left the transpose byte by 1 and then shifted |
* arithmetically right the same byte to achieve the final, |
* signed transpose value. Since we can't do arithmetic shifts |
* in C, we just duplicate the 7th bit into the 8th one and |
* discard the 8th one completely. |
*/ |
if(transpose & 64) |
{ |
transp |= 128; |
} |
if(transpose & 128) |
{ |
sound = (comlo + transp) & maxsound; |
high = comhi << 4; |
} else { |
sound = comlo & maxsound; |
high = (comhi + transp) << 4; |
} |
/* |
PASCAL: |
sound = comlo & maxsound; |
high = (comhi + (((transpose + 0x24) & 0xff) - 0x24)) << 4; |
*/ |
if(!chandelay[chan]) { |
lds_playsound(sound, chan, high); |
} else { |
c->chancheat.chandelay = chandelay[chan]; |
c->chancheat.sound = sound; |
c->chancheat.high = high; |
} |
} |
} |
} |
c->packpos++; |
} else { |
c->packwait--; |
} |
} |
tempo_now = tempo; |
/* |
The continue table is updated here, but this is only used in the |
original player, which can be paused in the middle of a song and then |
unpaused. Since AdPlug does all this for us automatically, we don't |
have a continue table here. The continue table update code is noted |
here for reference only. |
if(!pattplay) { |
conttab[speed & maxcont].position = posplay & 0xff; |
conttab[speed & maxcont].tempo = tempo; |
} |
*/ |
pattplay++; |
if(vbreak) |
{ |
pattplay = 0; |
for(i = 0; i < 9; i++) |
{ |
channel[i].packpos = channel[i].packwait = 0; |
} |
posplay = jumppos; |
} else { |
if(pattplay >= pattlen) { |
pattplay = 0; |
for(i = 0; i < 9; i++) |
{ |
channel[i].packpos = channel[i].packwait = 0; |
} |
posplay = (posplay + 1) & maxpos; |
} |
} |
} else { |
tempo_now--; |
} |
/* make effects */ |
for(chan = 0; chan < 9; chan++) { |
c = &channel[chan]; |
regnum = op_table[chan]; |
if(c->keycount > 0) { |
if(c->keycount == 1) |
lds_setregs_adv(0xb0 + chan, 0xdf, 0); |
c->keycount--; |
} |
/* arpeggio */ |
if(c->arp_size == 0) |
arpreg = 0; |
else { |
arpreg = c->arp_tab[c->arp_pos] << 4; |
if(arpreg == 0x800) { |
if(c->arp_pos > 0) c->arp_tab[0] = c->arp_tab[c->arp_pos - 1]; |
c->arp_size = 1; c->arp_pos = 0; |
arpreg = c->arp_tab[0] << 4; |
} |
if(c->arp_count == c->arp_speed) { |
c->arp_pos++; |
if(c->arp_pos >= c->arp_size) c->arp_pos = 0; |
c->arp_count = 0; |
} else |
c->arp_count++; |
} |
/* glide & portamento */ |
if(c->lasttune && (c->lasttune != c->gototune)) { |
if(c->lasttune > c->gototune) { |
if(c->lasttune - c->gototune < c->portspeed) |
c->lasttune = c->gototune; |
else |
c->lasttune -= c->portspeed; |
} else { |
if(c->gototune - c->lasttune < c->portspeed) |
c->lasttune = c->gototune; |
else |
c->lasttune += c->portspeed; |
} |
if(arpreg >= 0x800) |
arpreg = c->lasttune - (arpreg ^ 0xff0) - 16; |
else |
arpreg += c->lasttune; |
freq = frequency[arpreg % (12 * 16)]; |
octave = arpreg / (12 * 16) - 1; |
lds_setregs(0xa0 + chan, freq & 0xff); |
lds_setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); |
} else { |
/* vibrato */ |
if(!c->vibwait) { |
if(c->vibrate) { |
wibc = vibtab[c->vibcount & 0x3f] * c->vibrate; |
if((c->vibcount & 0x40) == 0) |
tune = c->lasttune + (wibc >> 8); |
else |
tune = c->lasttune - (wibc >> 8); |
if(arpreg >= 0x800) |
tune = tune - (arpreg ^ 0xff0) - 16; |
else |
tune += arpreg; |
freq = frequency[tune % (12 * 16)]; |
octave = tune / (12 * 16) - 1; |
lds_setregs(0xa0 + chan, freq & 0xff); |
lds_setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); |
c->vibcount += c->vibspeed; |
} else if(c->arp_size != 0) { /* no vibrato, just arpeggio */ |
if(arpreg >= 0x800) |
tune = c->lasttune - (arpreg ^ 0xff0) - 16; |
else |
tune = c->lasttune + arpreg; |
freq = frequency[tune % (12 * 16)]; |
octave = tune / (12 * 16) - 1; |
lds_setregs(0xa0 + chan, freq & 0xff); |
lds_setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); |
} |
} else { /* no vibrato, just arpeggio */ |
c->vibwait--; |
if(c->arp_size != 0) { |
if(arpreg >= 0x800) |
tune = c->lasttune - (arpreg ^ 0xff0) - 16; |
else |
tune = c->lasttune + arpreg; |
freq = frequency[tune % (12 * 16)]; |
octave = tune / (12 * 16) - 1; |
lds_setregs(0xa0 + chan, freq & 0xff); |
lds_setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); |
} |
} |
} |
/* tremolo (modulator) */ |
if(!c->trmwait) { |
if(c->trmrate) { |
tremc = tremtab[c->trmcount & 0x7f] * c->trmrate; |
if((tremc >> 8) <= (c->volmod & 0x3f)) |
level = (c->volmod & 0x3f) - (tremc >> 8); |
else |
level = 0; |
if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) |
lds_setregs_adv(0x40 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f); |
else |
lds_setregs_adv(0x40 + regnum, 0xc0, level ^ 0x3f); |
c->trmcount += c->trmspeed; |
} else if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) |
lds_setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); |
else |
lds_setregs_adv(0x40 + regnum, 0xc0, (c->volmod ^ 0x3f) & 0x3f); |
} else { |
c->trmwait--; |
if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) |
lds_setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); |
} |
/* tremolo (carrier) */ |
if(!c->trcwait) { |
if(c->trcrate) { |
tremc = tremtab[c->trccount & 0x7f] * c->trcrate; |
if((tremc >> 8) <= (c->volcar & 0x3f)) |
level = (c->volcar & 0x3f) - (tremc >> 8); |
else |
level = 0; |
if(allvolume != 0) |
lds_setregs_adv(0x43 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f); |
else |
lds_setregs_adv(0x43 + regnum, 0xc0, level ^ 0x3f); |
c->trccount += c->trcspeed; |
} else if(allvolume != 0) |
lds_setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); |
else |
lds_setregs_adv(0x43 + regnum, 0xc0, (c->volcar ^ 0x3f) & 0x3f); |
} else { |
c->trcwait--; |
if(allvolume != 0) |
lds_setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); |
} |
} |
return (!playing || songlooped) ? false : true; |
} |
void lds_playsound(int inst_number, int channel_number, int tunehigh) |
{ |
Channel *c = &channel[channel_number]; /* current channel */ |
SoundBank *i = &soundbank[inst_number]; /* current instrument */ |
Uint32 regnum = op_table[channel_number]; /* channel's OPL2 register */ |
Uint8 volcalc, octave; |
Uint16 freq; |
/* set fine tune */ |
tunehigh += ((i->finetune + c->finetune + 0x80) & 0xff) - 0x80; |
/* arpeggio handling */ |
if(!i->arpeggio) { |
Uint16 arpcalc = i->arp_tab[0] << 4; |
if(arpcalc > 0x800) |
tunehigh = tunehigh - (arpcalc ^ 0xff0) - 16; |
else |
tunehigh += arpcalc; |
} |
/* glide handling */ |
if(c->glideto != 0) { |
c->gototune = tunehigh; |
c->portspeed = c->glideto; |
c->glideto = c->finetune = 0; |
return; |
} |
/* set modulator registers */ |
lds_setregs(0x20 + regnum, i->mod_misc); |
volcalc = i->mod_vol; |
if(!c->nextvol || !(i->feedback & 1)) |
c->volmod = volcalc; |
else |
c->volmod = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6)); |
if((i->feedback & 1) == 1 && allvolume != 0) |
lds_setregs(0x40 + regnum, ((c->volmod & 0xc0) | (((c->volmod & 0x3f) * allvolume) >> 8)) ^ 0x3f); |
else |
lds_setregs(0x40 + regnum, c->volmod ^ 0x3f); |
lds_setregs(0x60 + regnum, i->mod_ad); |
lds_setregs(0x80 + regnum, i->mod_sr); |
lds_setregs(0xe0 + regnum, i->mod_wave); |
/* Set carrier registers */ |
lds_setregs(0x23 + regnum, i->car_misc); |
volcalc = i->car_vol; |
if(!c->nextvol) |
c->volcar = volcalc; |
else |
c->volcar = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6)); |
if(allvolume) |
lds_setregs(0x43 + regnum, ((c->volcar & 0xc0) | (((c->volcar & 0x3f) * allvolume) >> 8)) ^ 0x3f); |
else |
lds_setregs(0x43 + regnum, c->volcar ^ 0x3f); |
lds_setregs(0x63 + regnum, i->car_ad); |
lds_setregs(0x83 + regnum, i->car_sr); |
lds_setregs(0xe3 + regnum, i->car_wave); |
lds_setregs(0xc0 + channel_number, i->feedback); |
lds_setregs_adv(0xb0 + channel_number, 0xdf, 0); /* key off */ |
freq = frequency[tunehigh % (12 * 16)]; |
octave = tunehigh / (12 * 16) - 1; |
if(!i->glide) { |
if(!i->portamento || !c->lasttune) { |
lds_setregs(0xa0 + channel_number, freq & 0xff); |
lds_setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); |
c->lasttune = c->gototune = tunehigh; |
} else { |
c->gototune = tunehigh; |
c->portspeed = i->portamento; |
lds_setregs_adv(0xb0 + channel_number, 0xdf, 0x20); /* key on */ |
} |
} else { |
lds_setregs(0xa0 + channel_number, freq & 0xff); |
lds_setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); |
c->lasttune = tunehigh; |
c->gototune = tunehigh + ((i->glide + 0x80) & 0xff) - 0x80; /* set destination */ |
c->portspeed = i->portamento; |
} |
if(!i->vibrato) |
c->vibwait = c->vibspeed = c->vibrate = 0; |
else { |
c->vibwait = i->vibdelay; |
/* PASCAL: c->vibspeed = ((i->vibrato >> 4) & 15) + 1; */ |
c->vibspeed = (i->vibrato >> 4) + 2; |
c->vibrate = (i->vibrato & 15) + 1; |
} |
if(!(c->trmstay & 0xf0)) { |
c->trmwait = (i->tremwait & 0xf0) >> 3; |
/* PASCAL: c->trmspeed = (i->mod_trem >> 4) & 15; */ |
c->trmspeed = i->mod_trem >> 4; |
c->trmrate = i->mod_trem & 15; |
c->trmcount = 0; |
} |
if(!(c->trmstay & 0x0f)) { |
c->trcwait = (i->tremwait & 15) << 1; |
/* PASCAL: c->trcspeed = (i->car_trem >> 4) & 15; */ |
c->trcspeed = i->car_trem >> 4; |
c->trcrate = i->car_trem & 15; |
c->trccount = 0; |
} |
c->arp_size = i->arpeggio & 15; |
c->arp_speed = i->arpeggio >> 4; |
memcpy(c->arp_tab, i->arp_tab, 12); |
c->keycount = i->keyoff; |
c->nextvol = c->glideto = c->finetune = c->vibcount = c->arp_pos = c->arp_count = 0; |
} |
/contrib/games/opentyrian/src/lds_play.h |
---|
0,0 → 1,74 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef LDS_PLAY_H |
#define LDS_PLAY_H |
#include "opentyr.h" |
#include <stdio.h> |
extern bool playing, songlooped; |
int lds_update( void ); |
bool lds_load( FILE *f, unsigned int music_offset, unsigned int music_size ); |
void lds_free( void ); |
void lds_rewind( void ); |
#define REFRESH 70.0f |
/*unsigned int getorders() { return numposi; } |
unsigned int getorder() { return posplay; } |
unsigned int getrow() { return pattplay; } |
unsigned int getspeed() { return speed; } |
unsigned int getinstruments() { return numpatch; }*/ |
typedef struct { |
unsigned char mod_misc, mod_vol, mod_ad, mod_sr, mod_wave, |
car_misc, car_vol, car_ad, car_sr, car_wave, feedback, keyoff, |
portamento, glide, finetune, vibrato, vibdelay, mod_trem, car_trem, |
tremwait, arpeggio, arp_tab[12]; |
unsigned short start, size; |
unsigned char fms; |
unsigned short transp; |
unsigned char midinst, midvelo, midkey, midtrans, middum1, middum2; |
} SoundBank; |
typedef struct { |
unsigned short gototune, lasttune, packpos; |
unsigned char finetune, glideto, portspeed, nextvol, volmod, volcar, |
vibwait, vibspeed, vibrate, trmstay, trmwait, trmspeed, trmrate, trmcount, |
trcwait, trcspeed, trcrate, trccount, arp_size, arp_speed, keycount, |
vibcount, arp_pos, arp_count, packwait, arp_tab[12]; |
struct { |
unsigned char chandelay, sound; |
unsigned short high; |
} chancheat; |
} Channel; |
typedef struct { |
unsigned short patnum; |
unsigned char transpose; |
} Position; |
void lds_playsound(int inst_number, int channel_number, int tunehigh); |
void lds_setregs(unsigned char reg, unsigned char val); |
void lds_setregs_adv(unsigned char reg, unsigned char mask, unsigned char val); |
#endif /* LDS_PLAY_H */ |
/contrib/games/opentyrian/src/loudness.c |
---|
0,0 → 1,294 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "loudness.h" |
#include "file.h" |
#include "lds_play.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "params.h" |
float music_volume = 0, sample_volume = 0; |
bool music_stopped = true; |
unsigned int song_playing = 0; |
bool audio_disabled = false, music_disabled = false, samples_disabled = false; |
/* SYN: These shouldn't be used outside this file. Hands off! */ |
FILE *music_file = NULL; |
Uint32 *song_offset; |
Uint16 song_count = 0; |
SAMPLE_TYPE *channel_buffer[SFX_CHANNELS] = { NULL }; |
SAMPLE_TYPE *channel_pos[SFX_CHANNELS] = { NULL }; |
Uint32 channel_len[SFX_CHANNELS] = { 0 }; |
Uint8 channel_vol[SFX_CHANNELS]; |
int sound_init_state = false; |
int freq = 11025 * OUTPUT_QUALITY; |
static SDL_AudioCVT audio_cvt; // used for format conversion |
void audio_cb( void *userdata, unsigned char *feedme, int howmuch ); |
void load_song( unsigned int song_num ); |
bool init_audio( void ) |
{ |
if (audio_disabled) |
return false; |
SDL_AudioSpec ask, got; |
ask.freq = freq; |
ask.format = (BYTES_PER_SAMPLE == 2) ? AUDIO_S16SYS : AUDIO_S8; |
ask.channels = 1; |
ask.samples = 2048; |
ask.callback = audio_cb; |
printf("\trequested %d Hz, %d channels, %d samples\n", ask.freq, ask.channels, ask.samples); |
#ifdef _KOLIBRI |
SDL_AudioInit(NULL); |
#endif |
if (SDL_OpenAudio(&ask, &got) == -1) |
{ |
fprintf(stderr, "error: failed to initialize SDL audio: %s\n", SDL_GetError()); |
audio_disabled = true; |
return false; |
} |
printf("\tobtained %d Hz, %d channels, %d samples\n", got.freq, got.channels, got.samples); |
SDL_BuildAudioCVT(&audio_cvt, ask.format, ask.channels, ask.freq, got.format, got.channels, got.freq); |
opl_init(); |
SDL_PauseAudio(0); // unpause |
return true; |
} |
void audio_cb( void *user_data, unsigned char *sdl_buffer, int howmuch ) |
{ |
(void)user_data; |
// prepare for conversion |
howmuch /= audio_cvt.len_mult; |
audio_cvt.buf = sdl_buffer; |
audio_cvt.len = howmuch; |
static long ct = 0; |
SAMPLE_TYPE *feedme = (SAMPLE_TYPE *)sdl_buffer; |
if (!music_disabled && !music_stopped) |
{ |
/* SYN: Simulate the fm synth chip */ |
SAMPLE_TYPE *music_pos = feedme; |
long remaining = howmuch / BYTES_PER_SAMPLE; |
while (remaining > 0) |
{ |
while (ct < 0) |
{ |
ct += freq; |
lds_update(); /* SYN: Do I need to use the return value for anything here? */ |
} |
/* SYN: Okay, about the calculations below. I still don't 100% get what's going on, but... |
- freq is samples/time as output by SDL. |
- REFRESH is how often the play proc would have been called in Tyrian. Standard speed is |
70Hz, which is the default value of 70.0f |
- ct represents the margin between play time (representing # of samples) and tick speed of |
the songs (70Hz by default). It keeps track of which one is ahead, because they don't |
synch perfectly. */ |
/* set i to smaller of data requested by SDL and a value calculated from the refresh rate */ |
long i = (long)((ct / REFRESH) + 4) & ~3; |
i = (i > remaining) ? remaining : i; /* i should now equal the number of samples we get */ |
opl_update((SAMPLE_TYPE *)music_pos, i); |
music_pos += i; |
remaining -= i; |
ct -= (long)(REFRESH * i); |
} |
/* Reduce the music volume. */ |
int qu = howmuch / BYTES_PER_SAMPLE; |
for (int smp = 0; smp < qu; smp++) |
{ |
feedme[smp] *= music_volume; |
} |
} |
if (!samples_disabled) |
{ |
/* SYN: Mix sound channels and shove into audio buffer */ |
for (int ch = 0; ch < SFX_CHANNELS; ch++) |
{ |
float volume = sample_volume * (channel_vol[ch] / (float)SFX_CHANNELS); |
/* SYN: Don't copy more data than is in the channel! */ |
unsigned int qu = ((unsigned)howmuch > channel_len[ch] ? channel_len[ch] : (unsigned)howmuch) / BYTES_PER_SAMPLE; |
for (unsigned int smp = 0; smp < qu; smp++) |
{ |
#if (BYTES_PER_SAMPLE == 2) |
Sint32 clip = (Sint32)feedme[smp] + (Sint32)(channel_pos[ch][smp] * volume); |
feedme[smp] = (clip > 0x7fff) ? 0x7fff : (clip <= -0x8000) ? -0x8000 : (Sint16)clip; |
#else /* BYTES_PER_SAMPLE */ |
Sint16 clip = (Sint16)feedme[smp] + (Sint16)(channel_pos[ch][smp] * volume); |
feedme[smp] = (clip > 0x7f) ? 0x7f : (clip <= -0x80) ? -0x80 : (Sint8)clip; |
#endif /* BYTES_PER_SAMPLE */ |
} |
channel_pos[ch] += qu; |
channel_len[ch] -= qu * BYTES_PER_SAMPLE; |
/* SYN: If we've emptied a channel buffer, let's free the memory and clear the channel. */ |
if (channel_len[ch] == 0) |
{ |
free(channel_buffer[ch]); |
channel_buffer[ch] = channel_pos[ch] = NULL; |
} |
} |
} |
// do conversion |
SDL_ConvertAudio(&audio_cvt); |
} |
void deinit_audio( void ) |
{ |
if (audio_disabled) |
return; |
SDL_PauseAudio(1); // pause |
SDL_CloseAudio(); |
for (unsigned int i = 0; i < SFX_CHANNELS; i++) |
{ |
free(channel_buffer[i]); |
channel_buffer[i] = channel_pos[i] = NULL; |
channel_len[i] = 0; |
} |
lds_free(); |
} |
void load_music( void ) |
{ |
if (music_file == NULL) |
{ |
music_file = dir_fopen_die(data_dir(), "music.mus", "rb"); |
efread(&song_count, sizeof(song_count), 1, music_file); |
song_offset = malloc((song_count + 1) * sizeof(*song_offset)); |
efread(song_offset, 4, song_count, music_file); |
song_offset[song_count] = ftell_eof(music_file); |
} |
} |
void load_song( unsigned int song_num ) |
{ |
if (audio_disabled) |
return; |
SDL_LockAudio(); |
if (song_num < song_count) |
{ |
unsigned int song_size = song_offset[song_num + 1] - song_offset[song_num]; |
lds_load(music_file, song_offset[song_num], song_size); |
} |
else |
{ |
fprintf(stderr, "warning: failed to load song %d\n", song_num + 1); |
} |
SDL_UnlockAudio(); |
} |
void play_song( unsigned int song_num ) |
{ |
if (song_num != song_playing) |
{ |
load_song(song_num); |
song_playing = song_num; |
} |
music_stopped = false; |
} |
void restart_song( void ) |
{ |
unsigned int temp = song_playing; |
song_playing = -1; |
play_song(temp); |
} |
void stop_song( void ) |
{ |
music_stopped = true; |
} |
void fade_song( void ) |
{ |
/* STUB: we have no implementation of this to port */ |
} |
void set_volume( unsigned int music, unsigned int sample ) |
{ |
music_volume = music * (1.5f / 255.0f); |
sample_volume = sample * (1.0f / 255.0f); |
} |
void JE_multiSamplePlay(JE_byte *buffer, JE_word size, JE_byte chan, JE_byte vol) |
{ |
if (audio_disabled || samples_disabled) |
return; |
SDL_LockAudio(); |
free(channel_buffer[chan]); |
channel_len[chan] = size * BYTES_PER_SAMPLE * SAMPLE_SCALING; |
channel_buffer[chan] = malloc(channel_len[chan]); |
channel_pos[chan] = channel_buffer[chan]; |
channel_vol[chan] = vol + 1; |
for (int i = 0; i < size; i++) |
{ |
for (int ex = 0; ex < SAMPLE_SCALING; ex++) |
{ |
#if (BYTES_PER_SAMPLE == 2) |
channel_buffer[chan][(i * SAMPLE_SCALING) + ex] = (Sint8)buffer[i] << 8; |
#else /* BYTES_PER_SAMPLE */ |
channel_buffer[chan][(i * SAMPLE_SCALING) + ex] = (Sint8)buffer[i]; |
#endif /* BYTES_PER_SAMPLE */ |
} |
} |
SDL_UnlockAudio(); |
} |
/contrib/games/opentyrian/src/loudness.h |
---|
0,0 → 1,59 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef LOUDNESS_H |
#define LOUDNESS_H |
#include "opentyr.h" |
#include "opl.h" |
#include "SDL.h" |
#define SFX_CHANNELS 8 |
#if defined(TARGET_GP2X) || defined(TARGET_DINGUX) |
#define OUTPUT_QUALITY 2 // 22 kHz |
#else |
#define OUTPUT_QUALITY 4 // 44 kHz |
#endif |
#define SAMPLE_SCALING OUTPUT_QUALITY |
#define SAMPLE_TYPE Bit16s |
#define BYTES_PER_SAMPLE 2 |
extern float music_volume, sample_volume; |
extern unsigned int song_playing; |
extern bool audio_disabled, music_disabled, samples_disabled; |
bool init_audio( void ); |
void deinit_audio( void ); |
void load_music( void ); |
void play_song( unsigned int song_num ); |
void restart_song( void ); |
void stop_song( void ); |
void fade_song( void ); |
void set_volume( unsigned int music, unsigned int sample ); |
void JE_multiSamplePlay(JE_byte *buffer, JE_word size, JE_byte chan, JE_byte vol); |
#endif /* LOUDNESS_H */ |
/contrib/games/opentyrian/src/lvllib.c |
---|
0,0 → 1,42 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "lvllib.h" |
#include "file.h" |
#include "opentyr.h" |
JE_LvlPosType lvlPos; |
char levelFile[13]; /* string [12] */ |
JE_word lvlNum; |
void JE_analyzeLevel( void ) |
{ |
FILE *f = dir_fopen_die(data_dir(), levelFile, "rb"); |
efread(&lvlNum, sizeof(JE_word), 1, f); |
for (int x = 0; x < lvlNum; x++) |
efread(&lvlPos[x], sizeof(JE_longint), 1, f); |
lvlPos[lvlNum] = ftell_eof(f); |
fclose(f); |
} |
/contrib/games/opentyrian/src/lvllib.h |
---|
0,0 → 1,34 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef LVLLIB_H |
#define LVLLIB_H |
#include "opentyr.h" |
typedef JE_longint JE_LvlPosType[43]; /* [1..42 + 1] */ |
extern JE_LvlPosType lvlPos; |
extern char levelFile[13]; /* string [12] */ |
extern JE_word lvlNum; |
void JE_analyzeLevel( void ); |
#endif /* LVLLIB_H */ |
/contrib/games/opentyrian/src/lvlmast.c |
---|
0,0 → 1,173 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "lvlmast.h" |
#include "opentyr.h" |
const JE_char shapeFile[34] = /* [1..34] */ |
{ |
'2', '4', '7', '8', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', |
'O', 'P', 'Q', 'R', 'S', 'T', 'U', '5', '#', 'V', '0', '@', '3', '^', '5', '9' |
}; |
const char lvlFile[LVL_NUM][9] = /* [1..LVLnum] of string [8] */ |
{ |
/* 1*/ "ASTROID4", "MAINMAPE", |
/* 2*/ "ASTROID5", "MAINMAPD", |
/* 3*/ "ASTROID7", "MAINMAPC", |
/* 4*/ "BUBBLES", "MAINMAPT", |
/* 5*/ "DELI", "MAINMAPS", |
/* 6*/ "MINES2", "MAINMAPQ", |
/* 7*/ "MINES", "MAINMAPI", |
/* 8*/ "SAVARA", "MAINMAPY", |
/* 9*/ "TYRLEV", "MAINMAPZ", |
/*10*/ "BONUS1-1", "MAINMAP0", |
/*11*/ "HOLES", "MAINMAP8", |
/*12*/ "SAVARA3", "MAINMAP3", |
/*13*/ "DESERT", "MAINMAAA", |
/*14*/ "WINDY", "MAINMAAB", |
/*15*/ "TYRLEV3", "MAINMAPZ", |
/*16*/ "UNDERTYR", "MAINMAAU", |
/*17*/ "SAVARA5", "MAINMAAW", |
/*18*/ "BEER", "MAINMAAX" |
}; |
const char lvlFile2[LVL_NUM_2][9] = /* [1..LVLnum2] of string [8] */ |
{ |
"JUNGLE", "MAINMAPF", |
"GIGER", "MAINMAPR", |
"BONUS1-2", "MAINMAP0", |
"ASTCITY2", "MAINMAP1", |
"SPACEATK", "MAINMAPH", |
"STATION", "MAINMAPV", |
"GEMWAR", "MAINMAPH", |
"MARKERS", "MAINMAPH", |
"PATHS", "MAINMAPH", |
"JUNGLE2", "MAINMAP5", |
"JUNGLE3", "MAINMAP7", |
"JUNGLE4", "MAINMAAP" |
}; |
const char lvlFile3[LVL_NUM_3][9] = /* [1..LVLnum3] of string [8] */ |
{ |
"ICE", "MAINMAPX", |
"ASTCITY", "MAINMAPP", |
"MINES3", "MAINMAPO", |
"TUNNEL", "MAINMAPW", |
"DELI2", "MAINMAPU", /*Bonus 3*/ |
"FLEET", "MAINMAPB", |
"STARGATE", "MAINMAP2", /*Bubbly*/ |
"TYRLEV2", "MAINMAPZ", |
"TUNNEL2", "MAINMAPA", /*Tunnel*/ |
"SAVARA2", "MAINMAPY", |
"DELI3", "MAINMAPS", |
"MACES", "MAINMAP9" /*Bonus Maces*/ |
}; |
const char lvlFile4[LVL_NUM_4][9] = /* [1..LVLnum4] of string [8] */ |
{ |
"HARVEST", "MAINMAAC", /*Harvest World ooooo */ |
"MAZE", "MAINMAAD", /*Windy 2 ooooo */ |
"SAVARA4", "MAINMAAF", /*Savara IV ooooo */ |
"DESERT3", "MAINMAAG", /*Desert ooooo */ |
"LAVA1", "MAINMAAH", /*Lava Core ooooo */ |
"LAVA2", "MAINMAAJ", /*Lava Center ooooo */ |
"CORE", "MAINMAAI", /*Tec tiles ooooo */ |
"ICE1", "MAINMAAK", /*Ice exit ooooo */ |
"LAVA3", "MAINMAAL", /*Lava Exit ooooo */ |
"DESERT4", "MAINMAAM", /*Desert Run ooooo */ |
"TUNNEL3", "MAINMAAN", /*Secret Tunnel ooooo */ |
"LAVA4", "MAINMAAO", /*Lava Run ooooo */ |
"EYESPY", "MAINMAAQ", /*Giger Eye ooooo */ |
"FLEET2", "MAINMAPH", /*Dread Not ooooo */ |
"BRAIN", "MAINMAAR", /*Brainiac ooooo */ |
"NOSE", "MAINMAAS", /*Nose ooooo */ |
"DESERT5", "MAINMAAT", /*Time War ooooo */ |
"GALAGA", "MAINMAAV", /*Galaga ooooo */ |
/*19*/ "SAVARA6", "MAINMAAY", /*Savara Approach ooooo */ |
/*20*/ "SPACEAT2", "MAINMABB" /*Camanis Go ooooo */ |
}; |
const char lvlFile5[LVL_NUM_5][9] = /* [1..lvlnum5] of string [8] */ |
{ |
/* 1*/ "E5LVL01", "MAINMA51" /*FogWalls ----- */ |
}; |
/*! JE_LvlPosType lvlPos;*/ |
/* |
Episode 4 uses... |
NEWSH(.SHP |
NEWSH^.SHP |
NEWSH7.SHP |
NEWSHP.SHP |
NEWSH&.SHP |
NEWSHE.SHP |
NEWSHV.SHP |
NEWSH#.SHP |
NEWSHJ.SHP |
NEWSH{.SHP |
NEWSHK.SHP |
SHAPESZ.DAT |
SHAPESW.DAT |
SHAPESX.DAT |
SHAPES}.DAT |
*/ |
/* |
TYPE 5: Shape Files |
SHAPES1.DAT o - - - - Items |
SHAPES3.DAT o - - - - Shots |
SHAPES6.DAT o - - - - Explosions |
SHAPES9.DAT o - - - - Player ships/options |
1 SHAPES2.DAT - o - - - Tyrian ships |
2 SHAPES4.DAT - o - - - TyrianBoss |
3 SHAPES7.DAT - - - - - Iceships |
4 SHAPES8.DAT - - - - - Tunnel World |
5 SHAPESA.DAT o - - - - Mine Stuff |
6 SHAPESB.DAT - - - - - IceBoss |
7 SHAPESC.DAT - o - - - Deliani Stuff |
8 SHAPESD.DAT o - - - - Asteroid Stuff I |
9 SHAPESE.DAT - o - - - Tyrian Bonus Rock + Bubbles |
10 SHAPESF.DAT - o - - - Savara Stuff I |
11 SHAPESG.DAT - - - - - Giger Stuff |
12 SHAPESH.DAT - - - - - Giger Stuff |
13 SHAPESI.DAT - o - - - Savara Stuff II + Savara Boss |
14 SHAPESJ.DAT - - - - - Jungle Stuff |
15 SHAPESK.DAT - - - - - Snowballs |
16 SHAPESL.DAT - - - - o Satellites |
17 SHAPESM.DAT o - - - - Asteroid Stuff IV |
18 SHAPESN.DAT - - - - - Giger Boss |
19 SHAPESO.DAT - o - - - Savara Boss |
20 SHAPESP.DAT o - - - - Asteroid Stuff III |
21 SHAPESQ.DAT o - - - - Coins and Gems |
22 SHAPESR.DAT - - - - - TunnelWorld Boss |
23 SHAPESS.DAT o - - - - Asteroid Stuff II |
24 SHAPEST.DAT - o - - - Deli Boss |
25 SHAPESU.DAT - - - - - Deli Stuff II |
28 SHAPESV.DAT - - o - o Misc Stuff/Cars |
27 SHAPES#.DAT - - - o o Sawblades |
31 SHAPES(.DAT - - - - o Desert/Lava |
M 1 2 3 4 episode |
*/ |
/contrib/games/opentyrian/src/lvlmast.h |
---|
0,0 → 1,47 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef LVLMAST_H |
#define LVLMAST_H |
#include "opentyr.h" |
#define EVENT_MAXIMUM 2500 |
#define WEAP_NUM 780 |
#define PORT_NUM 42 |
#define ARMOR_NUM 4 |
#define POWER_NUM 6 |
#define ENGINE_NUM 6 |
#define OPTION_NUM 30 |
#define SHIP_NUM 13 |
#define SHIELD_NUM 10 |
#define SPECIAL_NUM 46 |
#define ENEMY_NUM 850 |
#define LVL_NUM (18 * 2) |
#define LVL_NUM_2 (12 * 2) |
#define LVL_NUM_3 (12 * 2) |
#define LVL_NUM_4 (20 * 2) |
#define LVL_NUM_5 (1 * 2) |
extern const JE_char shapeFile[34]; /* [1..34] */ |
#endif /* LVLMAST_H */ |
/contrib/games/opentyrian/src/mainint.c |
---|
0,0 → 1,4538 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "mainint.h" |
#include "backgrnd.h" |
#include "config.h" |
#include "editship.h" |
#include "episodes.h" |
#include "file.h" |
#include "fonthand.h" |
#include "helptext.h" |
#include "helptext.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "lds_play.h" |
#include "loudness.h" |
#include "menus.h" |
#include "mouse.h" |
#include "mtrand.h" |
#include "network.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "params.h" |
#include "pcxmast.h" |
#include "picload.h" |
#include "player.h" |
#include "setup.h" |
#include "shots.h" |
#include "sndmast.h" |
#include "sprite.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include <assert.h> |
#include <ctype.h> |
#include <string.h> |
bool button[4]; |
#define MAX_PAGE 8 |
#define TOPICS 6 |
const JE_byte topicStart[TOPICS] = { 0, 1, 2, 3, 7, 255 }; |
JE_shortint constantLastX; |
JE_word textErase; |
JE_word upgradeCost; |
JE_word downgradeCost; |
JE_boolean performSave; |
JE_boolean jumpSection; |
JE_boolean useLastBank; /* See if I want to use the last 16 colors for DisplayText */ |
bool pause_pressed = false, ingamemenu_pressed = false; |
/* Draws a message at the bottom text window on the playing screen */ |
void JE_drawTextWindow( const char *text ) |
{ |
if (textErase > 0) // erase current text |
blit_sprite(VGAScreenSeg, 16, 189, OPTION_SHAPES, 36); // in-game text area |
textErase = 100; |
JE_outText(VGAScreenSeg, 20, 190, text, 0, 4); |
} |
void JE_outCharGlow( JE_word x, JE_word y, const char *s ) |
{ |
JE_integer maxloc, loc, z; |
JE_shortint glowcol[60]; /* [1..60] */ |
JE_shortint glowcolc[60]; /* [1..60] */ |
JE_word textloc[60]; /* [1..60] */ |
JE_byte bank; |
setjasondelay2(1); |
bank = (warningRed) ? 7 : ((useLastBank) ? 15 : 14); |
if (s[0] == '\0') |
return; |
if (frameCountMax == 0) |
{ |
JE_textShade(VGAScreen, x, y, s, bank, 0, PART_SHADE); |
JE_showVGA(); |
} |
else |
{ |
maxloc = strlen(s); |
for (z = 0; z < 60; z++) |
{ |
glowcol[z] = -8; |
glowcolc[z] = 1; |
} |
loc = x; |
for (z = 0; z < maxloc; z++) |
{ |
textloc[z] = loc; |
int sprite_id = font_ascii[(unsigned char)s[z]]; |
if (s[z] == ' ') |
loc += 6; |
else if (sprite_id != -1) |
loc += sprite(TINY_FONT, sprite_id)->width + 1; |
} |
for (loc = 0; (unsigned)loc < strlen(s) + 28; loc++) |
{ |
if (!ESCPressed) |
{ |
setjasondelay(frameCountMax); |
NETWORK_KEEP_ALIVE(); |
int sprite_id = -1; |
for (z = loc - 28; z <= loc; z++) |
{ |
if (z >= 0 && z < maxloc) |
{ |
sprite_id = font_ascii[(unsigned char)s[z]]; |
if (sprite_id != -1) |
{ |
blit_sprite_hv(VGAScreen, textloc[z], y, TINY_FONT, sprite_id, bank, glowcol[z]); |
glowcol[z] += glowcolc[z]; |
if (glowcol[z] > 9) |
glowcolc[z] = -1; |
} |
} |
} |
if (sprite_id != -1 && --z < maxloc) |
blit_sprite_dark(VGAScreen, textloc[z] + 1, y + 1, TINY_FONT, sprite_id, true); |
if (JE_anyButton()) |
frameCountMax = 0; |
do |
{ |
if (levelWarningDisplay) |
JE_updateWarning(VGAScreen); |
uSDL_Delay(16); |
} |
while (!(delaycount() == 0 || ESCPressed)); |
JE_showVGA(); |
} |
} |
} |
} |
void JE_drawPortConfigButtons( void ) // rear weapon pattern indicator |
{ |
if (twoPlayerMode) |
return; |
if (player[0].weapon_mode == 1) |
{ |
blit_sprite(VGAScreenSeg, 285, 44, OPTION_SHAPES, 18); // lit |
blit_sprite(VGAScreenSeg, 302, 44, OPTION_SHAPES, 19); // unlit |
} |
else // == 2 |
{ |
blit_sprite(VGAScreenSeg, 285, 44, OPTION_SHAPES, 19); // unlit |
blit_sprite(VGAScreenSeg, 302, 44, OPTION_SHAPES, 18); // lit |
} |
} |
void JE_helpSystem( JE_byte startTopic ) |
{ |
JE_integer page, lastPage = 0; |
JE_byte menu; |
page = topicStart[startTopic-1]; |
fade_black(10); |
JE_loadPic(VGAScreen, 2, false); |
play_song(SONG_MAPVIEW); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
do |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
temp2 = 0; |
for (temp = 0; temp < TOPICS; temp++) |
{ |
if (topicStart[temp] <= page) |
{ |
temp2 = temp; |
} |
} |
if (page > 0) |
{ |
JE_char buf[128]; |
sprintf(buf, "%s %d", miscText[24], page-topicStart[temp2]+1); |
JE_outText(VGAScreen, 10, 192, buf, 13, 5); |
sprintf(buf, "%s %d of %d", miscText[25], page, MAX_PAGE); |
JE_outText(VGAScreen, 220, 192, buf, 13, 5); |
JE_dString(VGAScreen, JE_fontCenter(topicName[temp2], SMALL_FONT_SHAPES), 1, topicName[temp2], SMALL_FONT_SHAPES); |
} |
menu = 0; |
helpBoxBrightness = 3; |
verticalHeight = 8; |
switch (page) |
{ |
case 0: |
menu = 2; |
if (lastPage == MAX_PAGE) |
{ |
menu = TOPICS; |
} |
JE_dString(VGAScreen, JE_fontCenter(topicName[0], FONT_SHAPES), 30, topicName[0], FONT_SHAPES); |
do |
{ |
for (temp = 1; temp <= TOPICS; temp++) |
{ |
char buf[21+1]; |
if (temp == menu-1) |
{ |
strcpy(buf+1, topicName[temp]); |
buf[0] = '~'; |
} else { |
strcpy(buf, topicName[temp]); |
} |
JE_dString(VGAScreen, JE_fontCenter(topicName[temp], SMALL_FONT_SHAPES), temp * 20 + 40, buf, SMALL_FONT_SHAPES); |
} |
//JE_waitRetrace(); didn't do anything anyway? |
JE_showVGA(); |
tempW = 0; |
JE_textMenuWait(&tempW, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
menu--; |
if (menu < 2) |
{ |
menu = TOPICS; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
menu++; |
if (menu > TOPICS) |
{ |
menu = 2; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
default: |
break; |
} |
} |
} while (!(lastkey_sym == SDLK_ESCAPE || lastkey_sym == SDLK_RETURN)); |
if (lastkey_sym == SDLK_RETURN) |
{ |
page = topicStart[menu-1]; |
JE_playSampleNum(S_CLICK); |
} |
break; |
case 1: /* One-Player Menu */ |
JE_HBox(VGAScreen, 10, 20, 2, 60); |
JE_HBox(VGAScreen, 10, 50, 5, 60); |
JE_HBox(VGAScreen, 10, 80, 21, 60); |
JE_HBox(VGAScreen, 10, 110, 1, 60); |
JE_HBox(VGAScreen, 10, 140, 28, 60); |
break; |
case 2: /* Two-Player Menu */ |
JE_HBox(VGAScreen, 10, 20, 1, 60); |
JE_HBox(VGAScreen, 10, 60, 2, 60); |
JE_HBox(VGAScreen, 10, 100, 21, 60); |
JE_HBox(VGAScreen, 10, 140, 28, 60); |
break; |
case 3: /* Upgrade Ship */ |
JE_HBox(VGAScreen, 10, 20, 5, 60); |
JE_HBox(VGAScreen, 10, 70, 6, 60); |
JE_HBox(VGAScreen, 10, 110, 7, 60); |
break; |
case 4: |
JE_HBox(VGAScreen, 10, 20, 8, 60); |
JE_HBox(VGAScreen, 10, 55, 9, 60); |
JE_HBox(VGAScreen, 10, 87, 10, 60); |
JE_HBox(VGAScreen, 10, 120, 11, 60); |
JE_HBox(VGAScreen, 10, 170, 13, 60); |
break; |
case 5: |
JE_HBox(VGAScreen, 10, 20, 14, 60); |
JE_HBox(VGAScreen, 10, 80, 15, 60); |
JE_HBox(VGAScreen, 10, 120, 16, 60); |
break; |
case 6: |
JE_HBox(VGAScreen, 10, 20, 17, 60); |
JE_HBox(VGAScreen, 10, 40, 18, 60); |
JE_HBox(VGAScreen, 10, 130, 20, 60); |
break; |
case 7: /* Options */ |
JE_HBox(VGAScreen, 10, 20, 21, 60); |
JE_HBox(VGAScreen, 10, 70, 22, 60); |
JE_HBox(VGAScreen, 10, 110, 23, 60); |
JE_HBox(VGAScreen, 10, 140, 24, 60); |
break; |
case 8: |
JE_HBox(VGAScreen, 10, 20, 25, 60); |
JE_HBox(VGAScreen, 10, 60, 26, 60); |
JE_HBox(VGAScreen, 10, 100, 27, 60); |
JE_HBox(VGAScreen, 10, 140, 28, 60); |
JE_HBox(VGAScreen, 10, 170, 29, 60); |
break; |
} |
helpBoxBrightness = 1; |
verticalHeight = 7; |
lastPage = page; |
if (menu == 0) |
{ |
do { |
setjasondelay(3); |
push_joysticks_as_keyboard(); |
service_SDL_events(true); |
JE_showVGA(); |
wait_delay(); |
} while (!newkey && !newmouse); |
wait_noinput(false, true, false); |
if (newmouse) |
{ |
switch (lastmouse_but) |
{ |
case SDL_BUTTON_LEFT: |
lastkey_sym = SDLK_RIGHT; |
break; |
case SDL_BUTTON_RIGHT: |
lastkey_sym = SDLK_LEFT; |
break; |
case SDL_BUTTON_MIDDLE: |
lastkey_sym = SDLK_ESCAPE; |
break; |
} |
do |
{ |
service_SDL_events(false); |
} while (mousedown); |
newkey = true; |
} |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_LEFT: |
case SDLK_UP: |
case SDLK_PAGEUP: |
page--; |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_RIGHT: |
case SDLK_DOWN: |
case SDLK_PAGEDOWN: |
case SDLK_RETURN: |
case SDLK_SPACE: |
if (page == MAX_PAGE) |
{ |
page = 0; |
} else { |
page++; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_F1: |
page = 0; |
JE_playSampleNum(S_CURSOR); |
break; |
default: |
break; |
} |
} |
} |
if (page == 255) |
{ |
lastkey_sym = SDLK_ESCAPE; |
} |
} while (lastkey_sym != SDLK_ESCAPE); |
} |
// cost to upgrade a weapon power from power-1 (where power == 0 indicates an unupgraded weapon) |
long weapon_upgrade_cost( long base_cost, unsigned int power ) |
{ |
assert(power <= 11); |
unsigned int temp = 0; |
// 0 1 3 6 10 15 21 29 ... |
for (; power > 0; power--) |
temp += power; |
return base_cost * temp; |
} |
ulong JE_getCost( JE_byte itemType, JE_word itemNum ) |
{ |
long cost = 0; |
switch (itemType) |
{ |
case 2: |
cost = (itemNum > 90) ? 100 : ships[itemNum].cost; |
break; |
case 3: |
case 4: |
cost = weaponPort[itemNum].cost; |
const uint port = itemType - 3, |
item_power = player[0].items.weapon[port].power - 1; |
downgradeCost = weapon_upgrade_cost(cost, item_power); |
upgradeCost = weapon_upgrade_cost(cost, item_power + 1); |
break; |
case 5: |
cost = shields[itemNum].cost; |
break; |
case 6: |
cost = powerSys[itemNum].cost; |
break; |
case 7: |
case 8: |
cost = options[itemNum].cost; |
break; |
} |
return cost; |
} |
void JE_loadScreen( void ) |
{ |
JE_boolean quit; |
JE_byte sel, screen, min = 0, max = 0; |
char *tempstr; |
char *tempstr2; |
JE_boolean mal_str = false; |
int len; |
tempstr = NULL; |
free_sprite2s(&shapes6); |
JE_loadCompShapes(&shapes6, '1'); // need arrow sprites |
fade_black(10); |
JE_loadPic(VGAScreen, 2, false); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
screen = 1; |
sel = 1; |
quit = false; |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
do |
{ |
while (mousedown) |
{ |
service_SDL_events(false); |
tempX = mouse_x; |
tempY = mouse_y; |
} |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
JE_dString(VGAScreen, JE_fontCenter(miscText[38 + screen - 1], FONT_SHAPES), 5, miscText[38 + screen - 1], FONT_SHAPES); |
switch (screen) |
{ |
case 1: |
min = 1; |
max = 12; |
break; |
case 2: |
min = 12; |
max = 23; |
} |
/* SYN: Go through text line by line */ |
for (x = min; x <= max; x++) |
{ |
tempY = 30 + (x - min) * 13; |
if (x == max) |
{ |
/* Last line is return to main menu, not a save game */ |
if (mal_str) |
{ |
free(tempstr); |
mal_str = false; |
} |
tempstr = miscText[34 - 1]; |
if (x == sel) /* Highlight if selected */ |
{ |
temp2 = 254; |
} else { |
temp2 = 250; |
} |
} else { |
if (x == sel) /* Highlight if selected */ |
{ |
temp2 = 254; |
} else { |
temp2 = 250 - ((saveFiles[x - 1].level == 0) << 1); |
} |
if (saveFiles[x - 1].level == 0) /* I think this means the save file is unused */ |
{ |
if (mal_str) |
{ |
free(tempstr); |
mal_str = false; |
} |
tempstr = miscText[3 - 1]; |
} else { |
if (mal_str) |
{ |
free(tempstr); |
mal_str = false; |
} |
tempstr = saveFiles[x - 1].name; |
} |
} |
/* Write first column text */ |
JE_textShade(VGAScreen, 10, tempY, tempstr, 13, (temp2 % 16) - 8, FULL_SHADE); |
if (x < max) /* Write additional columns for all but the last row */ |
{ |
if (saveFiles[x - 1].level == 0) |
{ |
if (mal_str) |
{ |
free(tempstr); |
} |
tempstr = malloc(7); |
mal_str = true; |
strcpy(tempstr, "-----"); /* Unused save slot */ |
} else { |
tempstr = saveFiles[x - 1].levelName; |
tempstr2 = malloc(5 + strlen(miscTextB[2-1])); |
sprintf(tempstr2, "%s %d", miscTextB[2-1], saveFiles[x - 1].episode); |
JE_textShade(VGAScreen, 250, tempY, tempstr2, 5, (temp2 % 16) - 8, FULL_SHADE); |
free(tempstr2); |
} |
len = strlen(miscTextB[3-1]) + 2 + strlen(tempstr); |
tempstr2 = malloc(len); |
sprintf(tempstr2, "%s %s", miscTextB[3 - 1], tempstr); |
JE_textShade(VGAScreen, 120, tempY, tempstr2, 5, (temp2 % 16) - 8, FULL_SHADE); |
free(tempstr2); |
} |
} |
if (screen == 2) |
{ |
blit_sprite2x2(VGAScreen, 90, 180, shapes6, 279); |
} |
if (screen == 1) |
{ |
blit_sprite2x2(VGAScreen, 220, 180, shapes6, 281); |
} |
helpBoxColor = 15; |
JE_helpBox(VGAScreen, 110, 182, miscText[56-1], 25); |
JE_showVGA(); |
tempW = 0; |
JE_textMenuWait(&tempW, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
sel--; |
if (sel < min) |
{ |
sel = max; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
sel++; |
if (sel > max) |
{ |
sel = min; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_LEFT: |
case SDLK_RIGHT: |
if (screen == 1) |
{ |
screen = 2; |
sel += 11; |
} else { |
screen = 1; |
sel -= 11; |
} |
break; |
case SDLK_RETURN: |
if (sel < max) |
{ |
if (saveFiles[sel - 1].level > 0) |
{ |
JE_playSampleNum(S_SELECT); |
performSave = false; |
JE_operation(sel); |
quit = true; |
} else { |
JE_playSampleNum(S_CLINK); |
} |
} else { |
quit = true; |
} |
break; |
case SDLK_ESCAPE: |
quit = true; |
break; |
default: |
break; |
} |
} |
} while (!quit); |
} |
ulong JE_totalScore( const Player *this_player ) |
{ |
ulong temp = this_player->cash; |
temp += JE_getValue(2, this_player->items.ship); |
temp += JE_getValue(3, this_player->items.weapon[FRONT_WEAPON].id); |
temp += JE_getValue(4, this_player->items.weapon[REAR_WEAPON].id); |
temp += JE_getValue(5, this_player->items.shield); |
temp += JE_getValue(6, this_player->items.generator); |
temp += JE_getValue(7, this_player->items.sidekick[LEFT_SIDEKICK]); |
temp += JE_getValue(8, this_player->items.sidekick[RIGHT_SIDEKICK]); |
return temp; |
} |
JE_longint JE_getValue( JE_byte itemType, JE_word itemNum ) |
{ |
long value = 0; |
switch (itemType) |
{ |
case 2: |
value = ships[itemNum].cost; |
break; |
case 3: |
case 4:; |
const long base_value = weaponPort[itemNum].cost; |
// if two-player, use first player's front and second player's rear weapon |
const uint port = itemType - 3; |
const uint item_power = player[twoPlayerMode ? port : 0].items.weapon[port].power - 1; |
value = base_value; |
for (unsigned int i = 1; i <= item_power; ++i) |
value += weapon_upgrade_cost(base_value, i); |
break; |
case 5: |
value = shields[itemNum].cost; |
break; |
case 6: |
value = powerSys[itemNum].cost; |
break; |
case 7: |
case 8: |
value = options[itemNum].cost; |
break; |
} |
return value; |
} |
void JE_nextEpisode( void ) |
{ |
strcpy(lastLevelName, "Completed"); |
if (episodeNum == initial_episode_num && !gameHasRepeated && episodeNum != EPISODE_AVAILABLE && |
!isNetworkGame && !constantPlay) |
{ |
JE_highScoreCheck(); |
} |
unsigned int newEpisode = JE_findNextEpisode(); |
if (jumpBackToEpisode1) |
{ |
// shareware version check |
if (episodeNum == 1 && |
!isNetworkGame && !constantPlay) |
{ |
// JE_loadOrderingInfo(); |
} |
if (episodeNum > 2 && |
!constantPlay) |
{ |
JE_playCredits(); |
} |
// randomly give player the SuperCarrot |
if ((mt_rand() % 6) == 0) |
{ |
player[0].items.ship = 2; // SuperCarrot |
player[0].items.weapon[FRONT_WEAPON].id = 23; // Banana Blast |
player[0].items.weapon[REAR_WEAPON].id = 24; // Banana Blast Rear |
for (uint i = 0; i < COUNTOF(player[0].items.weapon); ++i) |
player[0].items.weapon[i].power = 1; |
player[1].items.weapon[REAR_WEAPON].id = 24; // Banana Blast Rear |
player[0].last_items = player[0].items; |
} |
} |
if (newEpisode != episodeNum) |
JE_initEpisode(newEpisode); |
gameLoaded = true; |
mainLevel = FIRST_LEVEL; |
saveLevel = FIRST_LEVEL; |
play_song(26); |
JE_clr256(VGAScreen); |
memcpy(colors, palettes[6-1], sizeof(colors)); |
JE_dString(VGAScreen, JE_fontCenter(episode_name[episodeNum], SMALL_FONT_SHAPES), 130, episode_name[episodeNum], SMALL_FONT_SHAPES); |
JE_dString(VGAScreen, JE_fontCenter(miscText[5-1], SMALL_FONT_SHAPES), 185, miscText[5-1], SMALL_FONT_SHAPES); |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
JE_wipeKey(); |
if (!constantPlay) |
{ |
do |
{ |
NETWORK_KEEP_ALIVE(); |
uSDL_Delay(16); |
} while (!JE_anyButton()); |
} |
fade_black(15); |
} |
void JE_initPlayerData( void ) |
{ |
/* JE: New Game Items/Data */ |
player[0].items.ship = 1; // USP Talon |
player[0].items.weapon[FRONT_WEAPON].id = 1; // Pulse Cannon |
player[0].items.weapon[REAR_WEAPON].id = 0; // None |
player[0].items.shield = 4; // Gencore High Energy Shield |
player[0].items.generator = 2; // Advanced MR-12 |
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i) |
player[0].items.sidekick[i] = 0; // None |
player[0].items.special = 0; // None |
player[0].last_items = player[0].items; |
player[1].items = player[0].items; |
player[1].items.weapon[REAR_WEAPON].id = 15; // Vulcan Cannon |
player[1].items.sidekick_level = 101; // 101, 102, 103 |
player[1].items.sidekick_series = 0; // None |
gameHasRepeated = false; |
onePlayerAction = false; |
superArcadeMode = SA_NONE; |
superTyrian = false; |
twoPlayerMode = false; |
secretHint = (mt_rand() % 3) + 1; |
for (uint p = 0; p < COUNTOF(player); ++p) |
{ |
for (uint i = 0; i < COUNTOF(player->items.weapon); ++i) |
{ |
player[p].items.weapon[i].power = 1; |
} |
player[p].weapon_mode = 1; |
player[p].armor = ships[player[p].items.ship].dmg; |
player[p].is_dragonwing = (p == 1); |
player[p].lives = &player[p].items.weapon[p].power; |
} |
mainLevel = FIRST_LEVEL; |
saveLevel = FIRST_LEVEL; |
strcpy(lastLevelName, miscText[19]); |
} |
void JE_sortHighScores( void ) |
{ |
JE_byte x; |
temp = 0; |
for (x = 0; x < 6; x++) |
{ |
JE_sort(); |
temp += 3; |
} |
} |
void JE_highScoreScreen( void ) |
{ |
int min = 1; |
int max = 3; |
int x, z; |
short int chg; |
int quit; |
char scoretemp[32]; |
free_sprite2s(&shapes6); |
JE_loadCompShapes(&shapes6, '1'); // need arrow sprites |
fade_black(10); |
JE_loadPic(VGAScreen, 2, false); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
quit = false; |
x = 1; |
chg = 1; |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
do |
{ |
if (episodeAvail[x-1]) |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
JE_dString(VGAScreen, JE_fontCenter(miscText[51 - 1], FONT_SHAPES), 03, miscText[51 - 1], FONT_SHAPES); |
JE_dString(VGAScreen, JE_fontCenter(episode_name[x], SMALL_FONT_SHAPES), 30, episode_name[x], SMALL_FONT_SHAPES); |
/* Player 1 */ |
temp = (x * 6) - 6; |
JE_dString(VGAScreen, JE_fontCenter(miscText[47 - 1], SMALL_FONT_SHAPES), 55, miscText[47 - 1], SMALL_FONT_SHAPES); |
for (z = 0; z < 3; z++) |
{ |
int difficulty = saveFiles[temp + z].highScoreDiff; |
if (difficulty > 9) |
{ |
saveFiles[temp + z].highScoreDiff = 0; |
difficulty = 0; |
} |
sprintf(scoretemp, "~#%d:~ %d", z + 1, saveFiles[temp+z].highScore1); |
JE_textShade(VGAScreen, 250, ((z+1) * 10) + 65 , difficultyNameB[difficulty], 15, difficulty + (difficulty == 0 ? 0 : -1), FULL_SHADE); |
JE_textShade(VGAScreen, 20, ((z+1) * 10) + 65 , scoretemp, 15, 0, FULL_SHADE); |
JE_textShade(VGAScreen, 110, ((z+1) * 10) + 65 , saveFiles[temp + z].highScoreName, 15, 2, FULL_SHADE); |
} |
/* Player 2 */ |
temp += 3; |
JE_dString(VGAScreen, JE_fontCenter( miscText[48 - 1], SMALL_FONT_SHAPES), 120, miscText[48 - 1], SMALL_FONT_SHAPES); |
/*{ textshade(20,125,misctext[49],15,3,_FullShade); |
textshade(80,125,misctext[50],15,3,_FullShade);}*/ |
for (z = 0; z < 3; z++) |
{ |
int difficulty = saveFiles[temp + z].highScoreDiff; |
if (difficulty > 9) |
{ |
saveFiles[temp + z].highScoreDiff = 0; |
difficulty = 0; |
} |
sprintf(scoretemp, "~#%d:~ %d", z + 1, saveFiles[temp+z].highScore1); /* Not .highScore2 for some reason */ |
JE_textShade(VGAScreen, 250, ((z+1) * 10) + 125 , difficultyNameB[difficulty], 15, difficulty + (difficulty == 0 ? 0 : -1), FULL_SHADE); |
JE_textShade(VGAScreen, 20, ((z+1) * 10) + 125 , scoretemp, 15, 0, FULL_SHADE); |
JE_textShade(VGAScreen, 110, ((z+1) * 10) + 125 , saveFiles[temp + z].highScoreName, 15, 2, FULL_SHADE); |
} |
if (x > 1) |
{ |
blit_sprite2x2(VGAScreen, 90, 180, shapes6, 279); |
} |
if ( ( (x < 2) && episodeAvail[2-1] ) || ( (x < 3) && episodeAvail[3-1] ) ) |
{ |
blit_sprite2x2(VGAScreen, 220, 180, shapes6, 281); |
} |
helpBoxColor = 15; |
JE_helpBox(VGAScreen, 110, 182, miscText[57 - 1], 25); |
/* {Dstring(fontcenter(misctext[57],_SmallFontShapes),190,misctext[57],_SmallFontShapes);} */ |
JE_showVGA(); |
tempW = 0; |
JE_textMenuWait(&tempW, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_LEFT: |
x--; |
chg = -1; |
break; |
case SDLK_RIGHT: |
x++; |
chg = 1; |
break; |
default: |
break; |
} |
} |
} else { |
x += chg; |
} |
x = ( x < min ) ? max : ( x > max ) ? min : x; |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_RETURN: |
case SDLK_ESCAPE: |
quit = true; |
break; |
default: |
break; |
} |
} |
} while (!quit); |
} |
void JE_gammaCorrect_func( JE_byte *col, JE_real r ) |
{ |
int temp = roundf(*col * r); |
if (temp > 255) |
{ |
temp = 255; |
} |
*col = temp; |
} |
void JE_gammaCorrect( Palette *colorBuffer, JE_byte gamma ) |
{ |
int x; |
JE_real r = 1 + (JE_real)gamma / 10; |
for (x = 0; x < 256; x++) |
{ |
JE_gammaCorrect_func(&(*colorBuffer)[x].r, r); |
JE_gammaCorrect_func(&(*colorBuffer)[x].g, r); |
JE_gammaCorrect_func(&(*colorBuffer)[x].b, r); |
} |
} |
JE_boolean JE_gammaCheck( void ) |
{ |
bool temp = keysactive[SDLK_F11] != 0; |
if (temp) |
{ |
keysactive[SDLK_F11] = false; |
newkey = false; |
gammaCorrection = (gammaCorrection + 1) % 4; |
memcpy(colors, palettes[pcxpal[3-1]], sizeof(colors)); |
JE_gammaCorrect(&colors, gammaCorrection); |
set_palette(colors, 0, 255); |
} |
return temp; |
} |
void JE_doInGameSetup( void ) |
{ |
haltGame = false; |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
network_prepare(PACKET_GAME_MENU); |
network_send(4); // PACKET_GAME_MENU |
while (true) |
{ |
service_SDL_events(false); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_GAME_MENU) |
{ |
network_update(); |
break; |
} |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
} |
#endif |
if (yourInGameMenuRequest) |
{ |
if (JE_inGameSetup()) |
{ |
reallyEndLevel = true; |
playerEndLevel = true; |
} |
quitRequested = false; |
keysactive[SDLK_ESCAPE] = false; |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
if (!playerEndLevel) |
{ |
network_prepare(PACKET_WAITING); |
network_send(4); // PACKET_WAITING |
} else { |
network_prepare(PACKET_GAME_QUIT); |
network_send(4); // PACKET_GAMEQUIT |
} |
} |
#endif |
} |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
if (!yourInGameMenuRequest) |
{ |
JE_barShade(VGAScreen, 3, 60, 257, 80); /*Help Box*/ |
JE_barShade(VGAScreen, 5, 62, 255, 78); |
JE_dString(VGAScreen, 10, 65, "Other player in options menu.", SMALL_FONT_SHAPES); |
JE_showVGA(); |
while (true) |
{ |
service_SDL_events(false); |
JE_showVGA(); |
if (packet_in[0]) |
{ |
if (SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_WAITING) |
{ |
network_check(); |
break; |
} else if (SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_GAME_QUIT) { |
reallyEndLevel = true; |
playerEndLevel = true; |
network_check(); |
break; |
} |
} |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
} else { |
/* |
JE_barShade(3, 160, 257, 180); /-*Help Box*-/ |
JE_barShade(5, 162, 255, 178); |
tempScreenSeg = VGAScreen; |
JE_dString(VGAScreen, 10, 165, "Waiting for other player.", SMALL_FONT_SHAPES); |
JE_showVGA(); |
*/ |
} |
while (!network_is_sync()) |
{ |
service_SDL_events(false); |
network_check(); |
uSDL_Delay(16); |
} |
VGAScreen = temp_surface; /* side-effect of game_screen */ |
} |
#endif |
yourInGameMenuRequest = false; |
//skipStarShowVGA = true; |
} |
JE_boolean JE_inGameSetup( void ) |
{ |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_boolean returnvalue = false; |
const JE_byte help[6] /* [1..6] */ = {15, 15, 28, 29, 26, 27}; |
JE_byte sel; |
JE_boolean quit; |
bool first = true; |
//tempScreenSeg = VGAScreenSeg; /* <MXD> ? should work as VGAScreen */ |
quit = false; |
sel = 1; |
JE_barShade(VGAScreen, 3, 13, 217, 137); /*Main Box*/ |
JE_barShade(VGAScreen, 5, 15, 215, 135); |
JE_barShade(VGAScreen, 3, 143, 257, 157); /*Help Box*/ |
JE_barShade(VGAScreen, 5, 145, 255, 155); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
do |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
for (x = 0; x < 6; x++) |
{ |
JE_outTextAdjust(VGAScreen, 10, (x + 1) * 20, inGameText[x], 15, ((sel == x+1) << 1) - 4, SMALL_FONT_SHAPES, true); |
} |
JE_outTextAdjust(VGAScreen, 120, 3 * 20, detailLevel[processorType-1], 15, ((sel == 3) << 1) - 4, SMALL_FONT_SHAPES, true); |
JE_outTextAdjust(VGAScreen, 120, 4 * 20, gameSpeedText[gameSpeed-1], 15, ((sel == 4) << 1) - 4, SMALL_FONT_SHAPES, true); |
JE_outTextAdjust(VGAScreen, 10, 147, mainMenuHelp[help[sel-1]-1], 14, 6, TINY_FONT, true); |
JE_barDrawShadow(VGAScreen, 120, 20, 1, music_disabled ? 12 : 16, tyrMusicVolume / 12, 3, 13); |
JE_barDrawShadow(VGAScreen, 120, 40, 1, samples_disabled ? 12 : 16, fxVolume / 12, 3, 13); |
JE_showVGA(); |
if (first) |
{ |
first = false; |
wait_noinput(false, false, true); // TODO: should up the joystick repeat temporarily instead |
} |
tempW = 0; |
JE_textMenuWait(&tempW, true); |
if (inputDetected) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_RETURN: |
JE_playSampleNum(S_SELECT); |
switch (sel) |
{ |
case 1: |
music_disabled = !music_disabled; |
break; |
case 2: |
samples_disabled = !samples_disabled; |
break; |
case 3: |
case 4: |
sel = 5; |
break; |
case 5: |
quit = true; |
break; |
case 6: |
returnvalue = true; |
quit = true; |
if (constantPlay) |
{ |
JE_tyrianHalt(0); |
} |
if (isNetworkGame) |
{ /*Tell other computer to exit*/ |
haltGame = true; |
playerEndLevel = true; |
} |
break; |
} |
break; |
case SDLK_ESCAPE: |
quit = true; |
JE_playSampleNum(S_SPRING); |
break; |
case SDLK_UP: |
if (--sel < 1) |
{ |
sel = 6; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
if (++sel > 6) |
{ |
sel = 1; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_LEFT: |
switch (sel) |
{ |
case 1: |
JE_changeVolume(&tyrMusicVolume, -12, &fxVolume, 0); |
if (music_disabled) |
{ |
music_disabled = false; |
restart_song(); |
} |
break; |
case 2: |
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, -12); |
samples_disabled = false; |
break; |
case 3: |
if (--processorType < 1) |
{ |
processorType = 4; |
} |
JE_initProcessorType(); |
JE_setNewGameSpeed(); |
break; |
case 4: |
if (--gameSpeed < 1) |
{ |
gameSpeed = 5; |
} |
JE_initProcessorType(); |
JE_setNewGameSpeed(); |
break; |
} |
if (sel < 5) |
{ |
JE_playSampleNum(S_CURSOR); |
} |
break; |
case SDLK_RIGHT: |
switch (sel) |
{ |
case 1: |
JE_changeVolume(&tyrMusicVolume, 12, &fxVolume, 0); |
if (music_disabled) |
{ |
music_disabled = false; |
restart_song(); |
} |
break; |
case 2: |
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, 12); |
samples_disabled = false; |
break; |
case 3: |
if (++processorType > 4) |
{ |
processorType = 1; |
} |
JE_initProcessorType(); |
JE_setNewGameSpeed(); |
break; |
case 4: |
if (++gameSpeed > 5) |
{ |
gameSpeed = 1; |
} |
JE_initProcessorType(); |
JE_setNewGameSpeed(); |
break; |
} |
if (sel < 5) |
{ |
JE_playSampleNum(S_CURSOR); |
} |
break; |
case SDLK_w: |
if (sel == 3) |
{ |
processorType = 6; |
JE_initProcessorType(); |
} |
default: |
break; |
} |
} |
} while (!(quit || haltGame)); |
VGAScreen = temp_surface; /* side-effect of game_screen */ |
return returnvalue; |
} |
void JE_inGameHelp( void ) |
{ |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
//tempScreenSeg = VGAScreenSeg; |
JE_clearKeyboard(); |
JE_wipeKey(); |
JE_barShade(VGAScreen, 1, 1, 262, 182); /*Main Box*/ |
JE_barShade(VGAScreen, 3, 3, 260, 180); |
JE_barShade(VGAScreen, 5, 5, 258, 178); |
JE_barShade(VGAScreen, 7, 7, 256, 176); |
fill_rectangle_xy(VGAScreen, 9, 9, 254, 174, 0); |
if (twoPlayerMode) // Two-Player Help |
{ |
helpBoxColor = 3; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 20, 4, 36, 50); |
// weapon help |
blit_sprite(VGAScreenSeg, 2, 21, OPTION_SHAPES, 43); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 55, 20, 37, 40); |
// sidekick help |
blit_sprite(VGAScreenSeg, 5, 36, OPTION_SHAPES, 41); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 40, 43, 34, 44); |
// sheild/armor help |
blit_sprite(VGAScreenSeg, 2, 79, OPTION_SHAPES, 42); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 54, 84, 35, 40); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 5, 126, 38, 55); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 5, 160, 39, 55); |
} |
else |
{ |
// power bar help |
blit_sprite(VGAScreenSeg, 15, 5, OPTION_SHAPES, 40); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 40, 10, 31, 45); |
// weapon help |
blit_sprite(VGAScreenSeg, 5, 37, OPTION_SHAPES, 39); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 40, 40, 32, 44); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 40, 60, 33, 44); |
// sidekick help |
blit_sprite(VGAScreenSeg, 5, 98, OPTION_SHAPES, 41); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 40, 103, 34, 44); |
// shield/armor help |
blit_sprite(VGAScreenSeg, 2, 138, OPTION_SHAPES, 42); |
helpBoxColor = 5; |
helpBoxBrightness = 3; |
JE_HBox(VGAScreen, 54, 143, 35, 40); |
} |
// "press a key" |
blit_sprite(VGAScreenSeg, 16, 189, OPTION_SHAPES, 36); // in-game text area |
JE_outText(VGAScreenSeg, 120 - JE_textWidth(miscText[5-1], TINY_FONT) / 2 + 20, 190, miscText[5-1], 0, 4); |
JE_showVGA(); |
do |
{ |
tempW = 0; |
JE_textMenuWait(&tempW, true); |
} |
while (!inputDetected); |
textErase = 1; |
VGAScreen = temp_surface; |
} |
void JE_highScoreCheck( void ) |
{ |
free_sprite2s(&shapes6); |
JE_loadCompShapes(&shapes6, '1'); // need mouse cursor sprite |
Sint32 temp_score; |
for (int temp_p = 0; temp_p < (twoPlayerMode ? 2 : 1); ++temp_p) |
{ |
JE_sortHighScores(); |
int p = temp_p; |
if (twoPlayerMode) |
{ |
// ask for the highest scorer first |
if (player[0].cash < player[1].cash) |
p = (temp_p == 0) ? 1 : 0; |
temp_score = (p == 0) ? player[0].cash : player[1].cash; |
} |
else |
{ |
// single player highscore includes cost of upgrades |
temp_score = JE_totalScore(&player[0]); |
} |
int slot; |
const int first_slot = (initial_episode_num - 1) * 6 + (twoPlayerMode ? 3 : 0), |
slot_limit = first_slot + 3; |
for (slot = first_slot; slot < slot_limit; ++slot) |
{ |
if (temp_score > saveFiles[slot].highScore1) |
break; |
} |
// did you get a high score? |
if (slot < slot_limit) |
{ |
// shift down old scores |
for (int i = slot_limit - 1; i > slot; --i) |
{ |
saveFiles[i].highScore1 = saveFiles[i - 1].highScore1; |
strcpy(saveFiles[i].highScoreName, saveFiles[i - 1].highScoreName); |
} |
wait_noinput(false, true, false); |
JE_clr256(VGAScreen); |
JE_showVGA(); |
memcpy(colors, palettes[0], sizeof(colors)); |
play_song(33); |
{ |
/* Enter Thy name */ |
JE_byte flash = 8 * 16 + 10; |
JE_boolean fadein = true; |
JE_boolean quit = false, cancel = false; |
char stemp[30], tempstr[30]; |
char buffer[256]; |
strcpy(stemp, " "); |
temp = 0; |
JE_barShade(VGAScreen, 65, 55, 255, 155); |
do |
{ |
service_SDL_events(true); |
JE_dString(VGAScreen, JE_fontCenter(miscText[51], FONT_SHAPES), 3, miscText[51], FONT_SHAPES); |
temp3 = twoPlayerMode ? 58 + p : 53; |
JE_dString(VGAScreen, JE_fontCenter(miscText[temp3-1], SMALL_FONT_SHAPES), 30, miscText[temp3-1], SMALL_FONT_SHAPES); |
blit_sprite(VGAScreenSeg, 50, 50, OPTION_SHAPES, 35); // message box |
if (twoPlayerMode) |
{ |
sprintf(buffer, "%s %s", miscText[48 + p], miscText[53]); |
JE_textShade(VGAScreen, 60, 55, buffer, 11, 4, FULL_SHADE); |
} |
else |
{ |
JE_textShade(VGAScreen, 60, 55, miscText[53], 11, 4, FULL_SHADE); |
} |
sprintf(buffer, "%s %d", miscText[37], temp_score); |
JE_textShade(VGAScreen, 70, 70, buffer, 11, 4, FULL_SHADE); |
do |
{ |
flash = (flash == 8 * 16 + 10) ? 8 * 16 + 2 : 8 * 16 + 10; |
temp3 = (temp3 == 6) ? 2 : 6; |
strncpy(tempstr, stemp, temp); |
tempstr[temp] = '\0'; |
JE_outText(VGAScreen, 65, 89, tempstr, 8, 3); |
tempW = 65 + JE_textWidth(tempstr, TINY_FONT); |
JE_barShade(VGAScreen, tempW + 2, 90, tempW + 6, 95); |
fill_rectangle_xy(VGAScreen, tempW + 1, 89, tempW + 5, 94, flash); |
for (int i = 0; i < 14; i++) |
{ |
setjasondelay(1); |
JE_mouseStart(); |
JE_showVGA(); |
if (fadein) |
{ |
fade_palette(colors, 15, 0, 255); |
fadein = false; |
} |
JE_mouseReplace(); |
push_joysticks_as_keyboard(); |
service_wait_delay(); |
if (newkey || newmouse) |
break; |
} |
} while (!newkey && !newmouse); |
if (!playing) |
play_song(31); |
if (mouseButton > 0) |
{ |
if (mouseX > 56 && mouseX < 142 && mouseY > 123 && mouseY < 149) |
{ |
quit = true; |
} |
else if (mouseX > 151 && mouseX < 237 && mouseY > 123 && mouseY < 149) |
{ |
quit = true; |
cancel = true; |
} |
} |
else if (newkey) |
{ |
bool validkey = false; |
lastkey_char = toupper(lastkey_char); |
switch(lastkey_char) |
{ |
case ' ': |
case '-': |
case '.': |
case ',': |
case ':': |
case '!': |
case '?': |
case '#': |
case '@': |
case '$': |
case '%': |
case '*': |
case '(': |
case ')': |
case '/': |
case '=': |
case '+': |
case '<': |
case '>': |
case ';': |
case '"': |
case '\'': |
validkey = true; |
// fall through |
default: |
if (temp < 28 && (validkey || (lastkey_char >= 'A' && lastkey_char <= 'Z') || (lastkey_char >= '0' && lastkey_char <= '9'))) |
{ |
stemp[temp] = lastkey_char; |
temp++; |
} |
break; |
case SDLK_BACKSPACE: |
case SDLK_DELETE: |
if (temp) |
{ |
temp--; |
stemp[temp] = ' '; |
} |
break; |
case SDLK_ESCAPE: |
quit = true; |
cancel = true; |
break; |
case SDLK_RETURN: |
quit = true; |
break; |
} |
} |
} |
while (!quit); |
if (!cancel) |
{ |
saveFiles[slot].highScore1 = temp_score; |
strcpy(saveFiles[slot].highScoreName, stemp); |
saveFiles[slot].highScoreDiff = difficultyLevel; |
} |
fade_black(15); |
JE_loadPic(VGAScreen, 2, false); |
JE_dString(VGAScreen, JE_fontCenter(miscText[50], FONT_SHAPES), 10, miscText[50], FONT_SHAPES); |
JE_dString(VGAScreen, JE_fontCenter(episode_name[episodeNum], SMALL_FONT_SHAPES), 35, episode_name[episodeNum], SMALL_FONT_SHAPES); |
for (int i = first_slot; i < slot_limit; ++i) |
{ |
if (i != slot) |
{ |
sprintf(buffer, "~#%d:~ %d", (i - first_slot + 1), saveFiles[i].highScore1); |
JE_textShade(VGAScreen, 20, ((i - first_slot + 1) * 12) + 65, buffer, 15, 0, FULL_SHADE); |
JE_textShade(VGAScreen, 150, ((i - first_slot + 1) * 12) + 65, saveFiles[i].highScoreName, 15, 2, FULL_SHADE); |
} |
} |
JE_showVGA(); |
fade_palette(colors, 15, 0, 255); |
sprintf(buffer, "~#%d:~ %d", (slot - first_slot + 1), saveFiles[slot].highScore1); |
frameCountMax = 6; |
textGlowFont = TINY_FONT; |
textGlowBrightness = 10; |
JE_outTextGlow(VGAScreenSeg, 20, (slot - first_slot + 1) * 12 + 65, buffer); |
textGlowBrightness = 10; |
JE_outTextGlow(VGAScreenSeg, 150, (slot - first_slot + 1) * 12 + 65, saveFiles[slot].highScoreName); |
textGlowBrightness = 10; |
JE_outTextGlow(VGAScreenSeg, JE_fontCenter(miscText[4], TINY_FONT), 180, miscText[4]); |
JE_showVGA(); |
if (frameCountMax != 0) |
wait_input(true, true, true); |
fade_black(15); |
} |
} |
} |
} |
// increases game difficulty based on player's total score / total of players' scores |
void adjust_difficulty( void ) |
{ |
const float score_multiplier[10] = |
{ |
0, // Wimp (doesn't exist) |
0.4f, // Easy |
0.8f, // Normal |
1.3f, // Hard |
1.6f, // Impossible |
2, // Insanity |
2, // Suicide |
3, // Maniacal |
3, // Zinglon |
3, // Nortaneous |
}; |
assert(initialDifficulty > 0 && initialDifficulty < 10); |
const ulong score = twoPlayerMode ? (player[0].cash + player[1].cash) : JE_totalScore(&player[0]), |
adjusted_score = roundf(score * score_multiplier[initialDifficulty]); |
uint new_difficulty = 0; |
if (twoPlayerMode) |
{ |
if (adjusted_score < 10000) |
new_difficulty = 1; // Easy |
else if (adjusted_score < 20000) |
new_difficulty = 2; // Normal |
else if (adjusted_score < 50000) |
new_difficulty = 3; // Hard |
else if (adjusted_score < 80000) |
new_difficulty = 4; // Impossible |
else if (adjusted_score < 125000) |
new_difficulty = 5; // Insanity |
else if (adjusted_score < 200000) |
new_difficulty = 6; // Suicide |
else if (adjusted_score < 400000) |
new_difficulty = 7; // Maniacal |
else if (adjusted_score < 600000) |
new_difficulty = 8; // Zinglon |
else |
new_difficulty = 9; // Nortaneous |
} |
else |
{ |
if (adjusted_score < 40000) |
new_difficulty = 1; // Easy |
else if (adjusted_score < 70000) |
new_difficulty = 2; // Normal |
else if (adjusted_score < 150000) |
new_difficulty = 3; // Hard |
else if (adjusted_score < 300000) |
new_difficulty = 4; // Impossible |
else if (adjusted_score < 600000) |
new_difficulty = 5; // Insanity |
else if (adjusted_score < 1000000) |
new_difficulty = 6; // Suicide |
else if (adjusted_score < 2000000) |
new_difficulty = 7; // Maniacal |
else if (adjusted_score < 3000000) |
new_difficulty = 8; // Zinglon |
else |
new_difficulty = 9; // Nortaneous |
} |
difficultyLevel = MAX((unsigned)difficultyLevel, new_difficulty); |
} |
bool load_next_demo( void ) |
{ |
if (++demo_num > 5) |
demo_num = 1; |
char demo_filename[9]; |
snprintf(demo_filename, sizeof(demo_filename), "demo.%d", demo_num); |
demo_file = dir_fopen_die(data_dir(), demo_filename, "rb"); // TODO: only play demos from existing file (instead of dying) |
difficultyLevel = 2; |
bonusLevelCurrent = false; |
Uint8 temp = fgetc(demo_file); |
JE_initEpisode(temp); |
efread(levelName, 1, 10, demo_file); levelName[10] = '\0'; |
lvlFileNum = fgetc(demo_file); |
player[0].items.weapon[FRONT_WEAPON].id = fgetc(demo_file); |
player[0].items.weapon[REAR_WEAPON].id = fgetc(demo_file); |
player[0].items.super_arcade_mode = fgetc(demo_file); |
player[0].items.sidekick[LEFT_SIDEKICK] = fgetc(demo_file); |
player[0].items.sidekick[RIGHT_SIDEKICK] = fgetc(demo_file); |
player[0].items.generator = fgetc(demo_file); |
player[0].items.sidekick_level = fgetc(demo_file); // could probably ignore |
player[0].items.sidekick_series = fgetc(demo_file); // could probably ignore |
initial_episode_num = fgetc(demo_file); // could probably ignore |
player[0].items.shield = fgetc(demo_file); |
player[0].items.special = fgetc(demo_file); |
player[0].items.ship = fgetc(demo_file); |
for (uint i = 0; i < 2; ++i) |
player[0].items.weapon[i].power = fgetc(demo_file); |
fseek(demo_file, 3, SEEK_CUR); |
levelSong = fgetc(demo_file); |
demo_keys_wait = 0; |
demo_keys = next_demo_keys = 0; |
printf("loaded demo '%s'\n", demo_filename); |
return true; |
} |
bool replay_demo_keys( void ) |
{ |
if (demo_keys_wait == 0) |
if (read_demo_keys() == false) |
return false; // no more keys |
if (demo_keys_wait > 0) |
demo_keys_wait--; |
if (demo_keys & (1 << 0)) |
player[0].y -= CURRENT_KEY_SPEED; |
if (demo_keys & (1 << 1)) |
player[0].y += CURRENT_KEY_SPEED; |
if (demo_keys & (1 << 2)) |
player[0].x -= CURRENT_KEY_SPEED; |
if (demo_keys & (1 << 3)) |
player[0].x += CURRENT_KEY_SPEED; |
button[0] = (bool)(demo_keys & (1 << 4)); |
button[3] = (bool)(demo_keys & (1 << 5)); |
button[1] = (bool)(demo_keys & (1 << 6)); |
button[2] = (bool)(demo_keys & (1 << 7)); |
return true; |
} |
bool read_demo_keys( void ) |
{ |
demo_keys = next_demo_keys; |
efread(&demo_keys_wait, sizeof(Uint16), 1, demo_file); |
demo_keys_wait = SDL_Swap16(demo_keys_wait); |
next_demo_keys = getc(demo_file); |
return !feof(demo_file); |
} |
/*Street Fighter codes*/ |
void JE_SFCodes( JE_byte playerNum_, JE_integer PX_, JE_integer PY_, JE_integer mouseX_, JE_integer mouseY_ ) |
{ |
JE_byte temp, temp2, temp3, temp4, temp5; |
uint ship = player[playerNum_-1].items.ship; |
/*Get direction*/ |
if (playerNum_ == 2 && ship < 15) |
{ |
ship = 0; |
} |
if (ship < 15) |
{ |
temp2 = (mouseY_ > PY_) + /*UP*/ |
(mouseY_ < PY_) + /*DOWN*/ |
(PX_ < mouseX_) + /*LEFT*/ |
(PX_ > mouseX_); /*RIGHT*/ |
temp = (mouseY_ > PY_) * 1 + /*UP*/ |
(mouseY_ < PY_) * 2 + /*DOWN*/ |
(PX_ < mouseX_) * 3 + /*LEFT*/ |
(PX_ > mouseX_) * 4; /*RIGHT*/ |
if (temp == 0) // no direction being pressed |
{ |
if (!button[0]) // if fire button is released |
{ |
temp = 9; |
temp2 = 1; |
} else { |
temp2 = 0; |
temp = 99; |
} |
} |
if (temp2 == 1) // if exactly one direction pressed or firebutton is released |
{ |
temp += button[0] * 4; |
temp3 = superTyrian ? 21 : 3; |
for (temp2 = 0; temp2 < temp3; temp2++) |
{ |
/*Use SuperTyrian ShipCombos or not?*/ |
temp5 = superTyrian ? shipCombosB[temp2] : shipCombos[ship][temp2]; |
// temp5 == selected combo in ship |
if (temp5 == 0) /* combo doesn't exists */ |
{ |
// mark twiddles as cancelled/finished |
SFCurrentCode[playerNum_-1][temp2] = 0; |
} else { |
// get next combo key |
temp4 = keyboardCombos[temp5-1][SFCurrentCode[playerNum_-1][temp2]]; |
// correct key |
if (temp4 == temp) |
{ |
SFCurrentCode[playerNum_-1][temp2]++; |
temp4 = keyboardCombos[temp5-1][SFCurrentCode[playerNum_-1][temp2]]; |
if (temp4 > 100 && temp4 <= 100 + SPECIAL_NUM) |
{ |
SFCurrentCode[playerNum_-1][temp2] = 0; |
SFExecuted[playerNum_-1] = temp4 - 100; |
} |
} else { |
if ((temp != 9) && |
(temp4 - 1) % 4 != (temp - 1) % 4 && |
(SFCurrentCode[playerNum_-1][temp2] == 0 || |
keyboardCombos[temp5-1][SFCurrentCode[playerNum_-1][temp2]-1] != temp)) |
{ |
SFCurrentCode[playerNum_-1][temp2] = 0; |
} |
} |
} |
} |
} |
} |
} |
void JE_sort( void ) |
{ |
JE_byte a, b; |
for (a = 0; a < 2; a++) |
{ |
for (b = a + 1; b < 3; b++) |
{ |
if (saveFiles[temp + a].highScore1 < saveFiles[temp + b].highScore1) |
{ |
JE_longint tempLI; |
char tempStr[30]; |
JE_byte tempByte; |
tempLI = saveFiles[temp + a].highScore1; |
saveFiles[temp + a].highScore1 = saveFiles[temp + b].highScore1; |
saveFiles[temp + b].highScore1 = tempLI; |
strcpy(tempStr, saveFiles[temp + a].highScoreName); |
strcpy(saveFiles[temp + a].highScoreName, saveFiles[temp + b].highScoreName); |
strcpy(saveFiles[temp + b].highScoreName, tempStr); |
tempByte = saveFiles[temp + a].highScoreDiff; |
saveFiles[temp + a].highScoreDiff = saveFiles[temp + b].highScoreDiff; |
saveFiles[temp + b].highScoreDiff = tempByte; |
} |
} |
} |
} |
void JE_playCredits( void ) |
{ |
enum { lines_max = 132 }; |
enum { line_max_length = 65 }; |
char credstr[lines_max][line_max_length + 1]; |
int lines = 0; |
JE_byte currentpic = 0, fade = 0; |
JE_shortint fadechg = 1; |
JE_byte currentship = 0; |
JE_integer shipx = 0, shipxwait = 0; |
JE_shortint shipxc = 0, shipxca = 0; |
load_sprites_file(EXTRA_SHAPES, "estsc.shp"); |
setjasondelay2(1000); |
play_song(8); |
// load credits text |
FILE *f = dir_fopen_die(data_dir(), "tyrian.cdt", "rb"); |
for (lines = 0; !feof(f) && lines < lines_max; ++lines) |
{ |
read_encrypted_pascal_string(credstr[lines], sizeof(credstr[lines]), f); |
} |
if (lines == lines_max) |
--lines; |
fclose(f); |
memcpy(colors, palettes[6-1], sizeof(colors)); |
JE_clr256(VGAScreen); |
JE_showVGA(); |
fade_palette(colors, 2, 0, 255); |
//tempScreenSeg = VGAScreenSeg; |
const int ticks_max = lines * 20 * 3; |
for (int ticks = 0; ticks < ticks_max; ++ticks) |
{ |
setjasondelay(1); |
JE_clr256(VGAScreen); |
blit_sprite_hv(VGAScreenSeg, 319 - sprite(EXTRA_SHAPES, currentpic)->width, 100 - (sprite(EXTRA_SHAPES, currentpic)->height / 2), EXTRA_SHAPES, currentpic, 0x0, fade - 15); |
fade += fadechg; |
if (fade == 0 && fadechg == -1) |
{ |
fadechg = 1; |
++currentpic; |
if (currentpic >= sprite_table[EXTRA_SHAPES].count) |
currentpic = 0; |
} |
if (fade == 15) |
fadechg = 0; |
if (delaycount2() == 0) |
{ |
fadechg = -1; |
setjasondelay2(900); |
} |
if (ticks % 200 == 0) |
{ |
currentship = (mt_rand() % 11) + 1; |
shipxwait = (mt_rand() % 80) + 10; |
if ((mt_rand() % 2) == 1) |
{ |
shipx = 1; |
shipxc = 0; |
shipxca = 1; |
} |
else |
{ |
shipx = 900; |
shipxc = 0; |
shipxca = -1; |
} |
} |
shipxwait--; |
if (shipxwait == 0) |
{ |
if (shipx == 1 || shipx == 900) |
shipxc = 0; |
shipxca = -shipxca; |
shipxwait = (mt_rand() % 40) + 15; |
} |
shipxc += shipxca; |
shipx += shipxc; |
if (shipx < 1) |
{ |
shipx = 1; |
shipxwait = 1; |
} |
if (shipx > 900) |
{ |
shipx = 900; |
shipxwait = 1; |
} |
int tmp_unknown = shipxc * shipxc; |
if (450 + tmp_unknown < 0 || 450 + tmp_unknown > 900) |
{ |
if (shipxca < 0 && shipxc < 0) |
shipxwait = 1; |
if (shipxca > 0 && shipxc > 0) |
shipxwait = 1; |
} |
uint ship_sprite = ships[currentship].shipgraphic; |
if (shipxc < -10) |
ship_sprite -= (shipxc < -20) ? 4 : 2; |
else if (shipxc > 10) |
ship_sprite += (shipxc > 20) ? 4 : 2; |
blit_sprite2x2(VGAScreen, shipx / 40, 184 - (ticks % 200), shapes9, ship_sprite); |
const int bottom_line = (ticks / 3) / 20; |
int y = 20 - ((ticks / 3) % 20); |
for (int line = bottom_line - 10; line < bottom_line; ++line) |
{ |
if (line >= 0 && line < lines_max) |
{ |
if (strcmp(&credstr[line][0], ".") != 0 && strlen(credstr[line])) |
{ |
const Uint8 color = credstr[line][0] - 65; |
const char *text = &credstr[line][1]; |
const int x = 110 - JE_textWidth(text, SMALL_FONT_SHAPES) / 2; |
JE_outTextAdjust(VGAScreen, x + abs((y / 18) % 4 - 2) - 1, y - 1, text, color, -8, SMALL_FONT_SHAPES, false); |
JE_outTextAdjust(VGAScreen, x, y, text, color, -2, SMALL_FONT_SHAPES, false); |
} |
} |
y += 20; |
} |
fill_rectangle_xy(VGAScreen, 0, 0, 319, 10, 0); |
fill_rectangle_xy(VGAScreen, 0, 190, 319, 199, 0); |
if (currentpic == sprite_table[EXTRA_SHAPES].count - 1) |
JE_outTextAdjust(VGAScreen, 5, 180, miscText[54], 2, -2, SMALL_FONT_SHAPES, false); // levels-in-episode |
if (bottom_line == lines_max - 8) |
fade_song(); |
if (ticks == ticks_max - 1) |
{ |
--ticks; |
play_song(9); |
} |
NETWORK_KEEP_ALIVE(); |
JE_showVGA(); |
wait_delay(); |
if (JE_anyButton()) |
break; |
} |
fade_black(10); |
free_sprites(EXTRA_SHAPES); |
} |
void JE_endLevelAni( void ) |
{ |
JE_word x, y; |
JE_byte temp; |
char tempStr[256]; |
Sint8 i; |
if (!constantPlay) |
{ |
// grant shipedit privileges |
// special |
if (player[0].items.special < 21) |
saveTemp[SAVE_FILES_SIZE + 81 + player[0].items.special] = 1; |
for (uint p = 0; p < COUNTOF(player); ++p) |
{ |
// front, rear |
for (uint i = 0; i < COUNTOF(player[p].items.weapon); ++i) |
saveTemp[SAVE_FILES_SIZE + player[p].items.weapon[i].id] = 1; |
// options |
for (uint i = 0; i < COUNTOF(player[p].items.sidekick); ++i) |
saveTemp[SAVE_FILES_SIZE + 51 + player[p].items.sidekick[i]] = 1; |
} |
} |
adjust_difficulty(); |
player[0].last_items = player[0].items; |
strcpy(lastLevelName, levelName); |
JE_wipeKey(); |
frameCountMax = 4; |
textGlowFont = SMALL_FONT_SHAPES; |
SDL_Color white = { 255, 255, 255 }; |
set_colors(white, 254, 254); |
if (!levelTimer || levelTimerCountdown > 0 || !(episodeNum == 4)) |
JE_playSampleNum(V_LEVEL_END); |
else |
play_song(21); |
if (bonusLevel) |
{ |
JE_outTextGlow(VGAScreenSeg, 20, 20, miscText[17-1]); |
} |
else if (all_players_alive()) |
{ |
sprintf(tempStr, "%s %s", miscText[27-1], levelName); // "Completed" |
JE_outTextGlow(VGAScreenSeg, 20, 20, tempStr); |
} |
else |
{ |
sprintf(tempStr, "%s %s", miscText[62-1], levelName); // "Exiting" |
JE_outTextGlow(VGAScreenSeg, 20, 20, tempStr); |
} |
if (twoPlayerMode) |
{ |
for (uint i = 0; i < 2; ++i) |
{ |
snprintf(tempStr, sizeof(tempStr), "%s %lu", miscText[40 + i], player[i].cash); |
JE_outTextGlow(VGAScreenSeg, 30, 50 + 20 * i, tempStr); |
} |
} |
else |
{ |
sprintf(tempStr, "%s %lu", miscText[28-1], player[0].cash); |
JE_outTextGlow(VGAScreenSeg, 30, 50, tempStr); |
} |
temp = (totalEnemy == 0) ? 0 : roundf(enemyKilled * 100 / totalEnemy); |
sprintf(tempStr, "%s %d%%", miscText[63-1], temp); |
JE_outTextGlow(VGAScreenSeg, 40, 90, tempStr); |
if (!constantPlay) |
editorLevel += temp / 5; |
if (!onePlayerAction && !twoPlayerMode) |
{ |
JE_outTextGlow(VGAScreenSeg, 30, 120, miscText[4-1]); /*Cubes*/ |
if (cubeMax > 0) |
{ |
if (cubeMax > 4) |
cubeMax = 4; |
if (frameCountMax != 0) |
frameCountMax = 1; |
for (temp = 1; temp <= cubeMax; temp++) |
{ |
NETWORK_KEEP_ALIVE(); |
JE_playSampleNum(S_ITEM); |
x = 20 + 30 * temp; |
y = 135; |
JE_drawCube(VGAScreenSeg, x, y, 9, 0); |
JE_showVGA(); |
for (i = -15; i <= 10; i++) |
{ |
setjasondelay(frameCountMax); |
blit_sprite_hv(VGAScreenSeg, x, y, OPTION_SHAPES, 25, 0x9, i); |
if (JE_anyButton()) |
frameCountMax = 0; |
JE_showVGA(); |
wait_delay(); |
} |
for (i = 10; i >= 0; i--) |
{ |
setjasondelay(frameCountMax); |
blit_sprite_hv(VGAScreenSeg, x, y, OPTION_SHAPES, 25, 0x9, i); |
if (JE_anyButton()) |
frameCountMax = 0; |
JE_showVGA(); |
wait_delay(); |
} |
} |
} |
else |
{ |
JE_outTextGlow(VGAScreenSeg, 50, 135, miscText[15-1]); |
} |
} |
if (frameCountMax != 0) |
{ |
frameCountMax = 6; |
temp = 1; |
} else { |
temp = 0; |
} |
temp2 = twoPlayerMode ? 150 : 160; |
JE_outTextGlow(VGAScreenSeg, 90, temp2, miscText[5-1]); |
if (!constantPlay) |
{ |
do |
{ |
setjasondelay(1); |
NETWORK_KEEP_ALIVE(); |
wait_delay(); |
} while (!(JE_anyButton() || (frameCountMax == 0 && temp == 1))); |
} |
wait_noinput(false, false, true); // TODO: should up the joystick repeat temporarily instead |
fade_black(15); |
JE_clr256(VGAScreen); |
} |
void JE_drawCube( SDL_Surface * screen, JE_word x, JE_word y, JE_byte filter, JE_byte brightness ) |
{ |
blit_sprite_dark(screen, x + 4, y + 4, OPTION_SHAPES, 25, false); |
blit_sprite_dark(screen, x + 3, y + 3, OPTION_SHAPES, 25, false); |
blit_sprite_hv(screen, x, y, OPTION_SHAPES, 25, filter, brightness); |
} |
void JE_handleChat( void ) |
{ |
// STUB(); Annoying piece of crap =P |
} |
bool str_pop_int( char *str, int *val ) |
{ |
bool success = false; |
char buf[256]; |
assert(strlen(str) < sizeof(buf)); |
// grab the value from str |
char *end; |
*val = strtol(str, &end, 10); |
if (end != str) |
{ |
success = true; |
// shift the rest to the beginning |
strcpy(buf, end); |
strcpy(str, buf); |
} |
return success; |
} |
void JE_operation( JE_byte slot ) |
{ |
JE_byte flash; |
char stemp[21]; |
char tempStr[51]; |
if (!performSave) |
{ |
if (saveFiles[slot-1].level > 0) |
{ |
gameJustLoaded = true; |
JE_loadGame(slot); |
gameLoaded = true; |
} |
} |
else if (slot % 11 != 0) |
{ |
strcpy(stemp, " "); |
memcpy(stemp, saveFiles[slot-1].name, strlen(saveFiles[slot-1].name)); |
temp = strlen(stemp); |
while (stemp[temp-1] == ' ' && --temp); |
flash = 8 * 16 + 10; |
wait_noinput(false, true, false); |
JE_barShade(VGAScreen, 65, 55, 255, 155); |
bool quit = false; |
while (!quit) |
{ |
service_SDL_events(true); |
blit_sprite(VGAScreen, 50, 50, OPTION_SHAPES, 35); // message box |
JE_textShade(VGAScreen, 60, 55, miscText[1-1], 11, 4, DARKEN); |
JE_textShade(VGAScreen, 70, 70, levelName, 11, 4, DARKEN); |
do |
{ |
flash = (flash == 8 * 16 + 10) ? 8 * 16 + 2 : 8 * 16 + 10; |
temp3 = (temp3 == 6) ? 2 : 6; |
strcpy(tempStr, miscText[2-1]); |
strncat(tempStr, stemp, temp); |
JE_outText(VGAScreen, 65, 89, tempStr, 8, 3); |
tempW = 65 + JE_textWidth(tempStr, TINY_FONT); |
JE_barShade(VGAScreen, tempW + 2, 90, tempW + 6, 95); |
fill_rectangle_xy(VGAScreen, tempW + 1, 89, tempW + 5, 94, flash); |
for (int i = 0; i < 14; i++) |
{ |
setjasondelay(1); |
JE_mouseStart(); |
JE_showVGA(); |
JE_mouseReplace(); |
push_joysticks_as_keyboard(); |
service_wait_delay(); |
if (newkey || newmouse) |
break; |
} |
} |
while (!newkey && !newmouse); |
if (mouseButton > 0) |
{ |
if (mouseX > 56 && mouseX < 142 && mouseY > 123 && mouseY < 149) |
{ |
quit = true; |
JE_saveGame(slot, stemp); |
JE_playSampleNum(S_SELECT); |
} |
else if (mouseX > 151 && mouseX < 237 && mouseY > 123 && mouseY < 149) |
{ |
quit = true; |
JE_playSampleNum(S_SPRING); |
} |
} |
else if (newkey) |
{ |
bool validkey = false; |
lastkey_char = toupper(lastkey_char); |
switch (lastkey_char) |
{ |
case ' ': |
case '-': |
case '.': |
case ',': |
case ':': |
case '!': |
case '?': |
case '#': |
case '@': |
case '$': |
case '%': |
case '*': |
case '(': |
case ')': |
case '/': |
case '=': |
case '+': |
case '<': |
case '>': |
case ';': |
case '"': |
case '\'': |
validkey = true; |
// fall through |
default: |
if (temp < 14 && (validkey || (lastkey_char >= 'A' && lastkey_char <= 'Z') || (lastkey_char >= '0' && lastkey_char <= '9'))) |
{ |
JE_playSampleNum(S_CURSOR); |
stemp[temp] = lastkey_char; |
temp++; |
} |
break; |
case SDLK_BACKSPACE: |
case SDLK_DELETE: |
if (temp) |
{ |
temp--; |
stemp[temp] = ' '; |
JE_playSampleNum(S_CLICK); |
} |
break; |
case SDLK_ESCAPE: |
quit = true; |
JE_playSampleNum(S_SPRING); |
break; |
case SDLK_RETURN: |
quit = true; |
JE_saveGame(slot, stemp); |
JE_playSampleNum(S_SELECT); |
break; |
} |
} |
} |
} |
wait_noinput(false, true, false); |
} |
void JE_inGameDisplays( void ) |
{ |
char stemp[21]; |
char tempstr[256]; |
for (uint i = 0; i < ((twoPlayerMode && !galagaMode) ? 2 : 1); ++i) |
{ |
snprintf(tempstr, sizeof(tempstr), "%lu", player[i].cash); |
JE_textShade(VGAScreen, 30 + 200 * i, 175, tempstr, 2, 4, FULL_SHADE); |
} |
/*Special Weapon?*/ |
if (player[0].items.special > 0) |
blit_sprite2x2(VGAScreen, 25, 1, eShapes[5], special[player[0].items.special].itemgraphic); |
/*Lives Left*/ |
if (onePlayerAction || twoPlayerMode) |
{ |
for (int temp = 0; temp < (onePlayerAction ? 1 : 2); temp++) |
{ |
const uint extra_lives = *player[temp].lives - 1; |
int y = (temp == 0 && player[0].items.special > 0) ? 35 : 15; |
tempW = (temp == 0) ? 30: 270; |
if (extra_lives >= 5) |
{ |
blit_sprite2(VGAScreen, tempW, y, shapes9, 285); |
tempW = (temp == 0) ? 45 : 250; |
sprintf(tempstr, "%d", extra_lives); |
JE_textShade(VGAScreen, tempW, y + 3, tempstr, 15, 1, FULL_SHADE); |
} |
else if (extra_lives >= 1) |
{ |
for (uint i = 0; i < extra_lives; ++i) |
{ |
blit_sprite2(VGAScreen, tempW, y, shapes9, 285); |
tempW += (temp == 0) ? 12 : -12; |
} |
} |
strcpy(stemp, (temp == 0) ? miscText[49-1] : miscText[50-1]); |
if (isNetworkGame) |
{ |
strcpy(stemp, JE_getName(temp+1)); |
} |
tempW = (temp == 0) ? 28 : (285 - JE_textWidth(stemp, TINY_FONT)); |
JE_textShade(VGAScreen, tempW, y - 7, stemp, 2, 6, FULL_SHADE); |
} |
} |
/*Super Bombs!!*/ |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
int x = (i == 0) ? 30 : 270; |
for (uint j = player[i].superbombs; j > 0; --j) |
{ |
blit_sprite2(VGAScreen, x, 160, shapes9, 304); |
x += (i == 0) ? 12 : -12; |
} |
} |
if (youAreCheating) |
{ |
JE_outText(VGAScreen, 90, 170, "Cheaters always prosper.", 3, 4); |
} |
} |
void JE_mainKeyboardInput( void ) |
{ |
JE_gammaCheck(); |
/* { Network Request Commands } */ |
if (!isNetworkGame) |
{ |
/* { Edited Ships } for Player 1 */ |
if (extraAvail && keysactive[SDLK_TAB] && !isNetworkGame && !superTyrian) |
{ |
for (x = SDLK_0; x <= SDLK_9; x++) |
{ |
if (keysactive[x]) |
{ |
int z = x == SDLK_0 ? 10 : x - SDLK_0; |
player[0].items.ship = 90 + z; /*Ships*/ |
z = (z - 1) * 15; |
player[0].items.weapon[FRONT_WEAPON].id = extraShips[z + 1]; |
player[0].items.weapon[REAR_WEAPON].id = extraShips[z + 2]; |
player[0].items.special = extraShips[z + 3]; |
player[0].items.sidekick[LEFT_SIDEKICK] = extraShips[z + 4]; |
player[0].items.sidekick[RIGHT_SIDEKICK] = extraShips[z + 5]; |
player[0].items.generator = extraShips[z + 6]; |
/*Armor*/ |
player[0].items.shield = extraShips[z + 8]; |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
if (player[0].weapon_mode > JE_portConfigs()) |
player[0].weapon_mode = 1; |
tempW = player[0].armor; |
JE_getShipInfo(); |
if (player[0].armor > tempW && editShip1) |
player[0].armor = tempW; |
else |
editShip1 = true; |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; |
JE_wipeShieldArmorBars(); |
JE_drawArmor(); |
JE_drawShield(); |
VGAScreen = temp_surface; |
JE_drawOptions(); |
keysactive[x] = false; |
} |
} |
} |
/* for Player 2 */ |
if (extraAvail && keysactive[SDLK_CAPSLOCK] && !isNetworkGame && !superTyrian) |
{ |
for (x = SDLK_0; x <= SDLK_9; x++) |
{ |
if (keysactive[x]) |
{ |
int z = x == SDLK_0 ? 10 : x - SDLK_0; |
player[1].items.ship = 90 + z; |
z = (z - 1) * 15; |
player[1].items.weapon[FRONT_WEAPON].id = extraShips[z + 1]; |
player[1].items.weapon[REAR_WEAPON].id = extraShips[z + 2]; |
player[1].items.special = extraShips[z + 3]; |
player[1].items.sidekick[LEFT_SIDEKICK] = extraShips[z + 4]; |
player[1].items.sidekick[RIGHT_SIDEKICK] = extraShips[z + 5]; |
player[1].items.generator = extraShips[z + 6]; |
/*Armor*/ |
player[1].items.shield = extraShips[z + 8]; |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
if (player[1].weapon_mode > JE_portConfigs()) |
player[1].weapon_mode = 1; |
tempW = player[1].armor; |
JE_getShipInfo(); |
if (player[1].armor > tempW && editShip2) |
player[1].armor = tempW; |
else |
editShip2 = true; |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; |
JE_wipeShieldArmorBars(); |
JE_drawArmor(); |
JE_drawShield(); |
VGAScreen = temp_surface; |
JE_drawOptions(); |
keysactive[x] = false; |
} |
} |
} |
} |
/* { In-Game Help } */ |
if (keysactive[SDLK_F1]) |
{ |
if (isNetworkGame) |
{ |
helpRequest = true; |
} else { |
JE_inGameHelp(); |
skipStarShowVGA = true; |
} |
} |
/* {!Activate Nort Ship!} */ |
if (keysactive[SDLK_F2] && keysactive[SDLK_F4] && keysactive[SDLK_F6] && keysactive[SDLK_F7] && |
keysactive[SDLK_F9] && keysactive[SDLK_BACKSLASH] && keysactive[SDLK_SLASH]) |
{ |
if (isNetworkGame) |
{ |
nortShipRequest = true; |
} |
else |
{ |
player[0].items.ship = 12; // Nort Ship |
player[0].items.special = 13; // Astral Zone |
player[0].items.weapon[FRONT_WEAPON].id = 36; // NortShip Super Pulse |
player[0].items.weapon[REAR_WEAPON].id = 37; // NortShip Spreader |
shipGr = 1; |
} |
} |
/* {Cheating} */ |
if (!isNetworkGame && !twoPlayerMode && !superTyrian && superArcadeMode == SA_NONE) |
{ |
if (keysactive[SDLK_F2] && keysactive[SDLK_F3] && keysactive[SDLK_F6]) |
{ |
youAreCheating = !youAreCheating; |
keysactive[SDLK_F2] = false; |
} |
if (keysactive[SDLK_F2] && keysactive[SDLK_F3] && (keysactive[SDLK_F4] || keysactive[SDLK_F5])) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].armor = 0; |
youAreCheating = !youAreCheating; |
JE_drawTextWindow(miscText[63-1]); |
} |
if (constantPlay && keysactive[SDLK_c]) |
{ |
youAreCheating = !youAreCheating; |
keysactive[SDLK_c] = false; |
} |
} |
if (superTyrian) |
{ |
youAreCheating = false; |
} |
/* {Personal Commands} */ |
/* {DEBUG} */ |
if (keysactive[SDLK_F10] && keysactive[SDLK_BACKSPACE]) |
{ |
keysactive[SDLK_F10] = false; |
debug = !debug; |
debugHist = 1; |
debugHistCount = 1; |
/* YKS: clock ticks since midnight replaced by SDL_GetTicks */ |
lastDebugTime = SDL_GetTicks(); |
} |
/* {CHEAT-SKIP LEVEL} */ |
if (keysactive[SDLK_F2] && keysactive[SDLK_F6] && (keysactive[SDLK_F7] || keysactive[SDLK_F8]) && !keysactive[SDLK_F9] |
&& !superTyrian && superArcadeMode == SA_NONE) |
{ |
if (isNetworkGame) |
{ |
skipLevelRequest = true; |
} else { |
levelTimer = true; |
levelTimerCountdown = 0; |
endLevel = true; |
levelEnd = 40; |
} |
} |
/* pause game */ |
pause_pressed = pause_pressed || keysactive[SDLK_p]; |
/* in-game setup */ |
ingamemenu_pressed = ingamemenu_pressed || keysactive[SDLK_ESCAPE]; |
if (keysactive[SDLK_BACKSPACE]) |
{ |
/* toggle screenshot pause */ |
if (keysactive[SDLK_NUMLOCK]) |
{ |
superPause = !superPause; |
} |
/* {SMOOTHIES} */ |
if (keysactive[SDLK_F12] && keysactive[SDLK_SCROLLOCK]) |
{ |
for (temp = SDLK_2; temp <= SDLK_9; temp++) |
{ |
if (keysactive[temp]) |
{ |
smoothies[temp-SDLK_2] = !smoothies[temp-SDLK_2]; |
} |
} |
if (keysactive[SDLK_0]) |
{ |
smoothies[8] = !smoothies[8]; |
} |
} else |
/* {CYCLE THROUGH FILTER COLORS} */ |
if (keysactive[SDLK_MINUS]) |
{ |
if (levelFilter == -99) |
{ |
levelFilter = 0; |
} else { |
levelFilter++; |
if (levelFilter == 16) |
{ |
levelFilter = -99; |
} |
} |
} else |
/* {HYPER-SPEED} */ |
if (keysactive[SDLK_1]) |
{ |
fastPlay++; |
if (fastPlay > 2) |
{ |
fastPlay = 0; |
} |
keysactive[SDLK_1] = false; |
JE_setNewGameSpeed(); |
} |
/* {IN-GAME RANDOM MUSIC SELECTION} */ |
if (keysactive[SDLK_SCROLLOCK]) |
{ |
play_song(mt_rand() % MUSIC_NUM); |
} |
} |
} |
void JE_pauseGame( void ) |
{ |
JE_boolean done = false; |
JE_word mouseX, mouseY; |
//tempScreenSeg = VGAScreenSeg; // sega000 |
if (!superPause) |
{ |
JE_dString(VGAScreenSeg, 120, 90, miscText[22], FONT_SHAPES); |
VGAScreen = VGAScreenSeg; |
JE_showVGA(); |
} |
set_volume(tyrMusicVolume / 2, fxVolume); |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
network_prepare(PACKET_GAME_PAUSE); |
network_send(4); // PACKET_GAME_PAUSE |
while (true) |
{ |
service_SDL_events(false); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_GAME_PAUSE) |
{ |
network_update(); |
break; |
} |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
} |
#endif |
wait_noinput(false, false, true); // TODO: should up the joystick repeat temporarily instead |
do |
{ |
setjasondelay(2); |
push_joysticks_as_keyboard(); |
service_SDL_events(true); |
if ((newkey && lastkey_sym != SDLK_LCTRL && lastkey_sym != SDLK_RCTRL && lastkey_sym != SDLK_LALT && lastkey_sym != SDLK_RALT) |
|| JE_mousePosition(&mouseX, &mouseY) > 0) |
{ |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
network_prepare(PACKET_WAITING); |
network_send(4); // PACKET_WAITING |
} |
#endif |
done = true; |
} |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
network_check(); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_WAITING) |
{ |
network_check(); |
done = true; |
} |
} |
#endif |
wait_delay(); |
} while (!done); |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
while (!network_is_sync()) |
{ |
service_SDL_events(false); |
network_check(); |
uSDL_Delay(16); |
} |
} |
#endif |
set_volume(tyrMusicVolume, fxVolume); |
//skipStarShowVGA = true; |
} |
void JE_playerMovement( Player *this_player, |
JE_byte inputDevice, |
JE_byte playerNum_, |
JE_word shipGr_, |
Sprite2_array *shapes9ptr_, |
JE_word *mouseX_, JE_word *mouseY_ ) |
{ |
JE_integer mouseXC, mouseYC; |
JE_integer accelXC, accelYC; |
if (playerNum_ == 2 || !twoPlayerMode) |
{ |
tempW = weaponPort[this_player->items.weapon[REAR_WEAPON].id].opnum; |
if (this_player->weapon_mode > tempW) |
this_player->weapon_mode = 1; |
} |
#ifdef WITH_NETWORK |
if (isNetworkGame && thisPlayerNum == playerNum_) |
{ |
network_state_prepare(); |
memset(&packet_state_out[0]->data[4], 0, 10); |
} |
#endif |
redo: |
if (isNetworkGame) |
{ |
inputDevice = 0; |
} |
mouseXC = 0; |
mouseYC = 0; |
accelXC = 0; |
accelYC = 0; |
bool link_gun_analog = false; |
float link_gun_angle = 0; |
/* Draw Player */ |
if (!this_player->is_alive) |
{ |
if (this_player->exploding_ticks > 0) |
{ |
--this_player->exploding_ticks; |
if (levelEndFxWait > 0) |
{ |
levelEndFxWait--; |
} |
else |
{ |
levelEndFxWait = (mt_rand() % 6) + 3; |
if ((mt_rand() % 3) == 1) |
soundQueue[6] = S_EXPLOSION_9; |
else |
soundQueue[5] = S_EXPLOSION_11; |
} |
int explosion_x = this_player->x + (mt_rand() % 32) - 16; |
int explosion_y = this_player->y + (mt_rand() % 32) - 16; |
JE_setupExplosionLarge(false, 0, explosion_x, explosion_y + 7); |
JE_setupExplosionLarge(false, 0, this_player->x, this_player->y + 7); |
if (levelEnd > 0) |
levelEnd--; |
} |
else |
{ |
if (twoPlayerMode || onePlayerAction) // if arcade mode |
{ |
if (*this_player->lives > 1) // respawn if any extra lives |
{ |
--(*this_player->lives); |
reallyEndLevel = false; |
shotMultiPos[playerNum_-1] = 0; |
calc_purple_balls_needed(this_player); |
twoPlayerLinked = false; |
if (galagaMode) |
twoPlayerMode = false; |
this_player->y = 160; |
this_player->invulnerable_ticks = 100; |
this_player->is_alive = true; |
endLevel = false; |
if (galagaMode || episodeNum == 4) |
this_player->armor = this_player->initial_armor; |
else |
this_player->armor = this_player->initial_armor / 2; |
if (galagaMode) |
this_player->shield = 0; |
else |
this_player->shield = this_player->shield_max / 2; |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_drawArmor(); |
JE_drawShield(); |
VGAScreen = game_screen; /* side-effect of game_screen */ |
goto redo; |
} |
else |
{ |
if (galagaMode) |
twoPlayerMode = false; |
if (allPlayersGone && isNetworkGame) |
reallyEndLevel = true; |
} |
} |
} |
} |
else if (constantDie) |
{ |
// finished exploding? start dying again |
if (this_player->exploding_ticks == 0) |
{ |
this_player->shield = 0; |
if (this_player->armor > 0) |
{ |
--this_player->armor; |
} |
else |
{ |
this_player->is_alive = false; |
this_player->exploding_ticks = 60; |
levelEnd = 40; |
} |
JE_wipeShieldArmorBars(); |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_drawArmor(); |
VGAScreen = game_screen; /* side-effect of game_screen */ |
// as if instant death weren't enough, player also gets infinite lives in order to enjoy an infinite number of deaths -_- |
if (*player[0].lives < 11) |
++(*player[0].lives); |
} |
} |
if (!this_player->is_alive) |
{ |
explosionFollowAmountX = explosionFollowAmountY = 0; |
return; |
} |
if (!endLevel) |
{ |
*mouseX_ = this_player->x; |
*mouseY_ = this_player->y; |
button[1-1] = false; |
button[2-1] = false; |
button[3-1] = false; |
button[4-1] = false; |
/* --- Movement Routine Beginning --- */ |
if (!isNetworkGame || playerNum_ == thisPlayerNum) |
{ |
if (endLevel) |
{ |
this_player->y -= 2; |
} |
else |
{ |
if (record_demo || play_demo) |
inputDevice = 1; // keyboard is required device for demo recording |
// demo playback input |
if (play_demo) |
{ |
if (!replay_demo_keys()) |
{ |
endLevel = true; |
levelEnd = 40; |
} |
} |
/* joystick input */ |
if ((inputDevice == 0 || inputDevice >= 3) && joysticks > 0) |
{ |
int j = inputDevice == 0 ? 0 : inputDevice - 3; |
int j_max = inputDevice == 0 ? joysticks : inputDevice - 3 + 1; |
for (; j < j_max; j++) |
{ |
poll_joystick(j); |
if (joystick[j].analog) |
{ |
mouseXC += joystick_axis_reduce(j, joystick[j].x); |
mouseYC += joystick_axis_reduce(j, joystick[j].y); |
link_gun_analog = joystick_analog_angle(j, &link_gun_angle); |
} |
else |
{ |
this_player->x += (joystick[j].direction[3] ? -CURRENT_KEY_SPEED : 0) + (joystick[j].direction[1] ? CURRENT_KEY_SPEED : 0); |
this_player->y += (joystick[j].direction[0] ? -CURRENT_KEY_SPEED : 0) + (joystick[j].direction[2] ? CURRENT_KEY_SPEED : 0); |
} |
button[0] |= joystick[j].action[0]; |
button[1] |= joystick[j].action[2]; |
button[2] |= joystick[j].action[3]; |
button[3] |= joystick[j].action_pressed[1]; |
ingamemenu_pressed |= joystick[j].action_pressed[4]; |
pause_pressed |= joystick[j].action_pressed[5]; |
} |
} |
service_SDL_events(false); |
/* mouse input */ |
if ((inputDevice == 0 || inputDevice == 2) && has_mouse) |
{ |
button[0] |= mouse_pressed[0]; |
button[1] |= mouse_pressed[1]; |
button[2] |= mouse_has_three_buttons ? mouse_pressed[2] : mouse_pressed[1]; |
if (input_grab_enabled) |
{ |
mouseXC += mouse_x - 159; |
mouseYC += mouse_y - 100; |
} |
if ((!isNetworkGame || playerNum_ == thisPlayerNum) |
&& (!galagaMode || (playerNum_ == 2 || !twoPlayerMode || player[1].exploding_ticks > 0))) |
{ |
set_mouse_position(159, 100); |
} |
} |
/* keyboard input */ |
if ((inputDevice == 0 || inputDevice == 1) && !play_demo) |
{ |
if (keysactive[keySettings[0]]) |
this_player->y -= CURRENT_KEY_SPEED; |
if (keysactive[keySettings[1]]) |
this_player->y += CURRENT_KEY_SPEED; |
if (keysactive[keySettings[2]]) |
this_player->x -= CURRENT_KEY_SPEED; |
if (keysactive[keySettings[3]]) |
this_player->x += CURRENT_KEY_SPEED; |
button[0] = button[0] || keysactive[keySettings[4]]; |
button[3] = button[3] || keysactive[keySettings[5]]; |
button[1] = button[1] || keysactive[keySettings[6]]; |
button[2] = button[2] || keysactive[keySettings[7]]; |
if (constantPlay) |
{ |
for (unsigned int i = 0; i < 4; i++) |
button[i] = true; |
++this_player->y; |
this_player->x += constantLastX; |
} |
// TODO: check if demo recording still works |
if (record_demo) |
{ |
bool new_input = false; |
for (unsigned int i = 0; i < 8; i++) |
{ |
bool temp = demo_keys & (1 << i); |
if (temp != keysactive[keySettings[i]]) |
new_input = true; |
} |
demo_keys_wait++; |
if (new_input) |
{ |
demo_keys_wait = SDL_Swap16(demo_keys_wait); |
efwrite(&demo_keys_wait, sizeof(Uint16), 1, demo_file); |
demo_keys = 0; |
for (unsigned int i = 0; i < 8; i++) |
demo_keys |= keysactive[keySettings[i]] ? (1 << i) : 0; |
fputc(demo_keys, demo_file); |
demo_keys_wait = 0; |
} |
} |
} |
if (smoothies[9-1]) |
{ |
*mouseY_ = this_player->y - (*mouseY_ - this_player->y); |
mouseYC = -mouseYC; |
} |
accelXC += this_player->x - *mouseX_; |
accelYC += this_player->y - *mouseY_; |
if (mouseXC > 30) |
mouseXC = 30; |
else if (mouseXC < -30) |
mouseXC = -30; |
if (mouseYC > 30) |
mouseYC = 30; |
else if (mouseYC < -30) |
mouseYC = -30; |
if (mouseXC > 0) |
this_player->x += (mouseXC + 3) / 4; |
else if (mouseXC < 0) |
this_player->x += (mouseXC - 3) / 4; |
if (mouseYC > 0) |
this_player->y += (mouseYC + 3) / 4; |
else if (mouseYC < 0) |
this_player->y += (mouseYC - 3) / 4; |
if (mouseXC > 3) |
accelXC++; |
else if (mouseXC < -2) |
accelXC--; |
if (mouseYC > 2) |
accelYC++; |
else if (mouseYC < -2) |
accelYC--; |
} /*endLevel*/ |
#ifdef WITH_NETWORK |
if (isNetworkGame && playerNum_ == thisPlayerNum) |
{ |
Uint16 buttons = 0; |
for (int i = 4 - 1; i >= 0; i--) |
{ |
buttons <<= 1; |
buttons |= button[i]; |
} |
SDLNet_Write16(this_player->x - *mouseX_, &packet_state_out[0]->data[4]); |
SDLNet_Write16(this_player->y - *mouseY_, &packet_state_out[0]->data[6]); |
SDLNet_Write16(accelXC, &packet_state_out[0]->data[8]); |
SDLNet_Write16(accelYC, &packet_state_out[0]->data[10]); |
SDLNet_Write16(buttons, &packet_state_out[0]->data[12]); |
this_player->x = *mouseX_; |
this_player->y = *mouseY_; |
button[0] = false; |
button[1] = false; |
button[2] = false; |
button[3] = false; |
accelXC = 0; |
accelYC = 0; |
} |
#endif |
} /*isNetworkGame*/ |
/* --- Movement Routine Ending --- */ |
moveOk = true; |
#ifdef WITH_NETWORK |
if (isNetworkGame && !network_state_is_reset()) |
{ |
if (playerNum_ != thisPlayerNum) |
{ |
if (thisPlayerNum == 2) |
difficultyLevel = SDLNet_Read16(&packet_state_in[0]->data[16]); |
Uint16 buttons = SDLNet_Read16(&packet_state_in[0]->data[12]); |
for (int i = 0; i < 4; i++) |
{ |
button[i] = buttons & 1; |
buttons >>= 1; |
} |
this_player->x += (Sint16)SDLNet_Read16(&packet_state_in[0]->data[4]); |
this_player->y += (Sint16)SDLNet_Read16(&packet_state_in[0]->data[6]); |
accelXC = (Sint16)SDLNet_Read16(&packet_state_in[0]->data[8]); |
accelYC = (Sint16)SDLNet_Read16(&packet_state_in[0]->data[10]); |
} |
else |
{ |
Uint16 buttons = SDLNet_Read16(&packet_state_out[network_delay]->data[12]); |
for (int i = 0; i < 4; i++) |
{ |
button[i] = buttons & 1; |
buttons >>= 1; |
} |
this_player->x += (Sint16)SDLNet_Read16(&packet_state_out[network_delay]->data[4]); |
this_player->y += (Sint16)SDLNet_Read16(&packet_state_out[network_delay]->data[6]); |
accelXC = (Sint16)SDLNet_Read16(&packet_state_out[network_delay]->data[8]); |
accelYC = (Sint16)SDLNet_Read16(&packet_state_out[network_delay]->data[10]); |
} |
} |
#endif |
/*Street-Fighter codes*/ |
JE_SFCodes(playerNum_, this_player->x, this_player->y, *mouseX_, *mouseY_); |
if (moveOk) |
{ |
/* END OF MOVEMENT ROUTINES */ |
/*Linking Routines*/ |
if (twoPlayerMode && !twoPlayerLinked && this_player->x == *mouseX_ && this_player->y == *mouseY_ |
&& abs(player[0].x - player[1].x) < 8 && abs(player[0].y - player[1].y) < 8 |
&& player[0].is_alive && player[1].is_alive && !galagaMode) |
{ |
twoPlayerLinked = true; |
} |
if (playerNum_ == 1 && (button[3-1] || button[2-1]) && !galagaMode) |
twoPlayerLinked = false; |
if (twoPlayerMode && twoPlayerLinked && playerNum_ == 2 |
&& (this_player->x != *mouseX_ || this_player->y != *mouseY_)) |
{ |
if (button[0]) |
{ |
if (link_gun_analog) |
{ |
linkGunDirec = link_gun_angle; |
} |
else |
{ |
JE_real tempR; |
if (abs(this_player->x - *mouseX_) > abs(this_player->y - *mouseY_)) |
tempR = (this_player->x - *mouseX_ > 0) ? M_PI_2 : (M_PI + M_PI_2); |
else |
tempR = (this_player->y - *mouseY_ > 0) ? 0 : M_PI; |
if (fabsf(linkGunDirec - tempR) < 0.3f) |
linkGunDirec = tempR; |
else if (linkGunDirec < tempR && linkGunDirec - tempR > -3.24f) |
linkGunDirec += 0.2f; |
else if (linkGunDirec - tempR < M_PI) |
linkGunDirec -= 0.2f; |
else |
linkGunDirec += 0.2f; |
} |
if (linkGunDirec >= (2 * M_PI)) |
linkGunDirec -= (2 * M_PI); |
else if (linkGunDirec < 0) |
linkGunDirec += (2 * M_PI); |
} |
else if (!galagaMode) |
{ |
twoPlayerLinked = false; |
} |
} |
} |
} |
if (levelEnd > 0 && all_players_dead()) |
reallyEndLevel = true; |
/* End Level Fade-Out */ |
if (this_player->is_alive && endLevel) |
{ |
if (levelEnd == 0) |
{ |
reallyEndLevel = true; |
} |
else |
{ |
this_player->y -= levelEndWarp; |
if (this_player->y < -200) |
reallyEndLevel = true; |
int trail_spacing = 1; |
int trail_y = this_player->y; |
int num_trails = abs(41 - levelEnd); |
if (num_trails > 20) |
num_trails = 20; |
for (int i = 0; i < num_trails; i++) |
{ |
trail_y += trail_spacing; |
trail_spacing++; |
} |
for (int i = 1; i < num_trails; i++) |
{ |
trail_y -= trail_spacing; |
trail_spacing--; |
if (trail_y > 0 && trail_y < 170) |
{ |
if (shipGr_ == 0) |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 17, trail_y - 7, *shapes9ptr_, 13); |
blit_sprite2x2(VGAScreen, this_player->x + 7 , trail_y - 7, *shapes9ptr_, 51); |
} |
else if (shipGr_ == 1) |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 17, trail_y - 7, *shapes9ptr_, 220); |
blit_sprite2x2(VGAScreen, this_player->x + 7 , trail_y - 7, *shapes9ptr_, 222); |
} |
else |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 5, trail_y - 7, *shapes9ptr_, shipGr_); |
} |
} |
} |
} |
} |
if (play_demo) |
JE_dString(VGAScreen, 115, 10, miscText[7], SMALL_FONT_SHAPES); // insert coin |
if (this_player->is_alive && !endLevel) |
{ |
if (!twoPlayerLinked || playerNum_ < 2) |
{ |
if (!twoPlayerMode || shipGr2 != 0) // if not dragonwing |
{ |
if (this_player->sidekick[LEFT_SIDEKICK].style == 0) |
{ |
this_player->sidekick[LEFT_SIDEKICK].x = *mouseX_ - 14; |
this_player->sidekick[LEFT_SIDEKICK].y = *mouseY_; |
} |
if (this_player->sidekick[RIGHT_SIDEKICK].style == 0) |
{ |
this_player->sidekick[RIGHT_SIDEKICK].x = *mouseX_ + 16; |
this_player->sidekick[RIGHT_SIDEKICK].y = *mouseY_; |
} |
} |
if (this_player->x_friction_ticks > 0) |
{ |
--this_player->x_friction_ticks; |
} |
else |
{ |
this_player->x_friction_ticks = 1; |
if (this_player->x_velocity < 0) |
++this_player->x_velocity; |
else if (this_player->x_velocity > 0) |
--this_player->x_velocity; |
} |
if (this_player->y_friction_ticks > 0) |
{ |
--this_player->y_friction_ticks; |
} |
else |
{ |
this_player->y_friction_ticks = 2; |
if (this_player->y_velocity < 0) |
++this_player->y_velocity; |
else if (this_player->y_velocity > 0) |
--this_player->y_velocity; |
} |
this_player->x_velocity += accelXC; |
this_player->y_velocity += accelYC; |
this_player->x_velocity = MIN(MAX(-4, this_player->x_velocity), 4); |
this_player->y_velocity = MIN(MAX(-4, this_player->y_velocity), 4); |
this_player->x += this_player->x_velocity; |
this_player->y += this_player->y_velocity; |
// if player moved, add new ship x, y history entry |
if (this_player->x - *mouseX_ != 0 || this_player->y - *mouseY_ != 0) |
{ |
for (uint i = 1; i < COUNTOF(player->old_x); ++i) |
{ |
this_player->old_x[i - 1] = this_player->old_x[i]; |
this_player->old_y[i - 1] = this_player->old_y[i]; |
} |
this_player->old_x[COUNTOF(player->old_x) - 1] = this_player->x; |
this_player->old_y[COUNTOF(player->old_x) - 1] = this_player->y; |
} |
} |
else /*twoPlayerLinked*/ |
{ |
if (shipGr_ == 0) |
this_player->x = player[0].x - 1; |
else |
this_player->x = player[0].x; |
this_player->y = player[0].y + 8; |
this_player->x_velocity = player[0].x_velocity; |
this_player->y_velocity = 4; |
// turret direction marker/shield |
shotMultiPos[SHOT_MISC] = 0; |
b = player_shot_create(0, SHOT_MISC, this_player->x + 1 + roundf(sinf(linkGunDirec + 0.2f) * 26), this_player->y + roundf(cosf(linkGunDirec + 0.2f) * 26), *mouseX_, *mouseY_, 148, playerNum_); |
shotMultiPos[SHOT_MISC] = 0; |
b = player_shot_create(0, SHOT_MISC, this_player->x + 1 + roundf(sinf(linkGunDirec - 0.2f) * 26), this_player->y + roundf(cosf(linkGunDirec - 0.2f) * 26), *mouseX_, *mouseY_, 148, playerNum_); |
shotMultiPos[SHOT_MISC] = 0; |
b = player_shot_create(0, SHOT_MISC, this_player->x + 1 + roundf(sinf(linkGunDirec) * 26), this_player->y + roundf(cosf(linkGunDirec) * 26), *mouseX_, *mouseY_, 147, playerNum_); |
if (shotRepeat[SHOT_REAR] > 0) |
{ |
--shotRepeat[SHOT_REAR]; |
} |
else if (button[1-1]) |
{ |
shotMultiPos[SHOT_REAR] = 0; |
b = player_shot_create(0, SHOT_REAR, this_player->x + 1 + roundf(sinf(linkGunDirec) * 20), this_player->y + roundf(cosf(linkGunDirec) * 20), *mouseX_, *mouseY_, linkGunWeapons[this_player->items.weapon[REAR_WEAPON].id-1], playerNum_); |
player_shot_set_direction(b, this_player->items.weapon[REAR_WEAPON].id, linkGunDirec); |
} |
} |
} |
if (!endLevel) |
{ |
if (this_player->x > 256) |
{ |
this_player->x = 256; |
constantLastX = -constantLastX; |
} |
if (this_player->x < 40) |
{ |
this_player->x = 40; |
constantLastX = -constantLastX; |
} |
if (isNetworkGame && playerNum_ == 1) |
{ |
if (this_player->y > 154) |
this_player->y = 154; |
} |
else |
{ |
if (this_player->y > 160) |
this_player->y = 160; |
} |
if (this_player->y < 10) |
this_player->y = 10; |
// Determines the ship banking sprite to display, depending on horizontal velocity and acceleration |
int ship_banking = this_player->x_velocity / 2 + (this_player->x - *mouseX_) / 6; |
ship_banking = MAX(-2, MIN(ship_banking, 2)); |
int ship_sprite = ship_banking * 2 + shipGr_; |
explosionFollowAmountX = this_player->x - this_player->last_x_explosion_follow; |
explosionFollowAmountY = this_player->y - this_player->last_y_explosion_follow; |
if (explosionFollowAmountY < 0) |
explosionFollowAmountY = 0; |
this_player->last_x_explosion_follow = this_player->x; |
this_player->last_y_explosion_follow = this_player->y; |
if (shipGr_ == 0) |
{ |
if (background2) |
{ |
blit_sprite2x2_darken(VGAScreen, this_player->x - 17 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite + 13); |
blit_sprite2x2_darken(VGAScreen, this_player->x + 7 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite + 51); |
if (superWild) |
{ |
blit_sprite2x2_darken(VGAScreen, this_player->x - 16 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite + 13); |
blit_sprite2x2_darken(VGAScreen, this_player->x + 6 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite + 51); |
} |
} |
} |
else if (shipGr_ == 1) |
{ |
if (background2) |
{ |
blit_sprite2x2_darken(VGAScreen, this_player->x - 17 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, 220); |
blit_sprite2x2_darken(VGAScreen, this_player->x + 7 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, 222); |
} |
} |
else |
{ |
if (background2) |
{ |
blit_sprite2x2_darken(VGAScreen, this_player->x - 5 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite); |
if (superWild) |
{ |
blit_sprite2x2_darken(VGAScreen, this_player->x - 4 - mapX2Ofs + 30, this_player->y - 7 + shadowYDist, *shapes9ptr_, ship_sprite); |
} |
} |
} |
if (this_player->invulnerable_ticks > 0) |
{ |
--this_player->invulnerable_ticks; |
if (shipGr_ == 0) |
{ |
blit_sprite2x2_blend(VGAScreen, this_player->x - 17, this_player->y - 7, *shapes9ptr_, ship_sprite + 13); |
blit_sprite2x2_blend(VGAScreen, this_player->x + 7 , this_player->y - 7, *shapes9ptr_, ship_sprite + 51); |
} |
else if (shipGr_ == 1) |
{ |
blit_sprite2x2_blend(VGAScreen, this_player->x - 17, this_player->y - 7, *shapes9ptr_, 220); |
blit_sprite2x2_blend(VGAScreen, this_player->x + 7 , this_player->y - 7, *shapes9ptr_, 222); |
} |
else |
blit_sprite2x2_blend(VGAScreen, this_player->x - 5, this_player->y - 7, *shapes9ptr_, ship_sprite); |
} |
else |
{ |
if (shipGr_ == 0) |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 17, this_player->y - 7, *shapes9ptr_, ship_sprite + 13); |
blit_sprite2x2(VGAScreen, this_player->x + 7, this_player->y - 7, *shapes9ptr_, ship_sprite + 51); |
} |
else if (shipGr_ == 1) |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 17, this_player->y - 7, *shapes9ptr_, 220); |
blit_sprite2x2(VGAScreen, this_player->x + 7, this_player->y - 7, *shapes9ptr_, 222); |
int ship_banking = 0; |
switch (ship_sprite) |
{ |
case 5: |
blit_sprite2(VGAScreen, this_player->x - 17, this_player->y + 7, *shapes9ptr_, 40); |
tempW = this_player->x - 7; |
ship_banking = -2; |
break; |
case 3: |
blit_sprite2(VGAScreen, this_player->x - 17, this_player->y + 7, *shapes9ptr_, 39); |
tempW = this_player->x - 7; |
ship_banking = -1; |
break; |
case 1: |
ship_banking = 0; |
break; |
case -1: |
blit_sprite2(VGAScreen, this_player->x + 19, this_player->y + 7, *shapes9ptr_, 58); |
tempW = this_player->x + 9; |
ship_banking = 1; |
break; |
case -3: |
blit_sprite2(VGAScreen, this_player->x + 19, this_player->y + 7, *shapes9ptr_, 59); |
tempW = this_player->x + 9; |
ship_banking = 2; |
break; |
} |
if (ship_banking != 0) // NortSparks |
{ |
if (shotRepeat[SHOT_NORTSPARKS] > 0) |
{ |
--shotRepeat[SHOT_NORTSPARKS]; |
} |
else |
{ |
b = player_shot_create(0, SHOT_NORTSPARKS, tempW + (mt_rand() % 8) - 4, this_player->y + (mt_rand() % 8) - 4, *mouseX_, *mouseY_, 671, 1); |
shotRepeat[SHOT_NORTSPARKS] = abs(ship_banking) - 1; |
} |
} |
} |
else |
{ |
blit_sprite2x2(VGAScreen, this_player->x - 5, this_player->y - 7, *shapes9ptr_, ship_sprite); |
} |
} |
/*Options Location*/ |
if (playerNum_ == 2 && shipGr_ == 0) // if dragonwing |
{ |
if (this_player->sidekick[LEFT_SIDEKICK].style == 0) |
{ |
this_player->sidekick[LEFT_SIDEKICK].x = this_player->x - 14 + ship_banking * 2; |
this_player->sidekick[LEFT_SIDEKICK].y = this_player->y; |
} |
if (this_player->sidekick[RIGHT_SIDEKICK].style == 0) |
{ |
this_player->sidekick[RIGHT_SIDEKICK].x = this_player->x + 17 + ship_banking * 2; |
this_player->sidekick[RIGHT_SIDEKICK].y = this_player->y; |
} |
} |
} // !endLevel |
if (moveOk) |
{ |
if (this_player->is_alive) |
{ |
if (!endLevel) |
{ |
this_player->delta_x_shot_move = this_player->x - this_player->last_x_shot_move; |
this_player->delta_y_shot_move = this_player->y - this_player->last_y_shot_move; |
/* PLAYER SHOT Change */ |
if (button[4-1]) |
{ |
portConfigChange = true; |
if (portConfigDone) |
{ |
shotMultiPos[SHOT_REAR] = 0; |
if (superArcadeMode != SA_NONE && superArcadeMode <= SA_NORTSHIPZ) |
{ |
shotMultiPos[SHOT_SPECIAL] = 0; |
shotMultiPos[SHOT_SPECIAL2] = 0; |
if (player[0].items.special == SASpecialWeapon[superArcadeMode-1]) |
{ |
player[0].items.special = SASpecialWeaponB[superArcadeMode-1]; |
this_player->weapon_mode = 2; |
} |
else |
{ |
player[0].items.special = SASpecialWeapon[superArcadeMode-1]; |
this_player->weapon_mode = 1; |
} |
} |
else if (++this_player->weapon_mode > JE_portConfigs()) |
this_player->weapon_mode = 1; |
JE_drawPortConfigButtons(); |
portConfigDone = false; |
} |
} |
/* PLAYER SHOT Creation */ |
/*SpecialShot*/ |
if (!galagaMode) |
JE_doSpecialShot(playerNum_, &this_player->armor, &this_player->shield); |
/*Normal Main Weapons*/ |
if (!(twoPlayerLinked && playerNum_ == 2)) |
{ |
int min, max; |
if (!twoPlayerMode) |
min = 1, max = 2; |
else |
min = max = playerNum_; |
for (temp = min - 1; temp < max; temp++) |
{ |
const uint item = this_player->items.weapon[temp].id; |
if (item > 0) |
{ |
if (shotRepeat[temp] > 0) |
{ |
--shotRepeat[temp]; |
} |
else if (button[1-1]) |
{ |
const uint item_power = galagaMode ? 0 : this_player->items.weapon[temp].power - 1, |
item_mode = (temp == REAR_WEAPON) ? this_player->weapon_mode - 1 : 0; |
b = player_shot_create(item, temp, this_player->x, this_player->y, *mouseX_, *mouseY_, weaponPort[item].op[item_mode][item_power], playerNum_); |
} |
} |
} |
} |
/*Super Charge Weapons*/ |
if (playerNum_ == 2) |
{ |
if (!twoPlayerLinked) |
blit_sprite2(VGAScreen, this_player->x + (shipGr_ == 0) + 1, this_player->y - 13, eShapes[5], 77 + chargeLevel + chargeGr * 19); |
if (chargeGrWait > 0) |
{ |
chargeGrWait--; |
} |
else |
{ |
chargeGr++; |
if (chargeGr == 4) |
chargeGr = 0; |
chargeGrWait = 3; |
} |
if (chargeLevel > 0) |
{ |
fill_rectangle_xy(VGAScreenSeg, 269, 107 + (chargeLevel - 1) * 3, 275, 108 + (chargeLevel - 1) * 3, 193); |
} |
if (chargeWait > 0) |
{ |
chargeWait--; |
} |
else |
{ |
if (chargeLevel < chargeMax) |
chargeLevel++; |
chargeWait = 28 - this_player->items.weapon[REAR_WEAPON].power * 2; |
if (difficultyLevel > 3) |
chargeWait -= 5; |
} |
if (chargeLevel > 0) |
fill_rectangle_xy(VGAScreenSeg, 269, 107 + (chargeLevel - 1) * 3, 275, 108 + (chargeLevel - 1) * 3, 204); |
if (shotRepeat[SHOT_P2_CHARGE] > 0) |
{ |
--shotRepeat[SHOT_P2_CHARGE]; |
} |
else if (button[1-1] && (!twoPlayerLinked || chargeLevel > 0)) |
{ |
shotMultiPos[SHOT_P2_CHARGE] = 0; |
b = player_shot_create(16, SHOT_P2_CHARGE, this_player->x, this_player->y, *mouseX_, *mouseY_, chargeGunWeapons[player[1].items.weapon[REAR_WEAPON].id-1] + chargeLevel, playerNum_); |
if (chargeLevel > 0) |
fill_rectangle_xy(VGAScreenSeg, 269, 107 + (chargeLevel - 1) * 3, 275, 108 + (chargeLevel - 1) * 3, 193); |
chargeLevel = 0; |
chargeWait = 30 - this_player->items.weapon[REAR_WEAPON].power * 2; |
} |
} |
/*SUPER BOMB*/ |
temp = playerNum_; |
if (temp == 0) |
temp = 1; /*Get whether player 1 or 2*/ |
if (player[temp-1].superbombs > 0) |
{ |
if (shotRepeat[SHOT_P1_SUPERBOMB + temp-1] > 0) |
{ |
--shotRepeat[SHOT_P1_SUPERBOMB + temp-1]; |
} |
else if (button[3-1] || button[2-1]) |
{ |
--player[temp-1].superbombs; |
shotMultiPos[SHOT_P1_SUPERBOMB + temp-1] = 0; |
b = player_shot_create(16, SHOT_P1_SUPERBOMB + temp-1, this_player->x, this_player->y, *mouseX_, *mouseY_, 535, playerNum_); |
} |
} |
// sidekicks |
if (this_player->sidekick[LEFT_SIDEKICK].style == 4 && this_player->sidekick[RIGHT_SIDEKICK].style == 4) |
optionSatelliteRotate += 0.2f; |
else if (this_player->sidekick[LEFT_SIDEKICK].style == 4 || this_player->sidekick[RIGHT_SIDEKICK].style == 4) |
optionSatelliteRotate += 0.15f; |
switch (this_player->sidekick[LEFT_SIDEKICK].style) |
{ |
case 1: // trailing |
case 3: |
this_player->sidekick[LEFT_SIDEKICK].x = this_player->old_x[COUNTOF(player->old_x) / 2 - 1]; |
this_player->sidekick[LEFT_SIDEKICK].y = this_player->old_y[COUNTOF(player->old_x) / 2 - 1]; |
break; |
case 2: // front-mounted |
this_player->sidekick[LEFT_SIDEKICK].x = this_player->x; |
this_player->sidekick[LEFT_SIDEKICK].y = MAX(10, this_player->y - 20); |
break; |
case 4: // orbitting |
this_player->sidekick[LEFT_SIDEKICK].x = this_player->x + roundf(sinf(optionSatelliteRotate) * 20); |
this_player->sidekick[LEFT_SIDEKICK].y = this_player->y + roundf(cosf(optionSatelliteRotate) * 20); |
break; |
} |
switch (this_player->sidekick[RIGHT_SIDEKICK].style) |
{ |
case 4: // orbitting |
this_player->sidekick[RIGHT_SIDEKICK].x = this_player->x - roundf(sinf(optionSatelliteRotate) * 20); |
this_player->sidekick[RIGHT_SIDEKICK].y = this_player->y - roundf(cosf(optionSatelliteRotate) * 20); |
break; |
case 1: // trailing |
case 3: |
this_player->sidekick[RIGHT_SIDEKICK].x = this_player->old_x[0]; |
this_player->sidekick[RIGHT_SIDEKICK].y = this_player->old_y[0]; |
break; |
case 2: // front-mounted |
if (!optionAttachmentLinked) |
{ |
this_player->sidekick[RIGHT_SIDEKICK].y += optionAttachmentMove / 2; |
if (optionAttachmentMove >= -2) |
{ |
if (optionAttachmentReturn) |
temp = 2; |
else |
temp = 0; |
if (this_player->sidekick[RIGHT_SIDEKICK].y > (this_player->y - 20) + 5) |
{ |
temp = 2; |
optionAttachmentMove -= 1 + optionAttachmentReturn; |
} |
else if (this_player->sidekick[RIGHT_SIDEKICK].y > (this_player->y - 20) - 0) |
{ |
temp = 3; |
if (optionAttachmentMove > 0) |
optionAttachmentMove--; |
else |
optionAttachmentMove++; |
} |
else if (this_player->sidekick[RIGHT_SIDEKICK].y > (this_player->y - 20) - 5) |
{ |
temp = 2; |
optionAttachmentMove++; |
} |
else if (optionAttachmentMove < 2 + optionAttachmentReturn * 4) |
{ |
optionAttachmentMove += 1 + optionAttachmentReturn; |
} |
if (optionAttachmentReturn) |
temp = temp * 2; |
if (abs(this_player->sidekick[RIGHT_SIDEKICK].x - this_player->x) < temp) |
temp = 1; |
if (this_player->sidekick[RIGHT_SIDEKICK].x > this_player->x) |
this_player->sidekick[RIGHT_SIDEKICK].x -= temp; |
else if (this_player->sidekick[RIGHT_SIDEKICK].x < this_player->x) |
this_player->sidekick[RIGHT_SIDEKICK].x += temp; |
if (abs(this_player->sidekick[RIGHT_SIDEKICK].y - (this_player->y - 20)) + abs(this_player->sidekick[RIGHT_SIDEKICK].x - this_player->x) < 8) |
{ |
optionAttachmentLinked = true; |
soundQueue[2] = S_CLINK; |
} |
if (button[3-1]) |
optionAttachmentReturn = true; |
} |
else // sidekick needs to catch up to player |
{ |
optionAttachmentMove += 1 + optionAttachmentReturn; |
JE_setupExplosion(this_player->sidekick[RIGHT_SIDEKICK].x + 1, this_player->sidekick[RIGHT_SIDEKICK].y + 10, 0, 0, false, false); |
} |
} |
else |
{ |
this_player->sidekick[RIGHT_SIDEKICK].x = this_player->x; |
this_player->sidekick[RIGHT_SIDEKICK].y = this_player->y - 20; |
if (button[3-1]) |
{ |
optionAttachmentLinked = false; |
optionAttachmentReturn = false; |
optionAttachmentMove = -20; |
soundQueue[3] = S_WEAPON_26; |
} |
} |
if (this_player->sidekick[RIGHT_SIDEKICK].y < 10) |
this_player->sidekick[RIGHT_SIDEKICK].y = 10; |
break; |
} |
if (playerNum_ == 2 || !twoPlayerMode) // if player has sidekicks |
{ |
for (uint i = 0; i < COUNTOF(player->items.sidekick); ++i) |
{ |
uint shot_i = (i == 0) ? SHOT_LEFT_SIDEKICK : SHOT_RIGHT_SIDEKICK; |
JE_OptionType *this_option = &options[this_player->items.sidekick[i]]; |
// fire/refill sidekick |
if (this_option->wport > 0) |
{ |
if (shotRepeat[shot_i] > 0) |
{ |
--shotRepeat[shot_i]; |
} |
else |
{ |
const int ammo_max = this_player->sidekick[i].ammo_max; |
if (ammo_max > 0) // sidekick has limited ammo |
{ |
if (this_player->sidekick[i].ammo_refill_ticks > 0) |
{ |
--this_player->sidekick[i].ammo_refill_ticks; |
} |
else // refill one ammo |
{ |
this_player->sidekick[i].ammo_refill_ticks = this_player->sidekick[i].ammo_refill_ticks_max; |
if (this_player->sidekick[i].ammo < ammo_max) |
++this_player->sidekick[i].ammo; |
// draw sidekick refill ammo gauge |
const int y = hud_sidekick_y[twoPlayerMode ? 1 : 0][i] + 13; |
draw_segmented_gauge(VGAScreenSeg, 284, y, 112, 2, 2, MAX(1, ammo_max / 10), this_player->sidekick[i].ammo); |
} |
if (button[1 + i] && this_player->sidekick[i].ammo > 0) |
{ |
b = player_shot_create(this_option->wport, shot_i, this_player->sidekick[i].x, this_player->sidekick[i].y, *mouseX_, *mouseY_, this_option->wpnum + this_player->sidekick[i].charge, playerNum_); |
--this_player->sidekick[i].ammo; |
if (this_player->sidekick[i].charge > 0) |
{ |
shotMultiPos[shot_i] = 0; |
this_player->sidekick[i].charge = 0; |
} |
this_player->sidekick[i].charge_ticks = 20; |
this_player->sidekick[i].animation_enabled = true; |
// draw sidekick discharge ammo gauge |
const int y = hud_sidekick_y[twoPlayerMode ? 1 : 0][i] + 13; |
fill_rectangle_xy(VGAScreenSeg, 284, y, 312, y + 2, 0); |
draw_segmented_gauge(VGAScreenSeg, 284, y, 112, 2, 2, MAX(1, ammo_max / 10), this_player->sidekick[i].ammo); |
} |
} |
else // has infinite ammo |
{ |
if (button[0] || button[1 + i]) |
{ |
b = player_shot_create(this_option->wport, shot_i, this_player->sidekick[i].x, this_player->sidekick[i].y, *mouseX_, *mouseY_, this_option->wpnum + this_player->sidekick[i].charge, playerNum_); |
if (this_player->sidekick[i].charge > 0) |
{ |
shotMultiPos[shot_i] = 0; |
this_player->sidekick[i].charge = 0; |
} |
this_player->sidekick[i].charge_ticks = 20; |
this_player->sidekick[i].animation_enabled = true; |
} |
} |
} |
} |
} |
} // end of if player has sidekicks |
} // !endLevel |
} // this_player->is_alive |
} // moveOK |
// draw sidekicks |
if ((playerNum_ == 2 || !twoPlayerMode) && !endLevel) |
{ |
for (uint i = 0; i < COUNTOF(this_player->sidekick); ++i) |
{ |
JE_OptionType *this_option = &options[this_player->items.sidekick[i]]; |
if (this_option->option > 0) |
{ |
if (this_player->sidekick[i].animation_enabled) |
{ |
if (++this_player->sidekick[i].animation_frame >= this_option->ani) |
{ |
this_player->sidekick[i].animation_frame = 0; |
this_player->sidekick[i].animation_enabled = (this_option->option == 1); |
} |
} |
const int x = this_player->sidekick[i].x, |
y = this_player->sidekick[i].y; |
const uint sprite = this_option->gr[this_player->sidekick[i].animation_frame] + this_player->sidekick[i].charge; |
if (this_player->sidekick[i].style == 1 || this_player->sidekick[i].style == 2) |
blit_sprite2x2(VGAScreen, x - 6, y, eShapes[5], sprite); |
else |
blit_sprite2(VGAScreen, x, y, shapes9, sprite); |
} |
if (--this_player->sidekick[i].charge_ticks == 0) |
{ |
if (this_player->sidekick[i].charge < this_option->pwr) |
++this_player->sidekick[i].charge; |
this_player->sidekick[i].charge_ticks = 20; |
} |
} |
} |
} |
void JE_mainGamePlayerFunctions( void ) |
{ |
/*PLAYER MOVEMENT/MOUSE ROUTINES*/ |
if (endLevel && levelEnd > 0) |
{ |
levelEnd--; |
levelEndWarp++; |
} |
/*Reset Street-Fighter commands*/ |
memset(SFExecuted, 0, sizeof(SFExecuted)); |
portConfigChange = false; |
if (twoPlayerMode) |
{ |
JE_playerMovement(&player[0], |
!galagaMode ? inputDevice[0] : 0, 1, shipGr, shipGrPtr, |
&mouseX, &mouseY); |
JE_playerMovement(&player[1], |
!galagaMode ? inputDevice[1] : 0, 2, shipGr2, shipGr2ptr, |
&mouseXB, &mouseYB); |
} |
else |
{ |
JE_playerMovement(&player[0], |
0, 1, shipGr, shipGrPtr, |
&mouseX, &mouseY); |
} |
/* == Parallax Map Scrolling == */ |
if (twoPlayerMode) |
{ |
tempX = (player[0].x + player[1].x) / 2; |
} else { |
tempX = player[0].x; |
} |
tempW = floorf((260.0f - (tempX - 36.0f)) / (260.0f - 36.0f) * (24.0f * 3.0f) - 1.0f); |
mapX3Ofs = tempW; |
mapX3Pos = mapX3Ofs % 24; |
mapX3bpPos = 1 - (mapX3Ofs / 24); |
mapX2Ofs = (tempW * 2) / 3; |
mapX2Pos = mapX2Ofs % 24; |
mapX2bpPos = 1 - (mapX2Ofs / 24); |
oldMapXOfs = mapXOfs; |
mapXOfs = mapX2Ofs / 2; |
mapXPos = mapXOfs % 24; |
mapXbpPos = 1 - (mapXOfs / 24); |
if (background3x1) |
{ |
mapX3Ofs = mapXOfs; |
mapX3Pos = mapXPos; |
mapX3bpPos = mapXbpPos - 1; |
} |
} |
const char *JE_getName( JE_byte pnum ) |
{ |
if (pnum == thisPlayerNum && network_player_name[0] != '\0') |
return network_player_name; |
else if (network_opponent_name[0] != '\0') |
return network_opponent_name; |
return miscText[47 + pnum]; |
} |
void JE_playerCollide( Player *this_player, JE_byte playerNum_ ) |
{ |
char tempStr[256]; |
for (int z = 0; z < 100; z++) |
{ |
if (enemyAvail[z] != 1) |
{ |
int enemy_screen_x = enemy[z].ex + enemy[z].mapoffset; |
if (abs(this_player->x - enemy_screen_x) < 12 && abs(this_player->y - enemy[z].ey) < 14) |
{ /*Collide*/ |
int evalue = enemy[z].evalue; |
if (evalue > 29999) |
{ |
if (evalue == 30000) // spawn dragonwing in galaga mode, otherwise just a purple ball |
{ |
this_player->cash += 100; |
if (!galagaMode) |
{ |
handle_got_purple_ball(this_player); |
} |
else |
{ |
// spawn the dragonwing? |
if (twoPlayerMode) |
this_player->cash += 2400; |
twoPlayerMode = true; |
twoPlayerLinked = true; |
player[1].items.weapon[REAR_WEAPON].power = 1; |
player[1].armor = 10; |
player[1].is_alive = true; |
} |
enemyAvail[z] = 1; |
soundQueue[7] = S_POWERUP; |
} |
else if (superArcadeMode != SA_NONE && evalue > 30000) |
{ |
shotMultiPos[SHOT_FRONT] = 0; |
shotRepeat[SHOT_FRONT] = 10; |
tempW = SAWeapon[superArcadeMode-1][evalue - 30000-1]; |
// if picked up already-owned weapon, power weapon up |
if (tempW == player[0].items.weapon[FRONT_WEAPON].id) |
{ |
this_player->cash += 1000; |
power_up_weapon(this_player, FRONT_WEAPON); |
} |
// else weapon also gives purple ball |
else |
{ |
handle_got_purple_ball(this_player); |
} |
player[0].items.weapon[FRONT_WEAPON].id = tempW; |
this_player->cash += 200; |
soundQueue[7] = S_POWERUP; |
enemyAvail[z] = 1; |
} |
else if (evalue > 32100) |
{ |
if (playerNum_ == 1) |
{ |
this_player->cash += 250; |
player[0].items.special = evalue - 32100; |
shotMultiPos[SHOT_SPECIAL] = 0; |
shotRepeat[SHOT_SPECIAL] = 10; |
shotMultiPos[SHOT_SPECIAL2] = 0; |
shotRepeat[SHOT_SPECIAL2] = 0; |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(1), miscTextB[4-1], special[evalue - 32100].name); |
else if (twoPlayerMode) |
sprintf(tempStr, "%s %s", miscText[43-1], special[evalue - 32100].name); |
else |
sprintf(tempStr, "%s %s", miscText[64-1], special[evalue - 32100].name); |
JE_drawTextWindow(tempStr); |
soundQueue[7] = S_POWERUP; |
enemyAvail[z] = 1; |
} |
} |
else if (evalue > 32000) |
{ |
if (playerNum_ == 2) |
{ |
enemyAvail[z] = 1; |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(2), miscTextB[4-1], options[evalue - 32000].name); |
else |
sprintf(tempStr, "%s %s", miscText[44-1], options[evalue - 32000].name); |
JE_drawTextWindow(tempStr); |
// if picked up a different sidekick than player already has, then reset sidekicks to least powerful, else power them up |
if (evalue - 32000u != player[1].items.sidekick_series) |
{ |
player[1].items.sidekick_series = evalue - 32000; |
player[1].items.sidekick_level = 101; |
} |
else if (player[1].items.sidekick_level < 103) |
{ |
++player[1].items.sidekick_level; |
} |
uint temp = player[1].items.sidekick_level - 100 - 1; |
for (uint i = 0; i < COUNTOF(player[1].items.sidekick); ++i) |
player[1].items.sidekick[i] = optionSelect[player[1].items.sidekick_series][temp][i]; |
shotMultiPos[SHOT_LEFT_SIDEKICK] = 0; |
shotMultiPos[SHOT_RIGHT_SIDEKICK] = 0; |
JE_drawOptions(); |
soundQueue[7] = S_POWERUP; |
} |
else if (onePlayerAction) |
{ |
enemyAvail[z] = 1; |
sprintf(tempStr, "%s %s", miscText[64-1], options[evalue - 32000].name); |
JE_drawTextWindow(tempStr); |
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i) |
player[0].items.sidekick[i] = evalue - 32000; |
shotMultiPos[SHOT_LEFT_SIDEKICK] = 0; |
shotMultiPos[SHOT_RIGHT_SIDEKICK] = 0; |
JE_drawOptions(); |
soundQueue[7] = S_POWERUP; |
} |
if (enemyAvail[z] == 1) |
this_player->cash += 250; |
} |
else if (evalue > 31000) |
{ |
this_player->cash += 250; |
if (playerNum_ == 2) |
{ |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(2), miscTextB[4-1], weaponPort[evalue - 31000].name); |
else |
sprintf(tempStr, "%s %s", miscText[44-1], weaponPort[evalue - 31000].name); |
JE_drawTextWindow(tempStr); |
player[1].items.weapon[REAR_WEAPON].id = evalue - 31000; |
shotMultiPos[SHOT_REAR] = 0; |
enemyAvail[z] = 1; |
soundQueue[7] = S_POWERUP; |
} |
else if (onePlayerAction) |
{ |
sprintf(tempStr, "%s %s", miscText[64-1], weaponPort[evalue - 31000].name); |
JE_drawTextWindow(tempStr); |
player[0].items.weapon[REAR_WEAPON].id = evalue - 31000; |
shotMultiPos[SHOT_REAR] = 0; |
enemyAvail[z] = 1; |
soundQueue[7] = S_POWERUP; |
if (player[0].items.weapon[REAR_WEAPON].power == 0) // does this ever happen? |
player[0].items.weapon[REAR_WEAPON].power = 1; |
} |
} |
else if (evalue > 30000) |
{ |
if (playerNum_ == 1 && twoPlayerMode) |
{ |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(1), miscTextB[4-1], weaponPort[evalue - 30000].name); |
else |
sprintf(tempStr, "%s %s", miscText[43-1], weaponPort[evalue - 30000].name); |
JE_drawTextWindow(tempStr); |
player[0].items.weapon[FRONT_WEAPON].id = evalue - 30000; |
shotMultiPos[SHOT_FRONT] = 0; |
enemyAvail[z] = 1; |
soundQueue[7] = S_POWERUP; |
} |
else if (onePlayerAction) |
{ |
sprintf(tempStr, "%s %s", miscText[64-1], weaponPort[evalue - 30000].name); |
JE_drawTextWindow(tempStr); |
player[0].items.weapon[FRONT_WEAPON].id = evalue - 30000; |
shotMultiPos[SHOT_FRONT] = 0; |
enemyAvail[z] = 1; |
soundQueue[7] = S_POWERUP; |
} |
if (enemyAvail[z] == 1) |
{ |
player[0].items.special = specialArcadeWeapon[evalue - 30000-1]; |
if (player[0].items.special > 0) |
{ |
shotMultiPos[SHOT_SPECIAL] = 0; |
shotRepeat[SHOT_SPECIAL] = 0; |
shotMultiPos[SHOT_SPECIAL2] = 0; |
shotRepeat[SHOT_SPECIAL2] = 0; |
} |
this_player->cash += 250; |
} |
} |
} |
else if (evalue > 20000) |
{ |
if (twoPlayerLinked) |
{ |
// share the armor evenly between linked players |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
player[i].armor += (evalue - 20000) / COUNTOF(player); |
if (player[i].armor > 28) |
player[i].armor = 28; |
} |
} |
else |
{ |
this_player->armor += evalue - 20000; |
if (this_player->armor > 28) |
this_player->armor = 28; |
} |
enemyAvail[z] = 1; |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_drawArmor(); |
VGAScreen = game_screen; /* side-effect of game_screen */ |
soundQueue[7] = S_POWERUP; |
} |
else if (evalue > 10000 && enemyAvail[z] == 2) |
{ |
if (!bonusLevel) |
{ |
play_song(30); /*Zanac*/ |
bonusLevel = true; |
nextLevel = evalue - 10000; |
enemyAvail[z] = 1; |
displayTime = 150; |
} |
} |
else if (enemy[z].scoreitem) |
{ |
enemyAvail[z] = 1; |
soundQueue[7] = S_ITEM; |
if (evalue == 1) |
{ |
cubeMax++; |
soundQueue[3] = V_DATA_CUBE; |
} |
else if (evalue == -1) // got front weapon powerup |
{ |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(1), miscTextB[4-1], miscText[45-1]); |
else if (twoPlayerMode) |
sprintf(tempStr, "%s %s", miscText[43-1], miscText[45-1]); |
else |
strcpy(tempStr, miscText[45-1]); |
JE_drawTextWindow(tempStr); |
power_up_weapon(&player[0], FRONT_WEAPON); |
soundQueue[7] = S_POWERUP; |
} |
else if (evalue == -2) // got rear weapon powerup |
{ |
if (isNetworkGame) |
sprintf(tempStr, "%s %s %s", JE_getName(2), miscTextB[4-1], miscText[46-1]); |
else if (twoPlayerMode) |
sprintf(tempStr, "%s %s", miscText[44-1], miscText[46-1]); |
else |
strcpy(tempStr, miscText[46-1]); |
JE_drawTextWindow(tempStr); |
power_up_weapon(twoPlayerMode ? &player[1] : &player[0], REAR_WEAPON); |
soundQueue[7] = S_POWERUP; |
} |
else if (evalue == -3) |
{ |
// picked up orbiting asteroid killer |
shotMultiPos[SHOT_MISC] = 0; |
b = player_shot_create(0, SHOT_MISC, this_player->x, this_player->y, mouseX, mouseY, 104, playerNum_); |
shotAvail[z] = 0; |
} |
else if (evalue == -4) |
{ |
if (player[playerNum_-1].superbombs < 10) |
++player[playerNum_-1].superbombs; |
} |
else if (evalue == -5) |
{ |
player[0].items.weapon[FRONT_WEAPON].id = 25; // HOT DOG! |
player[0].items.weapon[REAR_WEAPON].id = 26; |
player[1].items.weapon[REAR_WEAPON].id = 26; |
player[0].last_items = player[0].items; |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].weapon_mode = 1; |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
} |
else if (twoPlayerLinked) |
{ |
// players get equal share of pick-up cash when linked |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].cash += evalue / COUNTOF(player); |
} |
else |
{ |
this_player->cash += evalue; |
} |
JE_setupExplosion(enemy_screen_x, enemy[z].ey, 0, enemyDat[enemy[z].enemytype].explosiontype, true, false); |
} |
else if (this_player->invulnerable_ticks == 0 && enemyAvail[z] == 0 && |
(enemyDat[enemy[z].enemytype].explosiontype & 1) == 0) // explosiontype & 1 == 0: not ground enemy |
{ |
int armorleft = enemy[z].armorleft; |
if (armorleft > damageRate) |
armorleft = damageRate; |
JE_playerDamage(armorleft, this_player); |
// player ship gets push-back from collision |
if (enemy[z].armorleft > 0) |
{ |
this_player->x_velocity += (enemy[z].exc * enemy[z].armorleft) / 2; |
this_player->y_velocity += (enemy[z].eyc * enemy[z].armorleft) / 2; |
} |
int armorleft2 = enemy[z].armorleft; |
if (armorleft2 == 255) |
armorleft2 = 30000; |
temp = enemy[z].linknum; |
if (temp == 0) |
temp = 255; |
b = z; |
if (armorleft2 > armorleft) |
{ |
// damage enemy |
if (enemy[z].armorleft != 255) |
enemy[z].armorleft -= armorleft; |
soundQueue[5] = S_ENEMY_HIT; |
} |
else |
{ |
// kill enemy |
for (temp2 = 0; temp2 < 100; temp2++) |
{ |
if (enemyAvail[temp2] != 1) |
{ |
temp3 = enemy[temp2].linknum; |
if (temp2 == b || |
(temp != 255 && |
(temp == temp3 || temp - 100 == temp3 |
|| (temp3 > 40 && temp3 / 20 == temp / 20 && temp3 <= temp)))) |
{ |
int enemy_screen_x = enemy[temp2].ex + enemy[temp2].mapoffset; |
enemy[temp2].linknum = 0; |
enemyAvail[temp2] = 1; |
if (enemyDat[enemy[temp2].enemytype].esize == 1) |
{ |
JE_setupExplosionLarge(enemy[temp2].enemyground, enemy[temp2].explonum, enemy_screen_x, enemy[temp2].ey); |
soundQueue[6] = S_EXPLOSION_9; |
} |
else |
{ |
JE_setupExplosion(enemy_screen_x, enemy[temp2].ey, 0, 1, false, false); |
soundQueue[5] = S_EXPLOSION_4; |
} |
} |
} |
} |
enemyAvail[z] = 1; |
} |
} |
} |
} |
} |
} |
/contrib/games/opentyrian/src/mainint.h |
---|
0,0 → 1,93 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef MAININT_H |
#define MAININT_H |
#include "config.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "player.h" |
#include "sprite.h" |
extern bool button[4]; // fire, left fire, right fire, mode swap |
extern JE_shortint constantLastX; |
extern JE_word textErase; |
extern JE_word upgradeCost; |
extern JE_word downgradeCost; |
extern JE_boolean performSave; |
extern JE_boolean jumpSection; |
extern JE_boolean useLastBank; |
extern bool pause_pressed, ingamemenu_pressed; |
/*void JE_textMenuWait ( JE_word waittime, JE_boolean dogamma );*/ |
void JE_drawTextWindow( const char *text ); |
void JE_initPlayerData( void ); |
void JE_highScoreScreen( void ); |
void JE_gammaCorrect_func( JE_byte *col, JE_real r ); |
void JE_gammaCorrect( Palette *colorBuffer, JE_byte gamma ); |
JE_boolean JE_gammaCheck( void ); |
/* void JE_textMenuWait( JE_word *waitTime, JE_boolean doGamma ); /!\ In setup.h */ |
void JE_loadOrderingInfo( void ); |
void JE_nextEpisode( void ); |
void JE_helpSystem( JE_byte startTopic ); |
void JE_doInGameSetup( void ); |
JE_boolean JE_inGameSetup( void ); |
void JE_inGameHelp( void ); |
void JE_sortHighScores( void ); |
void JE_highScoreCheck( void ); |
void adjust_difficulty( void ); |
bool load_next_demo( void ); |
bool replay_demo_keys( void ); |
bool read_demo_keys( void ); |
void JE_SFCodes( JE_byte playerNum_, JE_integer PX_, JE_integer PY_, JE_integer mouseX_, JE_integer mouseY_ ); |
void JE_sort( void ); |
long weapon_upgrade_cost( long base_cost, unsigned int power ); |
ulong JE_getCost( JE_byte itemType, JE_word itemNum ); |
JE_longint JE_getValue( JE_byte itemType, JE_word itemNum ); |
ulong JE_totalScore( const Player * ); |
void JE_drawPortConfigButtons( void ); |
void JE_outCharGlow( JE_word x, JE_word y, const char *s ); |
void JE_playCredits( void ); |
void JE_endLevelAni( void ); |
void JE_drawCube( SDL_Surface * screen, JE_word x, JE_word y, JE_byte filter, JE_byte brightness ); |
void JE_handleChat( void ); |
bool str_pop_int( char *str, int *val ); |
void JE_loadScreen( void ); |
void JE_operation( JE_byte slot ); |
void JE_inGameDisplays( void ); |
void JE_mainKeyboardInput( void ); |
void JE_pauseGame( void ); |
void JE_playerMovement( Player *this_player, JE_byte inputDevice, JE_byte playerNum, JE_word shipGr, Sprite2_array *shapes9ptr_, JE_word *mouseX, JE_word *mouseY ); |
void JE_mainGamePlayerFunctions( void ); |
const char *JE_getName( JE_byte pnum ); |
void JE_playerCollide( Player *this_player, JE_byte playerNum ); |
#endif /* MAININT_H */ |
/contrib/games/opentyrian/src/menus.c |
---|
0,0 → 1,262 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "menus.h" |
#include "config.h" |
#include "episodes.h" |
#include "fonthand.h" |
#include "keyboard.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "picload.h" |
#include "setup.h" |
#include "sprite.h" |
#include "video.h" |
char episode_name[6][31], difficulty_name[7][21], gameplay_name[GAMEPLAY_NAME_COUNT][26]; |
bool select_gameplay( void ) |
{ |
JE_loadPic(VGAScreen, 2, false); |
JE_dString(VGAScreen, JE_fontCenter(gameplay_name[0], FONT_SHAPES), 20, gameplay_name[0], FONT_SHAPES); |
int gameplay = 1, |
gameplay_max = GAMEPLAY_NAME_COUNT - 1; |
bool fade_in = true; |
for (; ; ) |
{ |
for (int i = 1; i <= gameplay_max; i++) |
{ |
JE_outTextAdjust(VGAScreen, JE_fontCenter(gameplay_name[i], SMALL_FONT_SHAPES), i * 24 + 30, gameplay_name[i], 15, -4 + (i == gameplay ? 2 : 0) - (i == (GAMEPLAY_NAME_COUNT - 1) ? 4 : 0), SMALL_FONT_SHAPES, true); |
} |
JE_showVGA(); |
if (fade_in) |
{ |
fade_palette(colors, 10, 0, 255); |
fade_in = false; |
} |
JE_word temp = 0; |
JE_textMenuWait(&temp, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
if (--gameplay < 1) |
gameplay = gameplay_max; |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
if (++gameplay > gameplay_max) |
gameplay = 1; |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_RETURN: |
if (gameplay == GAMEPLAY_NAME_COUNT - 1) |
{ |
JE_playSampleNum(S_SPRING); |
/* TODO: NETWORK */ |
fprintf(stderr, "error: networking via menu not implemented\n"); |
break; |
} |
JE_playSampleNum(S_SELECT); |
fade_black(10); |
onePlayerAction = (gameplay == 2); |
twoPlayerMode = (gameplay == GAMEPLAY_NAME_COUNT - 2); |
return true; |
case SDLK_ESCAPE: |
JE_playSampleNum(S_SPRING); |
/* fading handled elsewhere |
fade_black(10); */ |
return false; |
default: |
break; |
} |
} |
} |
} |
bool select_episode( void ) |
{ |
JE_loadPic(VGAScreen, 2, false); |
JE_dString(VGAScreen, JE_fontCenter(episode_name[0], FONT_SHAPES), 20, episode_name[0], FONT_SHAPES); |
int episode = 1, episode_max = EPISODE_AVAILABLE; |
bool fade_in = true; |
for (; ; ) |
{ |
for (int i = 1; i <= episode_max; i++) |
{ |
JE_outTextAdjust(VGAScreen, 20, i * 30 + 20, episode_name[i], 15, -4 + (i == episode ? 2 : 0) - (!episodeAvail[i - 1] ? 4 : 0), SMALL_FONT_SHAPES, true); |
} |
JE_showVGA(); |
if (fade_in) |
{ |
fade_palette(colors, 10, 0, 255); |
fade_in = false; |
} |
JE_word temp = 0; |
JE_textMenuWait(&temp, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
episode--; |
if (episode < 1) |
{ |
episode = episode_max; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
episode++; |
if (episode > episode_max) |
{ |
episode = 1; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_RETURN: |
if (!episodeAvail[episode - 1]) |
{ |
JE_playSampleNum(S_SPRING); |
break; |
} |
JE_playSampleNum(S_SELECT); |
fade_black(10); |
JE_initEpisode(episode); |
initial_episode_num = episodeNum; |
return true; |
case SDLK_ESCAPE: |
JE_playSampleNum(S_SPRING); |
/* fading handled elsewhere |
fade_black(10); */ |
return false; |
default: |
break; |
} |
} |
} |
} |
bool select_difficulty( void ) |
{ |
JE_loadPic(VGAScreen, 2, false); |
JE_dString(VGAScreen, JE_fontCenter(difficulty_name[0], FONT_SHAPES), 20, difficulty_name[0], FONT_SHAPES); |
difficultyLevel = 2; |
int difficulty_max = 3; |
bool fade_in = true; |
for (; ; ) |
{ |
for (int i = 1; i <= difficulty_max; i++) |
{ |
JE_outTextAdjust(VGAScreen, JE_fontCenter(difficulty_name[i], SMALL_FONT_SHAPES), i * 24 + 30, difficulty_name[i], 15, -4 + (i == difficultyLevel ? 2 : 0), SMALL_FONT_SHAPES, true); |
} |
JE_showVGA(); |
if (fade_in) |
{ |
fade_palette(colors, 10, 0, 255); |
fade_in = false; |
} |
JE_word temp = 0; |
JE_textMenuWait(&temp, false); |
if (SDL_GetModState() & KMOD_SHIFT) |
{ |
if ((difficulty_max < 4 && keysactive[SDLK_g]) || |
(difficulty_max == 4 && keysactive[SDLK_RIGHTBRACKET])) |
{ |
difficulty_max++; |
} |
} else if (difficulty_max == 5 && keysactive[SDLK_l] && keysactive[SDLK_o] && keysactive[SDLK_r] && keysactive[SDLK_d]) { |
difficulty_max++; |
} |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
difficultyLevel--; |
if (difficultyLevel < 1) |
{ |
difficultyLevel = difficulty_max; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
difficultyLevel++; |
if (difficultyLevel > difficulty_max) |
{ |
difficultyLevel = 1; |
} |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_RETURN: |
JE_playSampleNum(S_SELECT); |
/* fading handled elsewhere |
fade_black(10); */ |
if (difficultyLevel == 6) |
{ |
difficultyLevel = 8; |
} else if (difficultyLevel == 5) { |
difficultyLevel = 6; |
} |
return true; |
case SDLK_ESCAPE: |
JE_playSampleNum(S_SPRING); |
/* fading handled elsewhere |
fade_black(10); */ |
return false; |
default: |
break; |
} |
} |
} |
} |
/contrib/games/opentyrian/src/menus.h |
---|
0,0 → 1,32 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef MENUS_H |
#define MENUS_H |
#include "opentyr.h" |
#define GAMEPLAY_NAME_COUNT 5 |
extern char episode_name[6][31], difficulty_name[7][21], gameplay_name[GAMEPLAY_NAME_COUNT][26]; |
bool select_gameplay( void ); |
bool select_episode( void ); |
bool select_difficulty( void ); |
#endif /* MENUS_H */ |
/contrib/games/opentyrian/src/mouse.c |
---|
0,0 → 1,115 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "mouse.h" |
#include "keyboard.h" |
#include "nortvars.h" |
#include "sprite.h" |
#include "video.h" |
#include "vga256d.h" |
#if defined(TARGET_GP2X) || defined(TARGET_DINGUX) |
bool has_mouse = false; |
#else |
bool has_mouse = true; |
#endif |
bool mouse_has_three_buttons = true; |
JE_word lastMouseX, lastMouseY; |
JE_byte mouseCursor; |
JE_word mouseX, mouseY, mouseButton; |
JE_word mouseXB, mouseYB; |
JE_byte mouseGrabShape[24 * 28]; /* [1..24*28] */ |
void JE_drawShapeTypeOne( JE_word x, JE_word y, JE_byte *shape ) |
{ |
JE_word xloop = 0, yloop = 0; |
JE_byte *p = shape; /* shape pointer */ |
Uint8 *s; /* screen pointer, 8-bit specific */ |
Uint8 *s_limit; /* buffer boundary */ |
s = (Uint8 *)VGAScreen->pixels; |
s += y * VGAScreen->pitch + x; |
s_limit = (Uint8 *)VGAScreen->pixels; |
s_limit += VGAScreen->h * VGAScreen->pitch; |
for (yloop = 0; yloop < 28; yloop++) |
{ |
for (xloop = 0; xloop < 24; xloop++) |
{ |
if (s >= s_limit) return; |
*s = *p; |
s++; p++; |
} |
s -= 24; |
s += VGAScreen->pitch; |
} |
} |
void JE_grabShapeTypeOne( JE_word x, JE_word y, JE_byte *shape ) |
{ |
JE_word xloop = 0, yloop = 0; |
JE_byte *p = shape; /* shape pointer */ |
Uint8 *s; /* screen pointer, 8-bit specific */ |
Uint8 *s_limit; /* buffer boundary */ |
s = (Uint8 *)VGAScreen->pixels; |
s += y * VGAScreen->pitch + x; |
s_limit = (Uint8 *)VGAScreen->pixels; |
s_limit += VGAScreen->h * VGAScreen->pitch; |
for (yloop = 0; yloop < 28; yloop++) |
{ |
for (xloop = 0; xloop < 24; xloop++) |
{ |
if (s >= s_limit) return; |
*p = *s; |
s++; p++; |
} |
s -= 24; |
s += VGAScreen->pitch; |
} |
} |
void JE_mouseStart( void ) |
{ |
const JE_word mouseCursorGr[3] /* [1..3] */ = {273, 275, 277}; |
if (has_mouse) |
{ |
service_SDL_events(false); |
mouseButton = mousedown ? lastmouse_but : 0; /* incorrect, possibly unimportant */ |
lastMouseX = MIN(mouse_x, 320 - 13); |
lastMouseY = MIN(mouse_y, 200 - 16); |
JE_grabShapeTypeOne(lastMouseX, lastMouseY, mouseGrabShape); |
blit_sprite2x2(VGAScreen, lastMouseX, lastMouseY, shapes6, mouseCursorGr[mouseCursor]); |
} |
} |
void JE_mouseReplace( void ) |
{ |
if (has_mouse) |
JE_drawShapeTypeOne(lastMouseX, lastMouseY, mouseGrabShape); |
} |
/contrib/games/opentyrian/src/mouse.h |
---|
0,0 → 1,43 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef MOUSE_H |
#define MOUSE_H |
#include "opentyr.h" |
#include "SDL.h" |
extern bool has_mouse; |
extern bool mouse_has_three_buttons; |
extern JE_word lastMouseX, lastMouseY; |
extern JE_byte mouseCursor; |
extern JE_word mouseX, mouseY, mouseButton; |
extern JE_word mouseXB, mouseYB; |
extern JE_byte mouseGrabShape[24 * 28]; |
void JE_drawShapeTypeOne( JE_word x, JE_word y, JE_byte *shape ); |
void JE_grabShapeTypeOne( JE_word x, JE_word y, JE_byte *shape ); |
void JE_mouseStart( void ); |
void JE_mouseReplace( void ); |
#endif /* MOUSE_H */ |
/contrib/games/opentyrian/src/mtrand.c |
---|
0,0 → 1,107 |
/* |
Copyright (C) 1997--2004, Makoto Matsumoto, Takuji Nishimura, and |
Eric Landry; All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions |
are met: |
1. Redistributions of source code must retain the above copyright |
notice, this list of conditions and the following disclaimer. |
2. Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer |
in the documentation and/or other materials provided with the |
distribution. |
3. The names of its contributors may not be used to endorse or |
promote products derived from this software without specific |
prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Any feedback is very welcome. |
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html |
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) |
Reference: M. Matsumoto and T. Nishimura, "Mersenne Twister: |
A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number |
Generator", ACM Transactions on Modeling and Computer Simulation, |
Vol. 8, No. 1, January 1998, pp 3--30. |
*/ |
#include "mtrand.h" |
/* Period parameters */ |
#define N 624 |
#define M 397 |
#define MATRIX_A 0x9908b0dfUL /* constant vector a */ |
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ |
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ |
static unsigned long x[N]; /* the array for the state vector */ |
static unsigned long *p0, *p1, *pm; |
void mt_srand( unsigned long s ) |
{ |
int i; |
x[0] = s & 0xffffffffUL; |
for (i = 1; i < N; ++i) { |
x[i] = (1812433253UL * (x[i - 1] ^ (x[i - 1] >> 30)) + i) |
& 0xffffffffUL; /* for >32 bit machines */ |
} |
p0 = x; |
p1 = x + 1; |
pm = x + M; |
} |
/* generates a random number on the interval [0,0xffffffff] */ |
unsigned long mt_rand( void ) |
{ |
unsigned long y; |
if (!p0) { |
/* Default seed */ |
mt_srand(5489UL); |
} |
/* Twisted feedback */ |
y = *p0 = *pm++ ^ (((*p0 & UPPER_MASK) | (*p1 & LOWER_MASK)) >> 1) ^ ((~(*p1 & 1)+1) & MATRIX_A); |
p0 = p1++; |
if (pm == x + N) { |
pm = x; |
} |
if (p1 == x + N) { |
p1 = x; |
} |
/* Temper */ |
y ^= y >> 11; |
y ^= y << 7 & 0x9d2c5680UL; |
y ^= y << 15 & 0xefc60000UL; |
y ^= y >> 18; |
return y; |
} |
/* generates a random number on the interval [0,1]. */ |
float mt_rand_1( void ) |
{ |
return ((float)mt_rand() / (float)MT_RAND_MAX); |
} |
/* generates a random number on the interval [0,1). */ |
float mt_rand_lt1( void ) |
{ |
/* MT_RAND_MAX must be a float before adding one to it! */ |
return ((float)mt_rand() / ((float)MT_RAND_MAX + 1.0f)); |
} |
/contrib/games/opentyrian/src/mtrand.h |
---|
0,0 → 1,30 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef MTRAND_H |
#define MTRAND_H |
#define MT_RAND_MAX 0xffffffffUL |
void mt_srand( unsigned long s ); |
unsigned long mt_rand( void ); |
float mt_rand_1( void ); |
float mt_rand_lt1( void ); |
#endif /* MTRAND_H */ |
/contrib/games/opentyrian/src/musmast.c |
---|
0,0 → 1,116 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "musmast.h" |
#include "opentyr.h" |
JE_byte songBuy; |
const char musicFile[MUSIC_NUM][13] = |
{ |
/* 1 */ "ASTEROI2.DAT", |
/* 2 */ "ASTEROID.DAT", |
/* 3 */ "BUY.DAT", |
/* 4 */ "CAMANIS.DAT", |
/* 5 */ "CAMANISE.DAT", |
/* 6 */ "DELIANI.DAT", |
/* 7 */ "DELIANI2.DAT", |
/* 8 */ "ENDING1.DAT", |
/* 9 */ "ENDING2.DAT", |
/* 10 */ "ENDLEVEL.DAT", |
/* 11 */ "GAMEOVER.DAT", |
/* 12 */ "GRYPHON.DAT", |
/* 13 */ "GRYPHONE.DAT", |
/* 14 */ "GYGES.DAT", |
/* 15 */ "GYGESE.DAT", |
/* 16 */ "HALLOWS.DAT", |
/* 17 */ "ZICA.DAT", |
/* 18 */ "TYRSONG2.DAT", |
/* 19 */ "LOUDNESS.DAT", |
/* 20 */ "NAVC.DAT", |
/* 21 */ "SAVARA.DAT", |
/* 22 */ "SAVARAE.DAT", |
/* 23 */ "SPACE1.DAT", |
/* 24 */ "SPACE2.DAT", |
/* 25 */ "STARENDB.DAT", |
/* 26 */ "START5.DAT", |
/* 27 */ "TALK.DAT", |
/* 28 */ "TORM.DAT", |
/* 29 */ "TRANSON.DAT", |
/* 30 */ "TYRSONG.DAT", |
/* 31 */ "ZANAC3.DAT", |
/* 32 */ "ZANACS.DAT", |
/* 33 */ "SAVARA2.DAT", |
/* 34 */ "HISCORE.DAT", |
/* 35 */ "TYR4-1.DAT", /* OMF */ |
/* 36 */ "TYR4-3.DAT", /* SARAH */ |
/* 37 */ "TYR4-2.DAT", /* MAGFIELD */ |
/* 38 */ "TYR4-0.DAT", /* ROCKME */ |
/* 39 */ "TYR4-4.DAT", /* quiet music */ |
/* 40 */ "TYR4-5.DAT", /* piano */ |
/* 41 */ "TYR-BEER.DAT" /* BEER */ |
}; |
const char musicTitle[MUSIC_NUM][48] = |
{ |
"Asteroid Dance Part 2", |
"Asteroid Dance Part 1", |
"Buy/Sell Music", |
"CAMANIS", |
"CAMANISE", |
"Deli Shop Quartet", |
"Deli Shop Quartet No. 2", |
"Ending Number 1", |
"Ending Number 2", |
"End of Level", |
"Game Over Solo", |
"Gryphons of the West", |
"Somebody pick up the Gryphone", |
"Gyges, Will You Please Help Me?", |
"I speak Gygese", |
"Halloween Ramble", |
"Tunneling Trolls", |
"Tyrian, The Level", |
"The MusicMan", |
"The Navigator", |
"Come Back to Me, Savara", |
"Come Back again to Savara", |
"Space Journey 1", |
"Space Journey 2", |
"The final edge", |
"START5", |
"Parlance", |
"Torm - The Gathering", |
"TRANSON", |
"Tyrian: The Song", |
"ZANAC3", |
"ZANACS", |
"Return me to Savara", |
"High Score Table", |
"One Mustn't Fall", |
"Sarah's Song", |
"A Field for Mag", |
"Rock Garden", |
"Quest for Peace", |
"Composition in Q", |
"BEER" |
}; |
JE_boolean musicFade; |
/contrib/games/opentyrian/src/musmast.h |
---|
0,0 → 1,41 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef MUSMAST_H |
#define MUSMAST_H |
#include "opentyr.h" |
#define DEFAULT_SONG_BUY 2 |
#define SONG_LEVELEND 9 |
#define SONG_GAMEOVER 10 |
#define SONG_MAPVIEW 19 |
#define SONG_ENDGAME1 7 |
#define SONG_ZANAC 31 |
#define SONG_TITLE 29 |
#define MUSIC_NUM 41 |
extern JE_byte songBuy; |
extern const char musicFile[MUSIC_NUM][13]; |
extern const char musicTitle[MUSIC_NUM][48]; |
extern JE_boolean musicFade; |
#endif /* MUSMAST_H */ |
/contrib/games/opentyrian/src/network.c |
---|
0,0 → 1,791 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "network.h" |
#include "episodes.h" |
#include "fonthand.h" |
#include "helptext.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "mainint.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "picload.h" |
#include "sprite.h" |
#include "varz.h" |
#include "video.h" |
#include <assert.h> |
/* HERE BE DRAGONS! |
* |
* When I wrote this code I thought it was wonderful... that thought was very |
* wrong. It works, but good luck understanding how... I don't anymore. |
* |
* Hopefully it'll be rewritten some day. |
*/ |
#define NET_VERSION 2 // increment whenever networking changes might create incompatability |
#define NET_PORT 1333 // UDP |
#define NET_PACKET_SIZE 256 |
#define NET_PACKET_QUEUE 16 |
#define NET_RETRY 640 // ticks to wait for packet acknowledgement before resending |
#define NET_RESEND 320 // ticks to wait before requesting unreceived game packet |
#define NET_KEEP_ALIVE 1600 // ticks to wait between keep-alive packets |
#define NET_TIME_OUT 16000 // ticks to wait before considering connection dead |
bool isNetworkGame = false; |
int network_delay = 1 + 1; // minimum is 1 + 0 |
char *network_opponent_host = NULL; |
Uint16 network_player_port = NET_PORT, |
network_opponent_port = NET_PORT; |
static char empty_string[] = ""; |
char *network_player_name = empty_string, |
*network_opponent_name = empty_string; |
#ifdef WITH_NETWORK |
static UDPsocket socket; |
static IPaddress ip; |
UDPpacket *packet_out_temp; |
static UDPpacket *packet_temp; |
UDPpacket *packet_in[NET_PACKET_QUEUE] = { NULL }, |
*packet_out[NET_PACKET_QUEUE] = { NULL }; |
static Uint16 last_out_sync = 0, queue_in_sync = 0, queue_out_sync = 0, last_ack_sync = 0; |
static Uint32 last_in_tick = 0, last_out_tick = 0; |
UDPpacket *packet_state_in[NET_PACKET_QUEUE] = { NULL }; |
static UDPpacket *packet_state_in_xor[NET_PACKET_QUEUE] = { NULL }; |
UDPpacket *packet_state_out[NET_PACKET_QUEUE] = { NULL }; |
static Uint16 last_state_in_sync = 0, last_state_out_sync = 0; |
static Uint32 last_state_in_tick = 0; |
static bool net_initialized = false; |
static bool connected = false, quit = false; |
#endif |
uint thisPlayerNum = 0; /* Player number on this PC (1 or 2) */ |
JE_boolean haltGame = false; |
JE_boolean moveOk; |
/* Special Requests */ |
JE_boolean pauseRequest, skipLevelRequest, helpRequest, nortShipRequest; |
JE_boolean yourInGameMenuRequest, inGameMenuRequest; |
#ifdef WITH_NETWORK |
static void packet_copy( UDPpacket *dst, UDPpacket *src ) |
{ |
void *temp = dst->data; |
memcpy(dst, src, sizeof(*dst)); |
dst->data = temp; |
memcpy(dst->data, src->data, src->len); |
} |
static void packets_shift_up( UDPpacket **packet, int max_packets ) |
{ |
if (packet[0]) |
{ |
SDLNet_FreePacket(packet[0]); |
} |
for (int i = 0; i < max_packets - 1; i++) |
{ |
packet[i] = packet[i + 1]; |
} |
packet[max_packets - 1] = NULL; |
} |
static void packets_shift_down( UDPpacket **packet, int max_packets ) |
{ |
if (packet[max_packets - 1]) |
{ |
SDLNet_FreePacket(packet[max_packets - 1]); |
} |
for (int i = max_packets - 1; i > 0; i--) |
{ |
packet[i] = packet[i - 1]; |
} |
packet[0] = NULL; |
} |
// prepare new packet for sending |
void network_prepare( Uint16 type ) |
{ |
SDLNet_Write16(type, &packet_out_temp->data[0]); |
SDLNet_Write16(last_out_sync, &packet_out_temp->data[2]); |
} |
// send packet but don't expect acknoledgment of delivery |
static bool network_send_no_ack( int len ) |
{ |
packet_out_temp->len = len; |
if (!SDLNet_UDP_Send(socket, 0, packet_out_temp)) |
{ |
printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); |
return false; |
} |
return true; |
} |
// send packet and place it in queue to be acknowledged |
bool network_send( int len ) |
{ |
bool temp = network_send_no_ack(len); |
Uint16 i = last_out_sync - queue_out_sync; |
if (i < NET_PACKET_QUEUE) |
{ |
packet_out[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_out[i], packet_out_temp); |
} else { |
// connection is probably bad now |
fprintf(stderr, "warning: outbound packet queue overflow\n"); |
return false; |
} |
last_out_sync++; |
if (network_is_sync()) |
last_out_tick = SDL_GetTicks(); |
return temp; |
} |
// send acknowledgement packet |
static int network_acknowledge( Uint16 sync ) |
{ |
SDLNet_Write16(PACKET_ACKNOWLEDGE, &packet_out_temp->data[0]); |
SDLNet_Write16(sync, &packet_out_temp->data[2]); |
network_send_no_ack(4); |
return 0; |
} |
// activity lately? |
static bool network_is_alive( void ) |
{ |
return (SDL_GetTicks() - last_in_tick < NET_TIME_OUT || SDL_GetTicks() - last_state_in_tick < NET_TIME_OUT); |
} |
// poll for new packets received, check that connection is alive, resend queued packets if necessary |
int network_check( void ) |
{ |
if (!net_initialized) |
return -1; |
if (connected) |
{ |
// timeout |
if (!network_is_alive()) |
{ |
if (!quit) |
network_tyrian_halt(2, false); |
} |
// keep-alive |
static Uint32 keep_alive_tick = 0; |
if (SDL_GetTicks() - keep_alive_tick > NET_KEEP_ALIVE) |
{ |
network_prepare(PACKET_KEEP_ALIVE); |
network_send_no_ack(4); |
keep_alive_tick = SDL_GetTicks(); |
} |
} |
// retry |
if (packet_out[0] && SDL_GetTicks() - last_out_tick > NET_RETRY) |
{ |
if (!SDLNet_UDP_Send(socket, 0, packet_out[0])) |
{ |
printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); |
return -1; |
} |
last_out_tick = SDL_GetTicks(); |
} |
switch (SDLNet_UDP_Recv(socket, packet_temp)) |
{ |
case -1: |
printf("SDLNet_UDP_Recv: %s\n", SDL_GetError()); |
return -1; |
break; |
case 0: |
break; |
default: |
if (packet_temp->channel == 0 && packet_temp->len >= 4) |
{ |
switch (SDLNet_Read16(&packet_temp->data[0])) |
{ |
case PACKET_ACKNOWLEDGE: |
if ((Uint16)(SDLNet_Read16(&packet_temp->data[2]) - last_ack_sync) < NET_PACKET_QUEUE) |
{ |
last_ack_sync = SDLNet_Read16(&packet_temp->data[2]); |
} |
{ |
Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_out_sync; |
if (i < NET_PACKET_QUEUE) |
{ |
if (packet_out[i]) |
{ |
SDLNet_FreePacket(packet_out[i]); |
packet_out[i] = NULL; |
} |
} |
} |
// remove acknowledged packets from queue |
while (packet_out[0] == NULL && (Uint16)(last_ack_sync - queue_out_sync) < NET_PACKET_QUEUE) |
{ |
packets_shift_up(packet_out, NET_PACKET_QUEUE); |
queue_out_sync++; |
} |
last_in_tick = SDL_GetTicks(); |
break; |
case PACKET_CONNECT: |
queue_in_sync = SDLNet_Read16(&packet_temp->data[2]); |
for (int i = 0; i < NET_PACKET_QUEUE; i++) |
{ |
if (packet_in[i]) |
{ |
SDLNet_FreePacket(packet_in[i]); |
packet_in[i] = NULL; |
} |
} |
// fall through |
case PACKET_DETAILS: |
case PACKET_WAITING: |
case PACKET_BUSY: |
case PACKET_GAME_QUIT: |
case PACKET_GAME_PAUSE: |
case PACKET_GAME_MENU: |
{ |
Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_in_sync; |
if (i < NET_PACKET_QUEUE) |
{ |
if (packet_in[i] == NULL) |
packet_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_in[i], packet_temp); |
} else { |
// inbound packet queue overflow/underflow |
// under normal circumstances, this is okay |
} |
} |
network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); |
// fall through |
case PACKET_KEEP_ALIVE: |
last_in_tick = SDL_GetTicks(); |
break; |
case PACKET_QUIT: |
if (!quit) |
{ |
network_prepare(PACKET_QUIT); |
network_send(4); // PACKET_QUIT |
} |
network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); |
if (!quit) |
network_tyrian_halt(1, true); |
break; |
case PACKET_STATE: |
// place packet in queue if within limits |
{ |
Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; |
if (i < NET_PACKET_QUEUE) |
{ |
if (packet_state_in[i] == NULL) |
packet_state_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_state_in[i], packet_temp); |
} |
} |
break; |
case PACKET_STATE_XOR: |
// place packet in queue if within limits |
{ |
Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; |
if (i < NET_PACKET_QUEUE) |
{ |
if (packet_state_in_xor[i] == NULL) |
{ |
packet_state_in_xor[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_state_in_xor[i], packet_temp); |
} else if (SDLNet_Read16(&packet_state_in_xor[i]->data[0]) != PACKET_STATE_XOR) { |
for (int j = 4; j < packet_state_in_xor[i]->len; j++) |
packet_state_in_xor[i]->data[j] ^= packet_temp->data[j]; |
SDLNet_Write16(PACKET_STATE_XOR, &packet_state_in_xor[i]->data[0]); |
} |
} |
} |
break; |
case PACKET_STATE_RESEND: |
// resend requested state packet if still available |
{ |
Uint16 i = last_state_out_sync - SDLNet_Read16(&packet_temp->data[2]); |
if (i > 0 && i < NET_PACKET_QUEUE) |
{ |
if (packet_state_out[i]) |
{ |
if (!SDLNet_UDP_Send(socket, 0, packet_state_out[i])) |
{ |
printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); |
return -1; |
} |
} |
} |
} |
break; |
default: |
fprintf(stderr, "warning: bad packet %d received\n", SDLNet_Read16(&packet_temp->data[0])); |
return 0; |
break; |
} |
return 1; |
} |
break; |
} |
return 0; |
} |
// discard working packet, now processing next packet in queue |
bool network_update( void ) |
{ |
if (packet_in[0]) |
{ |
packets_shift_up(packet_in, NET_PACKET_QUEUE); |
queue_in_sync++; |
return true; |
} |
return false; |
} |
// has opponent gotten all the packets we've sent? |
bool network_is_sync( void ) |
{ |
return (queue_out_sync - last_ack_sync == 1); |
} |
// prepare new state for sending |
void network_state_prepare( void ) |
{ |
if (packet_state_out[0]) |
{ |
fprintf(stderr, "warning: state packet overwritten (previous packet remains unsent)\n"); |
} else { |
packet_state_out[0] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_state_out[0]->len = 28; |
} |
SDLNet_Write16(PACKET_STATE, &packet_state_out[0]->data[0]); |
SDLNet_Write16(last_state_out_sync, &packet_state_out[0]->data[2]); |
memset(&packet_state_out[0]->data[4], 0, 28 - 4); |
} |
// send state packet, xor packet if applicable |
int network_state_send( void ) |
{ |
if (!SDLNet_UDP_Send(socket, 0, packet_state_out[0])) |
{ |
printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); |
return -1; |
} |
// send xor of last network_delay packets |
if (network_delay > 1 && (last_state_out_sync + 1) % network_delay == 0 && packet_state_out[network_delay - 1] != NULL) |
{ |
packet_copy(packet_temp, packet_state_out[0]); |
SDLNet_Write16(PACKET_STATE_XOR, &packet_temp->data[0]); |
for (int i = 1; i < network_delay; i++) |
for (int j = 4; j < packet_temp->len; j++) |
packet_temp->data[j] ^= packet_state_out[i]->data[j]; |
if (!SDLNet_UDP_Send(socket, 0, packet_temp)) |
{ |
printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); |
return -1; |
} |
} |
packets_shift_down(packet_state_out, NET_PACKET_QUEUE); |
last_state_out_sync++; |
return 0; |
} |
// receive state packet, wait until received |
bool network_state_update( void ) |
{ |
if (network_state_is_reset()) |
{ |
return 0; |
} else { |
packets_shift_up(packet_state_in, NET_PACKET_QUEUE); |
packets_shift_up(packet_state_in_xor, NET_PACKET_QUEUE); |
last_state_in_sync++; |
// current xor packet index |
int x = network_delay - (last_state_in_sync - 1) % network_delay - 1; |
// loop until needed packet is available |
while (!packet_state_in[0]) |
{ |
// xor the packet from thin air, if possible |
if (packet_state_in_xor[x] && SDLNet_Read16(&packet_state_in_xor[x]->data[0]) == PACKET_STATE_XOR) |
{ |
// check for all other required packets |
bool okay = true; |
for (int i = 1; i <= x; i++) |
{ |
if (packet_state_in[i] == NULL) |
{ |
okay = false; |
break; |
} |
} |
if (okay) |
{ |
packet_state_in[0] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_state_in[0], packet_state_in_xor[x]); |
for (int i = 1; i <= x; i++) |
for (int j = 4; j < packet_state_in[0]->len; j++) |
packet_state_in[0]->data[j] ^= packet_state_in[i]->data[j]; |
break; |
} |
} |
static Uint32 resend_tick = 0; |
if (SDL_GetTicks() - last_state_in_tick > NET_RESEND && SDL_GetTicks() - resend_tick > NET_RESEND) |
{ |
SDLNet_Write16(PACKET_STATE_RESEND, &packet_out_temp->data[0]); |
SDLNet_Write16(last_state_in_sync - 1, &packet_out_temp->data[2]); |
network_send_no_ack(4); // PACKET_RESEND |
resend_tick = SDL_GetTicks(); |
} |
if (network_check() == 0) |
uSDL_Delay(1); |
} |
if (network_delay > 1) |
{ |
// process the current in packet against the xor queue |
if (packet_state_in_xor[x] == NULL) |
{ |
packet_state_in_xor[x] = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_copy(packet_state_in_xor[x], packet_state_in[0]); |
packet_state_in_xor[x]->status = 0; |
} else { |
for (int j = 4; j < packet_state_in_xor[x]->len; j++) |
packet_state_in_xor[x]->data[j] ^= packet_state_in[0]->data[j]; |
} |
} |
last_state_in_tick = SDL_GetTicks(); |
} |
return 1; |
} |
// ignore first network_delay states of level |
bool network_state_is_reset( void ) |
{ |
return (last_state_out_sync < network_delay); |
} |
// reset queues for new level |
void network_state_reset( void ) |
{ |
last_state_in_sync = last_state_out_sync = 0; |
for (int i = 0; i < NET_PACKET_QUEUE; i++) |
{ |
if (packet_state_in[i]) |
{ |
SDLNet_FreePacket(packet_state_in[i]); |
packet_state_in[i] = NULL; |
} |
} |
for (int i = 0; i < NET_PACKET_QUEUE; i++) |
{ |
if (packet_state_in_xor[i]) |
{ |
SDLNet_FreePacket(packet_state_in_xor[i]); |
packet_state_in_xor[i] = NULL; |
} |
} |
for (int i = 0; i < NET_PACKET_QUEUE; i++) |
{ |
if (packet_state_out[i]) |
{ |
SDLNet_FreePacket(packet_state_out[i]); |
packet_state_out[i] = NULL; |
} |
} |
last_state_in_tick = SDL_GetTicks(); |
} |
// attempt to punch through firewall by firing off UDP packets at the opponent |
// exchange game information |
int network_connect( void ) |
{ |
SDLNet_ResolveHost(&ip, network_opponent_host, network_opponent_port); |
SDLNet_UDP_Bind(socket, 0, &ip); |
Uint16 episodes = 0, episodes_local = 0; |
assert(EPISODE_MAX <= 16); |
for (int i = EPISODE_MAX - 1; i >= 0; i--) |
{ |
episodes <<= 1; |
episodes |= (episodeAvail[i] != 0); |
} |
episodes_local = episodes; |
assert(NET_PACKET_SIZE - 12 >= 20 + 1); |
if (strlen(network_player_name) > 20) |
network_player_name[20] = '\0'; |
connect_reset: |
network_prepare(PACKET_CONNECT); |
SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); |
SDLNet_Write16(network_delay, &packet_out_temp->data[6]); |
SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); |
SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); |
strcpy((char *)&packet_out_temp->data[12], network_player_name); |
network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT |
// until opponent sends connect packet |
while (true) |
{ |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
if (newkey && lastkey_sym == SDLK_ESCAPE) |
network_tyrian_halt(0, false); |
// never timeout |
last_in_tick = SDL_GetTicks(); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) |
break; |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
connect_again: |
if (SDLNet_Read16(&packet_in[0]->data[4]) != NET_VERSION) |
{ |
fprintf(stderr, "error: network version did not match opponent's\n"); |
network_tyrian_halt(4, true); |
} |
if (SDLNet_Read16(&packet_in[0]->data[6]) != network_delay) |
{ |
fprintf(stderr, "error: network delay did not match opponent's\n"); |
network_tyrian_halt(5, true); |
} |
if (SDLNet_Read16(&packet_in[0]->data[10]) == thisPlayerNum) |
{ |
fprintf(stderr, "error: player number conflicts with opponent's\n"); |
network_tyrian_halt(6, true); |
} |
episodes = SDLNet_Read16(&packet_in[0]->data[8]); |
for (int i = 0; i < EPISODE_MAX; i++) { |
episodeAvail[i] &= (episodes & 1); |
episodes >>= 1; |
} |
network_opponent_name = malloc(packet_in[0]->len - 12 + 1); |
strcpy(network_opponent_name, (char *)&packet_in[0]->data[12]); |
network_update(); |
// until opponent has acknowledged |
while (!network_is_sync()) |
{ |
service_SDL_events(false); |
// got a duplicate packet; process it again (but why?) |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) |
goto connect_again; |
network_check(); |
// maybe opponent didn't get our packet |
if (SDL_GetTicks() - last_out_tick > NET_RETRY) |
goto connect_reset; |
uSDL_Delay(16); |
} |
// send another packet since sometimes the network syncs without both connect packets exchanged |
// there should be a better way to handle this |
network_prepare(PACKET_CONNECT); |
SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); |
SDLNet_Write16(network_delay, &packet_out_temp->data[6]); |
SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); |
SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); |
strcpy((char *)&packet_out_temp->data[12], network_player_name); |
network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT |
connected = true; |
return 0; |
} |
// something has gone wrong :( |
void network_tyrian_halt( unsigned int err, bool attempt_sync ) |
{ |
const char *err_msg[] = { |
"Quitting...", |
"Other player quit the game.", |
"Network connection was lost.", |
"Network connection failed.", |
"Network version mismatch.", |
"Network delay mismatch.", |
"Network player number conflict.", |
}; |
quit = true; |
if (err >= COUNTOF(err_msg)) |
err = 0; |
fade_black(10); |
VGAScreen = VGAScreenSeg; |
JE_loadPic(VGAScreen, 2, false); |
JE_dString(VGAScreen, JE_fontCenter(err_msg[err], SMALL_FONT_SHAPES), 140, err_msg[err], SMALL_FONT_SHAPES); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
if (attempt_sync) |
{ |
while (!network_is_sync() && network_is_alive()) |
{ |
service_SDL_events(false); |
network_check(); |
uSDL_Delay(16); |
} |
} |
if (err) |
{ |
while (!JE_anyButton()) |
uSDL_Delay(16); |
} |
fade_black(10); |
SDLNet_Quit(); |
JE_tyrianHalt(5); |
} |
int network_init( void ) |
{ |
printf("Initializing network...\n"); |
if (network_delay * 2 > NET_PACKET_QUEUE - 2) |
{ |
fprintf(stderr, "error: network delay would overflow packet queue\n"); |
return -4; |
} |
if (SDLNet_Init() == -1) |
{ |
fprintf(stderr, "error: SDLNet_Init: %s\n", SDLNet_GetError()); |
return -1; |
} |
socket = SDLNet_UDP_Open(network_player_port); |
if (!socket) |
{ |
fprintf(stderr, "error: SDLNet_UDP_Open: %s\n", SDLNet_GetError()); |
return -2; |
} |
packet_temp = SDLNet_AllocPacket(NET_PACKET_SIZE); |
packet_out_temp = SDLNet_AllocPacket(NET_PACKET_SIZE); |
if (!packet_temp || !packet_out_temp) |
{ |
printf("SDLNet_AllocPacket: %s\n", SDLNet_GetError()); |
return -3; |
} |
net_initialized = true; |
return 0; |
} |
#endif |
void JE_clearSpecialRequests( void ) |
{ |
pauseRequest = false; |
inGameMenuRequest = false; |
skipLevelRequest = false; |
helpRequest = false; |
nortShipRequest = false; |
} |
/contrib/games/opentyrian/src/network.h |
---|
0,0 → 1,101 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef NETWORK_H |
#define NETWORK_H |
#include "opentyr.h" |
#include "SDL.h" |
#ifdef WITH_NETWORK |
# include "SDL_net.h" |
#endif |
#define PACKET_ACKNOWLEDGE 0x00 // |
#define PACKET_KEEP_ALIVE 0x01 // |
#define PACKET_CONNECT 0x10 // version, delay, episodes, player_number, name |
#define PACKET_DETAILS 0x11 // episode, difficulty |
#define PACKET_QUIT 0x20 // |
#define PACKET_WAITING 0x21 // |
#define PACKET_BUSY 0x22 // |
#define PACKET_GAME_QUIT 0x30 // |
#define PACKET_GAME_PAUSE 0x31 // |
#define PACKET_GAME_MENU 0x32 // |
#define PACKET_STATE_RESEND 0x40 // state_id |
#define PACKET_STATE 0x41 // <state> (not acknowledged) |
#define PACKET_STATE_XOR 0x42 // <xor state> (not acknowledged) |
extern bool isNetworkGame; |
extern int network_delay; |
extern char *network_opponent_host; |
extern Uint16 network_player_port, network_opponent_port; |
extern char *network_player_name, *network_opponent_name; |
#ifdef WITH_NETWORK |
extern UDPpacket *packet_out_temp; |
extern UDPpacket *packet_in[], *packet_out[], |
*packet_state_in[], *packet_state_out[]; |
#endif |
extern uint thisPlayerNum; |
extern JE_boolean haltGame; |
extern JE_boolean moveOk; |
extern JE_boolean pauseRequest, skipLevelRequest, helpRequest, nortShipRequest; |
extern JE_boolean yourInGameMenuRequest, inGameMenuRequest; |
#ifdef WITH_NETWORK |
void network_prepare( Uint16 type ); |
bool network_send( int len ); |
int network_check( void ); |
bool network_update( void ); |
bool network_is_sync( void ); |
void network_state_prepare( void ); |
int network_state_send( void ); |
bool network_state_update( void ); |
bool network_state_is_reset( void ); |
void network_state_reset( void ); |
int network_connect( void ); |
void network_tyrian_halt( unsigned int err, bool attempt_sync ); |
int network_init( void ); |
void JE_clearSpecialRequests( void ); |
#define NETWORK_KEEP_ALIVE() \ |
if (isNetworkGame) \ |
network_check(); |
#else |
#define NETWORK_KEEP_ALIVE() |
#endif |
#endif /* NETWORK_H */ |
/contrib/games/opentyrian/src/nortsong.c |
---|
0,0 → 1,225 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "nortsong.h" |
#include "file.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "loudness.h" |
#include "musmast.h" |
#include "opentyr.h" |
#include "params.h" |
#include "sndmast.h" |
#include "vga256d.h" |
#include "SDL.h" |
Uint32 target, target2; |
JE_boolean notYetLoadedSound = true; |
JE_word frameCount, frameCount2, frameCountMax; |
JE_byte *digiFx[SAMPLE_COUNT] = { NULL }; /* [1..soundnum + 9] */ |
JE_word fxSize[SAMPLE_COUNT]; /* [1..soundnum + 9] */ |
JE_word tyrMusicVolume, fxVolume; |
JE_word fxPlayVol; |
JE_word tempVolume; |
JE_word speed; /* JE: holds timer speed for 70Hz */ |
float jasondelay = 1000.0f / (1193180.0f / 0x4300); |
void setdelay( JE_byte delay ) |
{ |
target = (delay * 16) + SDL_GetTicks(); |
} |
void setjasondelay( int delay ) |
{ |
target = SDL_GetTicks() + delay * jasondelay; |
} |
void setjasondelay2( int delay ) |
{ |
target2 = SDL_GetTicks() + delay * jasondelay; |
} |
int delaycount( void ) |
{ |
return (SDL_GetTicks() < target ? target - SDL_GetTicks() : 0); |
} |
int delaycount2( void ) |
{ |
return (SDL_GetTicks() < target2 ? target2 - SDL_GetTicks() : 0); |
} |
void wait_delay( void ) |
{ |
Sint32 delay = target - SDL_GetTicks(); |
if (delay > 0) |
uSDL_Delay(delay); |
} |
void service_wait_delay( void ) |
{ |
while (SDL_GetTicks() < target) |
{ |
uSDL_Delay(SDL_GetTicks() - target > SDL_POLL_INTERVAL ? SDL_POLL_INTERVAL : SDL_GetTicks() - target); |
service_SDL_events(false); |
} |
} |
void wait_delayorinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) |
{ |
service_SDL_events(true); |
while (SDL_GetTicks() < target && !((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown))) |
{ |
uSDL_Delay(SDL_GetTicks() - target > SDL_POLL_INTERVAL ? SDL_POLL_INTERVAL : SDL_GetTicks() - target); |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
} |
} |
void JE_loadSndFile( const char *effects_sndfile, const char *voices_sndfile ) |
{ |
JE_byte y, z; |
JE_word x; |
JE_longint templ; |
JE_longint sndPos[2][SAMPLE_COUNT + 1]; |
JE_word sndNum; |
FILE *fi; |
/* SYN: Loading offsets into TYRIAN.SND */ |
fi = dir_fopen_die(data_dir(), effects_sndfile, "rb"); |
efread(&sndNum, sizeof(sndNum), 1, fi); |
for (x = 0; x < sndNum; x++) |
{ |
efread(&sndPos[0][x], sizeof(sndPos[0][x]), 1, fi); |
} |
fseek(fi, 0, SEEK_END); |
sndPos[0][sndNum] = ftell(fi); /* Store file size */ |
for (z = 0; z < sndNum; z++) |
{ |
fseek(fi, sndPos[0][z], SEEK_SET); |
fxSize[z] = (sndPos[0][z+1] - sndPos[0][z]); /* Store sample sizes */ |
free(digiFx[z]); |
digiFx[z] = malloc(fxSize[z]); |
efread(digiFx[z], 1, fxSize[z], fi); /* JE: Load sample to buffer */ |
} |
fclose(fi); |
/* SYN: Loading offsets into VOICES.SND */ |
fi = dir_fopen_die(data_dir(), voices_sndfile, "rb"); |
efread(&sndNum, sizeof(sndNum), 1, fi); |
for (x = 0; x < sndNum; x++) |
{ |
efread(&sndPos[1][x], sizeof(sndPos[1][x]), 1, fi); |
} |
fseek(fi, 0, SEEK_END); |
sndPos[1][sndNum] = ftell(fi); /* Store file size */ |
z = SAMPLE_COUNT - 9; |
for (y = 0; y < sndNum; y++) |
{ |
fseek(fi, sndPos[1][y], SEEK_SET); |
templ = (sndPos[1][y+1] - sndPos[1][y]) - 100; /* SYN: I'm not entirely sure what's going on here. */ |
if (templ < 1) templ = 1; |
fxSize[z + y] = templ; /* Store sample sizes */ |
digiFx[z + y] = malloc(fxSize[z + y]); |
efread(digiFx[z + y], 1, fxSize[z + y], fi); /* JE: Load sample to buffer */ |
} |
fclose(fi); |
notYetLoadedSound = false; |
} |
void JE_playSampleNum( JE_byte samplenum ) |
{ |
JE_multiSamplePlay(digiFx[samplenum-1], fxSize[samplenum-1], 0, fxPlayVol); |
} |
void JE_calcFXVol( void ) // TODO: not sure *exactly* what this does |
{ |
fxPlayVol = (fxVolume - 1) >> 5; |
} |
void JE_setTimerInt( void ) |
{ |
jasondelay = 1000.0f / (1193180.0f / speed); |
} |
void JE_resetTimerInt( void ) |
{ |
jasondelay = 1000.0f / (1193180.0f / 0x4300); |
} |
void JE_changeVolume( JE_word *music, int music_delta, JE_word *sample, int sample_delta ) |
{ |
int music_temp = *music + music_delta, |
sample_temp = *sample + sample_delta; |
if (music_delta) |
{ |
if (music_temp > 255) |
{ |
music_temp = 255; |
JE_playSampleNum(S_CLINK); |
} |
else if (music_temp < 0) |
{ |
music_temp = 0; |
JE_playSampleNum(S_CLINK); |
} |
} |
if (sample_delta) |
{ |
if (sample_temp > 255) |
{ |
sample_temp = 255; |
JE_playSampleNum(S_CLINK); |
} |
else if (sample_temp < 0) |
{ |
sample_temp = 0; |
JE_playSampleNum(S_CLINK); |
} |
} |
*music = music_temp; |
*sample = sample_temp; |
JE_calcFXVol(); |
set_volume(*music, *sample); |
} |
/contrib/games/opentyrian/src/nortsong.h |
---|
0,0 → 1,64 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef NORTSONG_H |
#define NORTSONG_H |
#include "opentyr.h" |
#include "musmast.h" |
#include "sndmast.h" |
#include "SDL.h" |
extern Uint32 target, target2; |
extern JE_word frameCount, frameCount2, frameCountMax; |
extern JE_byte *digiFx[SAMPLE_COUNT]; |
extern JE_word fxSize[SAMPLE_COUNT]; |
extern JE_word tyrMusicVolume, fxVolume; |
extern JE_word fxPlayVol; |
extern JE_word tempVolume; |
extern JE_word speed; |
extern float jasondelay; |
void setdelay( JE_byte delay ); |
void setjasondelay( int delay ); |
void setjasondelay2( int delay ); |
int delaycount( void ); |
int delaycount2( void ); |
void wait_delay( void ); |
void service_wait_delay( void ); |
void wait_delayorinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ); |
void JE_resetTimerInt( void ); |
void JE_setTimerInt( void ); |
void JE_calcFXVol( void ); |
void JE_changeVolume( JE_word *music, int music_delta, JE_word *sample, int sample_delta ); |
void JE_loadSndFile( const char *effects_sndfile, const char *voices_sndfile ); |
void JE_playSampleNum( JE_byte samplenum ); |
#endif /* NORTSONG_H */ |
/contrib/games/opentyrian/src/nortvars.c |
---|
0,0 → 1,88 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "nortvars.h" |
#include "file.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "opentyr.h" |
#include "vga256d.h" |
#include "video.h" |
#include <assert.h> |
#include <ctype.h> |
JE_boolean inputDetected; |
JE_boolean JE_anyButton( void ) |
{ |
poll_joysticks(); |
service_SDL_events(true); |
return newkey || mousedown || joydown; |
} |
void JE_dBar3( SDL_Surface *surface, JE_integer x, JE_integer y, JE_integer num, JE_integer col ) |
{ |
JE_byte z; |
JE_byte zWait = 2; |
col += 2; |
for (z = 0; z <= num; z++) |
{ |
JE_rectangle(surface, x, y - 1, x + 8, y, col); /* <MXD> SEGa000 */ |
if (zWait > 0) |
{ |
zWait--; |
} else { |
col++; |
zWait = 1; |
} |
y -= 2; |
} |
} |
void JE_barDrawShadow( SDL_Surface *surface, JE_word x, JE_word y, JE_word res, JE_word col, JE_word amt, JE_word xsize, JE_word ysize ) |
{ |
xsize--; |
ysize--; |
for (int z = 1; z <= amt / res; z++) |
{ |
JE_barShade(surface, x+2, y+2, x+xsize+2, y+ysize+2); |
fill_rectangle_xy(surface, x, y, x+xsize, y+ysize, col+12); |
fill_rectangle_xy(surface, x, y, x+xsize, y, col+13); |
JE_pix(surface, x, y, col+15); |
fill_rectangle_xy(surface, x, y+ysize, x+xsize, y+ysize, col+11); |
x += xsize + 2; |
} |
amt %= res; |
if (amt > 0) |
{ |
JE_barShade(surface, x+2, y+2, x+xsize+2, y+ysize+2); |
fill_rectangle_xy(surface, x,y, x+xsize, y+ysize, col+(12 / res * amt)); |
} |
} |
void JE_wipeKey( void ) |
{ |
// /!\ Doesn't seems to affect anything. |
} |
/contrib/games/opentyrian/src/nortvars.h |
---|
0,0 → 1,37 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef NORTVARS_H |
#define NORTVARS_H |
#include "opentyr.h" |
#include "SDL.h" |
extern JE_boolean inputDetected; |
JE_boolean JE_buttonPressed( void ); |
JE_boolean JE_anyButton( void ); |
void JE_dBar3( SDL_Surface *surface, JE_integer x, JE_integer y, JE_integer num, JE_integer col ); |
void JE_barDrawShadow( SDL_Surface *surface, JE_word x, JE_word y, JE_word res, JE_word col, JE_word amt, JE_word xsize, JE_word ysize ); |
void JE_wipeKey( void ); |
#endif /* NORTVARS_H */ |
/contrib/games/opentyrian/src/opentyr.c |
---|
0,0 → 1,392 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "opentyr.h" |
#include "config.h" |
#include "destruct.h" |
#include "editship.h" |
#include "episodes.h" |
#include "file.h" |
#include "font.h" |
#include "helptext.h" |
#include "joystick.h" |
#include "jukebox.h" |
#include "keyboard.h" |
#include "loudness.h" |
#include "mainint.h" |
#include "mtrand.h" |
#include "musmast.h" |
#include "network.h" |
#include "nortsong.h" |
#include "opentyrian_version.h" |
#include "params.h" |
#include "picload.h" |
#include "scroller.h" |
#include "setup.h" |
#include "sprite.h" |
#include "tyrian2.h" |
#include "xmas.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include "video_scale.h" |
#include "SDL.h" |
#include <assert.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <time.h> |
const char *opentyrian_str = "OpenTyrian"; |
const char *opentyrian_version = OPENTYRIAN_VERSION; |
void opentyrian_menu( void ) |
{ |
typedef enum |
{ |
MENU_ABOUT = 0, |
MENU_FULLSCREEN, |
MENU_SCALER, |
// MENU_DESTRUCT, |
MENU_JUKEBOX, |
MENU_RETURN, |
MenuOptions_MAX |
} MenuOptions; |
static const char *menu_items[] = |
{ |
"About OpenTyrian", |
"Toggle Fullscreen", |
"Scaler: None", |
// "Play Destruct", |
"Jukebox", |
"Return to Main Menu", |
}; |
bool menu_items_disabled[] = |
{ |
false, |
!can_init_any_scaler(false) || !can_init_any_scaler(true), |
false, |
// false, |
false, |
false, |
}; |
assert(COUNTOF(menu_items) == MenuOptions_MAX); |
assert(COUNTOF(menu_items_disabled) == MenuOptions_MAX); |
fade_black(10); |
JE_loadPic(VGAScreen, 13, false); |
draw_font_hv(VGAScreen, VGAScreen->w / 2, 5, opentyrian_str, large_font, centered, 15, -3); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
JE_showVGA(); |
play_song(36); // A Field for Mag |
MenuOptions sel = 0; |
uint temp_scaler = scaler; |
bool fade_in = true, quit = false; |
do |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
for (MenuOptions i = 0; i < MenuOptions_MAX; i++) |
{ |
const char *text = menu_items[i]; |
char buffer[100]; |
if (i == MENU_SCALER) |
{ |
snprintf(buffer, sizeof(buffer), "Scaler: %s", scalers[temp_scaler].name); |
text = buffer; |
} |
int y = i != MENU_RETURN ? i * 16 + 32 : 118; |
draw_font_hv(VGAScreen, VGAScreen->w / 2, y, text, normal_font, centered, 15, menu_items_disabled[i] ? -8 : i != sel ? -4 : -2); |
} |
JE_showVGA(); |
if (fade_in) |
{ |
fade_in = false; |
fade_palette(colors, 20, 0, 255); |
wait_noinput(true, false, false); |
} |
tempW = 0; |
JE_textMenuWait(&tempW, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
do |
{ |
if (sel-- == 0) |
sel = MenuOptions_MAX - 1; |
} |
while (menu_items_disabled[sel]); |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
do |
{ |
if (++sel >= MenuOptions_MAX) |
sel = 0; |
} |
while (menu_items_disabled[sel]); |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_LEFT: |
if (sel == MENU_SCALER) |
{ |
do |
{ |
if (temp_scaler == 0) |
temp_scaler = scalers_count; |
temp_scaler--; |
} |
while (!can_init_scaler(temp_scaler, fullscreen_enabled)); |
JE_playSampleNum(S_CURSOR); |
} |
break; |
case SDLK_RIGHT: |
if (sel == MENU_SCALER) |
{ |
do |
{ |
temp_scaler++; |
if (temp_scaler == scalers_count) |
temp_scaler = 0; |
} |
while (!can_init_scaler(temp_scaler, fullscreen_enabled)); |
JE_playSampleNum(S_CURSOR); |
} |
break; |
case SDLK_RETURN: |
switch (sel) |
{ |
case MENU_ABOUT: |
JE_playSampleNum(S_SELECT); |
scroller_sine(about_text); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
JE_showVGA(); |
fade_in = true; |
break; |
case MENU_FULLSCREEN: |
JE_playSampleNum(S_SELECT); |
if (!init_scaler(scaler, !fullscreen_enabled) && // try new fullscreen state |
!init_any_scaler(!fullscreen_enabled) && // try any scaler in new fullscreen state |
!init_scaler(scaler, fullscreen_enabled)) // revert on fail |
{ |
exit(EXIT_FAILURE); |
} |
set_palette(colors, 0, 255); // for switching between 8 bpp scalers |
break; |
case MENU_SCALER: |
JE_playSampleNum(S_SELECT); |
if (scaler != temp_scaler) |
{ |
if (!init_scaler(temp_scaler, fullscreen_enabled) && // try new scaler |
!init_scaler(temp_scaler, !fullscreen_enabled) && // try other fullscreen state |
!init_scaler(scaler, fullscreen_enabled)) // revert on fail |
{ |
exit(EXIT_FAILURE); |
} |
set_palette(colors, 0, 255); // for switching between 8 bpp scalers |
} |
break; |
case MENU_JUKEBOX: |
JE_playSampleNum(S_SELECT); |
fade_black(10); |
jukebox(); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
JE_showVGA(); |
fade_in = true; |
break; |
case MENU_RETURN: |
quit = true; |
JE_playSampleNum(S_SPRING); |
break; |
case MenuOptions_MAX: |
assert(false); |
break; |
} |
break; |
case SDLK_ESCAPE: |
quit = true; |
JE_playSampleNum(S_SPRING); |
break; |
default: |
break; |
} |
} |
} while (!quit); |
} |
int main( int argc, char *argv[] ) |
{ |
mt_srand(time(NULL)); |
printf("\nWelcome to... >> %s %s <<\n\n", opentyrian_str, opentyrian_version); |
printf("Copyright (C) 2007-2013 The OpenTyrian Development Team\n\n"); |
printf("This program comes with ABSOLUTELY NO WARRANTY.\n"); |
printf("This is free software, and you are welcome to redistribute it\n"); |
printf("under certain conditions. See the file GPL.txt for details.\n\n"); |
if (SDL_Init(0)) |
{ |
printf("Failed to initialize SDL: %s\n", SDL_GetError()); |
return -1; |
} |
JE_loadConfiguration(); |
xmas = xmas_time(); // arg handler may override |
JE_paramCheck(argc, argv); |
JE_scanForEpisodes(); |
init_video(); |
init_keyboard(); |
#ifndef _KOLIBRI |
init_joysticks(); |
printf("assuming mouse detected\n"); // SDL can't tell us if there isn't one |
#endif |
if (xmas && (!dir_file_exists(data_dir(), "tyrianc.shp") || !dir_file_exists(data_dir(), "voicesc.snd"))) |
{ |
xmas = false; |
fprintf(stderr, "warning: Christmas is missing.\n"); |
} |
JE_loadPals(); |
JE_loadMainShapeTables(xmas ? "tyrianc.shp" : "tyrian.shp"); |
if (xmas && !xmas_prompt()) |
{ |
xmas = false; |
free_main_shape_tables(); |
JE_loadMainShapeTables("tyrian.shp"); |
} |
/* Default Options */ |
youAreCheating = false; |
smoothScroll = true; |
loadDestruct = false; |
if (!audio_disabled) |
{ |
printf("initializing SDL audio...\n"); |
init_audio(); |
load_music(); |
JE_loadSndFile("tyrian.snd", xmas ? "voicesc.snd" : "voices.snd"); |
} |
else |
{ |
printf("audio disabled\n"); |
} |
if (record_demo) |
printf("demo recording enabled (input limited to keyboard)\n"); |
JE_loadExtraShapes(); /*Editship*/ |
JE_loadHelpText(); |
/*debuginfo("Help text complete");*/ |
if (isNetworkGame) |
{ |
#ifdef WITH_NETWORK |
if (network_init()) |
{ |
network_tyrian_halt(3, false); |
} |
#else |
fprintf(stderr, "OpenTyrian was compiled without networking support."); |
JE_tyrianHalt(5); |
#endif |
} |
#ifdef NDEBUG |
if (!isNetworkGame) |
intro_logos(); |
#endif |
for (; ; ) |
{ |
JE_initPlayerData(); |
JE_sortHighScores(); |
if (JE_titleScreen(true)) |
break; // user quit from title screen |
if (loadDestruct) |
{ |
JE_destructGame(); |
loadDestruct = false; |
} |
else |
{ |
JE_main(); |
} |
} |
JE_tyrianHalt(0); |
return 0; |
} |
/contrib/games/opentyrian/src/opentyr.h |
---|
0,0 → 1,69 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef OPENTYR_H |
#define OPENTYR_H |
#include "SDL_types.h" |
#include <math.h> |
#include <stdbool.h> |
#include <stdlib.h> |
#include <math.h> |
#include <string.h> |
#define COUNTOF(x) ((unsigned)(sizeof(x) / sizeof *(x))) // use only on arrays! |
#define MIN(a, b) ((a) < (b) ? (a) : (b)) |
#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
#ifndef M_PI |
#define M_PI 3.14159265358979323846 // pi |
#endif |
#ifndef M_PI_2 |
#define M_PI_2 1.57079632679489661923 // pi/2 |
#endif |
#ifndef M_PI_4 |
#define M_PI_4 0.78539816339744830962 // pi/4 |
#endif |
typedef unsigned int uint; |
typedef unsigned long ulong; |
// Pascal types, yuck. |
typedef Sint32 JE_longint; |
typedef Sint16 JE_integer; |
typedef Sint8 JE_shortint; |
typedef Uint16 JE_word; |
typedef Uint8 JE_byte; |
typedef bool JE_boolean; |
typedef char JE_char; |
typedef float JE_real; |
#define TYRIAN_VERSION "2.1" |
extern const char *opentyrian_str; |
extern const char *opentyrian_version; |
void opentyrian_menu( void ); |
#ifdef _KOLIBRI |
extern void uSDL_SetWinCenter(uint w, uint h); |
extern void uSDL_Delay(uint ms); |
#endif |
#endif /* OPENTYR_H */ |
/contrib/games/opentyrian/src/opentyrian_version.h |
---|
0,0 → 1,8 |
#ifndef OPENTYRIAN_VERSION_H |
#define OPENTYRIAN_VERSION_H |
#ifndef OPENTYRIAN_VERSION |
#define OPENTYRIAN_VERSION "v2.1.???" |
#endif |
#endif // OPENTYRIAN_VERSION_H |
/contrib/games/opentyrian/src/opl.c |
---|
0,0 → 1,1613 |
/* |
* Copyright (C) 2002-2010 The DOSBox Team |
* OPL2/OPL3 emulation library |
* |
* This 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. |
* |
* This 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 this library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
*/ |
/* |
* Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman |
* Copyright (C) 1998-2001 Ken Silverman |
* Ken Silverman's official web site: "http://www.advsys.net/ken" |
*/ |
#include "opl.h" |
#include <math.h> |
#include <stdbool.h> |
#include <stdlib.h> // rand() |
#include <string.h> // memset() |
#define fltype double |
/* |
define attribution that inlines/forces inlining of a function (optional) |
*/ |
#define OPL_INLINE inline |
#undef NUM_CHANNELS |
#if defined(OPLTYPE_IS_OPL3) |
#define NUM_CHANNELS 18 |
#else |
#define NUM_CHANNELS 9 |
#endif |
#define MAXOPERATORS (NUM_CHANNELS*2) |
#define FL05 ((fltype)0.5) |
#define FL2 ((fltype)2.0) |
#define PI ((fltype)3.1415926535897932384626433832795) |
#define FIXEDPT 0x10000 // fixed-point calculations using 16+16 |
#define FIXEDPT_LFO 0x1000000 // fixed-point calculations using 8+24 |
#define WAVEPREC 1024 // waveform precision (10 bits) |
#define INTFREQU ((fltype)(14318180.0 / 288.0)) // clocking of the chip |
#define OF_TYPE_ATT 0 |
#define OF_TYPE_DEC 1 |
#define OF_TYPE_REL 2 |
#define OF_TYPE_SUS 3 |
#define OF_TYPE_SUS_NOKEEP 4 |
#define OF_TYPE_OFF 5 |
#define ARC_CONTROL 0x00 |
#define ARC_TVS_KSR_MUL 0x20 |
#define ARC_KSL_OUTLEV 0x40 |
#define ARC_ATTR_DECR 0x60 |
#define ARC_SUSL_RELR 0x80 |
#define ARC_FREQ_NUM 0xa0 |
#define ARC_KON_BNUM 0xb0 |
#define ARC_PERC_MODE 0xbd |
#define ARC_FEEDBACK 0xc0 |
#define ARC_WAVE_SEL 0xe0 |
#define ARC_SECONDSET 0x100 // second operator set for OPL3 |
#define OP_ACT_OFF 0x00 |
#define OP_ACT_NORMAL 0x01 // regular channel activated (bitmasked) |
#define OP_ACT_PERC 0x02 // percussion channel activated (bitmasked) |
#define BLOCKBUF_SIZE 512 |
// vibrato constants |
#define VIBTAB_SIZE 8 |
#define VIBFAC 70/50000 // no braces, integer mul/div |
// tremolo constants and table |
#define TREMTAB_SIZE 53 |
#define TREM_FREQ ((fltype)(3.7)) // tremolo at 3.7hz |
/* operator struct definition |
For OPL2 all 9 channels consist of two operators each, carrier and modulator. |
Channel x has operators x as modulator and operators (9+x) as carrier. |
For OPL3 all 18 channels consist either of two operators (2op mode) or four |
operators (4op mode) which is determined through register4 of the second |
adlib register set. |
Only the channels 0,1,2 (first set) and 9,10,11 (second set) can act as |
4op channels. The two additional operators for a channel y come from the |
2op channel y+3 so the operatorss y, (9+y), y+3, (9+y)+3 make up a 4op |
channel. |
*/ |
typedef struct operator_struct { |
Bit32s cval, lastcval; // current output/last output (used for feedback) |
Bit32u tcount, wfpos, tinc; // time (position in waveform) and time increment |
fltype amp, step_amp; // and amplification (envelope) |
fltype vol; // volume |
fltype sustain_level; // sustain level |
Bit32s mfbi; // feedback amount |
fltype a0, a1, a2, a3; // attack rate function coefficients |
fltype decaymul, releasemul; // decay/release rate functions |
Bit32u op_state; // current state of operator (attack/decay/sustain/release/off) |
Bit32u toff; |
Bit32s freq_high; // highest three bits of the frequency, used for vibrato calculations |
Bit16s* cur_wform; // start of selected waveform |
Bit32u cur_wmask; // mask for selected waveform |
Bit32u act_state; // activity state (regular, percussion) |
bool sus_keep; // keep sustain level when decay finished |
bool vibrato,tremolo; // vibrato/tremolo enable bits |
// variables used to provide non-continuous envelopes |
Bit32u generator_pos; // for non-standard sample rates we need to determine how many samples have passed |
Bits cur_env_step; // current (standardized) sample position |
Bits env_step_a,env_step_d,env_step_r; // number of std samples of one step (for attack/decay/release mode) |
Bit8u step_skip_pos_a; // position of 8-cyclic step skipping (always 2^x to check against mask) |
Bits env_step_skip_a; // bitmask that determines if a step is skipped (respective bit is zero then) |
#if defined(OPLTYPE_IS_OPL3) |
bool is_4op,is_4op_attached; // base of a 4op channel/part of a 4op channel |
Bit32s left_pan,right_pan; // opl3 stereo panning amount |
#endif |
} op_type; |
// per-chip variables |
static op_type op[MAXOPERATORS]; |
static Bits int_samplerate; |
static Bit8u status; |
static Bit32u opl_index; |
#if defined(OPLTYPE_IS_OPL3) |
static Bit8u adlibreg[512]; // adlib register set (including second set) |
static Bit8u wave_sel[44]; // waveform selection |
#else |
static Bit8u adlibreg[256]; // adlib register set |
static Bit8u wave_sel[22]; // waveform selection |
#endif |
// vibrato/tremolo increment/counter |
static Bit32u vibtab_pos; |
static Bit32u vibtab_add; |
static Bit32u tremtab_pos; |
static Bit32u tremtab_add; |
// enable an operator |
void enable_operator(Bitu regbase, op_type* op_pt, Bit32u act_type); |
// functions to change parameters of an operator |
void change_frequency(Bitu chanbase, Bitu regbase, op_type* op_pt); |
void change_attackrate(Bitu regbase, op_type* op_pt); |
void change_decayrate(Bitu regbase, op_type* op_pt); |
void change_releaserate(Bitu regbase, op_type* op_pt); |
void change_sustainlevel(Bitu regbase, op_type* op_pt); |
void change_waveform(Bitu regbase, op_type* op_pt); |
void change_keepsustain(Bitu regbase, op_type* op_pt); |
void change_vibrato(Bitu regbase, op_type* op_pt); |
void change_feedback(Bitu chanbase, op_type* op_pt); |
static Bit32u generator_add; // should be a chip parameter |
static fltype recipsamp; // inverse of sampling rate |
static Bit16s wavtable[WAVEPREC*3]; // wave form table |
// vibrato/tremolo tables |
static Bit32s vib_table[VIBTAB_SIZE]; |
static Bit32s trem_table[TREMTAB_SIZE*2]; |
static Bit32s vibval_const[BLOCKBUF_SIZE]; |
static Bit32s tremval_const[BLOCKBUF_SIZE]; |
// vibrato value tables (used per-operator) |
static Bit32s vibval_var1[BLOCKBUF_SIZE]; |
static Bit32s vibval_var2[BLOCKBUF_SIZE]; |
//static Bit32s vibval_var3[BLOCKBUF_SIZE]; |
//static Bit32s vibval_var4[BLOCKBUF_SIZE]; |
// vibrato/trmolo value table pointers |
static Bit32s *vibval1, *vibval2, *vibval3, *vibval4; |
static Bit32s *tremval1, *tremval2, *tremval3, *tremval4; |
// key scale level lookup table |
static const fltype kslmul[4] = { |
0.0, 0.5, 0.25, 1.0 // -> 0, 3, 1.5, 6 dB/oct |
}; |
// frequency multiplicator lookup table |
static const fltype frqmul_tab[16] = { |
0.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15 |
}; |
// calculated frequency multiplication values (depend on sampling rate) |
static fltype frqmul[16]; |
// key scale levels |
static Bit8u kslev[8][16]; |
// map a channel number to the register offset of the modulator (=register base) |
static const Bit8u modulatorbase[9] = { |
0,1,2, |
8,9,10, |
16,17,18 |
}; |
// map a register base to a modulator operator number or operator number |
#if defined(OPLTYPE_IS_OPL3) |
static const Bit8u regbase2modop[44] = { |
0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8, // first set |
18,19,20,18,19,20,0,0,21,22,23,21,22,23,0,0,24,25,26,24,25,26 // second set |
}; |
static const Bit8u regbase2op[44] = { |
0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17, // first set |
18,19,20,27,28,29,0,0,21,22,23,30,31,32,0,0,24,25,26,33,34,35 // second set |
}; |
#else |
static const Bit8u regbase2modop[22] = { |
0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8 |
}; |
static const Bit8u regbase2op[22] = { |
0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17 |
}; |
#endif |
// start of the waveform |
static Bit32u waveform[8] = { |
WAVEPREC, |
WAVEPREC>>1, |
WAVEPREC, |
(WAVEPREC*3)>>2, |
0, |
0, |
(WAVEPREC*5)>>2, |
WAVEPREC<<1 |
}; |
// length of the waveform as mask |
static Bit32u wavemask[8] = { |
WAVEPREC-1, |
WAVEPREC-1, |
(WAVEPREC>>1)-1, |
(WAVEPREC>>1)-1, |
WAVEPREC-1, |
((WAVEPREC*3)>>2)-1, |
WAVEPREC>>1, |
WAVEPREC-1 |
}; |
// where the first entry resides |
static Bit32u wavestart[8] = { |
0, |
WAVEPREC>>1, |
0, |
WAVEPREC>>2, |
0, |
0, |
0, |
WAVEPREC>>3 |
}; |
// envelope generator function constants |
static fltype attackconst[4] = { |
(fltype)(1/2.82624), |
(fltype)(1/2.25280), |
(fltype)(1/1.88416), |
(fltype)(1/1.59744) |
}; |
static fltype decrelconst[4] = { |
(fltype)(1/39.28064), |
(fltype)(1/31.41608), |
(fltype)(1/26.17344), |
(fltype)(1/22.44608) |
}; |
void operator_advance(op_type* op_pt, Bit32s vib) { |
op_pt->wfpos = op_pt->tcount; // waveform position |
// advance waveform time |
op_pt->tcount += op_pt->tinc; |
op_pt->tcount += (Bit32s)(op_pt->tinc)*vib/FIXEDPT; |
op_pt->generator_pos += generator_add; |
} |
void operator_advance_drums(op_type* op_pt1, Bit32s vib1, op_type* op_pt2, Bit32s vib2, op_type* op_pt3, Bit32s vib3) { |
Bit32u c1 = op_pt1->tcount/FIXEDPT; |
Bit32u c3 = op_pt3->tcount/FIXEDPT; |
Bit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00; |
Bit32u noisebit = rand()&1; |
Bit32u snare_phase_bit = (((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1); |
//Hihat |
Bit32u inttm = (phasebit<<8) | (0x34<<(phasebit ^ (noisebit<<1))); |
op_pt1->wfpos = inttm*FIXEDPT; // waveform position |
// advance waveform time |
op_pt1->tcount += op_pt1->tinc; |
op_pt1->tcount += (Bit32s)(op_pt1->tinc)*vib1/FIXEDPT; |
op_pt1->generator_pos += generator_add; |
//Snare |
inttm = ((1+snare_phase_bit) ^ noisebit)<<8; |
op_pt2->wfpos = inttm*FIXEDPT; // waveform position |
// advance waveform time |
op_pt2->tcount += op_pt2->tinc; |
op_pt2->tcount += (Bit32s)(op_pt2->tinc)*vib2/FIXEDPT; |
op_pt2->generator_pos += generator_add; |
//Cymbal |
inttm = (1+phasebit)<<8; |
op_pt3->wfpos = inttm*FIXEDPT; // waveform position |
// advance waveform time |
op_pt3->tcount += op_pt3->tinc; |
op_pt3->tcount += (Bit32s)(op_pt3->tinc)*vib3/FIXEDPT; |
op_pt3->generator_pos += generator_add; |
} |
// output level is sustained, mode changes only when operator is turned off (->release) |
// or when the keep-sustained bit is turned off (->sustain_nokeep) |
void operator_output(op_type* op_pt, Bit32s modulator, Bit32s trem) { |
if (op_pt->op_state != OF_TYPE_OFF) { |
op_pt->lastcval = op_pt->cval; |
Bit32u i = (Bit32u)((op_pt->wfpos+modulator)/FIXEDPT); |
// wform: -16384 to 16383 (0x4000) |
// trem : 32768 to 65535 (0x10000) |
// step_amp: 0.0 to 1.0 |
// vol : 1/2^14 to 1/2^29 (/0x4000; /1../0x8000) |
op_pt->cval = (Bit32s)(op_pt->step_amp*op_pt->vol*op_pt->cur_wform[i&op_pt->cur_wmask]*trem/16.0); |
} |
} |
// no action, operator is off |
void operator_off(op_type* op_pt) { |
(void) op_pt; |
} |
// output level is sustained, mode changes only when operator is turned off (->release) |
// or when the keep-sustained bit is turned off (->sustain_nokeep) |
void operator_sustain(op_type* op_pt) { |
Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples |
for (Bit32u ct=0; ct<num_steps_add; ct++) { |
op_pt->cur_env_step++; |
} |
op_pt->generator_pos -= num_steps_add*FIXEDPT; |
} |
// operator in release mode, if output level reaches zero the operator is turned off |
void operator_release(op_type* op_pt) { |
// ??? boundary? |
if (op_pt->amp > 0.00000001) { |
// release phase |
op_pt->amp *= op_pt->releasemul; |
} |
Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples |
for (Bit32u ct=0; ct<num_steps_add; ct++) { |
op_pt->cur_env_step++; // sample counter |
if ((op_pt->cur_env_step & op_pt->env_step_r)==0) { |
if (op_pt->amp <= 0.00000001) { |
// release phase finished, turn off this operator |
op_pt->amp = 0.0; |
if (op_pt->op_state == OF_TYPE_REL) { |
op_pt->op_state = OF_TYPE_OFF; |
} |
} |
op_pt->step_amp = op_pt->amp; |
} |
} |
op_pt->generator_pos -= num_steps_add*FIXEDPT; |
} |
// operator in decay mode, if sustain level is reached the output level is either |
// kept (sustain level keep enabled) or the operator is switched into release mode |
void operator_decay(op_type* op_pt) { |
if (op_pt->amp > op_pt->sustain_level) { |
// decay phase |
op_pt->amp *= op_pt->decaymul; |
} |
Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples |
for (Bit32u ct=0; ct<num_steps_add; ct++) { |
op_pt->cur_env_step++; |
if ((op_pt->cur_env_step & op_pt->env_step_d)==0) { |
if (op_pt->amp <= op_pt->sustain_level) { |
// decay phase finished, sustain level reached |
if (op_pt->sus_keep) { |
// keep sustain level (until turned off) |
op_pt->op_state = OF_TYPE_SUS; |
op_pt->amp = op_pt->sustain_level; |
} else { |
// next: release phase |
op_pt->op_state = OF_TYPE_SUS_NOKEEP; |
} |
} |
op_pt->step_amp = op_pt->amp; |
} |
} |
op_pt->generator_pos -= num_steps_add*FIXEDPT; |
} |
// operator in attack mode, if full output level is reached, |
// the operator is switched into decay mode |
void operator_attack(op_type* op_pt) { |
op_pt->amp = ((op_pt->a3*op_pt->amp + op_pt->a2)*op_pt->amp + op_pt->a1)*op_pt->amp + op_pt->a0; |
Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples |
for (Bit32u ct=0; ct<num_steps_add; ct++) { |
op_pt->cur_env_step++; // next sample |
if ((op_pt->cur_env_step & op_pt->env_step_a)==0) { // check if next step already reached |
if (op_pt->amp > 1.0) { |
// attack phase finished, next: decay |
op_pt->op_state = OF_TYPE_DEC; |
op_pt->amp = 1.0; |
op_pt->step_amp = 1.0; |
} |
op_pt->step_skip_pos_a <<= 1; |
if (op_pt->step_skip_pos_a==0) op_pt->step_skip_pos_a = 1; |
if (op_pt->step_skip_pos_a & op_pt->env_step_skip_a) { // check if required to skip next step |
op_pt->step_amp = op_pt->amp; |
} |
} |
} |
op_pt->generator_pos -= num_steps_add*FIXEDPT; |
} |
typedef void (*optype_fptr)(op_type*); |
optype_fptr opfuncs[6] = { |
operator_attack, |
operator_decay, |
operator_release, |
operator_sustain, // sustain phase (keeping level) |
operator_release, // sustain_nokeep phase (release-style) |
operator_off |
}; |
void change_attackrate(Bitu regbase, op_type* op_pt) { |
Bits attackrate = adlibreg[ARC_ATTR_DECR+regbase]>>4; |
if (attackrate) { |
fltype f = (fltype)(pow(FL2,(fltype)attackrate+(op_pt->toff>>2)-1)*attackconst[op_pt->toff&3]*recipsamp); |
// attack rate coefficients |
op_pt->a0 = (fltype)(0.0377*f); |
op_pt->a1 = (fltype)(10.73*f+1); |
op_pt->a2 = (fltype)(-17.57*f); |
op_pt->a3 = (fltype)(7.42*f); |
Bits step_skip = attackrate*4 + op_pt->toff; |
Bits steps = step_skip >> 2; |
op_pt->env_step_a = (1<<(steps<=12?12-steps:0))-1; |
Bits step_num = (step_skip<=48)?(4-(step_skip&3)):0; |
static Bit8u step_skip_mask[5] = {0xff, 0xfe, 0xee, 0xba, 0xaa}; |
op_pt->env_step_skip_a = step_skip_mask[step_num]; |
#if defined(OPLTYPE_IS_OPL3) |
if (step_skip>=60) { |
#else |
if (step_skip>=62) { |
#endif |
op_pt->a0 = (fltype)(2.0); // something that triggers an immediate transition to amp:=1.0 |
op_pt->a1 = (fltype)(0.0); |
op_pt->a2 = (fltype)(0.0); |
op_pt->a3 = (fltype)(0.0); |
} |
} else { |
// attack disabled |
op_pt->a0 = 0.0; |
op_pt->a1 = 1.0; |
op_pt->a2 = 0.0; |
op_pt->a3 = 0.0; |
op_pt->env_step_a = 0; |
op_pt->env_step_skip_a = 0; |
} |
} |
void change_decayrate(Bitu regbase, op_type* op_pt) { |
Bits decayrate = adlibreg[ARC_ATTR_DECR+regbase]&15; |
// decaymul should be 1.0 when decayrate==0 |
if (decayrate) { |
fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp); |
op_pt->decaymul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(decayrate+(op_pt->toff>>2))))); |
Bits steps = (decayrate*4 + op_pt->toff) >> 2; |
op_pt->env_step_d = (1<<(steps<=12?12-steps:0))-1; |
} else { |
op_pt->decaymul = 1.0; |
op_pt->env_step_d = 0; |
} |
} |
void change_releaserate(Bitu regbase, op_type* op_pt) { |
Bits releaserate = adlibreg[ARC_SUSL_RELR+regbase]&15; |
// releasemul should be 1.0 when releaserate==0 |
if (releaserate) { |
fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp); |
op_pt->releasemul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(releaserate+(op_pt->toff>>2))))); |
Bits steps = (releaserate*4 + op_pt->toff) >> 2; |
op_pt->env_step_r = (1<<(steps<=12?12-steps:0))-1; |
} else { |
op_pt->releasemul = 1.0; |
op_pt->env_step_r = 0; |
} |
} |
void change_sustainlevel(Bitu regbase, op_type* op_pt) { |
Bits sustainlevel = adlibreg[ARC_SUSL_RELR+regbase]>>4; |
// sustainlevel should be 0.0 when sustainlevel==15 (max) |
if (sustainlevel<15) { |
op_pt->sustain_level = (fltype)(pow(FL2,(fltype)sustainlevel * (-FL05))); |
} else { |
op_pt->sustain_level = 0.0; |
} |
} |
void change_waveform(Bitu regbase, op_type* op_pt) { |
#if defined(OPLTYPE_IS_OPL3) |
if (regbase>=ARC_SECONDSET) regbase -= (ARC_SECONDSET-22); // second set starts at 22 |
#endif |
// waveform selection |
op_pt->cur_wmask = wavemask[wave_sel[regbase]]; |
op_pt->cur_wform = &wavtable[waveform[wave_sel[regbase]]]; |
// (might need to be adapted to waveform type here...) |
} |
void change_keepsustain(Bitu regbase, op_type* op_pt) { |
op_pt->sus_keep = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x20)>0; |
if (op_pt->op_state==OF_TYPE_SUS) { |
if (!op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS_NOKEEP; |
} else if (op_pt->op_state==OF_TYPE_SUS_NOKEEP) { |
if (op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS; |
} |
} |
// enable/disable vibrato/tremolo LFO effects |
void change_vibrato(Bitu regbase, op_type* op_pt) { |
op_pt->vibrato = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x40)!=0; |
op_pt->tremolo = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x80)!=0; |
} |
// change amount of self-feedback |
void change_feedback(Bitu chanbase, op_type* op_pt) { |
Bits feedback = adlibreg[ARC_FEEDBACK+chanbase]&14; |
if (feedback) op_pt->mfbi = (Bit32s)(pow(FL2,(fltype)((feedback>>1)+8))); |
else op_pt->mfbi = 0; |
} |
void change_frequency(Bitu chanbase, Bitu regbase, op_type* op_pt) { |
// frequency |
Bit32u frn = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])&3)<<8) + (Bit32u)adlibreg[ARC_FREQ_NUM+chanbase]; |
// block number/octave |
Bit32u oct = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])>>2)&7); |
op_pt->freq_high = (Bit32s)((frn>>7)&7); |
// keysplit |
Bit32u note_sel = (adlibreg[8]>>6)&1; |
op_pt->toff = ((frn>>9)&(note_sel^1)) | ((frn>>8)¬e_sel); |
op_pt->toff += (oct<<1); |
// envelope scaling (KSR) |
if (!(adlibreg[ARC_TVS_KSR_MUL+regbase]&0x10)) op_pt->toff >>= 2; |
// 20+a0+b0: |
op_pt->tinc = (Bit32u)((((fltype)(frn<<oct))*frqmul[adlibreg[ARC_TVS_KSR_MUL+regbase]&15])); |
// 40+a0+b0: |
fltype vol_in = (fltype)((fltype)(adlibreg[ARC_KSL_OUTLEV+regbase]&63) + |
kslmul[adlibreg[ARC_KSL_OUTLEV+regbase]>>6]*kslev[oct][frn>>6]); |
op_pt->vol = (fltype)(pow(FL2,(fltype)(vol_in * -0.125 - 14))); |
// operator frequency changed, care about features that depend on it |
change_attackrate(regbase,op_pt); |
change_decayrate(regbase,op_pt); |
change_releaserate(regbase,op_pt); |
} |
void enable_operator(Bitu regbase, op_type* op_pt, Bit32u act_type) { |
// check if this is really an off-on transition |
if (op_pt->act_state == OP_ACT_OFF) { |
Bits wselbase = regbase; |
if (wselbase>=ARC_SECONDSET) wselbase -= (ARC_SECONDSET-22); // second set starts at 22 |
op_pt->tcount = wavestart[wave_sel[wselbase]]*FIXEDPT; |
// start with attack mode |
op_pt->op_state = OF_TYPE_ATT; |
op_pt->act_state |= act_type; |
} |
} |
void disable_operator(op_type* op_pt, Bit32u act_type) { |
// check if this is really an on-off transition |
if (op_pt->act_state != OP_ACT_OFF) { |
op_pt->act_state &= (~act_type); |
if (op_pt->act_state == OP_ACT_OFF) { |
if (op_pt->op_state != OF_TYPE_OFF) op_pt->op_state = OF_TYPE_REL; |
} |
} |
} |
void adlib_init(Bit32u samplerate) { |
Bits i, j, oct; |
int_samplerate = samplerate; |
generator_add = (Bit32u)(INTFREQU*FIXEDPT/int_samplerate); |
memset((void *)adlibreg,0,sizeof(adlibreg)); |
memset((void *)op,0,sizeof(op_type)*MAXOPERATORS); |
memset((void *)wave_sel,0,sizeof(wave_sel)); |
for (i=0;i<MAXOPERATORS;i++) { |
op[i].op_state = OF_TYPE_OFF; |
op[i].act_state = OP_ACT_OFF; |
op[i].amp = 0.0; |
op[i].step_amp = 0.0; |
op[i].vol = 0.0; |
op[i].tcount = 0; |
op[i].tinc = 0; |
op[i].toff = 0; |
op[i].cur_wmask = wavemask[0]; |
op[i].cur_wform = &wavtable[waveform[0]]; |
op[i].freq_high = 0; |
op[i].generator_pos = 0; |
op[i].cur_env_step = 0; |
op[i].env_step_a = 0; |
op[i].env_step_d = 0; |
op[i].env_step_r = 0; |
op[i].step_skip_pos_a = 0; |
op[i].env_step_skip_a = 0; |
#if defined(OPLTYPE_IS_OPL3) |
op[i].is_4op = false; |
op[i].is_4op_attached = false; |
op[i].left_pan = 1; |
op[i].right_pan = 1; |
#endif |
} |
recipsamp = 1.0 / (fltype)int_samplerate; |
for (i=15;i>=0;i--) { |
frqmul[i] = (fltype)(frqmul_tab[i]*INTFREQU/(fltype)WAVEPREC*(fltype)FIXEDPT*recipsamp); |
} |
status = 0; |
opl_index = 0; |
// create vibrato table |
vib_table[0] = 8; |
vib_table[1] = 4; |
vib_table[2] = 0; |
vib_table[3] = -4; |
for (i=4; i<VIBTAB_SIZE; i++) vib_table[i] = vib_table[i-4]*-1; |
// vibrato at ~6.1 ?? (opl3 docs say 6.1, opl4 docs say 6.0, y8950 docs say 6.4) |
vibtab_add = (Bit32u)(VIBTAB_SIZE*FIXEDPT_LFO/8192*INTFREQU/int_samplerate); |
vibtab_pos = 0; |
for (i=0; i<BLOCKBUF_SIZE; i++) vibval_const[i] = 0; |
// create tremolo table |
Bit32s trem_table_int[TREMTAB_SIZE]; |
for (i=0; i<14; i++) trem_table_int[i] = i-13; // upwards (13 to 26 -> -0.5/6 to 0) |
for (i=14; i<41; i++) trem_table_int[i] = -i+14; // downwards (26 to 0 -> 0 to -1/6) |
for (i=41; i<53; i++) trem_table_int[i] = i-40-26; // upwards (1 to 12 -> -1/6 to -0.5/6) |
for (i=0; i<TREMTAB_SIZE; i++) { |
// 0.0 .. -26/26*4.8/6 == [0.0 .. -0.8], 4/53 steps == [1 .. 0.57] |
fltype trem_val1=(fltype)(((fltype)trem_table_int[i])*4.8/26.0/6.0); // 4.8db |
fltype trem_val2=(fltype)((fltype)((Bit32s)(trem_table_int[i]/4))*1.2/6.0/6.0); // 1.2db (larger stepping) |
trem_table[i] = (Bit32s)(pow(FL2,trem_val1)*FIXEDPT); |
trem_table[TREMTAB_SIZE+i] = (Bit32s)(pow(FL2,trem_val2)*FIXEDPT); |
} |
// tremolo at 3.7hz |
tremtab_add = (Bit32u)((fltype)TREMTAB_SIZE * TREM_FREQ * FIXEDPT_LFO / (fltype)int_samplerate); |
tremtab_pos = 0; |
for (i=0; i<BLOCKBUF_SIZE; i++) tremval_const[i] = FIXEDPT; |
static Bitu initfirstime = 0; |
if (!initfirstime) { |
initfirstime = 1; |
// create waveform tables |
for (i=0;i<(WAVEPREC>>1);i++) { |
wavtable[(i<<1) +WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<1) )*PI*2/WAVEPREC)); |
wavtable[(i<<1)+1+WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<1)+1)*PI*2/WAVEPREC)); |
wavtable[i] = wavtable[(i<<1) +WAVEPREC]; |
// alternative: (zero-less) |
/* wavtable[(i<<1) +WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<2)+1)*PI/WAVEPREC)); |
wavtable[(i<<1)+1+WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<2)+3)*PI/WAVEPREC)); |
wavtable[i] = wavtable[(i<<1)-1+WAVEPREC]; */ |
} |
for (i=0;i<(WAVEPREC>>3);i++) { |
wavtable[i+(WAVEPREC<<1)] = wavtable[i+(WAVEPREC>>3)]-16384; |
wavtable[i+((WAVEPREC*17)>>3)] = wavtable[i+(WAVEPREC>>2)]+16384; |
} |
// key scale level table verified ([table in book]*8/3) |
kslev[7][0] = 0; kslev[7][1] = 24; kslev[7][2] = 32; kslev[7][3] = 37; |
kslev[7][4] = 40; kslev[7][5] = 43; kslev[7][6] = 45; kslev[7][7] = 47; |
kslev[7][8] = 48; |
for (i=9;i<16;i++) kslev[7][i] = (Bit8u)(i+41); |
for (j=6;j>=0;j--) { |
for (i=0;i<16;i++) { |
oct = (Bits)kslev[j+1][i]-8; |
if (oct < 0) oct = 0; |
kslev[j][i] = (Bit8u)oct; |
} |
} |
} |
} |
void adlib_write(Bitu idx, Bit8u val) { |
Bit32u second_set = idx&0x100; |
adlibreg[idx] = val; |
switch (idx&0xf0) { |
case ARC_CONTROL: |
// here we check for the second set registers, too: |
switch (idx) { |
case 0x02: // timer1 counter |
case 0x03: // timer2 counter |
break; |
case 0x04: |
// IRQ reset, timer mask/start |
if (val&0x80) { |
// clear IRQ bits in status register |
status &= ~0x60; |
} else { |
status = 0; |
} |
break; |
#if defined(OPLTYPE_IS_OPL3) |
case 0x04|ARC_SECONDSET: |
// 4op enable/disable switches for each possible channel |
op[0].is_4op = (val&1)>0; |
op[3].is_4op_attached = op[0].is_4op; |
op[1].is_4op = (val&2)>0; |
op[4].is_4op_attached = op[1].is_4op; |
op[2].is_4op = (val&4)>0; |
op[5].is_4op_attached = op[2].is_4op; |
op[18].is_4op = (val&8)>0; |
op[21].is_4op_attached = op[18].is_4op; |
op[19].is_4op = (val&16)>0; |
op[22].is_4op_attached = op[19].is_4op; |
op[20].is_4op = (val&32)>0; |
op[23].is_4op_attached = op[20].is_4op; |
break; |
case 0x05|ARC_SECONDSET: |
break; |
#endif |
case 0x08: |
// CSW, note select |
break; |
default: |
break; |
} |
break; |
case ARC_TVS_KSR_MUL: |
case ARC_TVS_KSR_MUL+0x10: { |
// tremolo/vibrato/sustain keeping enabled; key scale rate; frequency multiplication |
int num = idx&7; |
Bitu base = (idx-ARC_TVS_KSR_MUL)&0xff; |
if ((num<6) && (base<22)) { |
Bitu modop = regbase2modop[second_set?(base+22):base]; |
Bitu regbase = base+second_set; |
Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop; |
// change tremolo/vibrato and sustain keeping of this operator |
op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)]; |
change_keepsustain(regbase,op_ptr); |
change_vibrato(regbase,op_ptr); |
// change frequency calculations of this operator as |
// key scale rate and frequency multiplicator can be changed |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) { |
// operator uses frequency of channel |
change_frequency(chanbase-3,regbase,op_ptr); |
} else { |
change_frequency(chanbase,regbase,op_ptr); |
} |
#else |
change_frequency(chanbase,base,op_ptr); |
#endif |
} |
} |
break; |
case ARC_KSL_OUTLEV: |
case ARC_KSL_OUTLEV+0x10: { |
// key scale level; output rate |
int num = idx&7; |
Bitu base = (idx-ARC_KSL_OUTLEV)&0xff; |
if ((num<6) && (base<22)) { |
Bitu modop = regbase2modop[second_set?(base+22):base]; |
Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop; |
// change frequency calculations of this operator as |
// key scale level and output rate can be changed |
op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)]; |
#if defined(OPLTYPE_IS_OPL3) |
Bitu regbase = base+second_set; |
if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) { |
// operator uses frequency of channel |
change_frequency(chanbase-3,regbase,op_ptr); |
} else { |
change_frequency(chanbase,regbase,op_ptr); |
} |
#else |
change_frequency(chanbase,base,op_ptr); |
#endif |
} |
} |
break; |
case ARC_ATTR_DECR: |
case ARC_ATTR_DECR+0x10: { |
// attack/decay rates |
int num = idx&7; |
Bitu base = (idx-ARC_ATTR_DECR)&0xff; |
if ((num<6) && (base<22)) { |
Bitu regbase = base+second_set; |
// change attack rate and decay rate of this operator |
op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]]; |
change_attackrate(regbase,op_ptr); |
change_decayrate(regbase,op_ptr); |
} |
} |
break; |
case ARC_SUSL_RELR: |
case ARC_SUSL_RELR+0x10: { |
// sustain level; release rate |
int num = idx&7; |
Bitu base = (idx-ARC_SUSL_RELR)&0xff; |
if ((num<6) && (base<22)) { |
Bitu regbase = base+second_set; |
// change sustain level and release rate of this operator |
op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]]; |
change_releaserate(regbase,op_ptr); |
change_sustainlevel(regbase,op_ptr); |
} |
} |
break; |
case ARC_FREQ_NUM: { |
// 0xa0-0xa8 low8 frequency |
Bitu base = (idx-ARC_FREQ_NUM)&0xff; |
if (base<9) { |
Bits opbase = second_set?(base+18):base; |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break; |
#endif |
// regbase of modulator: |
Bits modbase = modulatorbase[base]+second_set; |
Bitu chanbase = base+second_set; |
change_frequency(chanbase,modbase,&op[opbase]); |
change_frequency(chanbase,modbase+3,&op[opbase+9]); |
#if defined(OPLTYPE_IS_OPL3) |
// for 4op channels all four operators are modified to the frequency of the channel |
if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) { |
change_frequency(chanbase,modbase+8,&op[opbase+3]); |
change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]); |
} |
#endif |
} |
} |
break; |
case ARC_KON_BNUM: { |
if (idx == ARC_PERC_MODE) { |
#if defined(OPLTYPE_IS_OPL3) |
if (second_set) return; |
#endif |
if ((val&0x30) == 0x30) { // BassDrum active |
enable_operator(16,&op[6],OP_ACT_PERC); |
change_frequency(6,16,&op[6]); |
enable_operator(16+3,&op[6+9],OP_ACT_PERC); |
change_frequency(6,16+3,&op[6+9]); |
} else { |
disable_operator(&op[6],OP_ACT_PERC); |
disable_operator(&op[6+9],OP_ACT_PERC); |
} |
if ((val&0x28) == 0x28) { // Snare active |
enable_operator(17+3,&op[16],OP_ACT_PERC); |
change_frequency(7,17+3,&op[16]); |
} else { |
disable_operator(&op[16],OP_ACT_PERC); |
} |
if ((val&0x24) == 0x24) { // TomTom active |
enable_operator(18,&op[8],OP_ACT_PERC); |
change_frequency(8,18,&op[8]); |
} else { |
disable_operator(&op[8],OP_ACT_PERC); |
} |
if ((val&0x22) == 0x22) { // Cymbal active |
enable_operator(18+3,&op[8+9],OP_ACT_PERC); |
change_frequency(8,18+3,&op[8+9]); |
} else { |
disable_operator(&op[8+9],OP_ACT_PERC); |
} |
if ((val&0x21) == 0x21) { // Hihat active |
enable_operator(17,&op[7],OP_ACT_PERC); |
change_frequency(7,17,&op[7]); |
} else { |
disable_operator(&op[7],OP_ACT_PERC); |
} |
break; |
} |
// regular 0xb0-0xb8 |
Bitu base = (idx-ARC_KON_BNUM)&0xff; |
if (base<9) { |
Bits opbase = second_set?(base+18):base; |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break; |
#endif |
// regbase of modulator: |
Bits modbase = modulatorbase[base]+second_set; |
if (val&32) { |
// operator switched on |
enable_operator(modbase,&op[opbase],OP_ACT_NORMAL); // modulator (if 2op) |
enable_operator(modbase+3,&op[opbase+9],OP_ACT_NORMAL); // carrier (if 2op) |
#if defined(OPLTYPE_IS_OPL3) |
// for 4op channels all four operators are switched on |
if ((adlibreg[0x105]&1) && op[opbase].is_4op) { |
// turn on chan+3 operators as well |
enable_operator(modbase+8,&op[opbase+3],OP_ACT_NORMAL); |
enable_operator(modbase+3+8,&op[opbase+3+9],OP_ACT_NORMAL); |
} |
#endif |
} else { |
// operator switched off |
disable_operator(&op[opbase],OP_ACT_NORMAL); |
disable_operator(&op[opbase+9],OP_ACT_NORMAL); |
#if defined(OPLTYPE_IS_OPL3) |
// for 4op channels all four operators are switched off |
if ((adlibreg[0x105]&1) && op[opbase].is_4op) { |
// turn off chan+3 operators as well |
disable_operator(&op[opbase+3],OP_ACT_NORMAL); |
disable_operator(&op[opbase+3+9],OP_ACT_NORMAL); |
} |
#endif |
} |
Bitu chanbase = base+second_set; |
// change frequency calculations of modulator and carrier (2op) as |
// the frequency of the channel has changed |
change_frequency(chanbase,modbase,&op[opbase]); |
change_frequency(chanbase,modbase+3,&op[opbase+9]); |
#if defined(OPLTYPE_IS_OPL3) |
// for 4op channels all four operators are modified to the frequency of the channel |
if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) { |
// change frequency calculations of chan+3 operators as well |
change_frequency(chanbase,modbase+8,&op[opbase+3]); |
change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]); |
} |
#endif |
} |
} |
break; |
case ARC_FEEDBACK: { |
// 0xc0-0xc8 feedback/modulation type (AM/FM) |
Bitu base = (idx-ARC_FEEDBACK)&0xff; |
if (base<9) { |
Bits opbase = second_set?(base+18):base; |
Bitu chanbase = base+second_set; |
change_feedback(chanbase,&op[opbase]); |
#if defined(OPLTYPE_IS_OPL3) |
// OPL3 panning |
op[opbase].left_pan = ((val&0x10)>>4); |
op[opbase].right_pan = ((val&0x20)>>5); |
#endif |
} |
} |
break; |
case ARC_WAVE_SEL: |
case ARC_WAVE_SEL+0x10: { |
int num = idx&7; |
Bitu base = (idx-ARC_WAVE_SEL)&0xff; |
if ((num<6) && (base<22)) { |
#if defined(OPLTYPE_IS_OPL3) |
Bits wselbase = second_set?(base+22):base; // for easier mapping onto wave_sel[] |
// change waveform |
if (adlibreg[0x105]&1) wave_sel[wselbase] = val&7; // opl3 mode enabled, all waveforms accessible |
else wave_sel[wselbase] = val&3; |
op_type* op_ptr = &op[regbase2modop[wselbase]+((num<3) ? 0 : 9)]; |
change_waveform(wselbase,op_ptr); |
#else |
if (adlibreg[0x01]&0x20) { |
// wave selection enabled, change waveform |
wave_sel[base] = val&3; |
op_type* op_ptr = &op[regbase2modop[base]+((num<3) ? 0 : 9)]; |
change_waveform(base,op_ptr); |
} |
#endif |
} |
} |
break; |
default: |
break; |
} |
} |
Bitu adlib_reg_read(Bitu port) { |
#if defined(OPLTYPE_IS_OPL3) |
// opl3-detection routines require ret&6 to be zero |
if ((port&1)==0) { |
return status; |
} |
return 0x00; |
#else |
// opl2-detection routines require ret&6 to be 6 |
if ((port&1)==0) { |
return status|6; |
} |
return 0xff; |
#endif |
} |
void adlib_write_index(Bitu port, Bit8u val) { |
(void) port; |
opl_index = val; |
#if defined(OPLTYPE_IS_OPL3) |
if ((port&3)!=0) { |
// possibly second set |
if (((adlibreg[0x105]&1)!=0) || (opl_index==5)) opl_index |= ARC_SECONDSET; |
} |
#endif |
} |
OPL_INLINE static void clipit16(Bit32s ival, Bit16s* outval) { |
if (ival<32768) { |
if (ival>-32769) { |
*outval=(Bit16s)ival; |
} else { |
*outval = -32768; |
} |
} else { |
*outval = 32767; |
} |
} |
// be careful with this |
// uses cptr and chanval, outputs into outbufl(/outbufr) |
// for opl3 check if opl3-mode is enabled (which uses stereo panning) |
#undef CHANVAL_OUT |
#if defined(OPLTYPE_IS_OPL3) |
#define CHANVAL_OUT \ |
if (adlibreg[0x105]&1) { \ |
outbufl[i] += chanval*cptr[0].left_pan; \ |
outbufr[i] += chanval*cptr[0].right_pan; \ |
} else { \ |
outbufl[i] += chanval; \ |
} |
#else |
#define CHANVAL_OUT \ |
outbufl[i] += chanval; |
#endif |
void adlib_getsample(Bit16s* sndptr, Bits numsamples) { |
Bits i, endsamples; |
op_type* cptr; |
Bit32s outbufl[BLOCKBUF_SIZE]; |
#if defined(OPLTYPE_IS_OPL3) |
// second output buffer (right channel for opl3 stereo) |
Bit32s outbufr[BLOCKBUF_SIZE]; |
#endif |
// vibrato/tremolo lookup tables (global, to possibly be used by all operators) |
Bit32s vib_lut[BLOCKBUF_SIZE]; |
Bit32s trem_lut[BLOCKBUF_SIZE]; |
Bits samples_to_process = numsamples; |
for (Bits cursmp=0; cursmp<samples_to_process; cursmp+=endsamples) { |
endsamples = samples_to_process-cursmp; |
if (endsamples>BLOCKBUF_SIZE) endsamples = BLOCKBUF_SIZE; |
memset((void*)&outbufl,0,endsamples*sizeof(Bit32s)); |
#if defined(OPLTYPE_IS_OPL3) |
// clear second output buffer (opl3 stereo) |
if (adlibreg[0x105]&1) memset((void*)&outbufr,0,endsamples*sizeof(Bit32s)); |
#endif |
// calculate vibrato/tremolo lookup tables |
Bit32s vib_tshift = ((adlibreg[ARC_PERC_MODE]&0x40)==0) ? 1 : 0; // 14cents/7cents switching |
for (i=0;i<endsamples;i++) { |
// cycle through vibrato table |
vibtab_pos += vibtab_add; |
if (vibtab_pos/FIXEDPT_LFO>=VIBTAB_SIZE) vibtab_pos-=VIBTAB_SIZE*FIXEDPT_LFO; |
vib_lut[i] = vib_table[vibtab_pos/FIXEDPT_LFO]>>vib_tshift; // 14cents (14/100 of a semitone) or 7cents |
// cycle through tremolo table |
tremtab_pos += tremtab_add; |
if (tremtab_pos/FIXEDPT_LFO>=TREMTAB_SIZE) tremtab_pos-=TREMTAB_SIZE*FIXEDPT_LFO; |
if (adlibreg[ARC_PERC_MODE]&0x80) trem_lut[i] = trem_table[tremtab_pos/FIXEDPT_LFO]; |
else trem_lut[i] = trem_table[TREMTAB_SIZE+tremtab_pos/FIXEDPT_LFO]; |
} |
if (adlibreg[ARC_PERC_MODE]&0x20) { |
//BassDrum |
cptr = &op[6]; |
if (adlibreg[ARC_FEEDBACK+6]&1) { |
// additive synthesis |
if (cptr[9].op_state != OF_TYPE_OFF) { |
if (cptr[9].vibrato) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if (cptr[9].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[9],vibval1[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],0,tremval1[i]); |
Bit32s chanval = cptr[9].cval*2; |
CHANVAL_OUT |
} |
} |
} else { |
// frequency modulation |
if ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[0].op_state != OF_TYPE_OFF)) { |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
operator_advance(&cptr[9],vibval2[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]); |
Bit32s chanval = cptr[9].cval*2; |
CHANVAL_OUT |
} |
} |
} |
//TomTom (j=8) |
if (op[8].op_state != OF_TYPE_OFF) { |
cptr = &op[8]; |
if (cptr[0].vibrato) { |
vibval3 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval3[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval3 = vibval_const; |
if (cptr[0].tremolo) tremval3 = trem_lut; // tremolo enabled, use table |
else tremval3 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval3[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); //TomTom |
operator_output(&cptr[0],0,tremval3[i]); |
Bit32s chanval = cptr[0].cval*2; |
CHANVAL_OUT |
} |
} |
//Snare/Hihat (j=7), Cymbal (j=8) |
if ((op[7].op_state != OF_TYPE_OFF) || (op[16].op_state != OF_TYPE_OFF) || |
(op[17].op_state != OF_TYPE_OFF)) { |
cptr = &op[7]; |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
cptr = &op[8]; |
if ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF)) { |
vibval4 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval4[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval4 = vibval_const; |
if (cptr[9].tremolo) tremval4 = trem_lut; // tremolo enabled, use table |
else tremval4 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance_drums(&op[7],vibval1[i],&op[7+9],vibval2[i],&op[8+9],vibval4[i]); |
opfuncs[op[7].op_state](&op[7]); //Hihat |
operator_output(&op[7],0,tremval1[i]); |
opfuncs[op[7+9].op_state](&op[7+9]); //Snare |
operator_output(&op[7+9],0,tremval2[i]); |
opfuncs[op[8+9].op_state](&op[8+9]); //Cymbal |
operator_output(&op[8+9],0,tremval4[i]); |
Bit32s chanval = (op[7].cval + op[7+9].cval + op[8+9].cval)*2; |
CHANVAL_OUT |
} |
} |
} |
Bitu max_channel = NUM_CHANNELS; |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1)==0) max_channel = NUM_CHANNELS/2; |
#endif |
for (Bits cur_ch=max_channel-1; cur_ch>=0; cur_ch--) { |
// skip drum/percussion operators |
if ((adlibreg[ARC_PERC_MODE]&0x20) && (cur_ch >= 6) && (cur_ch < 9)) continue; |
Bitu k = cur_ch; |
#if defined(OPLTYPE_IS_OPL3) |
if (cur_ch < 9) { |
cptr = &op[cur_ch]; |
} else { |
cptr = &op[cur_ch+9]; // second set is operator18-operator35 |
k += (-9+256); // second set uses registers 0x100 onwards |
} |
// check if this operator is part of a 4-op |
if ((adlibreg[0x105]&1) && cptr->is_4op_attached) continue; |
#else |
cptr = &op[cur_ch]; |
#endif |
// check for FM/AM |
if (adlibreg[ARC_FEEDBACK+k]&1) { |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1) && cptr->is_4op) { |
if (adlibreg[ARC_FEEDBACK+k+3]&1) { |
// AM-AM-style synthesis (op1[fb] + (op2 * op3) + op4) |
if (cptr[0].op_state != OF_TYPE_OFF) { |
if (cptr[0].vibrato) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
Bit32s chanval = cptr[0].cval; |
CHANVAL_OUT |
} |
} |
if ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF)) { |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if (cptr[9].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[3].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[9],vibval1[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],0,tremval1[i]); |
operator_advance(&cptr[3],0); |
opfuncs[cptr[3].op_state](&cptr[3]); |
operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]); |
Bit32s chanval = cptr[3].cval; |
CHANVAL_OUT |
} |
} |
if (cptr[3+9].op_state != OF_TYPE_OFF) { |
if (cptr[3+9].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[3+9],0); |
opfuncs[cptr[3+9].op_state](&cptr[3+9]); |
operator_output(&cptr[3+9],0,tremval1[i]); |
Bit32s chanval = cptr[3+9].cval; |
CHANVAL_OUT |
} |
} |
} else { |
// AM-FM-style synthesis (op1[fb] + (op2 * op3 * op4)) |
if (cptr[0].op_state != OF_TYPE_OFF) { |
if (cptr[0].vibrato) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
Bit32s chanval = cptr[0].cval; |
CHANVAL_OUT |
} |
} |
if ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) { |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if (cptr[9].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[3].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
if (cptr[3+9].tremolo) tremval3 = trem_lut; // tremolo enabled, use table |
else tremval3 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[9],vibval1[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],0,tremval1[i]); |
operator_advance(&cptr[3],0); |
opfuncs[cptr[3].op_state](&cptr[3]); |
operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]); |
operator_advance(&cptr[3+9],0); |
opfuncs[cptr[3+9].op_state](&cptr[3+9]); |
operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval3[i]); |
Bit32s chanval = cptr[3+9].cval; |
CHANVAL_OUT |
} |
} |
} |
continue; |
} |
#endif |
// 2op additive synthesis |
if ((cptr[9].op_state == OF_TYPE_OFF) && (cptr[0].op_state == OF_TYPE_OFF)) continue; |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
// carrier1 |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
// carrier2 |
operator_advance(&cptr[9],vibval2[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],0,tremval2[i]); |
Bit32s chanval = cptr[9].cval + cptr[0].cval; |
CHANVAL_OUT |
} |
} else { |
#if defined(OPLTYPE_IS_OPL3) |
if ((adlibreg[0x105]&1) && cptr->is_4op) { |
if (adlibreg[ARC_FEEDBACK+k+3]&1) { |
// FM-AM-style synthesis ((op1[fb] * op2) + (op3 * op4)) |
if ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF)) { |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
operator_advance(&cptr[9],vibval2[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]); |
Bit32s chanval = cptr[9].cval; |
CHANVAL_OUT |
} |
} |
if ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) { |
if (cptr[3].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[3+9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[3],0); |
opfuncs[cptr[3].op_state](&cptr[3]); |
operator_output(&cptr[3],0,tremval1[i]); |
operator_advance(&cptr[3+9],0); |
opfuncs[cptr[3+9].op_state](&cptr[3+9]); |
operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval2[i]); |
Bit32s chanval = cptr[3+9].cval; |
CHANVAL_OUT |
} |
} |
} else { |
// FM-FM-style synthesis (op1[fb] * op2 * op3 * op4) |
if ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF) || |
(cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) { |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
if (cptr[3].tremolo) tremval3 = trem_lut; // tremolo enabled, use table |
else tremval3 = tremval_const; |
if (cptr[3+9].tremolo) tremval4 = trem_lut; // tremolo enabled, use table |
else tremval4 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
operator_advance(&cptr[9],vibval2[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]); |
operator_advance(&cptr[3],0); |
opfuncs[cptr[3].op_state](&cptr[3]); |
operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval3[i]); |
operator_advance(&cptr[3+9],0); |
opfuncs[cptr[3+9].op_state](&cptr[3+9]); |
operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval4[i]); |
Bit32s chanval = cptr[3+9].cval; |
CHANVAL_OUT |
} |
} |
} |
continue; |
} |
#endif |
// 2op frequency modulation |
if ((cptr[9].op_state == OF_TYPE_OFF) && (cptr[0].op_state == OF_TYPE_OFF)) continue; |
if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { |
vibval1 = vibval_var1; |
for (i=0;i<endsamples;i++) |
vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval1 = vibval_const; |
if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) { |
vibval2 = vibval_var2; |
for (i=0;i<endsamples;i++) |
vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC); |
} else vibval2 = vibval_const; |
if (cptr[0].tremolo) tremval1 = trem_lut; // tremolo enabled, use table |
else tremval1 = tremval_const; |
if (cptr[9].tremolo) tremval2 = trem_lut; // tremolo enabled, use table |
else tremval2 = tremval_const; |
// calculate channel output |
for (i=0;i<endsamples;i++) { |
// modulator |
operator_advance(&cptr[0],vibval1[i]); |
opfuncs[cptr[0].op_state](&cptr[0]); |
operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]); |
// carrier |
operator_advance(&cptr[9],vibval2[i]); |
opfuncs[cptr[9].op_state](&cptr[9]); |
operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]); |
Bit32s chanval = cptr[9].cval; |
CHANVAL_OUT |
} |
} |
} |
#if defined(OPLTYPE_IS_OPL3) |
if (adlibreg[0x105]&1) { |
// convert to 16bit samples (stereo) |
for (i=0;i<endsamples;i++) { |
clipit16(outbufl[i],sndptr++); |
clipit16(outbufr[i],sndptr++); |
} |
} else { |
// convert to 16bit samples (mono) |
for (i=0;i<endsamples;i++) { |
clipit16(outbufl[i],sndptr++); |
clipit16(outbufl[i],sndptr++); |
} |
} |
#else |
// convert to 16bit samples |
for (i=0;i<endsamples;i++) |
clipit16(outbufl[i],sndptr++); |
#endif |
} |
} |
/contrib/games/opentyrian/src/opl.h |
---|
0,0 → 1,51 |
/* |
* Copyright (C) 2002-2010 The DOSBox Team |
* OPL2/OPL3 emulation library |
* |
* This 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. |
* |
* This 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 this library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
*/ |
#ifndef OPL_H |
#define OPL_H |
/* |
* Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman |
* Copyright (C) 1998-2001 Ken Silverman |
* Ken Silverman's official web site: "http://www.advsys.net/ken" |
*/ |
#include <stdint.h> |
typedef uintptr_t Bitu; |
typedef intptr_t Bits; |
typedef uint32_t Bit32u; |
typedef int32_t Bit32s; |
typedef uint16_t Bit16u; |
typedef int16_t Bit16s; |
typedef uint8_t Bit8u; |
typedef int8_t Bit8s; |
// general functions |
void adlib_init(Bit32u samplerate); |
void adlib_write(Bitu idx, Bit8u val); |
void adlib_getsample(Bit16s* sndptr, Bits numsamples); |
Bitu adlib_reg_read(Bitu port); |
void adlib_write_index(Bitu port, Bit8u val); |
#define opl_init() adlib_init(OUTPUT_QUALITY * 11025) |
#define opl_write(reg, val) adlib_write(reg, val) |
#define opl_update(buf, num) adlib_getsample(buf, num) |
#endif /* OPL_H */ |
/contrib/games/opentyrian/src/palette.c |
---|
0,0 → 1,225 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "palette.h" |
#include "file.h" |
#include "nortsong.h" |
#include "opentyr.h" |
#include "video.h" |
#include <assert.h> |
static Uint32 rgb_to_yuv( int r, int g, int b ); |
#define PALETTE_COUNT 23 |
Palette palettes[PALETTE_COUNT]; |
int palette_count; |
static Palette palette; |
Uint32 rgb_palette[256], yuv_palette[256]; |
Palette colors; |
void JE_loadPals( void ) |
{ |
FILE *f = dir_fopen_die(data_dir(), "palette.dat", "rb"); |
palette_count = ftell_eof(f) / (256 * 3); |
assert(palette_count == PALETTE_COUNT); |
for (int p = 0; p < palette_count; ++p) |
{ |
for (int i = 0; i < 256; ++i) |
{ |
// The VGA hardware palette used only 6 bits per component, so the values need to be rescaled to |
// 8 bits. The naive way to do this is to simply do (c << 2), padding it with 0's, however this |
// makes the maximum value 252 instead of the proper 255. A trick to fix this is to use the upper 2 |
// bits of the original value instead. This ensures that the value goes to 255 as the original goes |
// to 63. |
int c = getc(f); |
palettes[p][i].r = (c << 2) | (c >> 4); |
c = getc(f); |
palettes[p][i].g = (c << 2) | (c >> 4); |
c = getc(f); |
palettes[p][i].b = (c << 2) | (c >> 4); |
} |
} |
fclose(f); |
} |
void set_palette( Palette colors, unsigned int first_color, unsigned int last_color ) |
{ |
SDL_Surface *const surface = SDL_GetVideoSurface(); |
const uint bpp = surface->format->BitsPerPixel; |
for (uint i = first_color; i <= last_color; ++i) |
{ |
palette[i] = colors[i]; |
if (bpp != 8) |
{ |
rgb_palette[i] = SDL_MapRGB(surface->format, palette[i].r, palette[i].g, palette[i].b); |
yuv_palette[i] = rgb_to_yuv(palette[i].r, palette[i].g, palette[i].b); |
} |
} |
if (bpp == 8) |
SDL_SetColors(surface, palette, first_color, last_color - first_color + 1); |
} |
void set_colors( SDL_Color color, unsigned int first_color, unsigned int last_color ) |
{ |
SDL_Surface *const surface = SDL_GetVideoSurface(); |
const uint bpp = surface->format->BitsPerPixel; |
for (uint i = first_color; i <= last_color; ++i) |
{ |
palette[i] = color; |
if (bpp != 8) |
{ |
rgb_palette[i] = SDL_MapRGB(surface->format, palette[i].r, palette[i].g, palette[i].b); |
yuv_palette[i] = rgb_to_yuv(palette[i].r, palette[i].g, palette[i].b); |
} |
} |
if (bpp == 8) |
SDL_SetColors(surface, palette, first_color, last_color - first_color + 1); |
} |
void init_step_fade_palette( int diff[256][3], Palette colors, unsigned int first_color, unsigned int last_color ) |
{ |
for (unsigned int i = first_color; i <= last_color; i++) |
{ |
diff[i][0] = (int)colors[i].r - palette[i].r; |
diff[i][1] = (int)colors[i].g - palette[i].g; |
diff[i][2] = (int)colors[i].b - palette[i].b; |
} |
} |
void init_step_fade_solid( int diff[256][3], SDL_Color color, unsigned int first_color, unsigned int last_color ) |
{ |
for (unsigned int i = first_color; i <= last_color; i++) |
{ |
diff[i][0] = (int)color.r - palette[i].r; |
diff[i][1] = (int)color.g - palette[i].g; |
diff[i][2] = (int)color.b - palette[i].b; |
} |
} |
void step_fade_palette( int diff[256][3], int steps, unsigned int first_color, unsigned int last_color ) |
{ |
assert(steps > 0); |
SDL_Surface *const surface = SDL_GetVideoSurface(); |
const uint bpp = surface->format->BitsPerPixel; |
for (unsigned int i = first_color; i <= last_color; i++) |
{ |
int delta[3] = { diff[i][0] / steps, diff[i][1] / steps, diff[i][2] / steps }; |
diff[i][0] -= delta[0]; |
diff[i][1] -= delta[1]; |
diff[i][2] -= delta[2]; |
palette[i].r += delta[0]; |
palette[i].g += delta[1]; |
palette[i].b += delta[2]; |
if (bpp != 8) |
{ |
rgb_palette[i] = SDL_MapRGB(surface->format, palette[i].r, palette[i].g, palette[i].b); |
yuv_palette[i] = rgb_to_yuv(palette[i].r, palette[i].g, palette[i].b); |
} |
} |
if (bpp == 8) |
SDL_SetColors(surface, palette, 0, 256); |
} |
void fade_palette( Palette colors, int steps, unsigned int first_color, unsigned int last_color ) |
{ |
assert(steps > 0); |
SDL_Surface *const surface = SDL_GetVideoSurface(); |
const uint bpp = surface->format->BitsPerPixel; |
static int diff[256][3]; |
init_step_fade_palette(diff, colors, first_color, last_color); |
for (; steps > 0; steps--) |
{ |
setdelay(1); |
step_fade_palette(diff, steps, first_color, last_color); |
if (bpp != 8) |
JE_showVGA(); |
wait_delay(); |
} |
} |
void fade_solid( SDL_Color color, int steps, unsigned int first_color, unsigned int last_color ) |
{ |
assert(steps > 0); |
SDL_Surface *const surface = SDL_GetVideoSurface(); |
const uint bpp = surface->format->BitsPerPixel; |
static int diff[256][3]; |
init_step_fade_solid(diff, color, first_color, last_color); |
for (; steps > 0; steps--) |
{ |
setdelay(1); |
step_fade_palette(diff, steps, first_color, last_color); |
if (bpp != 8) |
JE_showVGA(); |
wait_delay(); |
} |
} |
void fade_black( int steps ) |
{ |
SDL_Color black = { 0, 0, 0 }; |
fade_solid(black, steps, 0, 255); |
} |
void fade_white( int steps ) |
{ |
SDL_Color white = { 255, 255, 255 }; |
fade_solid(white, steps, 0, 255); |
} |
static Uint32 rgb_to_yuv( int r, int g, int b ) |
{ |
int y = (r + g + b) >> 2, |
u = 128 + ((r - b) >> 2), |
v = 128 + ((-r + 2 * g - b) >> 3); |
return (y << 16) + (u << 8) + v; |
} |
/contrib/games/opentyrian/src/palette.h |
---|
0,0 → 1,51 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PALETTE_H |
#define PALETTE_H |
#include "opentyr.h" |
#include "SDL.h" |
typedef SDL_Color Palette[256]; |
extern Palette palettes[]; |
extern int palette_count; |
extern Uint32 rgb_palette[256], yuv_palette[256]; |
extern Palette colors; // TODO: get rid of this |
void JE_loadPals( void ); |
void set_palette( Palette colors, unsigned int first_color, unsigned int last_color ); |
void set_colors( SDL_Color color, unsigned int first_color, unsigned int last_color ); |
void init_step_fade_palette( int diff[256][3], Palette colors, unsigned int first_color, unsigned int last_color ); |
void init_step_fade_solid( int diff[256][3], SDL_Color color, unsigned int first_color, unsigned int last_color ); |
void step_fade_palette( int diff[256][3], int steps, unsigned int first_color, unsigned int last_color ); |
void fade_palette( Palette colors, int steps, unsigned int first_color, unsigned int last_color ); |
void fade_solid( SDL_Color color, int steps, unsigned int first_color, unsigned int last_color ); |
void fade_black( int steps ); |
void fade_white( int steps ); |
#endif /* PALETTE_H */ |
/contrib/games/opentyrian/src/params.c |
---|
0,0 → 1,267 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "params.h" |
#include "arg_parse.h" |
#include "file.h" |
#include "joystick.h" |
#include "loudness.h" |
#include "network.h" |
#include "opentyr.h" |
#include "varz.h" |
#include "xmas.h" |
#include <assert.h> |
#include <ctype.h> |
#include <errno.h> |
#include <stdint.h> |
#include <string.h> |
JE_boolean richMode = false, constantPlay = false, constantDie = false; |
/* YKS: Note: LOOT cheat had non letters removed. */ |
const char pars[][9] = { |
"LOOT", "RECORD", "NOJOY", "CONSTANT", "DEATH", "NOSOUND", "NOXMAS", "YESXMAS" |
}; |
void JE_paramCheck( int argc, char *argv[] ) |
{ |
const Options options[] = |
{ |
{ 'h', 'h', "help", false }, |
{ 's', 's', "no-sound", false }, |
{ 'j', 'j', "no-joystick", false }, |
{ 'x', 'x', "no-xmas", false }, |
{ 't', 't', "data", true }, |
{ 'n', 'n', "net", true }, |
{ 256, 0, "net-player-name", true }, // TODO: no short codes because there should |
{ 257, 0, "net-player-number", true }, // be a menu for entering these in the future |
{ 'p', 'p', "net-port", true }, |
{ 'd', 'd', "net-delay", true }, |
{ 'X', 'X', "xmas", false }, |
{ 'c', 'c', "constant", false }, |
{ 'k', 'k', "death", false }, |
{ 'r', 'r', "record", false }, |
{ 'l', 'l', "loot", false }, |
{ 0, 0, NULL, false} |
}; |
Option option; |
for (; ; ) |
{ |
option = parse_args(argc, (const char **)argv, options); |
if (option.value == NOT_OPTION) |
break; |
switch (option.value) |
{ |
case INVALID_OPTION: |
case AMBIGUOUS_OPTION: |
case OPTION_MISSING_ARG: |
fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); |
exit(EXIT_FAILURE); |
break; |
case 'h': |
printf("Usage: %s [OPTION...]\n\n" |
"Options:\n" |
" -h, --help Show help about options\n\n" |
" -s, --no-sound Disable audio\n" |
" -j, --no-joystick Disable joystick/gamepad input\n" |
" -x, --no-xmas Disable Christmas mode\n\n" |
" -t, --data=DIR Set Tyrian data directory\n\n" |
" -n, --net=HOST[:PORT] Start a networked game\n" |
" --net-player-name=NAME Sets local player name in a networked game\n" |
" --net-player-number=NUMBER Sets local player number in a networked game\n" |
" (1 or 2)\n" |
" -p, --net-port=PORT Local port to bind (default is 1333)\n" |
" -d, --net-delay=FRAMES Set lag-compensation delay (default is 1)\n", argv[0]); |
exit(0); |
break; |
case 's': |
// Disables sound/music usage |
audio_disabled = true; |
break; |
case 'j': |
// Disables joystick detection |
ignore_joystick = true; |
break; |
case 'x': |
xmas = false; |
break; |
// set custom Tyrian data directory |
case 't': |
custom_data_dir = option.arg; |
break; |
case 'n': |
isNetworkGame = true; |
intptr_t temp = (intptr_t)strchr(option.arg, ':'); |
if (temp) |
{ |
temp -= (intptr_t)option.arg; |
int temp_port = atoi(&option.arg[temp + 1]); |
if (temp_port > 0 && temp_port < 49152) |
network_opponent_port = temp_port; |
else |
{ |
fprintf(stderr, "%s: error: invalid network port number\n", argv[0]); |
exit(EXIT_FAILURE); |
} |
network_opponent_host = malloc(temp + 1); |
SDL_strlcpy(network_opponent_host, option.arg, temp + 1); |
} |
else |
{ |
network_opponent_host = malloc(strlen(option.arg) + 1); |
strcpy(network_opponent_host, option.arg); |
} |
break; |
case 256: // --net-player-name |
network_player_name = malloc(strlen(option.arg) + 1); |
strcpy(network_player_name, option.arg); |
break; |
case 257: // --net-player-number |
{ |
int temp = atoi(option.arg); |
if (temp >= 1 && temp <= 2) |
thisPlayerNum = temp; |
else |
{ |
fprintf(stderr, "%s: error: invalid network player number\n", argv[0]); |
exit(EXIT_FAILURE); |
} |
break; |
} |
case 'p': |
{ |
int temp = atoi(option.arg); |
if (temp > 0 && temp < 49152) |
network_player_port = temp; |
else |
{ |
fprintf(stderr, "%s: error: invalid network port number\n", argv[0]); |
exit(EXIT_FAILURE); |
} |
break; |
} |
case 'd': |
{ |
int temp; |
if (sscanf(option.arg, "%d", &temp) == 1) |
network_delay = 1 + temp; |
else |
{ |
fprintf(stderr, "%s: error: invalid network delay value\n", argv[0]); |
exit(EXIT_FAILURE); |
} |
break; |
} |
case 'X': |
xmas = true; |
break; |
case 'c': |
/* Constant play for testing purposes (C key activates invincibility) |
This might be useful for publishers to see everything - especially |
those who can't play it */ |
constantPlay = true; |
break; |
case 'k': |
constantDie = true; |
break; |
case 'r': |
record_demo = true; |
break; |
case 'l': |
// Gives you mucho bucks |
richMode = true; |
break; |
default: |
assert(false); |
break; |
} |
} |
// legacy parameter support |
for (int i = option.argn; i < argc; ++i) |
{ |
for (uint j = 0; j < strlen(argv[i]); ++j) |
argv[i][j] = toupper((unsigned char)argv[i][j]); |
for (uint j = 0; j < COUNTOF(pars); ++j) |
{ |
if (strcmp(argv[i], pars[j]) == 0) |
{ |
switch (j) |
{ |
case 0: |
richMode = true; |
break; |
case 1: |
record_demo = true; |
break; |
case 2: |
ignore_joystick = true; |
break; |
case 3: |
constantPlay = true; |
break; |
case 4: |
constantDie = true; |
break; |
case 5: |
audio_disabled = true; |
break; |
case 6: |
xmas = false; |
break; |
case 7: |
xmas = true; |
break; |
default: |
assert(false); |
break; |
} |
} |
} |
} |
} |
/contrib/games/opentyrian/src/params.h |
---|
0,0 → 1,29 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PARAMS_H |
#define PARAMS_H |
#include "opentyr.h" |
extern JE_boolean richMode, constantPlay, constantDie; |
void JE_paramCheck( int argc, char *argv[] ); |
#endif /* PARAMS_H */ |
/contrib/games/opentyrian/src/pcxload.c |
---|
0,0 → 1,67 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "pcxload.h" |
#include "file.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "video.h" |
void JE_loadPCX( const char *file ) // this is only meant to load tshp2.pcx |
{ |
Uint8 *s = VGAScreen->pixels; /* 8-bit specific */ |
FILE *f = dir_fopen_die(data_dir(), file, "rb"); |
fseek(f, -769, SEEK_END); |
if (fgetc(f) == 12) |
{ |
for (int i = 0; i < 256; i++) |
{ |
efread(&colors[i].r, 1, 1, f); |
efread(&colors[i].g, 1, 1, f); |
efread(&colors[i].b, 1, 1, f); |
} |
} |
fseek(f, 128, SEEK_SET); |
for (int i = 0; i < 320 * 200; ) |
{ |
Uint8 p = fgetc(f); |
if ((p & 0xc0) == 0xc0) |
{ |
i += (p & 0x3f); |
memset(s, fgetc(f), (p & 0x3f)); |
s += (p & 0x3f); |
} else { |
i++; |
*s = p; |
s++; |
} |
if (i && (i % 320 == 0)) |
{ |
s += VGAScreen->pitch - 320; |
} |
} |
fclose(f); |
} |
/contrib/games/opentyrian/src/pcxload.h |
---|
0,0 → 1,27 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PCXLOAD_H |
#define PCXLOAD_H |
#include "opentyr.h" |
void JE_loadPCX( const char *file ); |
#endif /* PCXLOAD_H */ |
/contrib/games/opentyrian/src/pcxmast.c |
---|
0,0 → 1,48 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "pcxmast.h" |
#include "opentyr.h" |
const char *pcxfile[PCX_NUM] = /* [1..PCXnum] */ |
{ |
"INTSHPB.PCX", |
"SETUP2.PCX", |
"TYRPLAY.PCX", |
"TYRLOG2.PCX", |
"P1.PCX", |
"TYRPLAY2.PCX", |
"BUC4.PCX", |
"GMOVR4a.PCX", |
"GMOVR4b.PCX", |
"EPICSKY.PCX", |
"DESTRUCT.PCX", |
"ECLIPSE.PCX", |
"FIREPICA.PCX" |
}; |
const JE_byte pcxpal[PCX_NUM] = /* [1..PCXnum] */ |
{ 0, 7, 5, 8, 10, 5, 18, 19, 19, 20, 21, 22, 5}; |
/*FACEMAX*/ |
const JE_byte facepal[12] = /* [1..12] */ |
{ 1, 2, 3, 4, 6, 9, 11, 12, 16, 13, 14, 15}; |
JE_pcxpostype pcxpos; |
/contrib/games/opentyrian/src/pcxmast.h |
---|
0,0 → 1,35 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PCXMAST_H |
#define PCXMAST_H |
#include "opentyr.h" |
#define PCX_NUM 13 |
typedef JE_longint JE_pcxpostype[PCX_NUM + 1]; /* [1..PCXnum + 1] */ |
extern const char *pcxfile[PCX_NUM]; /* [1..PCXnum] */ |
extern const JE_byte pcxpal[PCX_NUM]; /* [1..PCXnum] */ |
extern const JE_byte facepal[12]; /* [1..12] */ |
extern JE_pcxpostype pcxpos; |
#endif /* PCXMAST_H */ |
/contrib/games/opentyrian/src/picload.c |
---|
0,0 → 1,87 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "picload.h" |
#include "file.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "pcxmast.h" |
#include "video.h" |
#include <string.h> |
void JE_loadPic(SDL_Surface *screen, JE_byte PCXnumber, JE_boolean storepal ) |
{ |
PCXnumber--; |
FILE *f = dir_fopen_die(data_dir(), "tyrian.pic", "rb"); |
static bool first = true; |
if (first) |
{ |
first = false; |
Uint16 temp; |
efread(&temp, sizeof(Uint16), 1, f); |
for (int i = 0; i < PCX_NUM; i++) |
{ |
efread(&pcxpos[i], sizeof(JE_longint), 1, f); |
} |
pcxpos[PCX_NUM] = ftell_eof(f); |
} |
unsigned int size = pcxpos[PCXnumber + 1] - pcxpos[PCXnumber]; |
Uint8 *buffer = malloc(size); |
fseek(f, pcxpos[PCXnumber], SEEK_SET); |
efread(buffer, sizeof(Uint8), size, f); |
fclose(f); |
Uint8 *p = buffer; |
Uint8 *s; /* screen pointer, 8-bit specific */ |
s = (Uint8 *)screen->pixels; |
for (int i = 0; i < 320 * 200; ) |
{ |
if ((*p & 0xc0) == 0xc0) |
{ |
i += (*p & 0x3f); |
memset(s, *(p + 1), (*p & 0x3f)); |
s += (*p & 0x3f); p += 2; |
} else { |
i++; |
*s = *p; |
s++; p++; |
} |
if (i && (i % 320 == 0)) |
{ |
s += screen->pitch - 320; |
} |
} |
free(buffer); |
memcpy(colors, palettes[pcxpal[PCXnumber]], sizeof(colors)); |
if (storepal) |
set_palette(colors, 0, 255); |
} |
/contrib/games/opentyrian/src/picload.h |
---|
0,0 → 1,29 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PICLOAD_H |
#define PICLOAD_H |
#include "opentyr.h" |
#include "SDL.h" |
void JE_loadPic(SDL_Surface *screen, JE_byte PCXnumber, JE_boolean storepal ); |
#endif /* PICLOAD_H */ |
/contrib/games/opentyrian/src/player.c |
---|
0,0 → 1,55 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "player.h" |
Player player[2]; |
void calc_purple_balls_needed( Player *this_player ) |
{ |
static const uint purple_balls_required[12] = { 1, 1, 2, 4, 8, 12, 16, 20, 25, 30, 40, 50 }; |
this_player->purple_balls_needed = purple_balls_required[*this_player->lives]; |
} |
bool power_up_weapon( Player *this_player, uint port ) |
{ |
const bool can_power_up = this_player->items.weapon[port].id != 0 && // not None |
this_player->items.weapon[port].power < 11; // not at max power |
if (can_power_up) |
{ |
++this_player->items.weapon[port].power; |
shotMultiPos[port] = 0; // TODO: should be part of Player structure |
calc_purple_balls_needed(this_player); |
} |
else // cash consolation prize |
{ |
this_player->cash += 1000; |
} |
return can_power_up; |
} |
void handle_got_purple_ball( Player *this_player ) |
{ |
if (this_player->purple_balls_needed > 1) |
--this_player->purple_balls_needed; |
else |
power_up_weapon(this_player, this_player->is_dragonwing ? REAR_WEAPON : FRONT_WEAPON); |
} |
/contrib/games/opentyrian/src/player.h |
---|
0,0 → 1,129 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef PLAYER_H |
#define PLAYER_H |
#include "config.h" |
#include "opentyr.h" |
enum |
{ |
FRONT_WEAPON = 0, |
REAR_WEAPON = 1 |
}; |
enum |
{ |
LEFT_SIDEKICK = 0, |
RIGHT_SIDEKICK = 1 |
}; |
typedef struct |
{ |
uint ship; |
uint generator; |
uint shield; |
struct { uint id; uint power; } weapon[2]; |
uint sidekick[2]; |
uint special; |
// Dragonwing only: |
// repeatedly collecting the same powerup gives a series of sidekick upgrades |
uint sidekick_series; |
uint sidekick_level; |
// Single-player only |
uint super_arcade_mode; // stored as an item for compatibility :( |
} |
PlayerItems; |
typedef struct |
{ |
ulong cash; |
PlayerItems items, last_items; |
bool is_dragonwing; // i.e., is player 2 |
uint *lives; |
// calculatable |
uint shield_max; |
uint initial_armor; |
uint shot_hit_area_x, shot_hit_area_y; |
// state |
bool is_alive; |
uint invulnerable_ticks; // ticks until ship can be damaged |
uint exploding_ticks; // ticks until ship done exploding |
uint shield; |
uint armor; |
uint weapon_mode; |
uint superbombs; |
uint purple_balls_needed; |
int x, y; |
int old_x[20], old_y[20]; |
int x_velocity, y_velocity; |
uint x_friction_ticks, y_friction_ticks; // ticks until friction is applied |
int delta_x_shot_move, delta_y_shot_move; |
int last_x_shot_move, last_y_shot_move; |
int last_x_explosion_follow, last_y_explosion_follow; |
struct |
{ |
// calculatable |
int ammo_max; |
uint ammo_refill_ticks_max; |
uint style; // affects movement and size |
// state |
int x, y; |
int ammo; |
uint ammo_refill_ticks; |
bool animation_enabled; |
uint animation_frame; |
uint charge; |
uint charge_ticks; |
} |
sidekick[2]; |
} |
Player; |
extern Player player[2]; |
static inline bool all_players_dead( void ) |
{ |
return (!player[0].is_alive && (!twoPlayerMode || !player[1].is_alive)); |
} |
static inline bool all_players_alive( void ) |
{ |
return (player[0].is_alive && (!twoPlayerMode || player[1].is_alive)); |
} |
void calc_purple_balls_needed( Player * ); |
bool power_up_weapon( Player *, uint port ); |
void handle_got_purple_ball( Player * ); |
#endif // PLAYER_H |
/contrib/games/opentyrian/src/scroller.c |
---|
0,0 → 1,315 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "scroller.h" |
#include "font.h" |
#include "joystick.h" |
#include "jukebox.h" |
#include "keyboard.h" |
#include "loudness.h" |
#include "mtrand.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "sprite.h" |
#include "varz.h" |
#include "vga256d.h" |
#include "video.h" |
#include <string.h> |
const struct about_text_type about_text[] = |
{ |
{0x30, "----- ~OpenTyrian~ -----"}, |
{0x00, ""}, |
{0x0b, "...eliminating Microsol,"}, |
{0x0b, "one planet at a time..."}, |
{0x00, ""}, |
{0x00, ""}, |
{0x30, "----- ~Developers~ -----"}, |
{0x00, ""}, |
{0x03, "Carl Reinke // Mindless"}, |
{0x07, "Yuri Schlesner // yuriks"}, |
{0x04, "Casey McCann // syntaxglitch"}, |
{0x00, ""}, |
{0x00, ""}, |
{0x30, "----- ~Thanks~ -----"}, |
{0x00, ""}, |
{0x0e, "Thanks to everyone who has"}, |
{0x0e, "assisted the developers by testing"}, |
{0x0e, "the game and reporting bugs."}, |
{0x00, ""}, |
{0x00, ""}, |
{0x05, "Thanks to ~DOSBox~ for the"}, |
{0x05, "FM-Synthesis emulator and"}, |
{0x05, "~AdPlug~ for the Loudness player."}, |
{0x00, ""}, |
{0x00, ""}, |
{0x32, "And special thanks to ~Jason Emery~"}, |
{0x32, "for making all this possible"}, |
{0x32, "by giving Tyrian to its fans."}, |
{0x00, ""}, |
{0x00, ""}, |
/* {0x00, "This is line color test ~0~."}, |
{0x01, "This is line color test ~1~."}, |
{0x02, "This is line color test ~2~."}, |
{0x03, "This is line color test ~3~."}, |
{0x04, "This is line color test ~4~."}, |
{0x05, "This is line color test ~5~."}, |
{0x06, "This is line color test ~6~."}, |
{0x07, "This is line color test ~7~."}, |
{0x08, "This is line color test ~8~."}, |
{0x09, "This is line color test ~9~."}, |
{0x0a, "This is line color test ~A~."}, |
{0x0b, "This is line color test ~B~."}, |
{0x0c, "This is line color test ~C~."}, |
{0x0d, "This is line color test ~D~."}, |
{0x0e, "This is line color test ~E~."}, |
{0x0f, "This is line color test ~F~."},*/ |
{0x00, ""}, |
{0x00, ""}, |
{0x00, ""}, |
{0x00, ""}, |
{0x00, ""}, |
{0x00, ""}, |
{0x00, "Press a key to leave."}, |
{0x00, NULL} |
}; |
#define LINE_HEIGHT 15 |
#define MAX_BEER 5 |
#define BEER_SHAPE 241 |
struct coin_def_type { |
int shape_num; |
int frame_count; |
bool reverse_anim; |
}; |
#define MAX_COINS 20 |
struct coin_def_type coin_defs[] = |
{ |
{1, 6}, {7, 6}, {20, 6}, {26, 6}, // Coins |
{14, 5, true}, {32, 5, true}, {51, 5, true} // Gems |
}; |
/* Text is an array of strings terminated by a NULL */ |
void scroller_sine( const struct about_text_type text[] ) |
{ |
bool ale = mt_rand() % 2; |
int visible_lines = vga_height / LINE_HEIGHT + 1; |
int current_line = -visible_lines; |
int y = 0; |
bool fade_in = true; |
struct coin_type { int x, y, vel, type, cur_frame; bool backwards; } coins[MAX_COINS]; |
struct { int x, y, ay, vx, vy; } beer[MAX_BEER]; |
if (ale) |
{ |
memset(beer, 0, sizeof(beer)); |
} else { |
for (int i = 0; i < MAX_COINS; i++) |
{ |
coins[i].x = mt_rand() % (vga_width - 12); |
coins[i].y = mt_rand() % (vga_height - 20 - 14); |
coins[i].vel = (mt_rand() % 4) + 1; |
coins[i].type = mt_rand() % COUNTOF(coin_defs); |
coins[i].cur_frame = mt_rand() % coin_defs[coins[i].type].frame_count; |
coins[i].backwards = false; |
} |
} |
fade_black(10); |
wait_noinput(true, true, true); |
play_song(40); // BEER |
while (!JE_anyButton()) |
{ |
setdelay(3); |
JE_clr256(VGAScreen); |
if (!ale) |
{ |
for (int i = 0; i < MAX_COINS/2; i++) |
{ |
struct coin_type *coin = &coins[i]; |
blit_sprite2(VGAScreen, coin->x, coin->y, eShapes[4], coin_defs[coin->type].shape_num + coin->cur_frame); |
} |
} |
for (int i = 0; i < visible_lines; i++) |
{ |
if (current_line + i >= 0) |
{ |
if (text[current_line + i].text == NULL) |
{ |
break; |
} |
int line_x = VGAScreen->w / 2; |
int line_y = i * LINE_HEIGHT - y; |
// smooths edges on sine-wave text |
if (text[i + current_line].effect & 0x20) |
{ |
draw_font_hv(VGAScreen, line_x + 1, line_y, text[i + current_line].text, normal_font, centered, text[i + current_line].effect & 0x0f, -10); |
draw_font_hv(VGAScreen, line_x - 1, line_y, text[i + current_line].text, normal_font, centered, text[i + current_line].effect & 0x0f, -10); |
} |
draw_font_hv(VGAScreen, line_x, line_y, text[i + current_line].text, normal_font, centered, text[i + current_line].effect & 0x0f, -4); |
if (text[i + current_line].effect & 0x10) |
{ |
for (int j = 0; j < LINE_HEIGHT; j++) |
{ |
if (line_y + j >= 10 && line_y + j <= vga_height - 10) |
{ |
int waver = sinf((((line_y + j) / 2) % 10) / 5.0f * M_PI) * 3; |
memmove(&((Uint8 *)VGAScreen->pixels)[VGAScreen->pitch * (line_y + j) + waver], |
&((Uint8 *)VGAScreen->pixels)[VGAScreen->pitch * (line_y + j)], |
VGAScreen->pitch); |
} |
} |
} |
} |
} |
if (++y == LINE_HEIGHT) |
{ |
y = 0; |
if (current_line < 0 || text[current_line].text != NULL) |
++current_line; |
else |
current_line = -visible_lines; |
} |
if (!ale) |
{ |
for (int i = MAX_COINS/2; i < MAX_COINS; i++) |
{ |
struct coin_type *coin = &coins[i]; |
blit_sprite2(VGAScreen, coin->x, coin->y, eShapes[4], coin_defs[coin->type].shape_num + coin->cur_frame); |
} |
} |
fill_rectangle_xy(VGAScreen, 0, 0, vga_width - 1, 14, 0); |
fill_rectangle_xy(VGAScreen, 0, vga_height - 14, vga_width - 1, vga_height - 1, 0); |
if (!ale) |
{ |
for (int i = 0; i < MAX_COINS; i++) |
{ |
struct coin_type *coin = &coins[i]; |
if (coin->backwards) |
{ |
coin->cur_frame--; |
} else { |
coin->cur_frame++; |
} |
if (coin->cur_frame == coin_defs[coin->type].frame_count) |
{ |
if (coin_defs[coin->type].reverse_anim) |
{ |
coin->backwards = true; |
coin->cur_frame -= 2; |
} else { |
coin->cur_frame = 0; |
} |
} |
if (coin->cur_frame == -1) |
{ |
coin->cur_frame = 1; |
coin->backwards = false; |
} |
coin->y += coin->vel; |
if (coin->y > vga_height - 14) |
{ |
coin->x = mt_rand() % (vga_width - 12); |
coin->y = 0; |
coin->vel = (mt_rand() % 4) + 1; |
coin->type = mt_rand() % COUNTOF(coin_defs); |
coin->cur_frame = mt_rand() % coin_defs[coin->type].frame_count; |
} |
} |
} else { |
for (uint i = 0; i < COUNTOF(beer); i++) |
{ |
while (beer[i].vx == 0) |
{ |
beer[i].x = mt_rand() % (vga_width - 24); |
beer[i].y = mt_rand() % (vga_height - 28 - 50); |
beer[i].vx = (mt_rand() % 5) - 2; |
} |
beer[i].vy++; |
if (beer[i].x + beer[i].vx > vga_width - 24 || beer[i].x + beer[i].vx < 0) // check if the beer hit the sides |
{ |
beer[i].vx = -beer[i].vx; |
} |
beer[i].x += beer[i].vx; |
if (beer[i].y + beer[i].vy > vga_height - 28) // check if the beer hit the bottom |
{ |
if ((beer[i].vy) < 8) // make sure the beer bounces! |
{ |
beer[i].vy += mt_rand() % 2; |
} else if (beer[i].vy > 16) { // make sure the beer doesn't bounce too high |
beer[i].vy = 16; |
} |
beer[i].vy = -beer[i].vy + (mt_rand() % 3 - 1); |
beer[i].x += (beer[i].vx > 0 ? 1 : -1) * (i % 2 ? 1 : -1); |
} |
beer[i].y += beer[i].vy; |
blit_sprite2x2(VGAScreen, beer[i].x, beer[i].y, eShapes[4], BEER_SHAPE); |
} |
} |
JE_showVGA(); |
if (fade_in) |
{ |
fade_in = false; |
fade_palette(colors, 10, 0, 255); |
SDL_Color white = { 255, 255, 255 }; |
set_colors(white, 254, 254); |
} |
wait_delay(); |
} |
fade_black(10); |
} |
/contrib/games/opentyrian/src/scroller.h |
---|
0,0 → 1,32 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SCROLLER_H |
#define SCROLLER_H |
#include "opentyr.h" |
extern const struct about_text_type { |
int effect; |
const char *text; |
} about_text[]; |
void scroller_sine( const struct about_text_type text[] ); |
#endif /* SCROLLER_H */ |
/contrib/games/opentyrian/src/setup.c |
---|
0,0 → 1,95 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "setup.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "network.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "mainint.h" |
#include "mouse.h" |
#include "video.h" |
#include "SDL.h" |
void JE_textMenuWait( JE_word *waitTime, JE_boolean doGamma ) |
{ |
set_mouse_position(160, 100); |
do |
{ |
JE_showVGA(); |
push_joysticks_as_keyboard(); |
service_SDL_events(true); |
if (doGamma) |
JE_gammaCheck(); |
inputDetected = newkey | mousedown; |
if (lastkey_sym == SDLK_SPACE) |
{ |
lastkey_sym = SDLK_RETURN; |
} |
if (mousedown) |
{ |
newkey = true; |
lastkey_sym = SDLK_RETURN; |
} |
if (has_mouse && input_grab_enabled) |
{ |
if (abs(mouse_y - 100) > 10) |
{ |
inputDetected = true; |
if (mouse_y - 100 < 0) |
{ |
lastkey_sym = SDLK_UP; |
} else { |
lastkey_sym = SDLK_DOWN; |
} |
newkey = true; |
} |
if (abs(mouse_x - 160) > 10) |
{ |
inputDetected = true; |
if (mouse_x - 160 < 0) |
{ |
lastkey_sym = SDLK_LEFT; |
} else { |
lastkey_sym = SDLK_RIGHT; |
} |
newkey = true; |
} |
} |
NETWORK_KEEP_ALIVE(); |
uSDL_Delay(16); |
if (*waitTime > 0) |
{ |
(*waitTime)--; |
} |
} while (!(inputDetected || *waitTime == 1 || haltGame)); |
} |
/contrib/games/opentyrian/src/setup.h |
---|
0,0 → 1,27 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SETUP_H |
#define SETUP_H |
#include "opentyr.h" |
void JE_textMenuWait( JE_word *waitTime, JE_boolean doGamma ); |
#endif /* SETUP_H */ |
/contrib/games/opentyrian/src/shots.c |
---|
0,0 → 1,500 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2013 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "shots.h" |
#include "player.h" |
#include "sprite.h" |
#include "video.h" |
#include "varz.h" |
// I'm pretty sure the last extra entry is never used. |
PlayerShotDataType playerShotData[MAX_PWEAPON + 1]; /* [1..MaxPWeapon+1] */ |
JE_byte shotAvail[MAX_PWEAPON]; /* [1..MaxPWeapon] */ /*0:Avail 1-255:Duration left*/ |
void simulate_player_shots( void ) |
{ |
/* Player Shot Images */ |
for (int z = 0; z < MAX_PWEAPON; z++) |
{ |
if (shotAvail[z] != 0) |
{ |
shotAvail[z]--; |
if (z != MAX_PWEAPON - 1) |
{ |
PlayerShotDataType* shot = &playerShotData[z]; |
shot->shotXM += shot->shotXC; |
if (shot->shotXM <= 100) |
shot->shotX += shot->shotXM; |
shot->shotYM += shot->shotYC; |
shot->shotY += shot->shotYM; |
if (shot->shotYM > 100) |
{ |
shot->shotY -= 120; |
shot->shotY += player[0].delta_y_shot_move; |
} |
if (shot->shotComplicated != 0) |
{ |
shot->shotDevX += shot->shotDirX; |
shot->shotX += shot->shotDevX; |
if (abs(shot->shotDevX) == shot->shotCirSizeX) |
shot->shotDirX = -shot->shotDirX; |
shot->shotDevY += shot->shotDirY; |
shot->shotY += shot->shotDevY; |
if (abs(shot->shotDevY) == shot->shotCirSizeY) |
shot->shotDirY = -shot->shotDirY; |
/*Double Speed Circle Shots - add a second copy of above loop*/ |
} |
int tempShotX = shot->shotX; |
int tempShotY = shot->shotY; |
if (shot->shotX < 0 || shot->shotX > 140 || |
shot->shotY < 0 || shot->shotY > 170) |
{ |
shotAvail[z] = 0; |
goto draw_player_shot_loop_end; |
} |
/* if (shot->shotTrail != 255) |
{ |
if (shot->shotTrail == 98) |
{ |
JE_setupExplosion(shot->shotX - shot->shotXM, shot->shotY - shot->shotYM, shot->shotTrail); |
} else { |
JE_setupExplosion(shot->shotX, shot->shotY, shot->shotTrail); |
} |
}*/ |
JE_word anim_frame = shot->shotGr + shot->shotAni; |
if (++shot->shotAni == shot->shotAniMax) |
shot->shotAni = 0; |
if (anim_frame < 6000) |
{ |
if (anim_frame > 1000) |
anim_frame = anim_frame % 1000; |
if (anim_frame > 500) |
blit_sprite2(VGAScreen, tempShotX+1, tempShotY, shapesW2, anim_frame - 500); |
else |
blit_sprite2(VGAScreen, tempShotX+1, tempShotY, shapesC1, anim_frame); |
} |
} |
draw_player_shot_loop_end: |
; |
} |
} |
} |
static const JE_word linkMultiGr[17] /* [0..16] */ = |
{77,221,183,301,1,282,164,202,58,201,163,281,39,300,182,220,77}; |
static const JE_word linkSonicGr[17] /* [0..16] */ = |
{85,242,131,303,47,284,150,223,66,224,149,283,9,302,130,243,85}; |
static const JE_word linkMult2Gr[17] /* [0..16] */ = |
{78,299,295,297,2,278,276,280,59,279,275,277,40,296,294,298,78}; |
void player_shot_set_direction( JE_integer shot_id, uint weapon_id, JE_real direction ) |
{ |
PlayerShotDataType* shot = &playerShotData[shot_id]; |
shot->shotXM = -roundf(sinf(direction) * shot->shotYM); |
shot->shotYM = -roundf(cosf(direction) * shot->shotYM); |
// Some weapons have sprites for each direction, use those. |
int rounded_dir; |
switch (weapon_id) |
{ |
case 27: |
case 32: |
case 10: |
rounded_dir = roundf(direction * (16 / (2 * M_PI))); /*16 directions*/ |
shot->shotGr = linkMultiGr[rounded_dir]; |
break; |
case 28: |
case 33: |
case 11: |
rounded_dir = roundf(direction * (16 / (2 * M_PI))); /*16 directions*/ |
shot->shotGr = linkSonicGr[rounded_dir]; |
break; |
case 30: |
case 35: |
case 14: |
if (direction > M_PI_2 && direction < M_PI + M_PI_2) |
{ |
shot->shotYC = 1; |
} |
break; |
case 38: |
case 22: |
rounded_dir = roundf(direction * (16 / (2 * M_PI))); /*16 directions*/ |
shot->shotGr = linkMult2Gr[rounded_dir]; |
break; |
} |
} |
bool player_shot_move_and_draw( |
int shot_id, bool* out_is_special, |
int* out_shotx, int* out_shoty, |
JE_integer* out_shot_damage, JE_byte* out_blast_filter, |
JE_byte* out_chain, JE_byte* out_playerNum, |
JE_word* out_special_radiusw, JE_word* out_special_radiush ) |
{ |
PlayerShotDataType* shot = &playerShotData[shot_id]; |
shotAvail[shot_id]--; |
if (shot_id != MAX_PWEAPON - 1) |
{ |
shot->shotXM += shot->shotXC; |
shot->shotX += shot->shotXM; |
JE_integer tmp_shotXM = shot->shotXM; |
if (shot->shotXM > 100) |
{ |
if (shot->shotXM == 101) |
{ |
shot->shotX -= 101; |
shot->shotX += player[shot->playerNumber-1].delta_x_shot_move; |
shot->shotY += player[shot->playerNumber-1].delta_y_shot_move; |
} |
else |
{ |
shot->shotX -= 120; |
shot->shotX += player[shot->playerNumber-1].delta_x_shot_move; |
} |
} |
shot->shotYM += shot->shotYC; |
shot->shotY += shot->shotYM; |
if (shot->shotYM > 100) |
{ |
shot->shotY -= 120; |
shot->shotY += player[shot->playerNumber-1].delta_y_shot_move; |
} |
if (shot->shotComplicated != 0) |
{ |
shot->shotDevX += shot->shotDirX; |
shot->shotX += shot->shotDevX; |
if (abs(shot->shotDevX) == shot->shotCirSizeX) |
shot->shotDirX = -shot->shotDirX; |
shot->shotDevY += shot->shotDirY; |
shot->shotY += shot->shotDevY; |
if (abs(shot->shotDevY) == shot->shotCirSizeY) |
shot->shotDirY = -shot->shotDirY; |
/*Double Speed Circle Shots - add a second copy of above loop*/ |
} |
*out_shotx = shot->shotX; |
*out_shoty = shot->shotY; |
if (shot->shotX < -34 || shot->shotX > 290 || |
shot->shotY < -15 || shot->shotY > 190) |
{ |
shotAvail[shot_id] = 0; |
return false; |
} |
if (shot->shotTrail != 255) |
{ |
if (shot->shotTrail == 98) |
JE_setupExplosion(shot->shotX - shot->shotXM, shot->shotY - shot->shotYM, 0, shot->shotTrail, false, false); |
else |
JE_setupExplosion(shot->shotX, shot->shotY, 0, shot->shotTrail, false, false); |
} |
if (shot->aimAtEnemy != 0) |
{ |
if (--shot->aimDelay == 0) |
{ |
shot->aimDelay = shot->aimDelayMax; |
if (enemyAvail[shot->aimAtEnemy - 1] != 1) |
{ |
if (shot->shotX < enemy[shot->aimAtEnemy - 1].ex) |
shot->shotXM++; |
else |
shot->shotXM--; |
if (shot->shotY < enemy[shot->aimAtEnemy - 1].ey) |
shot->shotYM++; |
else |
shot->shotYM--; |
} |
else |
{ |
if (shot->shotXM > 0) |
shot->shotXM++; |
else |
shot->shotXM--; |
} |
} |
} |
JE_word sprite_frame = shot->shotGr + shot->shotAni; |
if (++shot->shotAni == shot->shotAniMax) |
shot->shotAni = 0; |
*out_shot_damage = shot->shotDmg; |
*out_blast_filter = shot->shotBlastFilter; |
*out_chain = shot->chainReaction; |
*out_playerNum = shot->playerNumber; |
*out_is_special = sprite_frame > 60000; |
if (*out_is_special) |
{ |
blit_sprite_blend(VGAScreen, *out_shotx+1, *out_shoty, OPTION_SHAPES, sprite_frame - 60001); |
*out_special_radiusw = sprite(OPTION_SHAPES, sprite_frame - 60001)->width / 2; |
*out_special_radiush = sprite(OPTION_SHAPES, sprite_frame - 60001)->height / 2; |
} |
else |
{ |
if (sprite_frame > 1000) |
{ |
JE_doSP(*out_shotx+1 + 6, *out_shoty + 6, 5, 3, (sprite_frame / 1000) << 4); |
sprite_frame = sprite_frame % 1000; |
} |
if (sprite_frame > 500) |
{ |
if (background2 && *out_shoty + shadowYDist < 190 && tmp_shotXM < 100) |
blit_sprite2_darken(VGAScreen, *out_shotx+1, *out_shoty + shadowYDist, shapesW2, sprite_frame - 500); |
blit_sprite2(VGAScreen, *out_shotx+1, *out_shoty, shapesW2, sprite_frame - 500); |
} |
else |
{ |
if (background2 && *out_shoty + shadowYDist < 190 && tmp_shotXM < 100) |
blit_sprite2_darken(VGAScreen, *out_shotx+1, *out_shoty + shadowYDist, shapesC1, sprite_frame); |
blit_sprite2(VGAScreen, *out_shotx+1, *out_shoty, shapesC1, sprite_frame); |
} |
} |
} |
return true; |
} |
JE_integer player_shot_create( JE_word portNum, uint bay_i, JE_word PX, JE_word PY, JE_word mouseX, JE_word mouseY, JE_word wpNum, JE_byte playerNum ) |
{ |
static const JE_byte soundChannel[11] /* [1..11] */ = {0, 2, 4, 4, 2, 2, 5, 5, 1, 4, 1}; |
// Bounds check |
if (portNum > PORT_NUM || wpNum <= 0 || wpNum > WEAP_NUM) |
return MAX_PWEAPON; |
const JE_WeaponType* weapon = &weapons[wpNum]; |
if (power < weaponPort[portNum].poweruse) |
return MAX_PWEAPON; |
power -= weaponPort[portNum].poweruse; |
if (weapon->sound > 0) |
soundQueue[soundChannel[bay_i]] = weapon->sound; |
int shot_id = MAX_PWEAPON; |
/*Rot*/ |
for (int multi_i = 1; multi_i <= weapon->multi; multi_i++) |
{ |
for (shot_id = 0; shot_id < MAX_PWEAPON; shot_id++) |
if (shotAvail[shot_id] == 0) |
break; |
if (shot_id == MAX_PWEAPON) |
return MAX_PWEAPON; |
if (shotMultiPos[bay_i] == weapon->max || shotMultiPos[bay_i] > 8) |
shotMultiPos[bay_i] = 1; |
else |
shotMultiPos[bay_i]++; |
PlayerShotDataType* shot = &playerShotData[shot_id]; |
shot->chainReaction = 0; |
shot->playerNumber = playerNum; |
shot->shotAni = 0; |
shot->shotComplicated = weapon->circlesize != 0; |
if (weapon->circlesize == 0) |
{ |
shot->shotDevX = 0; |
shot->shotDirX = 0; |
shot->shotDevY = 0; |
shot->shotDirY = 0; |
shot->shotCirSizeX = 0; |
shot->shotCirSizeY = 0; |
} |
else |
{ |
JE_byte circsize = weapon->circlesize; |
if (circsize > 19) |
{ |
JE_byte circsize_mod20 = circsize % 20; |
shot->shotCirSizeX = circsize_mod20; |
shot->shotDevX = circsize_mod20 >> 1; |
circsize = circsize / 20; |
shot->shotCirSizeY = circsize; |
shot->shotDevY = circsize >> 1; |
} |
else |
{ |
shot->shotCirSizeX = circsize; |
shot->shotCirSizeY = circsize; |
shot->shotDevX = circsize >> 1; |
shot->shotDevY = circsize >> 1; |
} |
shot->shotDirX = 1; |
shot->shotDirY = -1; |
} |
shot->shotTrail = weapon->trail; |
if (weapon->attack[shotMultiPos[bay_i]-1] > 99 && weapon->attack[shotMultiPos[bay_i]-1] < 250) |
{ |
shot->chainReaction = weapon->attack[shotMultiPos[bay_i]-1] - 100; |
shot->shotDmg = 1; |
} |
else |
{ |
shot->shotDmg = weapon->attack[shotMultiPos[bay_i]-1]; |
} |
shot->shotBlastFilter = weapon->shipblastfilter; |
JE_integer tmp_by = weapon->by[shotMultiPos[bay_i]-1]; |
/*Note: Only front selection used for player shots...*/ |
shot->shotX = PX + weapon->bx[shotMultiPos[bay_i]-1]; |
shot->shotY = PY + tmp_by; |
shot->shotYC = -weapon->acceleration; |
shot->shotXC = weapon->accelerationx; |
shot->shotXM = weapon->sx[shotMultiPos[bay_i]-1]; |
// Not sure what this field does exactly. |
JE_byte del = weapon->del[shotMultiPos[bay_i]-1]; |
if (del == 121) |
{ |
shot->shotTrail = 0; |
del = 255; |
} |
shot->shotGr = weapon->sg[shotMultiPos[bay_i]-1]; |
if (shot->shotGr == 0) |
shotAvail[shot_id] = 0; |
else |
shotAvail[shot_id] = del; |
if (del > 100 && del < 120) |
shot->shotAniMax = (del - 100 + 1); |
else |
shot->shotAniMax = weapon->weapani + 1; |
if (del == 99 || del == 98) |
{ |
tmp_by = PX - mouseX; |
if (tmp_by < -5) |
tmp_by = -5; |
else if (tmp_by > 5) |
tmp_by = 5; |
shot->shotXM += tmp_by; |
} |
if (del == 99 || del == 100) |
{ |
tmp_by = PY - mouseY - weapon->sy[shotMultiPos[bay_i]-1]; |
if (tmp_by < -4) |
tmp_by = -4; |
else if (tmp_by > 4) |
tmp_by = 4; |
shot->shotYM = tmp_by; |
} |
else if (weapon->sy[shotMultiPos[bay_i]-1] == 98) |
{ |
shot->shotYM = 0; |
shot->shotYC = -1; |
} |
else if (weapon->sy[shotMultiPos[bay_i]-1] > 100) |
{ |
shot->shotYM = weapon->sy[shotMultiPos[bay_i]-1]; |
shot->shotY -= player[shot->playerNumber-1].delta_y_shot_move; |
} |
else |
{ |
shot->shotYM = -weapon->sy[shotMultiPos[bay_i]-1]; |
} |
if (weapon->sx[shotMultiPos[bay_i]-1] > 100) |
{ |
shot->shotXM = weapon->sx[shotMultiPos[bay_i]-1]; |
shot->shotX -= player[shot->playerNumber-1].delta_x_shot_move; |
if (shot->shotXM == 101) |
shot->shotY -= player[shot->playerNumber-1].delta_y_shot_move; |
} |
if (weapon->aim > 5) /*Guided Shot*/ |
{ |
uint best_dist = 65000; |
JE_byte closest_enemy = 0; |
/*Find Closest Enemy*/ |
for (x = 0; x < 100; x++) |
{ |
if (enemyAvail[x] != 1 && !enemy[x].scoreitem) |
{ |
y = abs(enemy[x].ex - shot->shotX) + abs(enemy[x].ey - shot->shotY); |
if (y < best_dist) |
{ |
best_dist = y; |
closest_enemy = x + 1; |
} |
} |
} |
shot->aimAtEnemy = closest_enemy; |
shot->aimDelay = 5; |
shot->aimDelayMax = weapon->aim - 5; |
} |
else |
{ |
shot->aimAtEnemy = 0; |
} |
shotRepeat[bay_i] = weapon->shotrepeat; |
} |
return shot_id; |
} |
/contrib/games/opentyrian/src/shots.h |
---|
0,0 → 1,58 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2013 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SHOTS_H |
#define SHOTS_H |
#include "opentyr.h" |
typedef struct { |
JE_integer shotX, shotY, shotXM, shotYM, shotXC, shotYC; |
JE_boolean shotComplicated; |
JE_integer shotDevX, shotDirX, shotDevY, shotDirY, shotCirSizeX, shotCirSizeY; |
JE_byte shotTrail; |
JE_word shotGr, shotAni, shotAniMax; |
Uint8 shotDmg; |
JE_byte shotBlastFilter, chainReaction, playerNumber, aimAtEnemy, aimDelay, aimDelayMax; |
} PlayerShotDataType; |
#define MAX_PWEAPON 81 /* 81*/ |
extern PlayerShotDataType playerShotData[MAX_PWEAPON + 1]; |
extern JE_byte shotAvail[MAX_PWEAPON]; |
/** Used in the shop to show weapon previews. */ |
void simulate_player_shots( void ); |
/** Points shot movement in the specified direction. Used for the turret gun. */ |
void player_shot_set_direction( JE_integer shot_id, uint weapon_id, JE_real direction ); |
/** Moves and draws a shot. Does \b not collide it with enemies. |
* \return False if the shot went offscreen, true otherwise. |
*/ |
bool player_shot_move_and_draw( |
int shot_id, bool* out_is_special, |
int* out_shotx, int* out_shoty, |
JE_integer* out_shot_damage, JE_byte* out_blast_filter, |
JE_byte* out_chain, JE_byte* out_playerNum, |
JE_word* out_special_radiusw, JE_word* out_special_radiush ); |
/** Creates a player shot. */ |
JE_integer player_shot_create( JE_word portnum, uint shot_i, JE_word px, JE_word py, |
JE_word mousex, JE_word mousey, |
JE_word wpnum, JE_byte playernum ); |
#endif // SHOTS_H |
/contrib/games/opentyrian/src/sizebuf.c |
---|
0,0 → 1,224 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
/* |
* This file is largely based on (and named after) a set of common reading/ |
* writing functions used in Quake engines. Its purpose is to allow extraction |
* of bytes, words, and dwords in a safe, endian adjused environment and should |
* probably be used in any situation where checking for buffer overflows |
* manually makes the code a godawful mess. |
* |
* Currently this is only used by the animation decoding. |
* |
* This file is written with the intention of being easily converted into a |
* class capable of throwing exceptions if data is out of range. |
* |
* If an operation fails, subsequent operations will also fail. The sizebuf |
* is assumed to be in an invalid state. This COULD be changed pretty easily |
* and in normal Quake IIRC it is. But our MO is to bail on failure, not |
* figure out what went wrong (making throws perfect). |
*/ |
#include "sizebuf.h" |
#include "SDL_endian.h" |
#include <assert.h> |
#include <stdio.h> |
#include <string.h> |
/* Construct buffer with the passed array and size */ |
void SZ_Init(sizebuf_t * sz, Uint8 * buf, unsigned int size) |
{ |
sz->data = buf; |
sz->bufferLen = size; |
sz->bufferPos = 0; |
sz->error = false; |
} |
/* Check error flags */ |
bool SZ_Error(sizebuf_t * sz) |
{ |
return(sz->error); |
} |
/* mimic memset */ |
void SZ_Memset(sizebuf_t * sz, int value, size_t count) |
{ |
/* Do bounds checking before writing */ |
if (sz->error || sz->bufferPos + count > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
/* Memset and increment pointer */ |
memset(sz->data + sz->bufferPos, value, count); |
sz->bufferPos += count; |
} |
/* Mimic memcpy. Two versions, one for buffers, one for sizebuf objects. |
* Overload in C++. */ |
void SZ_Memcpy(sizebuf_t * sz, const Uint8 * buf, size_t count) |
{ |
/* State checking */ |
if (sz->error || sz->bufferPos + count > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
/* Memcpy & increment */ |
memcpy(sz->data + sz->bufferPos, buf, count); |
sz->bufferPos += count; |
} |
void SZ_Memcpy2(sizebuf_t * sz, sizebuf_t * bf, size_t count) |
{ |
/* State checking */ |
if (sz->error || sz->bufferPos + count > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
if (bf->error || bf->bufferPos + count > bf->bufferLen) |
{ |
bf->error = true; |
return; |
} |
/* Memcpy & increment */ |
memcpy(sz->data + sz->bufferPos, bf->data + bf->bufferPos, count); |
sz->bufferPos += count; |
bf->bufferPos += count; |
} |
/* Reposition buffer pointer */ |
void SZ_Seek(sizebuf_t * sz, long count, int mode) |
{ |
/* Okay, it's reasonable to reset the error bool on seeking... */ |
switch(mode) |
{ |
case SEEK_SET: |
sz->bufferPos = count; |
break; |
case SEEK_CUR: |
sz->bufferPos += count; |
break; |
case SEEK_END: |
sz->bufferPos = sz->bufferLen - count; |
break; |
default: |
assert(false); |
} |
/* Check errors */ |
if (sz->bufferPos > sz->bufferLen) |
{ |
sz->error = true; |
} else { |
sz->error = false; |
} |
} |
const Uint8 * SZ_GetCurBufferPtr (sizebuf_t * sz) |
{ |
return(sz->data); |
} |
/* The code below makes use of pointer casts, similar to what is in efread. |
* It's not the ONLY way to write ints to a stream, but it's probably the |
* cleanest of the lot. Better to have it here than littered all over the code. |
*/ |
void MSG_WriteByte(sizebuf_t * sz, unsigned int value) |
{ |
if (sz->error || sz->bufferPos + 1 > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
sz->data[sz->bufferPos] = value; |
sz->bufferPos++; |
} |
void MSG_WriteWord(sizebuf_t * sz, unsigned int value) |
{ |
if (sz->error || sz->bufferPos + 2 > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
*((Uint16 *)(sz->data + sz->bufferPos)) = SDL_SwapLE16( ((Uint16)value) ); |
sz->bufferPos += 2; |
} |
void MSG_WriteDWord(sizebuf_t * sz, unsigned int value) |
{ |
if (sz->error || sz->bufferPos + 4 > sz->bufferLen) |
{ |
sz->error = true; |
return; |
} |
*((Uint32 *)(sz->data + sz->bufferPos)) = SDL_SwapLE32( ((Uint32)value) ); |
sz->bufferPos += 4; |
} |
unsigned int MSG_ReadByte(sizebuf_t * sz) |
{ |
unsigned int ret; |
if (sz->error || sz->bufferPos + 1 > sz->bufferLen) |
{ |
sz->error = true; |
return(0); |
} |
ret = sz->data[sz->bufferPos]; |
sz->bufferPos += 1; |
return(ret); |
} |
unsigned int MSG_ReadWord(sizebuf_t * sz) |
{ |
unsigned int ret; |
if (sz->error || sz->bufferPos + 2 > sz->bufferLen) |
{ |
sz->error = true; |
return(0); |
} |
ret = SDL_SwapLE16(*((Uint16 *)(sz->data + sz->bufferPos))); |
sz->bufferPos += 2; |
return(ret); |
} |
unsigned int MSG_ReadDWord(sizebuf_t * sz) |
{ |
unsigned int ret; |
if (sz->error || sz->bufferPos + 4 > sz->bufferLen) |
{ |
sz->error = true; |
return(0); |
} |
ret = SDL_SwapLE32(*((Uint32 *)(sz->data + sz->bufferPos))); |
sz->bufferPos += 4; |
return(ret); |
} |
/contrib/games/opentyrian/src/sizebuf.h |
---|
0,0 → 1,50 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SIZEBUF_H |
#define SIZEBUF_H |
#include "opentyr.h" |
typedef struct sizebuf_s |
{ |
Uint8 *data; |
unsigned int bufferLen; |
unsigned int bufferPos; |
bool error; |
} sizebuf_t; |
void SZ_Init ( sizebuf_t *, Uint8 *, unsigned int ); /* C style constructor */ |
bool SZ_Error ( sizebuf_t * ); |
void SZ_Memset ( sizebuf_t *, int, size_t ); /* memset with a sizebuf */ |
void SZ_Memcpy ( sizebuf_t *, const Uint8 *, size_t ); /* memcpy with a normal buffer */ |
void SZ_Memcpy2 ( sizebuf_t *, sizebuf_t *, size_t ); /* memcpy with a sizebuf */ |
void SZ_Seek ( sizebuf_t *, long, int ); /* fseek with a sizebuf. */ |
const Uint8 * SZ_GetCurBufferPtr ( sizebuf_t * ); /* Mimic private member, const return */ |
void MSG_WriteByte ( sizebuf_t *, unsigned int ); |
void MSG_WriteWord ( sizebuf_t *, unsigned int ); |
void MSG_WriteDWord ( sizebuf_t *, unsigned int ); |
unsigned int MSG_ReadByte ( sizebuf_t * ); |
unsigned int MSG_ReadWord ( sizebuf_t * ); |
unsigned int MSG_ReadDWord ( sizebuf_t * ); |
#endif |
/contrib/games/opentyrian/src/sndmast.c |
---|
0,0 → 1,77 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "sndmast.h" |
#include "opentyr.h" |
const char soundTitle[SAMPLE_COUNT][9] = /* [1..soundnum + 9] of string [8] */ |
{ |
"SCALEDN2", /*1*/ |
"F2", /*2*/ |
"TEMP10", |
"EXPLSM", |
"PASS3", /*5*/ |
"TEMP2", |
"BYPASS1", |
"EXP1RT", |
"EXPLLOW", |
"TEMP13", /*10*/ |
"EXPRETAP", |
"MT2BOOM", |
"TEMP3", |
"LAZB", /*28K*/ |
"LAZGUN2", /*15*/ |
"SPRING", |
"WARNING", |
"ITEM", |
"HIT2", /*14K*/ |
"MACHNGUN", /*20*/ |
"HYPERD2", |
"EXPLHUG", |
"CLINK1", |
"CLICK", |
"SCALEDN1", /*25*/ |
"TEMP11", |
"TEMP16", |
"SMALL1", |
"POWERUP", |
"VOICE1", |
"VOICE2", |
"VOICE3", |
"VOICE4", |
"VOICE5", |
"VOICE6", |
"VOICE7", |
"VOICE8", |
"VOICE9" |
}; |
const JE_byte windowTextSamples[9] = /* [1..9] */ |
{ |
V_DANGER, |
V_BOSS, |
V_ENEMIES, |
V_CLEARED_PLATFORM, |
V_DANGER, |
V_SPIKES, |
V_ACCELERATE, |
V_DANGER, |
V_ENEMIES |
}; |
/contrib/games/opentyrian/src/sndmast.h |
---|
0,0 → 1,74 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SNDMAST_H |
#define SNDMAST_H |
#include "opentyr.h" |
#define SAMPLE_COUNT 38 |
enum |
{ |
S_NONE = 0, |
S_WEAPON_1 = 1, |
S_WEAPON_2 = 2, |
S_ENEMY_HIT = 3, |
S_EXPLOSION_4 = 4, |
S_WEAPON_5 = 5, |
S_WEAPON_6 = 6, |
S_WEAPON_7 = 7, |
S_SELECT = 8, |
S_EXPLOSION_8 = 8, |
S_EXPLOSION_9 = 9, |
S_WEAPON_10 = 10, |
S_EXPLOSION_11 = 11, |
S_EXPLOSION_12 = 12, |
S_WEAPON_13 = 13, |
S_WEAPON_14 = 14, |
S_WEAPON_15 = 15, |
S_SPRING = 16, |
S_WARNING = 17, |
S_ITEM = 18, |
S_HULL_HIT = 19, |
S_MACHINE_GUN = 20, |
S_SOUL_OF_ZINGLON = 21, |
S_EXPLOSION_22 = 22, |
S_CLINK = 23, |
S_CLICK = 24, |
S_WEAPON_25 = 25, |
S_WEAPON_26 = 26, |
S_SHIELD_HIT = 27, |
S_CURSOR = 28, |
S_POWERUP = 29, |
V_CLEARED_PLATFORM = 30, // "Cleared enemy platform." |
V_BOSS = 31, // "Large enemy approaching." |
V_ENEMIES = 32, // "Enemies ahead." |
V_GOOD_LUCK = 33, // "Good luck." |
V_LEVEL_END = 34, // "Level completed." |
V_DANGER = 35, // "Danger." |
V_SPIKES = 36, // "Warning: spikes ahead." |
V_DATA_CUBE = 37, // "Data acquired." |
V_ACCELERATE = 38, // "Unexplained speed increase." |
}; |
extern const char soundTitle[SAMPLE_COUNT][9]; |
extern const JE_byte windowTextSamples[9]; |
#endif /* SNDMAST_H */ |
/contrib/games/opentyrian/src/sprite.c |
---|
0,0 → 1,734 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "sprite.h" |
#include "file.h" |
#include "opentyr.h" |
#include "video.h" |
#include <assert.h> |
#include <ctype.h> |
Sprite_array sprite_table[SPRITE_TABLES_MAX]; |
Sprite2_array eShapes[6]; |
Sprite2_array shapesC1, shapes6, shapes9, shapesW2; |
void load_sprites_file( unsigned int table, const char *filename ) |
{ |
free_sprites(table); |
FILE *f = dir_fopen_die(data_dir(), filename, "rb"); |
load_sprites(table, f); |
fclose(f); |
} |
void load_sprites( unsigned int table, FILE *f ) |
{ |
free_sprites(table); |
Uint16 temp; |
efread(&temp, sizeof(Uint16), 1, f); |
sprite_table[table].count = temp; |
assert(sprite_table[table].count <= SPRITES_PER_TABLE_MAX); |
for (unsigned int i = 0; i < sprite_table[table].count; ++i) |
{ |
Sprite * const cur_sprite = sprite(table, i); |
if (!getc(f)) // sprite is empty |
continue; |
efread(&cur_sprite->width, sizeof(Uint16), 1, f); |
efread(&cur_sprite->height, sizeof(Uint16), 1, f); |
efread(&cur_sprite->size, sizeof(Uint16), 1, f); |
cur_sprite->data = malloc(cur_sprite->size); |
efread(cur_sprite->data, sizeof(Uint8), cur_sprite->size, f); |
} |
} |
void free_sprites( unsigned int table ) |
{ |
for (unsigned int i = 0; i < sprite_table[table].count; ++i) |
{ |
Sprite * const cur_sprite = sprite(table, i); |
cur_sprite->width = 0; |
cur_sprite->height = 0; |
cur_sprite->size = 0; |
free(cur_sprite->data); |
cur_sprite->data = NULL; |
} |
sprite_table[table].count = 0; |
} |
// does not clip on left or right edges of surface |
void blit_sprite( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = *data; |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite_blend( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2); |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
// does not clip on left or right edges of surface |
// unsafe because it doesn't check that value won't overflow into hue |
// we can replace it when we know that we don't rely on that 'feature' |
void blit_sprite_hv_unsafe( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
hue <<= 4; |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = hue | ((*data & 0x0f) + value); |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite_hv( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
hue <<= 4; |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
{ |
Uint8 temp_value = (*data & 0x0f) + value; |
if (temp_value > 0xf) |
temp_value = (temp_value >= 0x1f) ? 0x0 : 0xf; |
*pixels = hue | temp_value; |
} |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite_hv_blend( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
hue <<= 4; |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
{ |
Uint8 temp_value = (*data & 0x0f) + value; |
if (temp_value > 0xf) |
temp_value = (temp_value >= 0x1f) ? 0x0 : 0xf; |
*pixels = hue | (((*pixels & 0x0f) + temp_value) / 2); |
} |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite_dark( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, bool black ) |
{ |
if (index >= sprite_table[table].count || !sprite_exists(table, index)) |
{ |
assert(false); |
return; |
} |
const Sprite * const cur_sprite = sprite(table, index); |
const Uint8 *data = cur_sprite->data; |
const Uint8 * const data_ul = data + cur_sprite->size; |
const unsigned int width = cur_sprite->width; |
unsigned int x_offset = 0; |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
for (; data < data_ul; ++data) |
{ |
switch (*data) |
{ |
case 255: // transparent pixels |
data++; // next byte tells how many |
pixels += *data; |
x_offset += *data; |
break; |
case 254: // next pixel row |
pixels += width - x_offset; |
x_offset = width; |
break; |
case 253: // 1 transparent pixel |
pixels++; |
x_offset++; |
break; |
default: // set a pixel |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = black ? 0x00 : ((*pixels & 0xf0) | ((*pixels & 0x0f) / 2)); |
pixels++; |
x_offset++; |
break; |
} |
if (x_offset >= width) |
{ |
pixels += surface->pitch - x_offset; |
x_offset = 0; |
} |
} |
} |
void JE_loadCompShapes( Sprite2_array *sprite2s, char s ) |
{ |
char buffer[20]; |
snprintf(buffer, sizeof(buffer), "newsh%c.shp", tolower((unsigned char)s)); |
FILE *f = dir_fopen_die(data_dir(), buffer, "rb"); |
sprite2s->size = ftell_eof(f); |
JE_loadCompShapesB(sprite2s, f); |
fclose(f); |
} |
void JE_loadCompShapesB( Sprite2_array *sprite2s, FILE *f ) |
{ |
free_sprite2s(sprite2s); |
sprite2s->data = malloc(sizeof(Uint8) * sprite2s->size); |
efread(sprite2s->data, sizeof(Uint8), sprite2s->size, f); |
} |
void free_sprite2s( Sprite2_array *sprite2s ) |
{ |
free(sprite2s->data); |
sprite2s->data = NULL; |
} |
// does not clip on left or right edges of surface |
void blit_sprite2( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]); |
for (; *data != 0x0f; ++data) |
{ |
pixels += *data & 0x0f; // second nibble: transparent pixel count |
unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count |
if (count == 0) // move to next pixel row |
{ |
pixels += VGAScreen->pitch - 12; |
} |
else |
{ |
while (count--) |
{ |
++data; |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = *data; |
++pixels; |
} |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite2_blend( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]); |
for (; *data != 0x0f; ++data) |
{ |
pixels += *data & 0x0f; // second nibble: transparent pixel count |
unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count |
if (count == 0) // move to next pixel row |
{ |
pixels += VGAScreen->pitch - 12; |
} |
else |
{ |
while (count--) |
{ |
++data; |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = (((*data & 0x0f) + (*pixels & 0x0f)) / 2) | (*data & 0xf0); |
++pixels; |
} |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite2_darken( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]); |
for (; *data != 0x0f; ++data) |
{ |
pixels += *data & 0x0f; // second nibble: transparent pixel count |
unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count |
if (count == 0) // move to next pixel row |
{ |
pixels += VGAScreen->pitch - 12; |
} |
else |
{ |
while (count--) |
{ |
++data; |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = ((*pixels & 0x0f) / 2) + (*pixels & 0xf0); |
++pixels; |
} |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite2_filter( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index, Uint8 filter ) |
{ |
assert(surface->format->BitsPerPixel == 8); |
Uint8 * pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x; |
const Uint8 * const pixels_ll = (Uint8 *)surface->pixels, // lower limit |
* const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit |
const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]); |
for (; *data != 0x0f; ++data) |
{ |
pixels += *data & 0x0f; // second nibble: transparent pixel count |
unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count |
if (count == 0) // move to next pixel row |
{ |
pixels += VGAScreen->pitch - 12; |
} |
else |
{ |
while (count--) |
{ |
++data; |
if (pixels >= pixels_ul) |
return; |
if (pixels >= pixels_ll) |
*pixels = filter | (*data & 0x0f); |
++pixels; |
} |
} |
} |
} |
// does not clip on left or right edges of surface |
void blit_sprite2x2( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
blit_sprite2(surface, x, y, sprite2s, index); |
blit_sprite2(surface, x + 12, y, sprite2s, index + 1); |
blit_sprite2(surface, x, y + 14, sprite2s, index + 19); |
blit_sprite2(surface, x + 12, y + 14, sprite2s, index + 20); |
} |
// does not clip on left or right edges of surface |
void blit_sprite2x2_blend( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
blit_sprite2_blend(surface, x, y, sprite2s, index); |
blit_sprite2_blend(surface, x + 12, y, sprite2s, index + 1); |
blit_sprite2_blend(surface, x, y + 14, sprite2s, index + 19); |
blit_sprite2_blend(surface, x + 12, y + 14, sprite2s, index + 20); |
} |
// does not clip on left or right edges of surface |
void blit_sprite2x2_darken( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index ) |
{ |
blit_sprite2_darken(surface, x, y, sprite2s, index); |
blit_sprite2_darken(surface, x + 12, y, sprite2s, index + 1); |
blit_sprite2_darken(surface, x, y + 14, sprite2s, index + 19); |
blit_sprite2_darken(surface, x + 12, y + 14, sprite2s, index + 20); |
} |
void JE_loadMainShapeTables( const char *shpfile ) |
{ |
enum { SHP_NUM = 12 }; |
FILE *f = dir_fopen_die(data_dir(), shpfile, "rb"); |
JE_word shpNumb; |
JE_longint shpPos[SHP_NUM + 1]; // +1 for storing file length |
efread(&shpNumb, sizeof(JE_word), 1, f); |
assert(shpNumb + 1u == COUNTOF(shpPos)); |
for (unsigned int i = 0; i < shpNumb; ++i) |
efread(&shpPos[i], sizeof(JE_longint), 1, f); |
fseek(f, 0, SEEK_END); |
for (unsigned int i = shpNumb; i < COUNTOF(shpPos); ++i) |
shpPos[i] = ftell(f); |
int i; |
// fonts, interface, option sprites |
for (i = 0; i < 7; i++) |
{ |
fseek(f, shpPos[i], SEEK_SET); |
load_sprites(i, f); |
} |
// player shot sprites |
shapesC1.size = shpPos[i + 1] - shpPos[i]; |
JE_loadCompShapesB(&shapesC1, f); |
i++; |
// player ship sprites |
shapes9.size = shpPos[i + 1] - shpPos[i]; |
JE_loadCompShapesB(&shapes9 , f); |
i++; |
// power-up sprites |
eShapes[5].size = shpPos[i + 1] - shpPos[i]; |
JE_loadCompShapesB(&eShapes[5], f); |
i++; |
// coins, datacubes, etc sprites |
eShapes[4].size = shpPos[i + 1] - shpPos[i]; |
JE_loadCompShapesB(&eShapes[4], f); |
i++; |
// more player shot sprites |
shapesW2.size = shpPos[i + 1] - shpPos[i]; |
JE_loadCompShapesB(&shapesW2, f); |
fclose(f); |
} |
void free_main_shape_tables( void ) |
{ |
for (uint i = 0; i < COUNTOF(sprite_table); ++i) |
free_sprites(i); |
free_sprite2s(&shapesC1); |
free_sprite2s(&shapes9); |
free_sprite2s(&eShapes[5]); |
free_sprite2s(&eShapes[4]); |
free_sprite2s(&shapesW2); |
} |
/contrib/games/opentyrian/src/sprite.h |
---|
0,0 → 1,116 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef SPRITE_H |
#define SPRITE_H |
#include "opentyr.h" |
#include "SDL.h" |
#include <assert.h> |
#include <stdio.h> |
#define FONT_SHAPES 0 |
#define SMALL_FONT_SHAPES 1 |
#define TINY_FONT 2 |
#define PLANET_SHAPES 3 |
#define FACE_SHAPES 4 |
#define OPTION_SHAPES 5 /*Also contains help shapes*/ |
#define WEAPON_SHAPES 6 |
#define EXTRA_SHAPES 7 /*Used for Ending pics*/ |
#define SPRITE_TABLES_MAX 8 |
#define SPRITES_PER_TABLE_MAX 151 |
typedef struct |
{ |
Uint16 width, height; |
Uint16 size; |
Uint8 *data; |
} |
Sprite; |
typedef struct |
{ |
unsigned int count; |
Sprite sprite[SPRITES_PER_TABLE_MAX]; |
} |
Sprite_array; |
extern Sprite_array sprite_table[SPRITE_TABLES_MAX]; |
static inline Sprite *sprite( unsigned int table, unsigned int index ) |
{ |
assert(table < COUNTOF(sprite_table)); |
assert(index < COUNTOF(sprite_table->sprite)); |
return &sprite_table[table].sprite[index]; |
} |
static inline bool sprite_exists( unsigned int table, unsigned int index ) |
{ |
return (sprite(table, index)->data != NULL); |
} |
static inline Uint16 get_sprite_width( unsigned int table, unsigned int index ) |
{ |
return (sprite_exists(table, index) ? sprite(table, index)->width : 0); |
} |
static inline Uint16 get_sprite_height( unsigned int table, unsigned int index ) |
{ |
return (sprite_exists(table, index) ? sprite(table, index)->height : 0); |
} |
void load_sprites_file( unsigned table, const char *filename ); |
void load_sprites( unsigned int table, FILE *f ); |
void free_sprites( unsigned int table ); |
void blit_sprite( SDL_Surface *, int x, int y, unsigned int table, unsigned int index ); // JE_newDrawCShapeNum |
void blit_sprite_blend( SDL_Surface *, int x, int y, unsigned int table, unsigned int index ); // JE_newDrawCShapeTrick |
void blit_sprite_hv_unsafe( SDL_Surface *, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ); // JE_newDrawCShapeBright |
void blit_sprite_hv( SDL_Surface *, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ); // JE_newDrawCShapeAdjust |
void blit_sprite_hv_blend( SDL_Surface *, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value ); // JE_newDrawCShapeModify |
void blit_sprite_dark( SDL_Surface *, int x, int y, unsigned int table, unsigned int index, bool black ); // JE_newDrawCShapeDarken, JE_newDrawCShapeShadow |
typedef struct |
{ |
unsigned int size; |
Uint8 *data; |
} |
Sprite2_array; |
extern Sprite2_array eShapes[6]; |
extern Sprite2_array shapesC1, shapes6, shapes9, shapesW2; |
void JE_loadCompShapes( Sprite2_array *, JE_char s ); |
void JE_loadCompShapesB( Sprite2_array *, FILE *f ); |
void free_sprite2s( Sprite2_array * ); |
void blit_sprite2( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void blit_sprite2_blend( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void blit_sprite2_darken( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void blit_sprite2_filter( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index, Uint8 filter ); |
void blit_sprite2x2( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void blit_sprite2x2_blend( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void blit_sprite2x2_darken( SDL_Surface *, int x, int y, Sprite2_array, unsigned int index ); |
void JE_loadMainShapeTables( const char *shpfile ); |
void free_main_shape_tables( void ); |
#endif // SPRITE_H |
/contrib/games/opentyrian/src/starlib.c |
---|
0,0 → 1,431 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "starlib.h" |
#include "keyboard.h" |
#include "mtrand.h" |
#include "opentyr.h" |
#include "video.h" |
#include <ctype.h> |
#define starlib_MAX_STARS 1000 |
#define MAX_TYPES 14 |
struct JE_StarType |
{ |
JE_integer spX, spY, spZ; |
JE_integer lastX, lastY; |
}; |
static int tempX, tempY; |
static JE_boolean run; |
static struct JE_StarType star[starlib_MAX_STARS]; |
static JE_byte setup; |
static JE_word stepCounter; |
static JE_word nsp2; |
static JE_shortint nspVar2Inc; |
/* JE: new sprite pointer */ |
static JE_real nsp; |
static JE_real nspVarInc; |
static JE_real nspVarVarInc; |
static JE_word changeTime; |
static JE_boolean doChange; |
static JE_boolean grayB; |
static JE_integer starlib_speed; |
static JE_shortint speedChange; |
static JE_byte pColor; |
void JE_starlib_main( void ) |
{ |
int off; |
JE_word i; |
JE_integer tempZ; |
JE_byte tempCol; |
struct JE_StarType *stars; |
Uint8 *surf; |
JE_wackyCol(); |
grayB = false; |
starlib_speed += speedChange; |
for(stars = star, i = starlib_MAX_STARS; i > 0; stars++, i--) |
{ |
/* Make a pointer to the screen... */ |
surf = VGAScreen->pixels; |
/* Calculate the offset to where we wish to draw */ |
off = (stars->lastX)+(stars->lastY)*320; |
/* We don't want trails in our star field. Erase the old graphic */ |
if (off >= 640 && off < (320*200)-640) |
{ |
surf[off] = 0; /* Shade Level 0 */ |
surf[off-1] = 0; /* Shade Level 1, 2 */ |
surf[off+1] = 0; |
surf[off-2] = 0; |
surf[off+2] = 0; |
surf[off-320] = 0; |
surf[off+320] = 0; |
surf[off-640] = 0; |
surf[off+640] = 0; |
} |
/* Move star */ |
tempZ = stars->spZ; |
tempX = (stars->spX / tempZ) + 160; |
tempY = (stars->spY / tempZ) + 100; |
tempZ -= starlib_speed; |
/* If star is out of range, make a new one */ |
if (tempZ <= 0 || |
tempY == 0 || tempY > 198 || |
tempX > 318 || tempX < 1) |
{ |
stars->spZ = 500; |
JE_newStar(); |
stars->spX = tempX; |
stars->spY = tempY; |
} |
else /* Otherwise, update & draw it */ |
{ |
stars->lastX = tempX; |
stars->lastY = tempY; |
stars->spZ = tempZ; |
off = tempX+tempY*320; |
if (grayB) |
{ |
tempCol = tempZ >> 1; |
} else { |
tempCol = pColor+((tempZ >> 4) & 31); |
} |
/* Draw the pixel! */ |
if (off >= 640 && off < (320*200)-640) |
{ |
surf[off] = tempCol; |
tempCol += 72; |
surf[off-1] = tempCol; |
surf[off+1] = tempCol; |
surf[off-320] = tempCol; |
surf[off+320] = tempCol; |
tempCol += 72; |
surf[off-2] = tempCol; |
surf[off+2] = tempCol; |
surf[off-640] = tempCol; |
surf[off+640] = tempCol; |
} |
} |
} |
if (newkey) |
{ |
switch (toupper(lastkey_char)) |
{ |
case '+': |
starlib_speed++; |
speedChange = 0; |
break; |
case '-': |
starlib_speed--; |
speedChange = 0; |
break; |
case '1': |
JE_changeSetup(1); |
break; |
case '2': |
JE_changeSetup(2); |
break; |
case '3': |
JE_changeSetup(3); |
break; |
case '4': |
JE_changeSetup(4); |
break; |
case '5': |
JE_changeSetup(5); |
break; |
case '6': |
JE_changeSetup(6); |
break; |
case '7': |
JE_changeSetup(7); |
break; |
case '8': |
JE_changeSetup(8); |
break; |
case '9': |
JE_changeSetup(9); |
break; |
case '0': |
JE_changeSetup(10); |
break; |
case '!': |
JE_changeSetup(11); |
break; |
case '@': |
JE_changeSetup(12); |
break; |
case '#': |
JE_changeSetup(13); |
break; |
case '$': |
JE_changeSetup(14); |
break; |
case 'C': |
JE_resetValues(); |
break; |
case 'S': |
nspVarVarInc = mt_rand_1() * 0.01f - 0.005f; |
break; |
case 'X': |
case 27: |
run = false; |
break; |
case '[': |
pColor--; |
break; |
case ']': |
pColor++; |
break; |
case '{': |
pColor -= 72; |
break; |
case '}': |
pColor += 72; |
break; |
case '`': /* ` */ |
doChange = !doChange; |
break; |
case 'P': |
wait_noinput(true, false, false); |
wait_input(true, false, false); |
break; |
default: |
break; |
} |
} |
if (doChange) |
{ |
stepCounter++; |
if (stepCounter > changeTime) |
{ |
JE_changeSetup(0); |
} |
} |
if ((mt_rand() % 1000) == 1) |
{ |
nspVarVarInc = mt_rand_1() * 0.01f - 0.005f; |
} |
nspVarInc += nspVarVarInc; |
} |
void JE_wackyCol( void ) |
{ |
/* YKS: Does nothing */ |
} |
void JE_starlib_init( void ) |
{ |
static JE_boolean initialized = false; |
if (!initialized) |
{ |
initialized = true; |
JE_resetValues(); |
JE_changeSetup(2); |
doChange = true; |
/* RANDOMIZE; */ |
for (int x = 0; x < starlib_MAX_STARS; x++) |
{ |
star[x].spX = (mt_rand() % 64000) - 32000; |
star[x].spY = (mt_rand() % 40000) - 20000; |
star[x].spZ = x+1; |
} |
} |
} |
void JE_resetValues( void ) |
{ |
nsp2 = 1; |
nspVar2Inc = 1; |
nspVarInc = 0.1f; |
nspVarVarInc = 0.0001f; |
nsp = 0; |
pColor = 32; |
starlib_speed = 2; |
speedChange = 0; |
} |
void JE_changeSetup( JE_byte setupType ) |
{ |
stepCounter = 0; |
changeTime = (mt_rand() % 1000); |
if (setupType > 0) |
{ |
setup = setupType; |
} else { |
setup = mt_rand() % (MAX_TYPES + 1); |
} |
if (setup == 1) |
{ |
nspVarInc = 0.1f; |
} |
if (nspVarInc > 2.2f) |
{ |
nspVarInc = 0.1f; |
} |
} |
void JE_newStar( void ) |
{ |
if (setup == 0) |
{ |
tempX = (mt_rand() % 64000) - 32000; |
tempY = (mt_rand() % 40000) - 20000; |
} else { |
nsp = nsp + nspVarInc; /* YKS: < lol */ |
switch (setup) |
{ |
case 1: |
tempX = (int)(sinf(nsp / 30) * 20000); |
tempY = (mt_rand() % 40000) - 20000; |
break; |
case 2: |
tempX = (int)(cosf(nsp) * 20000); |
tempY = (int)(sinf(nsp) * 20000); |
break; |
case 3: |
tempX = (int)(cosf(nsp * 15) * 100) * ((int)(nsp / 6) % 200); |
tempY = (int)(sinf(nsp * 15) * 100) * ((int)(nsp / 6) % 200); |
break; |
case 4: |
tempX = (int)(sinf(nsp / 60) * 20000); |
tempY = (int)(cosf(nsp) * (int)(sinf(nsp / 200) * 300) * 100); |
break; |
case 5: |
tempX = (int)(sinf(nsp / 2) * 20000); |
tempY = (int)(cosf(nsp) * (int)(sinf(nsp / 200) * 300) * 100); |
break; |
case 6: |
tempX = (int)(sinf(nsp) * 40000); |
tempY = (int)(cosf(nsp) * 20000); |
break; |
case 8: |
tempX = (int)(sinf(nsp / 2) * 40000); |
tempY = (int)(cosf(nsp) * 20000); |
break; |
case 7: |
tempX = mt_rand() % 65535; |
if ((mt_rand() % 2) == 0) |
{ |
tempY = (int)(cosf(nsp / 80) * 10000) + 15000; |
} else { |
tempY = 50000 - (int)(cosf(nsp / 80) * 13000); |
} |
break; |
case 9: |
nsp2 += nspVar2Inc; |
if ((nsp2 == 65535) || (nsp2 == 0)) |
{ |
nspVar2Inc = -nspVar2Inc; |
} |
tempX = (int)(cosf(sinf(nsp2 / 10.0f) + (nsp / 500)) * 32000); |
tempY = (int)(sinf(cosf(nsp2 / 10.0f) + (nsp / 500)) * 30000); |
break; |
case 10: |
nsp2 += nspVar2Inc; |
if ((nsp2 == 65535) || (nsp2 == 0)) |
{ |
nspVar2Inc = -nspVar2Inc; |
} |
tempX = (int)(cosf(sinf(nsp2 / 5.0f) + (nsp / 100)) * 32000); |
tempY = (int)(sinf(cosf(nsp2 / 5.0f) + (nsp / 100)) * 30000); |
break;; |
case 11: |
nsp2 += nspVar2Inc; |
if ((nsp2 == 65535) || (nsp2 == 0)) |
{ |
nspVar2Inc = -nspVar2Inc; |
} |
tempX = (int)(cosf(sinf(nsp2 / 1000.0f) + (nsp / 2)) * 32000); |
tempY = (int)(sinf(cosf(nsp2 / 1000.0f) + (nsp / 2)) * 30000); |
break; |
case 12: |
if (nsp != 0) |
{ |
nsp2 += nspVar2Inc; |
if ((nsp2 == 65535) || (nsp2 == 0)) |
{ |
nspVar2Inc = -nspVar2Inc; |
} |
tempX = (int)(cosf(sinf(nsp2 / 2.0f) / (sqrtf(fabsf(nsp)) / 10.0f + 1) + (nsp2 / 100.0f)) * 32000); |
tempY = (int)(sinf(cosf(nsp2 / 2.0f) / (sqrtf(fabsf(nsp)) / 10.0f + 1) + (nsp2 / 100.0f)) * 30000); |
} |
break; |
case 13: |
if (nsp != 0) |
{ |
nsp2 += nspVar2Inc; |
if ((nsp2 == 65535) || (nsp2 == 0)) |
{ |
nspVar2Inc = -nspVar2Inc; |
} |
tempX = (int)(cosf(sinf(nsp2 / 10.0f) / 2 + (nsp / 20)) * 32000); |
tempY = (int)(sinf(sinf(nsp2 / 11.0f) / 2 + (nsp / 20)) * 30000); |
} |
break; |
case 14: |
nsp2 += nspVar2Inc; |
tempX = (int)((sinf(nsp) + cosf(nsp2 / 1000.0f) * 3) * 12000); |
tempY = (int)(cosf(nsp) * 10000) + nsp2; |
break; |
} |
} |
} |
/contrib/games/opentyrian/src/starlib.h |
---|
0,0 → 1,32 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef STARLIB_H |
#define STARLIB_H |
#include "opentyr.h" |
void JE_starlib_main( void ); |
void JE_wackyCol( void ); |
void JE_starlib_init( void ); |
void JE_resetValues( void ); |
void JE_changeSetup( JE_byte setupType ); |
void JE_newStar( void ); |
#endif /* STARLIB_H */ |
/contrib/games/opentyrian/src/std_support.c |
---|
0,0 → 1,26 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "std_support.h" |
char *ot_strchrnul( const char *s, int c ) |
{ |
for (; *s != c && *s != '\0'; ++s) |
; |
return (char *)s; |
} |
/contrib/games/opentyrian/src/std_support.h |
---|
0,0 → 1,37 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef STD_SUPPORT_H |
#define STD_SUPPORT_H |
/*! |
* \file std_support.h |
* \brief Standard library support functions |
*/ |
/*! |
* \brief Locate a character in a a string. |
* |
* \param[in] s the string |
* \param[in] c the character |
* \return the pointer to the first occurrence of \p c in \p s if there is an occurrences; |
* otherwise the pointer to the terminating null character of \p s |
*/ |
char *ot_strchrnul( const char *s, int c ); |
#endif // STD_SUPPORT_H |
/contrib/games/opentyrian/src/tyrian2.c |
---|
0,0 → 1,5112 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "tyrian2.h" |
#include "animlib.h" |
#include "backgrnd.h" |
#include "episodes.h" |
#include "file.h" |
#include "font.h" |
#include "fonthand.h" |
#include "game_menu.h" |
#include "joystick.h" |
#include "keyboard.h" |
#include "lds_play.h" |
#include "loudness.h" |
#include "lvllib.h" |
#include "menus.h" |
#include "mainint.h" |
#include "mouse.h" |
#include "mtrand.h" |
#include "network.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "params.h" |
#include "pcxload.h" |
#include "pcxmast.h" |
#include "picload.h" |
#include "setup.h" |
#include "shots.h" |
#include "sprite.h" |
#include "vga256d.h" |
#include "video.h" |
#include <assert.h> |
#include <ctype.h> |
#include <math.h> |
#include <stdlib.h> |
#include <string.h> |
#include <stdint.h> |
inline static void blit_enemy( SDL_Surface *surface, unsigned int i, signed int x_offset, signed int y_offset, signed int sprite_offset ); |
boss_bar_t boss_bar[2]; |
/* Level Event Data */ |
JE_boolean quit, loadLevelOk; |
struct JE_EventRecType eventRec[EVENT_MAXIMUM]; /* [1..eventMaximum] */ |
JE_word levelEnemyMax; |
JE_word levelEnemyFrequency; |
JE_word levelEnemy[40]; /* [1..40] */ |
char tempStr[31]; |
/* Data used for ItemScreen procedure to indicate items available */ |
JE_byte itemAvail[9][10]; /* [1..9, 1..10] */ |
JE_byte itemAvailMax[9]; /* [1..9] */ |
void JE_starShowVGA( void ) |
{ |
JE_byte *src; |
Uint8 *s = NULL; /* screen pointer, 8-bit specific */ |
int x, y, lightx, lighty, lightdist; |
if (!playerEndLevel && !skipStarShowVGA) |
{ |
s = VGAScreenSeg->pixels; |
src = game_screen->pixels; |
src += 24; |
if (smoothScroll != 0 /*&& thisPlayerNum != 2*/) |
{ |
wait_delay(); |
setjasondelay(frameCountMax); |
} |
if (starShowVGASpecialCode == 1) |
{ |
src += game_screen->pitch * 183; |
for (y = 0; y < 184; y++) |
{ |
memmove(s, src, 264); |
s += VGAScreenSeg->pitch; |
src -= game_screen->pitch; |
} |
} |
else if (starShowVGASpecialCode == 2 && processorType >= 2) |
{ |
lighty = 172 - player[0].y; |
lightx = 281 - player[0].x; |
for (y = 184; y; y--) |
{ |
if (lighty > y) |
{ |
for (x = 320 - 56; x; x--) |
{ |
*s = (*src & 0xf0) | ((*src >> 2) & 0x03); |
s++; |
src++; |
} |
} |
else |
{ |
for (x = 320 - 56; x; x--) |
{ |
lightdist = abs(lightx - x) + lighty; |
if (lightdist < y) |
*s = *src; |
else if (lightdist - y <= 5) |
*s = (*src & 0xf0) | (((*src & 0x0f) + (3 * (5 - (lightdist - y)))) / 4); |
else |
*s = (*src & 0xf0) | ((*src & 0x0f) >> 2); |
s++; |
src++; |
} |
} |
s += 56 + VGAScreenSeg->pitch - 320; |
src += 56 + VGAScreenSeg->pitch - 320; |
} |
} |
else |
{ |
for (y = 0; y < 184; y++) |
{ |
memmove(s, src, 264); |
s += VGAScreenSeg->pitch; |
src += game_screen->pitch; |
} |
} |
JE_showVGA(); |
} |
quitRequested = false; |
skipStarShowVGA = false; |
} |
inline static void blit_enemy( SDL_Surface *surface, unsigned int i, signed int x_offset, signed int y_offset, signed int sprite_offset ) |
{ |
if (enemy[i].sprite2s == NULL) |
{ |
fprintf(stderr, "warning: enemy %d sprite missing\n", i); |
return; |
} |
const int x = enemy[i].ex + x_offset + tempMapXOfs, |
y = enemy[i].ey + y_offset; |
const unsigned int index = enemy[i].egr[enemy[i].enemycycle - 1] + sprite_offset; |
if (enemy[i].filter != 0) |
blit_sprite2_filter(surface, x, y, *enemy[i].sprite2s, index, enemy[i].filter); |
else |
blit_sprite2(surface, x, y, *enemy[i].sprite2s, index); |
} |
void JE_drawEnemy( int enemyOffset ) // actually does a whole lot more than just drawing |
{ |
player[0].x -= 25; |
for (int i = enemyOffset - 25; i < enemyOffset; i++) |
{ |
if (enemyAvail[i] != 1) |
{ |
enemy[i].mapoffset = tempMapXOfs; |
if (enemy[i].xaccel && enemy[i].xaccel - 89u > mt_rand() % 11) |
{ |
if (player[0].x > enemy[i].ex) |
{ |
if (enemy[i].exc < enemy[i].xaccel - 89) |
enemy[i].exc++; |
} |
else |
{ |
if (enemy[i].exc >= 0 || -enemy[i].exc < enemy[i].xaccel - 89) |
enemy[i].exc--; |
} |
} |
if (enemy[i].yaccel && enemy[i].yaccel - 89u > mt_rand() % 11) |
{ |
if (player[0].y > enemy[i].ey) |
{ |
if (enemy[i].eyc < enemy[i].yaccel - 89) |
enemy[i].eyc++; |
} |
else |
{ |
if (enemy[i].eyc >= 0 || -enemy[i].eyc < enemy[i].yaccel - 89) |
enemy[i].eyc--; |
} |
} |
if (enemy[i].ex + tempMapXOfs > -29 && enemy[i].ex + tempMapXOfs < 300) |
{ |
if (enemy[i].aniactive == 1) |
{ |
enemy[i].enemycycle++; |
if (enemy[i].enemycycle == enemy[i].animax) |
enemy[i].aniactive = enemy[i].aniwhenfire; |
else if (enemy[i].enemycycle > enemy[i].ani) |
enemy[i].enemycycle = enemy[i].animin; |
} |
if (enemy[i].egr[enemy[i].enemycycle - 1] == 999) |
goto enemy_gone; |
if (enemy[i].size == 1) // 2x2 enemy |
{ |
if (enemy[i].ey > -13) |
{ |
blit_enemy(VGAScreen, i, -6, -7, 0); |
blit_enemy(VGAScreen, i, 6, -7, 1); |
} |
if (enemy[i].ey > -26 && enemy[i].ey < 182) |
{ |
blit_enemy(VGAScreen, i, -6, 7, 19); |
blit_enemy(VGAScreen, i, 6, 7, 20); |
} |
} |
else |
{ |
if (enemy[i].ey > -13) |
blit_enemy(VGAScreen, i, 0, 0, 0); |
} |
enemy[i].filter = 0; |
} |
if (enemy[i].excc) |
{ |
if (--enemy[i].exccw <= 0) |
{ |
if (enemy[i].exc == enemy[i].exrev) |
{ |
enemy[i].excc = -enemy[i].excc; |
enemy[i].exrev = -enemy[i].exrev; |
enemy[i].exccadd = -enemy[i].exccadd; |
} |
else |
{ |
enemy[i].exc += enemy[i].exccadd; |
enemy[i].exccw = enemy[i].exccwmax; |
if (enemy[i].exc == enemy[i].exrev) |
{ |
enemy[i].excc = -enemy[i].excc; |
enemy[i].exrev = -enemy[i].exrev; |
enemy[i].exccadd = -enemy[i].exccadd; |
} |
} |
} |
} |
if (enemy[i].eycc) |
{ |
if (--enemy[i].eyccw <= 0) |
{ |
if (enemy[i].eyc == enemy[i].eyrev) |
{ |
enemy[i].eycc = -enemy[i].eycc; |
enemy[i].eyrev = -enemy[i].eyrev; |
enemy[i].eyccadd = -enemy[i].eyccadd; |
} |
else |
{ |
enemy[i].eyc += enemy[i].eyccadd; |
enemy[i].eyccw = enemy[i].eyccwmax; |
if (enemy[i].eyc == enemy[i].eyrev) |
{ |
enemy[i].eycc = -enemy[i].eycc; |
enemy[i].eyrev = -enemy[i].eyrev; |
enemy[i].eyccadd = -enemy[i].eyccadd; |
} |
} |
} |
} |
enemy[i].ey += enemy[i].fixedmovey; |
enemy[i].ex += enemy[i].exc; |
if (enemy[i].ex < -80 || enemy[i].ex > 340) |
goto enemy_gone; |
enemy[i].ey += enemy[i].eyc; |
if (enemy[i].ey < -112 || enemy[i].ey > 190) |
goto enemy_gone; |
goto enemy_still_exists; |
enemy_gone: |
/* enemy[i].egr[10] &= 0x00ff; <MXD> madness? */ |
enemyAvail[i] = 1; |
goto draw_enemy_end; |
enemy_still_exists: |
/*X bounce*/ |
if (enemy[i].ex <= enemy[i].xminbounce || enemy[i].ex >= enemy[i].xmaxbounce) |
enemy[i].exc = -enemy[i].exc; |
/*Y bounce*/ |
if (enemy[i].ey <= enemy[i].yminbounce || enemy[i].ey >= enemy[i].ymaxbounce) |
enemy[i].eyc = -enemy[i].eyc; |
/* Evalue != 0 - score item at boundary */ |
if (enemy[i].scoreitem) |
{ |
if (enemy[i].ex < -5) |
enemy[i].ex++; |
if (enemy[i].ex > 245) |
enemy[i].ex--; |
} |
enemy[i].ey += tempBackMove; |
if (enemy[i].ex <= -24 || enemy[i].ex >= 296) |
goto draw_enemy_end; |
tempX = enemy[i].ex; |
tempY = enemy[i].ey; |
temp = enemy[i].enemytype; |
/* Enemy Shots */ |
if (enemy[i].edamaged == 1) |
goto draw_enemy_end; |
enemyOnScreen++; |
if (enemy[i].iced) |
{ |
enemy[i].iced--; |
if (enemy[i].enemyground != 0) |
{ |
enemy[i].filter = 0x09; |
} |
goto draw_enemy_end; |
} |
for (int j = 3; j > 0; j--) |
{ |
if (enemy[i].freq[j-1]) |
{ |
temp3 = enemy[i].tur[j-1]; |
if (--enemy[i].eshotwait[j-1] == 0 && temp3) |
{ |
enemy[i].eshotwait[j-1] = enemy[i].freq[j-1]; |
if (difficultyLevel > 2) |
{ |
enemy[i].eshotwait[j-1] = (enemy[i].eshotwait[j-1] / 2) + 1; |
if (difficultyLevel > 7) |
enemy[i].eshotwait[j-1] = (enemy[i].eshotwait[j-1] / 2) + 1; |
} |
if (galagaMode && (enemy[i].eyc == 0 || (mt_rand() % 400) >= galagaShotFreq)) |
goto draw_enemy_end; |
switch (temp3) |
{ |
case 252: /* Savara Boss DualMissile */ |
if (enemy[i].ey > 20) |
{ |
JE_setupExplosion(tempX - 8 + tempMapXOfs, tempY - 20 - backMove * 8, -2, 6, false, false); |
JE_setupExplosion(tempX + 4 + tempMapXOfs, tempY - 20 - backMove * 8, -2, 6, false, false); |
} |
break; |
case 251:; /* Suck-O-Magnet */ |
const int attractivity = 4 - (abs(player[0].x - tempX) + abs(player[0].y - tempY)) / 100; |
player[0].x_velocity += (player[0].x > tempX) ? -attractivity : attractivity; |
break; |
case 253: /* Left ShortRange Magnet */ |
if (abs(player[0].x + 25 - 14 - tempX) < 24 && abs(player[0].y - tempY) < 28) |
{ |
player[0].x_velocity += 2; |
} |
if (twoPlayerMode && |
(abs(player[1].x - 14 - tempX) < 24 && abs(player[1].y - tempY) < 28)) |
{ |
player[1].x_velocity += 2; |
} |
break; |
case 254: /* Left ShortRange Magnet */ |
if (abs(player[0].x + 25 - 14 - tempX) < 24 && abs(player[0].y - tempY) < 28) |
{ |
player[0].x_velocity -= 2; |
} |
if (twoPlayerMode && |
(abs(player[1].x - 14 - tempX) < 24 && abs(player[1].y - tempY) < 28)) |
{ |
player[1].x_velocity -= 2; |
} |
break; |
case 255: /* Magneto RePulse!! */ |
if (difficultyLevel != 1) /*DIF*/ |
{ |
if (j == 3) |
{ |
enemy[i].filter = 0x70; |
} |
else |
{ |
const int repulsivity = 4 - (abs(player[0].x - tempX) + abs(player[0].y - tempY)) / 20; |
if (repulsivity > 0) |
player[0].x_velocity += (player[0].x > tempX) ? repulsivity : -repulsivity; |
} |
} |
break; |
default: |
/*Rot*/ |
for (int tempCount = weapons[temp3].multi; tempCount > 0; tempCount--) |
{ |
for (b = 0; b < ENEMY_SHOT_MAX; b++) |
{ |
if (enemyShotAvail[b] == 1) |
break; |
} |
if (b == ENEMY_SHOT_MAX) |
goto draw_enemy_end; |
enemyShotAvail[b] = !enemyShotAvail[b]; |
if (weapons[temp3].sound > 0) |
{ |
do |
temp = mt_rand() % 8; |
while (temp == 3); |
soundQueue[temp] = weapons[temp3].sound; |
} |
if (enemy[i].aniactive == 2) |
enemy[i].aniactive = 1; |
if (++enemy[i].eshotmultipos[j-1] > weapons[temp3].max) |
enemy[i].eshotmultipos[j-1] = 1; |
int tempPos = enemy[i].eshotmultipos[j-1] - 1; |
if (j == 1) |
temp2 = 4; |
enemyShot[b].sx = tempX + weapons[temp3].bx[tempPos] + tempMapXOfs; |
enemyShot[b].sy = tempY + weapons[temp3].by[tempPos]; |
enemyShot[b].sdmg = weapons[temp3].attack[tempPos]; |
enemyShot[b].tx = weapons[temp3].tx; |
enemyShot[b].ty = weapons[temp3].ty; |
enemyShot[b].duration = weapons[temp3].del[tempPos]; |
enemyShot[b].animate = 0; |
enemyShot[b].animax = weapons[temp3].weapani; |
enemyShot[b].sgr = weapons[temp3].sg[tempPos]; |
switch (j) |
{ |
case 1: |
enemyShot[b].syc = weapons[temp3].acceleration; |
enemyShot[b].sxc = weapons[temp3].accelerationx; |
enemyShot[b].sxm = weapons[temp3].sx[tempPos]; |
enemyShot[b].sym = weapons[temp3].sy[tempPos]; |
break; |
case 3: |
enemyShot[b].sxc = -weapons[temp3].acceleration; |
enemyShot[b].syc = weapons[temp3].accelerationx; |
enemyShot[b].sxm = -weapons[temp3].sy[tempPos]; |
enemyShot[b].sym = -weapons[temp3].sx[tempPos]; |
break; |
case 2: |
enemyShot[b].sxc = weapons[temp3].acceleration; |
enemyShot[b].syc = -weapons[temp3].acceleration; |
enemyShot[b].sxm = weapons[temp3].sy[tempPos]; |
enemyShot[b].sym = -weapons[temp3].sx[tempPos]; |
break; |
} |
if (weapons[temp3].aim > 0) |
{ |
int aim = weapons[temp3].aim; |
/*DIF*/ |
if (difficultyLevel > 2) |
{ |
aim += difficultyLevel - 2; |
} |
JE_word target_x = player[0].x; |
JE_word target_y = player[0].y; |
if (twoPlayerMode) |
{ |
// fire at live player(s) |
if (player[0].is_alive && !player[1].is_alive) |
temp = 0; |
else if (player[1].is_alive && !player[0].is_alive) |
temp = 1; |
else |
temp = mt_rand() % 2; |
if (temp == 1) |
{ |
target_x = player[1].x - 25; |
target_y = player[1].y; |
} |
} |
int relative_x = (target_x + 25) - tempX - tempMapXOfs - 4; |
if (relative_x == 0) |
relative_x = 1; |
int relative_y = target_y - tempY; |
if (relative_y == 0) |
relative_y = 1; |
const int longest_side = MAX(abs(relative_x), abs(relative_y)); |
enemyShot[b].sxm = roundf((float)relative_x / longest_side * aim); |
enemyShot[b].sym = roundf((float)relative_y / longest_side * aim); |
} |
} |
break; |
} |
} |
} |
} |
/* Enemy Launch Routine */ |
if (enemy[i].launchfreq) |
{ |
if (--enemy[i].launchwait == 0) |
{ |
enemy[i].launchwait = enemy[i].launchfreq; |
if (enemy[i].launchspecial != 0) |
{ |
/*Type 1 : Must be inline with player*/ |
if (abs(enemy[i].ey - player[0].y) > 5) |
goto draw_enemy_end; |
} |
if (enemy[i].aniactive == 2) |
{ |
enemy[i].aniactive = 1; |
} |
if (enemy[i].launchtype == 0) |
goto draw_enemy_end; |
tempW = enemy[i].launchtype; |
b = JE_newEnemy(enemyOffset == 50 ? 75 : enemyOffset - 25, tempW, 0); |
/*Launch Enemy Placement*/ |
if (b > 0) |
{ |
struct JE_SingleEnemyType* e = &enemy[b-1]; |
e->ex = tempX; |
e->ey = tempY + enemyDat[e->enemytype].startyc; |
if (e->size == 0) |
e->ey -= 7; |
if (e->launchtype > 0 && e->launchfreq == 0) |
{ |
if (e->launchtype > 90) |
{ |
e->ex += mt_rand() % ((e->launchtype - 90) * 4) - (e->launchtype - 90) * 2; |
} |
else |
{ |
int target_x = (player[0].x + 25) - tempX - tempMapXOfs - 4; |
if (target_x == 0) |
target_x = 1; |
int tempI5 = player[0].y - tempY; |
if (tempI5 == 0) |
tempI5 = 1; |
const int longest_side = MAX(abs(target_x), abs(tempI5)); |
e->exc = roundf(((float)target_x / longest_side) * e->launchtype); |
e->eyc = roundf(((float)tempI5 / longest_side) * e->launchtype); |
} |
} |
do |
temp = mt_rand() % 8; |
while (temp == 3); |
soundQueue[temp] = randomEnemyLaunchSounds[(mt_rand() % 3)]; |
if (enemy[i].launchspecial == 1 |
&& enemy[i].linknum < 100) |
{ |
e->linknum = enemy[i].linknum; |
} |
} |
} |
} |
} |
draw_enemy_end: |
; |
} |
player[0].x += 25; |
} |
void JE_main( void ) |
{ |
char buffer[256]; |
int lastEnemyOnScreen; |
/* NOTE: BEGIN MAIN PROGRAM HERE AFTER LOADING A GAME OR STARTING A NEW ONE */ |
/* ----------- GAME ROUTINES ------------------------------------- */ |
/* We need to jump to the beginning to make space for the routines */ |
/* --------------------------------------------------------------- */ |
goto start_level_first; |
/*------------------------------GAME LOOP-----------------------------------*/ |
/* Startlevel is called after a previous level is over. If the first level |
is started for a gaming session, startlevelfirst is called instead and |
this code is skipped. The code here finishes the level and prepares for |
the loadmap function. */ |
start_level: |
if (galagaMode) |
twoPlayerMode = false; |
JE_clearKeyboard(); |
free_sprite2s(&eShapes[0]); |
free_sprite2s(&eShapes[1]); |
free_sprite2s(&eShapes[2]); |
free_sprite2s(&eShapes[3]); |
/* Normal speed */ |
if (fastPlay != 0) |
{ |
smoothScroll = true; |
speed = 0x4300; |
JE_resetTimerInt(); |
JE_setTimerInt(); |
} |
if (play_demo || record_demo) |
{ |
if (demo_file) |
{ |
fclose(demo_file); |
demo_file = NULL; |
} |
if (play_demo) |
{ |
stop_song(); |
fade_black(10); |
wait_noinput(true, true, true); |
} |
} |
difficultyLevel = oldDifficultyLevel; /*Return difficulty to normal*/ |
if (!play_demo) |
{ |
if ((!all_players_dead() || normalBonusLevelCurrent || bonusLevelCurrent) && !playerEndLevel) |
{ |
mainLevel = nextLevel; |
JE_endLevelAni(); |
fade_song(); |
} |
else |
{ |
fade_song(); |
fade_black(10); |
JE_loadGame(twoPlayerMode ? 22 : 11); |
if (doNotSaveBackup) |
{ |
superTyrian = false; |
onePlayerAction = false; |
player[0].items.super_arcade_mode = SA_NONE; |
} |
if (bonusLevelCurrent && !playerEndLevel) |
{ |
mainLevel = nextLevel; |
} |
} |
} |
doNotSaveBackup = false; |
if (play_demo) |
return; |
start_level_first: |
set_volume(tyrMusicVolume, fxVolume); |
endLevel = false; |
reallyEndLevel = false; |
playerEndLevel = false; |
extraGame = false; |
doNotSaveBackup = false; |
JE_loadMap(); |
if (mainLevel == 0) // if quit itemscreen |
return; // back to titlescreen |
fade_song(); |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].is_alive = true; |
oldDifficultyLevel = difficultyLevel; |
if (episodeNum == EPISODE_AVAILABLE) |
difficultyLevel--; |
if (difficultyLevel < 1) |
difficultyLevel = 1; |
player[0].x = 100; |
player[0].y = 180; |
player[1].x = 190; |
player[1].y = 180; |
assert(COUNTOF(player->old_x) == COUNTOF(player->old_y)); |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
for (uint j = 0; j < COUNTOF(player->old_x); ++j) |
{ |
player[i].old_x[j] = player[i].x - (19 - j); |
player[i].old_y[j] = player[i].y - 18; |
} |
player[i].last_x_shot_move = player[i].x; |
player[i].last_y_shot_move = player[i].y; |
} |
JE_loadPic(VGAScreen, twoPlayerMode ? 6 : 3, false); |
JE_drawOptions(); |
JE_outText(VGAScreen, 268, twoPlayerMode ? 76 : 118, levelName, 12, 4); |
JE_showVGA(); |
JE_gammaCorrect(&colors, gammaCorrection); |
fade_palette(colors, 50, 0, 255); |
free_sprite2s(&shapes6); |
JE_loadCompShapes(&shapes6, '6'); // explosion sprites |
/* MAPX will already be set correctly */ |
mapY = 300 - 8; |
mapY2 = 600 - 8; |
mapY3 = 600 - 8; |
mapYPos = &megaData1.mainmap[mapY][0] - 1; |
mapY2Pos = &megaData2.mainmap[mapY2][0] - 1; |
mapY3Pos = &megaData3.mainmap[mapY3][0] - 1; |
mapXPos = 0; |
mapXOfs = 0; |
mapX2Pos = 0; |
mapX3Pos = 0; |
mapX3Ofs = 0; |
mapXbpPos = 0; |
mapX2bpPos = 0; |
mapX3bpPos = 0; |
map1YDelay = 1; |
map1YDelayMax = 1; |
map2YDelay = 1; |
map2YDelayMax = 1; |
musicFade = false; |
backPos = 0; |
backPos2 = 0; |
backPos3 = 0; |
power = 0; |
starfield_speed = 1; |
/* Setup player ship graphics */ |
JE_getShipInfo(); |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
player[i].x_velocity = 0; |
player[i].y_velocity = 0; |
player[i].invulnerable_ticks = 100; |
} |
newkey = newmouse = false; |
/* Initialize Level Data and Debug Mode */ |
levelEnd = 255; |
levelEndWarp = -4; |
levelEndFxWait = 0; |
warningCol = 120; |
warningColChange = 1; |
warningSoundDelay = 0; |
armorShipDelay = 50; |
bonusLevel = false; |
readyToEndLevel = false; |
firstGameOver = true; |
eventLoc = 1; |
curLoc = 0; |
backMove = 1; |
backMove2 = 2; |
backMove3 = 3; |
explodeMove = 2; |
enemiesActive = true; |
for(temp = 0; temp < 3; temp++) |
{ |
button[temp] = false; |
} |
stopBackgrounds = false; |
stopBackgroundNum = 0; |
background3x1 = false; |
background3x1b = false; |
background3over = 0; |
background2over = 1; |
topEnemyOver = false; |
skyEnemyOverAll = false; |
smallEnemyAdjust = false; |
starActive = true; |
enemyContinualDamage = false; |
levelEnemyFrequency = 96; |
quitRequested = false; |
for (unsigned int i = 0; i < COUNTOF(boss_bar); i++) |
boss_bar[i].link_num = 0; |
forceEvents = false; /*Force events to continue if background movement = 0*/ |
superEnemy254Jump = 0; /*When Enemy with PL 254 dies*/ |
/* Filter Status */ |
filterActive = true; |
filterFade = true; |
filterFadeStart = false; |
levelFilter = -99; |
levelBrightness = -14; |
levelBrightnessChg = 1; |
background2notTransparent = false; |
uint old_weapon_bar[2] = { 0, 0 }; // only redrawn when they change |
/* Initially erase power bars */ |
lastPower = power / 10; |
/* Initial Text */ |
JE_drawTextWindow(miscText[20]); |
/* Setup Armor/Shield Data */ |
shieldWait = 1; |
shieldT = shields[player[0].items.shield].tpwr * 20; |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
player[i].shield = shields[player[i].items.shield].mpwr; |
player[i].shield_max = player[i].shield * 2; |
} |
JE_drawShield(); |
JE_drawArmor(); |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].superbombs = 0; |
/* Set cubes to 0 */ |
cubeMax = 0; |
/* Secret Level Display */ |
flash = 0; |
flashChange = 1; |
displayTime = 0; |
play_song(levelSong - 1); |
JE_drawPortConfigButtons(); |
/* --- MAIN LOOP --- */ |
newkey = false; |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
JE_clearSpecialRequests(); |
mt_srand(32402394); |
} |
#endif |
initialize_starfield(); |
JE_setNewGameSpeed(); |
/* JE_setVol(tyrMusicVolume, fxPlayVol >> 2); NOTE: MXD killed this because it was broken */ |
/*Save backup game*/ |
if (!play_demo && !doNotSaveBackup) |
{ |
temp = twoPlayerMode ? 22 : 11; |
JE_saveGame(temp, "LAST LEVEL "); |
} |
if (!play_demo && record_demo) |
{ |
Uint8 new_demo_num = 0; |
do |
{ |
sprintf(tempStr, "demorec.%d", new_demo_num++); |
} |
while (dir_file_exists(get_user_directory(), tempStr)); // until file doesn't exist |
demo_file = dir_fopen_warn(get_user_directory(), tempStr, "wb"); |
if (!demo_file) |
exit(1); |
efwrite(&episodeNum, 1, 1, demo_file); |
efwrite(levelName, 1, 10, demo_file); |
efwrite(&lvlFileNum, 1, 1, demo_file); |
fputc(player[0].items.weapon[FRONT_WEAPON].id, demo_file); |
fputc(player[0].items.weapon[REAR_WEAPON].id, demo_file); |
fputc(player[0].items.super_arcade_mode, demo_file); |
fputc(player[0].items.sidekick[LEFT_SIDEKICK], demo_file); |
fputc(player[0].items.sidekick[RIGHT_SIDEKICK], demo_file); |
fputc(player[0].items.generator, demo_file); |
fputc(player[0].items.sidekick_level, demo_file); |
fputc(player[0].items.sidekick_series, demo_file); |
fputc(initial_episode_num, demo_file); |
fputc(player[0].items.shield, demo_file); |
fputc(player[0].items.special, demo_file); |
fputc(player[0].items.ship, demo_file); |
for (uint i = 0; i < 2; ++i) |
fputc(player[0].items.weapon[i].power, demo_file); |
for (uint i = 0; i < 3; ++i) |
fputc(0, demo_file); |
efwrite(&levelSong, 1, 1, demo_file); |
demo_keys = 0; |
demo_keys_wait = 0; |
} |
twoPlayerLinked = false; |
linkGunDirec = M_PI; |
for (uint i = 0; i < COUNTOF(player); ++i) |
calc_purple_balls_needed(&player[i]); |
damageRate = 2; /*Normal Rate for Collision Damage*/ |
chargeWait = 5; |
chargeLevel = 0; |
chargeMax = 5; |
chargeGr = 0; |
chargeGrWait = 3; |
portConfigChange = false; |
/*Destruction Ratio*/ |
totalEnemy = 0; |
enemyKilled = 0; |
astralDuration = 0; |
superArcadePowerUp = 1; |
yourInGameMenuRequest = false; |
constantLastX = -1; |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].exploding_ticks = 0; |
if (isNetworkGame) |
{ |
JE_loadItemDat(); |
} |
memset(enemyAvail, 1, sizeof(enemyAvail)); |
for (uint i = 0; i < COUNTOF(enemyShotAvail); i++) |
enemyShotAvail[i] = 1; |
/*Initialize Shots*/ |
memset(playerShotData, 0, sizeof(playerShotData)); |
memset(shotAvail, 0, sizeof(shotAvail)); |
memset(shotMultiPos, 0, sizeof(shotMultiPos)); |
memset(shotRepeat, 1, sizeof(shotRepeat)); |
memset(button, 0, sizeof(button)); |
memset(globalFlags, 0, sizeof(globalFlags)); |
memset(explosions, 0, sizeof(explosions)); |
memset(rep_explosions, 0, sizeof(rep_explosions)); |
/* --- Clear Sound Queue --- */ |
memset(soundQueue, 0, sizeof(soundQueue)); |
soundQueue[3] = V_GOOD_LUCK; |
memset(enemyShapeTables, 0, sizeof(enemyShapeTables)); |
memset(enemy, 0, sizeof(enemy)); |
memset(SFCurrentCode, 0, sizeof(SFCurrentCode)); |
memset(SFExecuted, 0, sizeof(SFExecuted)); |
zinglonDuration = 0; |
specialWait = 0; |
nextSpecialWait = 0; |
optionAttachmentMove = 0; /*Launch the Attachments!*/ |
optionAttachmentLinked = true; |
editShip1 = false; |
editShip2 = false; |
memset(smoothies, 0, sizeof(smoothies)); |
levelTimer = false; |
randomExplosions = false; |
last_superpixel = 0; |
memset(superpixels, 0, sizeof(superpixels)); |
returnActive = false; |
galagaShotFreq = 0; |
if (galagaMode) |
{ |
difficultyLevel = 2; |
} |
galagaLife = 10000; |
JE_drawOptionLevel(); |
// keeps map from scrolling past the top |
BKwrap1 = BKwrap1to = &megaData1.mainmap[1][0]; |
BKwrap2 = BKwrap2to = &megaData2.mainmap[1][0]; |
BKwrap3 = BKwrap3to = &megaData3.mainmap[1][0]; |
level_loop: |
//tempScreenSeg = game_screen; /* side-effect of game_screen */ |
if (isNetworkGame) |
{ |
smoothies[9-1] = false; |
smoothies[6-1] = false; |
} else { |
starShowVGASpecialCode = smoothies[9-1] + (smoothies[6-1] << 1); |
} |
/*Background Wrapping*/ |
if (mapYPos <= BKwrap1) |
{ |
mapYPos = BKwrap1to; |
} |
if (mapY2Pos <= BKwrap2) |
{ |
mapY2Pos = BKwrap2to; |
} |
if (mapY3Pos <= BKwrap3) |
{ |
mapY3Pos = BKwrap3to; |
} |
allPlayersGone = all_players_dead() && |
((*player[0].lives == 1 && player[0].exploding_ticks == 0) || (!onePlayerAction && !twoPlayerMode)) && |
((*player[1].lives == 1 && player[1].exploding_ticks == 0) || !twoPlayerMode); |
/*-----MUSIC FADE------*/ |
if (musicFade) |
{ |
if (tempVolume > 10) |
{ |
tempVolume--; |
set_volume(tempVolume, fxVolume); |
} |
else |
{ |
musicFade = false; |
} |
} |
if (!allPlayersGone && levelEnd > 0 && endLevel) |
{ |
play_song(9); |
musicFade = false; |
} |
else if (!playing && firstGameOver) |
{ |
play_song(levelSong - 1); |
} |
if (!endLevel) // draw HUD |
{ |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
/*-----------------------Message Bar------------------------*/ |
if (textErase > 0 && --textErase == 0) |
blit_sprite(VGAScreenSeg, 16, 189, OPTION_SHAPES, 36); // in-game message area |
/*------------------------Shield Gen-------------------------*/ |
if (galagaMode) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].shield = 0; |
// spawned dragonwing died :( |
if (*player[1].lives == 0 || player[1].armor == 0) |
twoPlayerMode = false; |
if (player[0].cash >= (unsigned)galagaLife) |
{ |
soundQueue[6] = S_EXPLOSION_11; |
soundQueue[7] = S_SOUL_OF_ZINGLON; |
if (*player[0].lives < 11) |
++(*player[0].lives); |
else |
player[0].cash += 1000; |
if (galagaLife == 10000) |
galagaLife = 20000; |
else |
galagaLife += 25000; |
} |
} |
else // not galagaMode |
{ |
if (twoPlayerMode) |
{ |
if (--shieldWait == 0) |
{ |
shieldWait = 15; |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
if (player[i].shield < player[i].shield_max && player[i].is_alive) |
++player[i].shield; |
} |
JE_drawShield(); |
} |
} |
else if (player[0].is_alive && player[0].shield < player[0].shield_max && power > shieldT) |
{ |
if (--shieldWait == 0) |
{ |
shieldWait = 15; |
power -= shieldT; |
++player[0].shield; |
if (player[1].shield < player[0].shield_max) |
++player[1].shield; |
JE_drawShield(); |
} |
} |
} |
/*---------------------Weapon Display-------------------------*/ |
for (uint i = 0; i < 2; ++i) |
{ |
uint item_power = player[twoPlayerMode ? i : 0].items.weapon[i].power; |
if (old_weapon_bar[i] != item_power) |
{ |
old_weapon_bar[i] = item_power; |
int x = twoPlayerMode ? 286 : 289, |
y = (i == 0) ? (twoPlayerMode ? 6 : 17) : (twoPlayerMode ? 100 : 38); |
fill_rectangle_xy(VGAScreenSeg, x, y, x + 1 + 10 * 2, y + 2, 0); |
for (uint j = 1; j <= item_power; ++j) |
{ |
JE_rectangle(VGAScreen, x, y, x + 1, y + 2, 115 + j); /* SEGa000 */ |
x += 2; |
} |
} |
} |
/*------------------------Power Bar-------------------------*/ |
if (twoPlayerMode || onePlayerAction) |
{ |
power = 900; |
} |
else |
{ |
power += powerAdd; |
if (power > 900) |
power = 900; |
temp = power / 10; |
if (temp != lastPower) |
{ |
if (temp > lastPower) |
fill_rectangle_xy(VGAScreenSeg, 269, 113 - 11 - temp, 276, 114 - 11 - lastPower, 113 + temp / 7); |
else |
fill_rectangle_xy(VGAScreenSeg, 269, 113 - 11 - lastPower, 276, 114 - 11 - temp, 0); |
lastPower = temp; |
} |
} |
oldMapX3Ofs = mapX3Ofs; |
enemyOnScreen = 0; |
} |
/* use game_screen for all the generic drawing functions */ |
VGAScreen = game_screen; |
/*---------------------------EVENTS-------------------------*/ |
while (eventRec[eventLoc-1].eventtime <= curLoc && eventLoc <= maxEvent) |
JE_eventSystem(); |
if (isNetworkGame && reallyEndLevel) |
goto start_level; |
/* SMOOTHIES! */ |
JE_checkSmoothies(); |
if (anySmoothies) |
VGAScreen = VGAScreen2; // this makes things complicated, but we do it anyway :( |
/* --- BACKGROUNDS --- */ |
/* --- BACKGROUND 1 --- */ |
if (forceEvents && !backMove) |
curLoc++; |
if (map1YDelayMax > 1 && backMove < 2) |
backMove = (map1YDelay == 1) ? 1 : 0; |
/*Draw background*/ |
if (astralDuration == 0) |
draw_background_1(VGAScreen); |
else |
JE_clr256(VGAScreen); |
/*Set Movement of background 1*/ |
if (--map1YDelay == 0) |
{ |
map1YDelay = map1YDelayMax; |
curLoc += backMove; |
backPos += backMove; |
if (backPos > 27) |
{ |
backPos -= 28; |
mapY--; |
mapYPos -= 14; /*Map Width*/ |
} |
} |
if (starActive || astralDuration > 0) |
{ |
update_and_draw_starfield(VGAScreen, starfield_speed); |
} |
if (processorType > 1 && smoothies[5-1]) |
{ |
iced_blur_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
/*-----------------------BACKGROUNDS------------------------*/ |
/*-----------------------BACKGROUND 2------------------------*/ |
if (background2over == 3) |
{ |
draw_background_2(VGAScreen); |
background2 = true; |
} |
if (background2over == 0) |
{ |
if (!(smoothies[2-1] && processorType < 4) && !(smoothies[1-1] && processorType == 3)) |
{ |
if (wild && !background2notTransparent) |
draw_background_2_blend(VGAScreen); |
else |
draw_background_2(VGAScreen); |
} |
} |
if (smoothies[0] && processorType > 2 && smoothie_data[0] == 0) |
{ |
lava_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
if (smoothies[2-1] && processorType > 2) |
{ |
water_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
/*-----------------------Ground Enemy------------------------*/ |
lastEnemyOnScreen = enemyOnScreen; |
tempMapXOfs = mapXOfs; |
tempBackMove = backMove; |
JE_drawEnemy(50); |
JE_drawEnemy(100); |
if (enemyOnScreen == 0 || enemyOnScreen == lastEnemyOnScreen) |
{ |
if (stopBackgroundNum == 1) |
stopBackgroundNum = 9; |
} |
if (smoothies[0] && processorType > 2 && smoothie_data[0] > 0) |
{ |
lava_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
if (superWild) |
{ |
neat += 3; |
JE_darkenBackground(neat); |
} |
/*-----------------------BACKGROUNDS------------------------*/ |
/*-----------------------BACKGROUND 2------------------------*/ |
if (!(smoothies[2-1] && processorType < 4) && |
!(smoothies[1-1] && processorType == 3)) |
{ |
if (background2over == 1) |
{ |
if (wild && !background2notTransparent) |
draw_background_2_blend(VGAScreen); |
else |
draw_background_2(VGAScreen); |
} |
} |
if (superWild) |
{ |
neat++; |
JE_darkenBackground(neat); |
} |
if (background3over == 2) |
draw_background_3(VGAScreen); |
/* New Enemy */ |
if (enemiesActive && mt_rand() % 100 > levelEnemyFrequency) |
{ |
tempW = levelEnemy[mt_rand() % levelEnemyMax]; |
if (tempW == 2) |
soundQueue[3] = S_WEAPON_7; |
b = JE_newEnemy(0, tempW, 0); |
} |
if (processorType > 1 && smoothies[3-1]) |
{ |
iced_blur_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
if (processorType > 1 && smoothies[4-1]) |
{ |
blur_filter(game_screen, VGAScreen); |
VGAScreen = game_screen; |
} |
/* Draw Sky Enemy */ |
if (!skyEnemyOverAll) |
{ |
lastEnemyOnScreen = enemyOnScreen; |
tempMapXOfs = mapX2Ofs; |
tempBackMove = 0; |
JE_drawEnemy(25); |
if (enemyOnScreen == lastEnemyOnScreen) |
{ |
if (stopBackgroundNum == 2) |
stopBackgroundNum = 9; |
} |
} |
if (background3over == 0) |
draw_background_3(VGAScreen); |
/* Draw Top Enemy */ |
if (!topEnemyOver) |
{ |
tempMapXOfs = (background3x1 == 0) ? oldMapX3Ofs : mapXOfs; |
tempBackMove = backMove3; |
JE_drawEnemy(75); |
} |
/* Player Shot Images */ |
for (int z = 0; z < MAX_PWEAPON; z++) |
{ |
if (shotAvail[z] != 0) |
{ |
bool is_special = false; |
int tempShotX = 0, tempShotY = 0; |
JE_byte chain; |
JE_byte playerNum; |
JE_word tempX2, tempY2; |
JE_integer damage; |
if (!player_shot_move_and_draw(z, &is_special, &tempShotX, &tempShotY, &damage, &temp2, &chain, &playerNum, &tempX2, &tempY2)) |
{ |
goto draw_player_shot_loop_end; |
} |
for (b = 0; b < 100; b++) |
{ |
if (enemyAvail[b] == 0) |
{ |
bool collided; |
if (z == MAX_PWEAPON - 1) |
{ |
temp = 25 - abs(zinglonDuration - 25); |
collided = abs(enemy[b].ex + enemy[b].mapoffset - (player[0].x + 7)) < temp; |
temp2 = 9; |
chain = 0; |
damage = 10; |
} |
else if (is_special) |
{ |
collided = ((enemy[b].enemycycle == 0) && |
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX - tempX2) < (25 + tempX2)) && |
(abs(enemy[b].ey - tempShotY - 12 - tempY2) < (29 + tempY2))) || |
((enemy[b].enemycycle > 0) && |
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX - tempX2) < (13 + tempX2)) && |
(abs(enemy[b].ey - tempShotY - 6 - tempY2) < (15 + tempY2))); |
} |
else |
{ |
collided = ((enemy[b].enemycycle == 0) && |
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX) < 25) && (abs(enemy[b].ey - tempShotY - 12) < 29)) || |
((enemy[b].enemycycle > 0) && |
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX) < 13) && (abs(enemy[b].ey - tempShotY - 6) < 15)); |
} |
if (collided) |
{ |
if (chain > 0) |
{ |
shotMultiPos[SHOT_MISC] = 0; |
b = player_shot_create(0, SHOT_MISC, tempShotX, tempShotY, mouseX, mouseY, chain, playerNum); |
shotAvail[z] = 0; |
goto draw_player_shot_loop_end; |
} |
infiniteShot = false; |
if (damage == 99) |
{ |
damage = 0; |
doIced = 40; |
enemy[b].iced = 40; |
} |
else |
{ |
doIced = 0; |
if (damage >= 250) |
{ |
damage = damage - 250; |
infiniteShot = true; |
} |
} |
int armorleft = enemy[b].armorleft; |
temp = enemy[b].linknum; |
if (temp == 0) |
temp = 255; |
if (enemy[b].armorleft < 255) |
{ |
for (unsigned int i = 0; i < COUNTOF(boss_bar); i++) |
if (temp == boss_bar[i].link_num) |
boss_bar[i].color = 6; |
if (enemy[b].enemyground) |
enemy[b].filter = temp2; |
for (unsigned int e = 0; e < COUNTOF(enemy); e++) |
{ |
if (enemy[e].linknum == temp && |
enemyAvail[e] != 1 && |
enemy[e].enemyground != 0) |
{ |
if (doIced) |
enemy[e].iced = doIced; |
enemy[e].filter = temp2; |
} |
} |
} |
if (armorleft > damage) |
{ |
if (z != MAX_PWEAPON - 1) |
{ |
if (enemy[b].armorleft != 255) |
{ |
enemy[b].armorleft -= damage; |
JE_setupExplosion(tempShotX, tempShotY, 0, 0, false, false); |
} |
else |
{ |
JE_doSP(tempShotX + 6, tempShotY + 6, damage / 2 + 3, damage / 4 + 2, temp2); |
} |
} |
soundQueue[5] = S_ENEMY_HIT; |
if ((armorleft - damage <= enemy[b].edlevel) && |
((!enemy[b].edamaged) ^ (enemy[b].edani < 0))) |
{ |
for (temp3 = 0; temp3 < 100; temp3++) |
{ |
if (enemyAvail[temp3] != 1) |
{ |
int linknum = enemy[temp3].linknum; |
if ( |
(temp3 == b) || |
( |
(temp != 255) && |
( |
((enemy[temp3].edlevel > 0) && (linknum == temp)) || |
( |
(enemyContinualDamage && (temp - 100 == linknum)) || |
((linknum > 40) && (linknum / 20 == temp / 20) && (linknum <= temp)) |
) |
) |
) |
) |
{ |
enemy[temp3].enemycycle = 1; |
enemy[temp3].edamaged = !enemy[temp3].edamaged; |
if (enemy[temp3].edani != 0) |
{ |
enemy[temp3].ani = abs(enemy[temp3].edani); |
enemy[temp3].aniactive = 1; |
enemy[temp3].animax = 0; |
enemy[temp3].animin = enemy[temp3].edgr; |
enemy[temp3].enemycycle = enemy[temp3].animin - 1; |
} |
else if (enemy[temp3].edgr > 0) |
{ |
enemy[temp3].egr[1-1] = enemy[temp3].edgr; |
enemy[temp3].ani = 1; |
enemy[temp3].aniactive = 0; |
enemy[temp3].animax = 0; |
enemy[temp3].animin = 1; |
} |
else |
{ |
enemyAvail[temp3] = 1; |
enemyKilled++; |
} |
enemy[temp3].aniwhenfire = 0; |
if (enemy[temp3].armorleft > (unsigned char)enemy[temp3].edlevel) |
enemy[temp3].armorleft = enemy[temp3].edlevel; |
tempX = enemy[temp3].ex + enemy[temp3].mapoffset; |
tempY = enemy[temp3].ey; |
if (enemyDat[enemy[temp3].enemytype].esize != 1) |
JE_setupExplosion(tempX, tempY - 6, 0, 1, false, false); |
else |
JE_setupExplosionLarge(enemy[temp3].enemyground, enemy[temp3].explonum / 2, tempX, tempY); |
} |
} |
} |
} |
} |
else |
{ |
if ((temp == 254) && (superEnemy254Jump > 0)) |
JE_eventJump(superEnemy254Jump); |
for (temp2 = 0; temp2 < 100; temp2++) |
{ |
if (enemyAvail[temp2] != 1) |
{ |
temp3 = enemy[temp2].linknum; |
if ((temp2 == b) || (temp == 254) || |
((temp != 255) && ((temp == temp3) || (temp - 100 == temp3) |
|| ((temp3 > 40) && (temp3 / 20 == temp / 20) && (temp3 <= temp))))) |
{ |
int enemy_screen_x = enemy[temp2].ex + enemy[temp2].mapoffset; |
if (enemy[temp2].special) |
{ |
assert((unsigned int) enemy[temp2].flagnum-1 < COUNTOF(globalFlags)); |
globalFlags[enemy[temp2].flagnum-1] = enemy[temp2].setto; |
} |
if ((enemy[temp2].enemydie > 0) && |
!((superArcadeMode != SA_NONE) && |
(enemyDat[enemy[temp2].enemydie].value == 30000))) |
{ |
int temp_b = b; |
tempW = enemy[temp2].enemydie; |
int enemy_offset = temp2 - (temp2 % 25); |
if (enemyDat[tempW].value > 30000) |
{ |
enemy_offset = 0; |
} |
b = JE_newEnemy(enemy_offset, tempW, 0); |
if (b != 0) { |
if ((superArcadeMode != SA_NONE) && (enemy[b-1].evalue > 30000)) |
{ |
superArcadePowerUp++; |
if (superArcadePowerUp > 5) |
superArcadePowerUp = 1; |
enemy[b-1].egr[1-1] = 5 + superArcadePowerUp * 2; |
enemy[b-1].evalue = 30000 + superArcadePowerUp; |
} |
if (enemy[b-1].evalue != 0) |
enemy[b-1].scoreitem = true; |
else |
enemy[b-1].scoreitem = false; |
enemy[b-1].ex = enemy[temp2].ex; |
enemy[b-1].ey = enemy[temp2].ey; |
} |
b = temp_b; |
} |
if ((enemy[temp2].evalue > 0) && (enemy[temp2].evalue < 10000)) |
{ |
if (enemy[temp2].evalue == 1) |
{ |
cubeMax++; |
} |
else |
{ |
// in galaga mode player 2 is sidekick, so give cash to player 1 |
player[galagaMode ? 0 : playerNum - 1].cash += enemy[temp2].evalue; |
} |
} |
if ((enemy[temp2].edlevel == -1) && (temp == temp3)) |
{ |
enemy[temp2].edlevel = 0; |
enemyAvail[temp2] = 2; |
enemy[temp2].egr[1-1] = enemy[temp2].edgr; |
enemy[temp2].ani = 1; |
enemy[temp2].aniactive = 0; |
enemy[temp2].animax = 0; |
enemy[temp2].animin = 1; |
enemy[temp2].edamaged = true; |
enemy[temp2].enemycycle = 1; |
} else { |
enemyAvail[temp2] = 1; |
enemyKilled++; |
} |
if (enemyDat[enemy[temp2].enemytype].esize == 1) |
{ |
JE_setupExplosionLarge(enemy[temp2].enemyground, enemy[temp2].explonum, enemy_screen_x, enemy[temp2].ey); |
soundQueue[6] = S_EXPLOSION_9; |
} |
else |
{ |
JE_setupExplosion(enemy_screen_x, enemy[temp2].ey, 0, 1, false, false); |
soundQueue[6] = S_EXPLOSION_8; |
} |
} |
} |
} |
} |
if (infiniteShot) |
{ |
damage += 250; |
} |
else if (z != MAX_PWEAPON - 1) |
{ |
if (damage <= armorleft) |
{ |
shotAvail[z] = 0; |
goto draw_player_shot_loop_end; |
} |
else |
{ |
playerShotData[z].shotDmg -= armorleft; |
} |
} |
} |
} |
} |
draw_player_shot_loop_end: |
; |
} |
} |
/* Player movement indicators for shots that track your ship */ |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
player[i].last_x_shot_move = player[i].x; |
player[i].last_y_shot_move = player[i].y; |
} |
/*=================================*/ |
/*=======Collisions Detection======*/ |
/*=================================*/ |
for (uint i = 0; i < (twoPlayerMode ? 2 : 1); ++i) |
if (player[i].is_alive && !endLevel) |
JE_playerCollide(&player[i], i + 1); |
if (firstGameOver) |
JE_mainGamePlayerFunctions(); /*--------PLAYER DRAW+MOVEMENT---------*/ |
if (!endLevel) |
{ /*MAIN DRAWING IS STOPPED STARTING HERE*/ |
/* Draw Enemy Shots */ |
for (int z = 0; z < ENEMY_SHOT_MAX; z++) |
{ |
if (enemyShotAvail[z] == 0) |
{ |
enemyShot[z].sxm += enemyShot[z].sxc; |
enemyShot[z].sx += enemyShot[z].sxm; |
if (enemyShot[z].tx != 0) |
{ |
if (enemyShot[z].sx > player[0].x) |
{ |
if (enemyShot[z].sxm > -enemyShot[z].tx) |
{ |
enemyShot[z].sxm--; |
} |
} else { |
if (enemyShot[z].sxm < enemyShot[z].tx) |
{ |
enemyShot[z].sxm++; |
} |
} |
} |
enemyShot[z].sym += enemyShot[z].syc; |
enemyShot[z].sy += enemyShot[z].sym; |
if (enemyShot[z].ty != 0) |
{ |
if (enemyShot[z].sy > player[0].y) |
{ |
if (enemyShot[z].sym > -enemyShot[z].ty) |
{ |
enemyShot[z].sym--; |
} |
} else { |
if (enemyShot[z].sym < enemyShot[z].ty) |
{ |
enemyShot[z].sym++; |
} |
} |
} |
if (enemyShot[z].duration-- == 0 || enemyShot[z].sy > 190 || enemyShot[z].sy <= -14 || enemyShot[z].sx > 275 || enemyShot[z].sx <= 0) |
{ |
enemyShotAvail[z] = true; |
} |
else // check if shot collided with player |
{ |
for (uint i = 0; i < (twoPlayerMode ? 2 : 1); ++i) |
{ |
if (player[i].is_alive && |
enemyShot[z].sx > player[i].x - (signed)player[i].shot_hit_area_x && |
enemyShot[z].sx < player[i].x + (signed)player[i].shot_hit_area_x && |
enemyShot[z].sy > player[i].y - (signed)player[i].shot_hit_area_y && |
enemyShot[z].sy < player[i].y + (signed)player[i].shot_hit_area_y) |
{ |
tempX = enemyShot[z].sx; |
tempY = enemyShot[z].sy; |
temp = enemyShot[z].sdmg; |
enemyShotAvail[z] = true; |
JE_setupExplosion(tempX, tempY, 0, 0, false, false); |
if (player[i].invulnerable_ticks == 0) |
{ |
if ((temp = JE_playerDamage(temp, &player[i])) > 0) |
{ |
player[i].x_velocity += (enemyShot[z].sxm * temp) / 2; |
player[i].y_velocity += (enemyShot[z].sym * temp) / 2; |
} |
} |
break; |
} |
} |
if (enemyShotAvail[z] == false) |
{ |
if (enemyShot[z].animax != 0) |
{ |
if (++enemyShot[z].animate >= enemyShot[z].animax) |
enemyShot[z].animate = 0; |
} |
if (enemyShot[z].sgr >= 500) |
blit_sprite2(VGAScreen, enemyShot[z].sx, enemyShot[z].sy, shapesW2, enemyShot[z].sgr + enemyShot[z].animate - 500); |
else |
blit_sprite2(VGAScreen, enemyShot[z].sx, enemyShot[z].sy, shapesC1, enemyShot[z].sgr + enemyShot[z].animate); |
} |
} |
} |
} |
} |
if (background3over == 1) |
draw_background_3(VGAScreen); |
/* Draw Top Enemy */ |
if (topEnemyOver) |
{ |
tempMapXOfs = (background3x1 == 0) ? oldMapX3Ofs : oldMapXOfs; |
tempBackMove = backMove3; |
JE_drawEnemy(75); |
} |
/* Draw Sky Enemy */ |
if (skyEnemyOverAll) |
{ |
lastEnemyOnScreen = enemyOnScreen; |
tempMapXOfs = mapX2Ofs; |
tempBackMove = 0; |
JE_drawEnemy(25); |
if (enemyOnScreen == lastEnemyOnScreen) |
{ |
if (stopBackgroundNum == 2) |
stopBackgroundNum = 9; |
} |
} |
/*-------------------------- Sequenced Explosions -------------------------*/ |
enemyStillExploding = false; |
for (int i = 0; i < MAX_REPEATING_EXPLOSIONS; i++) |
{ |
if (rep_explosions[i].ttl != 0) |
{ |
enemyStillExploding = true; |
if (rep_explosions[i].delay > 0) |
{ |
rep_explosions[i].delay--; |
continue; |
} |
rep_explosions[i].y += backMove2 + 1; |
tempX = rep_explosions[i].x + (mt_rand() % 24) - 12; |
tempY = rep_explosions[i].y + (mt_rand() % 27) - 24; |
if (rep_explosions[i].big) |
{ |
JE_setupExplosionLarge(false, 2, tempX, tempY); |
if (rep_explosions[i].ttl == 1 || mt_rand() % 5 == 1) |
soundQueue[7] = S_EXPLOSION_11; |
else |
soundQueue[6] = S_EXPLOSION_9; |
rep_explosions[i].delay = 4 + (mt_rand() % 3); |
} |
else |
{ |
JE_setupExplosion(tempX, tempY, 0, 1, false, false); |
soundQueue[5] = S_EXPLOSION_4; |
rep_explosions[i].delay = 3; |
} |
rep_explosions[i].ttl--; |
} |
} |
/*---------------------------- Draw Explosions ----------------------------*/ |
for (int j = 0; j < MAX_EXPLOSIONS; j++) |
{ |
if (explosions[j].ttl != 0) |
{ |
if (explosions[j].fixed_position != true) |
{ |
explosions[j].sprite++; |
explosions[j].y += explodeMove; |
} |
else if (explosions[j].follow_player == true) |
{ |
explosions[j].x += explosionFollowAmountX; |
explosions[j].y += explosionFollowAmountY; |
} |
explosions[j].y += explosions[j].delta_y; |
explosions[j].x += explosions[j].delta_x; |
if (explosions[j].y > 200 - 14) |
{ |
explosions[j].ttl = 0; |
} |
else |
{ |
if (explosionTransparent) |
blit_sprite2_blend(VGAScreen, explosions[j].x, explosions[j].y, shapes6, explosions[j].sprite + 1); |
else |
blit_sprite2(VGAScreen, explosions[j].x, explosions[j].y, shapes6, explosions[j].sprite + 1); |
explosions[j].ttl--; |
} |
} |
} |
if (!portConfigChange) |
portConfigDone = true; |
/*-----------------------BACKGROUNDS------------------------*/ |
/*-----------------------BACKGROUND 2------------------------*/ |
if (!(smoothies[2-1] && processorType < 4) && |
!(smoothies[1-1] && processorType == 3)) |
{ |
if (background2over == 2) |
{ |
if (wild && !background2notTransparent) |
draw_background_2_blend(VGAScreen); |
else |
draw_background_2(VGAScreen); |
} |
} |
/*-------------------------Warning---------------------------*/ |
if ((player[0].is_alive && player[0].armor < 6) || |
(twoPlayerMode && !galagaMode && player[1].is_alive && player[1].armor < 6)) |
{ |
int armor_amount = (player[0].is_alive && player[0].armor < 6) ? player[0].armor : player[1].armor; |
if (armorShipDelay > 0) |
{ |
armorShipDelay--; |
} |
else |
{ |
tempW = 560; |
b = JE_newEnemy(50, tempW, 0); |
if (b > 0) |
{ |
enemy[b-1].enemydie = 560 + (mt_rand() % 3) + 1; |
enemy[b-1].eyc -= backMove3; |
enemy[b-1].armorleft = 4; |
} |
armorShipDelay = 500; |
} |
if ((player[0].is_alive && player[0].armor < 6 && (!isNetworkGame || thisPlayerNum == 1)) || |
(twoPlayerMode && player[1].is_alive && player[1].armor < 6 && (!isNetworkGame || thisPlayerNum == 2))) |
{ |
tempW = armor_amount * 4 + 8; |
if (warningSoundDelay > tempW) |
warningSoundDelay = tempW; |
if (warningSoundDelay > 1) |
{ |
warningSoundDelay--; |
} |
else |
{ |
soundQueue[7] = S_WARNING; |
warningSoundDelay = tempW; |
} |
warningCol += warningColChange; |
if (warningCol > 113 + (14 - (armor_amount * 2))) |
{ |
warningColChange = -warningColChange; |
warningCol = 113 + (14 - (armor_amount * 2)); |
} |
else if (warningCol < 113) |
{ |
warningColChange = -warningColChange; |
} |
fill_rectangle_xy(VGAScreen, 24, 181, 138, 183, warningCol); |
fill_rectangle_xy(VGAScreen, 175, 181, 287, 183, warningCol); |
fill_rectangle_xy(VGAScreen, 24, 0, 287, 3, warningCol); |
JE_outText(VGAScreen, 140, 178, "WARNING", 7, (warningCol % 16) / 2); |
} |
} |
/*------- Random Explosions --------*/ |
if (randomExplosions && mt_rand() % 10 == 1) |
JE_setupExplosionLarge(false, 20, mt_rand() % 280, mt_rand() % 180); |
/*=================================*/ |
/*=======The Sound Routine=========*/ |
/*=================================*/ |
if (firstGameOver) |
{ |
temp = 0; |
for (temp2 = 0; temp2 < SFX_CHANNELS; temp2++) |
{ |
if (soundQueue[temp2] != S_NONE) |
{ |
temp = soundQueue[temp2]; |
if (temp2 == 3) |
temp3 = fxPlayVol; |
else if (temp == 15) |
temp3 = fxPlayVol / 4; |
else /*Lightning*/ |
temp3 = fxPlayVol / 2; |
JE_multiSamplePlay(digiFx[temp-1], fxSize[temp-1], temp2, temp3); |
soundQueue[temp2] = S_NONE; |
} |
} |
} |
if (returnActive && enemyOnScreen == 0) |
{ |
JE_eventJump(65535); |
returnActive = false; |
} |
/*------- DEbug ---------*/ |
debugTime = SDL_GetTicks(); |
tempW = lastmouse_but; |
tempX = mouse_x; |
tempY = mouse_y; |
if (debug) |
{ |
for (size_t i = 0; i < 9; i++) |
{ |
tempStr[i] = '0' + smoothies[i]; |
} |
tempStr[9] = '\0'; |
sprintf(buffer, "SM = %s", tempStr); |
JE_outText(VGAScreen, 30, 70, buffer, 4, 0); |
sprintf(buffer, "Memory left = %d", -1); |
JE_outText(VGAScreen, 30, 80, buffer, 4, 0); |
sprintf(buffer, "Enemies onscreen = %d", enemyOnScreen); |
JE_outText(VGAScreen, 30, 90, buffer, 6, 0); |
debugHist = debugHist + abs((JE_longint)debugTime - (JE_longint)lastDebugTime); |
debugHistCount++; |
sprintf(tempStr, "%2.3f", 1000.0f / roundf(debugHist / debugHistCount)); |
sprintf(buffer, "X:%d Y:%-5d %s FPS %d %d %d %d", (mapX - 1) * 12 + player[0].x, curLoc, tempStr, player[0].x_velocity, player[0].y_velocity, player[0].x, player[0].y); |
JE_outText(VGAScreen, 45, 175, buffer, 15, 3); |
lastDebugTime = debugTime; |
} |
if (displayTime > 0) |
{ |
displayTime--; |
JE_outTextAndDarken(VGAScreen, 90, 10, miscText[59], 15, (JE_byte)flash - 8, FONT_SHAPES); |
flash += flashChange; |
if (flash > 4 || flash == 0) |
flashChange = -flashChange; |
} |
/*Pentium Speed Mode?*/ |
if (pentiumMode) |
{ |
frameCountMax = (frameCountMax == 2) ? 3 : 2; |
} |
/*-------- Level Timer ---------*/ |
if (levelTimer && levelTimerCountdown > 0) |
{ |
levelTimerCountdown--; |
if (levelTimerCountdown == 0) |
JE_eventJump(levelTimerJumpTo); |
if (levelTimerCountdown > 200) |
{ |
if (levelTimerCountdown % 100 == 0) |
soundQueue[7] = S_WARNING; |
if (levelTimerCountdown % 10 == 0) |
soundQueue[6] = S_CLICK; |
} |
else if (levelTimerCountdown % 20 == 0) |
{ |
soundQueue[7] = S_WARNING; |
} |
JE_textShade (VGAScreen, 140, 6, miscText[66], 7, (levelTimerCountdown % 20) / 3, FULL_SHADE); |
sprintf(buffer, "%.1f", levelTimerCountdown / 100.0f); |
JE_dString (VGAScreen, 100, 2, buffer, SMALL_FONT_SHAPES); |
} |
/*GAME OVER*/ |
if (!constantPlay && !constantDie) |
{ |
if (allPlayersGone) |
{ |
if (player[0].exploding_ticks > 0 || player[1].exploding_ticks > 0) |
{ |
if (galagaMode) |
player[1].exploding_ticks = 0; |
musicFade = true; |
} |
else |
{ |
if (play_demo || normalBonusLevelCurrent || bonusLevelCurrent) |
reallyEndLevel = true; |
else |
JE_dString(VGAScreen, 120, 60, miscText[21], FONT_SHAPES); // game over |
set_mouse_position(159, 100); |
if (firstGameOver) |
{ |
if (!play_demo) |
{ |
play_song(SONG_GAMEOVER); |
set_volume(tyrMusicVolume, fxVolume); |
} |
firstGameOver = false; |
} |
if (!play_demo) |
{ |
push_joysticks_as_keyboard(); |
service_SDL_events(true); |
if ((newkey || button[0] || button[1] || button[2]) || newmouse) |
{ |
reallyEndLevel = true; |
} |
} |
if (isNetworkGame) |
reallyEndLevel = true; |
} |
} |
} |
if (play_demo) // input kills demo |
{ |
push_joysticks_as_keyboard(); |
service_SDL_events(false); |
if (newkey || newmouse) |
{ |
reallyEndLevel = true; |
stopped_demo = true; |
} |
} |
else // input handling for pausing, menu, cheats |
{ |
service_SDL_events(false); |
if (newkey) |
{ |
skipStarShowVGA = false; |
JE_mainKeyboardInput(); |
newkey = false; |
if (skipStarShowVGA) |
goto level_loop; |
} |
if (pause_pressed) |
{ |
pause_pressed = false; |
if (isNetworkGame) |
pauseRequest = true; |
else |
JE_pauseGame(); |
} |
if (ingamemenu_pressed) |
{ |
ingamemenu_pressed = false; |
if (isNetworkGame) |
{ |
inGameMenuRequest = true; |
} |
else |
{ |
yourInGameMenuRequest = true; |
JE_doInGameSetup(); |
skipStarShowVGA = true; |
} |
} |
} |
/*Network Update*/ |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
if (!reallyEndLevel) |
{ |
Uint16 requests = (pauseRequest == true) | |
(inGameMenuRequest == true) << 1 | |
(skipLevelRequest == true) << 2 | |
(nortShipRequest == true) << 3; |
SDLNet_Write16(requests, &packet_state_out[0]->data[14]); |
SDLNet_Write16(difficultyLevel, &packet_state_out[0]->data[16]); |
SDLNet_Write16(player[0].x, &packet_state_out[0]->data[18]); |
SDLNet_Write16(player[1].x, &packet_state_out[0]->data[20]); |
SDLNet_Write16(player[0].y, &packet_state_out[0]->data[22]); |
SDLNet_Write16(player[1].y, &packet_state_out[0]->data[24]); |
SDLNet_Write16(curLoc, &packet_state_out[0]->data[26]); |
network_state_send(); |
if (network_state_update()) |
{ |
assert(SDLNet_Read16(&packet_state_in[0]->data[26]) == SDLNet_Read16(&packet_state_out[network_delay]->data[26])); |
requests = SDLNet_Read16(&packet_state_in[0]->data[14]) ^ SDLNet_Read16(&packet_state_out[network_delay]->data[14]); |
if (requests & 1) |
{ |
JE_pauseGame(); |
} |
if (requests & 2) |
{ |
yourInGameMenuRequest = SDLNet_Read16(&packet_state_out[network_delay]->data[14]) & 2; |
JE_doInGameSetup(); |
yourInGameMenuRequest = false; |
if (haltGame) |
reallyEndLevel = true; |
} |
if (requests & 4) |
{ |
levelTimer = true; |
levelTimerCountdown = 0; |
endLevel = true; |
levelEnd = 40; |
} |
if (requests & 8) // nortship |
{ |
player[0].items.ship = 12; // Nort Ship |
player[0].items.special = 13; // Astral Zone |
player[0].items.weapon[FRONT_WEAPON].id = 36; // NortShip Super Pulse |
player[0].items.weapon[REAR_WEAPON].id = 37; // NortShip Spreader |
shipGr = 1; |
} |
for (int i = 0; i < 2; i++) |
{ |
if (SDLNet_Read16(&packet_state_in[0]->data[18 + i * 2]) != SDLNet_Read16(&packet_state_out[network_delay]->data[18 + i * 2]) || SDLNet_Read16(&packet_state_in[0]->data[20 + i * 2]) != SDLNet_Read16(&packet_state_out[network_delay]->data[20 + i * 2])) |
{ |
char temp[64]; |
sprintf(temp, "Player %d is unsynchronized!", i + 1); |
JE_textShade(game_screen, 40, 110 + i * 10, temp, 9, 2, FULL_SHADE); |
} |
} |
} |
} |
JE_clearSpecialRequests(); |
} |
#endif |
/** Test **/ |
JE_drawSP(); |
/*Filtration*/ |
if (filterActive) |
{ |
JE_filterScreen(levelFilter, levelBrightness); |
} |
draw_boss_bar(); |
JE_inGameDisplays(); |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_starShowVGA(); |
/*Start backgrounds if no enemies on screen |
End level if number of enemies left to kill equals 0.*/ |
if (stopBackgroundNum == 9 && backMove == 0 && !enemyStillExploding) |
{ |
backMove = 1; |
backMove2 = 2; |
backMove3 = 3; |
explodeMove = 2; |
stopBackgroundNum = 0; |
stopBackgrounds = false; |
if (waitToEndLevel) |
{ |
endLevel = true; |
levelEnd = 40; |
} |
if (allPlayersGone) |
{ |
reallyEndLevel = true; |
} |
} |
if (!endLevel && enemyOnScreen == 0) |
{ |
if (readyToEndLevel && !enemyStillExploding) |
{ |
if (levelTimerCountdown > 0) |
{ |
levelTimer = false; |
} |
readyToEndLevel = false; |
endLevel = true; |
levelEnd = 40; |
if (allPlayersGone) |
{ |
reallyEndLevel = true; |
} |
} |
if (stopBackgrounds) |
{ |
stopBackgrounds = false; |
backMove = 1; |
backMove2 = 2; |
backMove3 = 3; |
explodeMove = 2; |
} |
} |
/*Other Network Functions*/ |
JE_handleChat(); |
if (reallyEndLevel) |
{ |
goto start_level; |
} |
goto level_loop; |
} |
/* --- Load Level/Map Data --- */ |
void JE_loadMap( void ) |
{ |
JE_DanCShape shape; |
JE_word x, y; |
JE_integer yy; |
JE_word mapSh[3][128]; /* [1..3, 0..127] */ |
JE_byte *ref[3][128]; /* [1..3, 0..127] */ |
char s[256]; |
JE_byte mapBuf[15 * 600]; /* [1..15 * 600] */ |
JE_word bufLoc; |
char buffer[256]; |
int i; |
Uint8 pic_buffer[320*200]; /* screen buffer, 8-bit specific */ |
Uint8 *vga, *pic, *vga2; /* screen pointer, 8-bit specific */ |
lastCubeMax = cubeMax; |
/*Defaults*/ |
songBuy = DEFAULT_SONG_BUY; /*Item Screen default song*/ |
/* Load LEVELS.DAT - Section = MAINLEVEL */ |
saveLevel = mainLevel; |
new_game: |
galagaMode = false; |
useLastBank = false; |
extraGame = false; |
haltGame = false; |
gameLoaded = false; |
if (!play_demo) |
{ |
do |
{ |
FILE *ep_f = dir_fopen_die(data_dir(), episode_file, "rb"); |
jumpSection = false; |
loadLevelOk = false; |
/* Seek Section # Mainlevel */ |
int x = 0; |
while (x < mainLevel) |
{ |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
if (s[0] == '*') |
{ |
x++; |
s[0] = ' '; |
} |
} |
ESCPressed = false; |
do |
{ |
if (gameLoaded) |
{ |
fclose(ep_f); |
if (mainLevel == 0) // if quit itemscreen |
return; // back to title screen |
else |
goto new_game; |
} |
strcpy(s, " "); |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
if (s[0] == ']') |
{ |
switch (s[1]) |
{ |
case 'A': |
JE_playAnim("tyrend.anm", 0, 7); |
break; |
case 'G': |
mapOrigin = atoi(s + 4); |
mapPNum = atoi(s + 7); |
for (i = 0; i < mapPNum; i++) |
{ |
mapPlanet[i] = atoi(s + 1 + (i + 1) * 8); |
mapSection[i] = atoi(s + 4 + (i + 1) * 8); |
} |
break; |
case '?': |
temp = atoi(s + 4); |
for (i = 0; i < temp; i++) |
{ |
cubeList[i] = atoi(s + 3 + (i + 1) * 4); |
} |
if (cubeMax > temp) |
cubeMax = temp; |
break; |
case '!': |
cubeMax = atoi(s + 4); /*Auto set CubeMax*/ |
break; |
case '+': |
temp = atoi(s + 4); |
cubeMax += temp; |
if (cubeMax > 4) |
cubeMax = 4; |
break; |
case 'g': |
galagaMode = true; /*GALAGA mode*/ |
player[1].items = player[0].items; |
player[1].items.weapon[REAR_WEAPON].id = 15; // Vulcan Cannon |
for (uint i = 0; i < COUNTOF(player[1].items.sidekick); ++i) |
player[1].items.sidekick[i] = 0; // None |
break; |
case 'x': |
extraGame = true; |
break; |
case 'e': // ENGAGE mode, used for mini-games |
doNotSaveBackup = true; |
constantDie = false; |
onePlayerAction = true; |
superTyrian = true; |
twoPlayerMode = false; |
player[0].cash = 0; |
player[0].items.ship = 13; // The Stalker 21.126 |
player[0].items.weapon[FRONT_WEAPON].id = 39; // Atomic RailGun |
player[0].items.weapon[REAR_WEAPON].id = 0; // None |
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i) |
player[0].items.sidekick[i] = 0; // None |
player[0].items.generator = 2; // Advanced MR-12 |
player[0].items.shield = 4; // Advanced Integrity Field |
player[0].items.special = 0; // None |
player[0].items.weapon[FRONT_WEAPON].power = 3; |
player[0].items.weapon[REAR_WEAPON].power = 1; |
break; |
case 'J': // section jump |
temp = atoi(s + 3); |
mainLevel = temp; |
jumpSection = true; |
break; |
case '2': // two-player section jump |
temp = atoi(s + 3); |
if (twoPlayerMode || onePlayerAction) |
{ |
mainLevel = temp; |
jumpSection = true; |
} |
break; |
case 'w': // Stalker 21.126 section jump |
temp = atoi(s + 3); /*Allowed to go to Time War?*/ |
if (player[0].items.ship == 13) |
{ |
mainLevel = temp; |
jumpSection = true; |
} |
break; |
case 't': |
temp = atoi(s + 3); |
if (levelTimer && levelTimerCountdown == 0) |
{ |
mainLevel = temp; |
jumpSection = true; |
} |
break; |
case 'l': |
temp = atoi(s + 3); |
if (!all_players_alive()) |
{ |
mainLevel = temp; |
jumpSection = true; |
} |
break; |
case 's': |
saveLevel = mainLevel; |
break; /*store savepoint*/ |
case 'b': |
if (twoPlayerMode) |
{ |
temp = 22; |
} else { |
temp = 11; |
} |
JE_saveGame(11, "LAST LEVEL "); |
break; |
case 'i': |
temp = atoi(s + 3); |
songBuy = temp - 1; |
break; |
case 'I': /*Load Items Available Information*/ |
memset(&itemAvail, 0, sizeof(itemAvail)); |
for (int i = 0; i < 9; ++i) |
{ |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
char buf[256]; |
strncpy(buf, (strlen(s) > 8) ? s + 8 : "", sizeof(buf)); |
int j = 0, temp; |
while (str_pop_int(buf, &temp)) |
itemAvail[i][j++] = temp; |
itemAvailMax[i] = j; |
} |
JE_itemScreen(); |
break; |
case 'L': |
nextLevel = atoi(s + 9); |
SDL_strlcpy(levelName, s + 13, 10); |
levelSong = atoi(s + 22); |
if (nextLevel == 0) |
{ |
nextLevel = mainLevel + 1; |
} |
lvlFileNum = atoi(s + 25); |
loadLevelOk = true; |
bonusLevelCurrent = (strlen(s) > 28) & (s[28] == '$'); |
normalBonusLevelCurrent = (strlen(s) > 27) & (s[27] == '$'); |
gameJustLoaded = false; |
break; |
case '@': |
useLastBank = !useLastBank; |
break; |
case 'Q': |
ESCPressed = false; |
temp = secretHint + (mt_rand() % 3) * 3; |
if (twoPlayerMode) |
{ |
for (uint i = 0; i < 2; ++i) |
snprintf(levelWarningText[i], sizeof(*levelWarningText), "%s %lu", miscText[40], player[i].cash); |
strcpy(levelWarningText[2], ""); |
levelWarningLines = 3; |
} |
else |
{ |
sprintf(levelWarningText[0], "%s %lu", miscText[37], JE_totalScore(&player[0])); |
strcpy(levelWarningText[1], ""); |
levelWarningLines = 2; |
} |
for (x = 0; x < temp - 1; x++) |
{ |
do |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
while (s[0] != '#'); |
} |
do |
{ |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
strcpy(levelWarningText[levelWarningLines], s); |
levelWarningLines++; |
} |
while (s[0] != '#'); |
levelWarningLines--; |
JE_wipeKey(); |
frameCountMax = 4; |
if (!constantPlay) |
JE_displayText(); |
fade_black(15); |
JE_nextEpisode(); |
if (jumpBackToEpisode1 && !twoPlayerMode) |
{ |
JE_loadPic(VGAScreen, 1, false); // huh? |
JE_clr256(VGAScreen); |
if (superTyrian) |
{ |
// if completed Zinglon's Revenge, show SuperTyrian and Destruct codes |
// if completed SuperTyrian, show Nort-Ship Z code |
superArcadeMode = (initialDifficulty == 8) ? 8 : 1; |
} |
if (superArcadeMode < SA_ENGAGE) |
{ |
if (SANextShip[superArcadeMode] == SA_ENGAGE) |
{ |
sprintf(buffer, "%s %s", miscTextB[4], pName[0]); |
JE_dString(VGAScreen, JE_fontCenter(buffer, FONT_SHAPES), 100, buffer, FONT_SHAPES); |
sprintf(buffer, "Or play... %s", specialName[7]); |
JE_dString(VGAScreen, 80, 180, buffer, SMALL_FONT_SHAPES); |
} |
else |
{ |
JE_dString(VGAScreen, JE_fontCenter(superShips[0], FONT_SHAPES), 30, superShips[0], FONT_SHAPES); |
JE_dString(VGAScreen, JE_fontCenter(superShips[SANextShip[superArcadeMode]], SMALL_FONT_SHAPES), 100, superShips[SANextShip[superArcadeMode]], SMALL_FONT_SHAPES); |
} |
if (SANextShip[superArcadeMode] < SA_NORTSHIPZ) |
blit_sprite2x2(VGAScreen, 148, 70, shapes9, ships[SAShip[SANextShip[superArcadeMode]-1]].shipgraphic); |
else if (SANextShip[superArcadeMode] == SA_NORTSHIPZ) |
trentWin = true; |
sprintf(buffer, "Type %s at Title", specialName[SANextShip[superArcadeMode]-1]); |
JE_dString(VGAScreen, JE_fontCenter(buffer, SMALL_FONT_SHAPES), 160, buffer, SMALL_FONT_SHAPES); |
JE_showVGA(); |
fade_palette(colors, 50, 0, 255); |
if (!constantPlay) |
wait_input(true, true, true); |
} |
jumpSection = true; |
if (isNetworkGame) |
JE_readTextSync(); |
if (superTyrian) |
{ |
fade_black(10); |
// back to titlescreen |
mainLevel = 0; |
return; |
} |
} |
break; |
case 'P': |
if (!constantPlay) |
{ |
tempX = atoi(s + 3); |
if (tempX > 900) |
{ |
memcpy(colors, palettes[pcxpal[tempX-1 - 900]], sizeof(colors)); |
JE_clr256(VGAScreen); |
JE_showVGA(); |
fade_palette(colors, 1, 0, 255); |
} |
else |
{ |
if (tempX == 0) |
JE_loadPCX("tshp2.pcx"); |
else |
JE_loadPic(VGAScreen, tempX, false); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
} |
} |
break; |
case 'U': |
if (!constantPlay) |
{ |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
tempX = atoi(s + 3); |
JE_loadPic(VGAScreen, tempX, false); |
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer)); |
service_SDL_events(true); |
for (int z = 0; z <= 199; z++) |
{ |
if (!newkey) |
{ |
vga = VGAScreen->pixels; |
vga2 = VGAScreen2->pixels; |
pic = pic_buffer + (199 - z) * 320; |
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/ |
for (y = 0; y <= 199; y++) |
{ |
if (y <= z) |
{ |
memcpy(vga, pic, 320); |
pic += 320; |
} |
else |
{ |
memcpy(vga, vga2, VGAScreen->pitch); |
vga2 += VGAScreen->pitch; |
} |
vga += VGAScreen->pitch; |
} |
JE_showVGA(); |
if (isNetworkGame) |
{ |
/* TODO: NETWORK */ |
} |
service_wait_delay(); |
} |
} |
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer)); |
} |
break; |
case 'V': |
if (!constantPlay) |
{ |
/* TODO: NETWORK */ |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
tempX = atoi(s + 3); |
JE_loadPic(VGAScreen, tempX, false); |
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer)); |
service_SDL_events(true); |
for (int z = 0; z <= 199; z++) |
{ |
if (!newkey) |
{ |
vga = VGAScreen->pixels; |
vga2 = VGAScreen2->pixels; |
pic = pic_buffer; |
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/ |
for (y = 0; y < 199; y++) |
{ |
if (y <= 199 - z) |
{ |
memcpy(vga, vga2, VGAScreen->pitch); |
vga2 += VGAScreen->pitch; |
} |
else |
{ |
memcpy(vga, pic, 320); |
pic += 320; |
} |
vga += VGAScreen->pitch; |
} |
JE_showVGA(); |
if (isNetworkGame) |
{ |
/* TODO: NETWORK */ |
} |
service_wait_delay(); |
} |
} |
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer)); |
} |
break; |
case 'R': |
if (!constantPlay) |
{ |
/* TODO: NETWORK */ |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
tempX = atoi(s + 3); |
JE_loadPic(VGAScreen, tempX, false); |
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer)); |
service_SDL_events(true); |
for (int z = 0; z <= 318; z++) |
{ |
if (!newkey) |
{ |
vga = VGAScreen->pixels; |
vga2 = VGAScreen2->pixels; |
pic = pic_buffer; |
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/ |
for(y = 0; y < 200; y++) |
{ |
memcpy(vga, vga2 + z, 319 - z); |
vga += 320 - z; |
vga2 += VGAScreen2->pitch; |
memcpy(vga, pic, z + 1); |
vga += z; |
pic += 320; |
} |
JE_showVGA(); |
if (isNetworkGame) |
{ |
/* TODO: NETWORK */ |
} |
service_wait_delay(); |
} |
} |
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer)); |
} |
break; |
case 'C': |
if (!isNetworkGame) |
{ |
fade_black(10); |
} |
JE_clr256(VGAScreen); |
JE_showVGA(); |
memcpy(colors, palettes[7], sizeof(colors)); |
set_palette(colors, 0, 255); |
break; |
case 'B': |
if (!isNetworkGame) |
{ |
fade_black(10); |
} |
break; |
case 'F': |
if (!isNetworkGame) |
{ |
fade_white(100); |
fade_black(30); |
} |
JE_clr256(VGAScreen); |
JE_showVGA(); |
break; |
case 'W': |
if (!constantPlay) |
{ |
if (!ESCPressed) |
{ |
JE_wipeKey(); |
warningCol = 14 * 16 + 5; |
warningColChange = 1; |
warningSoundDelay = 0; |
levelWarningDisplay = (s[2] == 'y'); |
levelWarningLines = 0; |
frameCountMax = atoi(s + 4); |
setjasondelay2(6); |
warningRed = frameCountMax / 10; |
frameCountMax = frameCountMax % 10; |
do |
{ |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
if (s[0] != '#') |
{ |
strcpy(levelWarningText[levelWarningLines], s); |
levelWarningLines++; |
} |
} |
while (!(s[0] == '#')); |
JE_displayText(); |
newkey = false; |
} |
} |
break; |
case 'H': |
if (initialDifficulty < 3) |
{ |
mainLevel = atoi(s + 4); |
jumpSection = true; |
} |
break; |
case 'h': |
if (initialDifficulty > 2) |
{ |
read_encrypted_pascal_string(s, sizeof(s), ep_f); |
} |
break; |
case 'S': |
if (isNetworkGame) |
{ |
JE_readTextSync(); |
} |
break; |
case 'n': |
ESCPressed = false; |
break; |
case 'M': |
temp = atoi(s + 3); |
play_song(temp - 1); |
break; |
} |
} |
} while (!(loadLevelOk || jumpSection)); |
fclose(ep_f); |
} while (!loadLevelOk); |
} |
if (play_demo) |
load_next_demo(); |
else |
fade_black(50); |
FILE *level_f = dir_fopen_die(data_dir(), levelFile, "rb"); |
fseek(level_f, lvlPos[(lvlFileNum-1) * 2], SEEK_SET); |
fgetc(level_f); // char_mapFile |
JE_char char_shapeFile = fgetc(level_f); |
efread(&mapX, sizeof(JE_word), 1, level_f); |
efread(&mapX2, sizeof(JE_word), 1, level_f); |
efread(&mapX3, sizeof(JE_word), 1, level_f); |
efread(&levelEnemyMax, sizeof(JE_word), 1, level_f); |
for (x = 0; x < levelEnemyMax; x++) |
{ |
efread(&levelEnemy[x], sizeof(JE_word), 1, level_f); |
} |
efread(&maxEvent, sizeof(JE_word), 1, level_f); |
for (x = 0; x < maxEvent; x++) |
{ |
efread(&eventRec[x].eventtime, sizeof(JE_word), 1, level_f); |
efread(&eventRec[x].eventtype, sizeof(JE_byte), 1, level_f); |
efread(&eventRec[x].eventdat, sizeof(JE_integer), 1, level_f); |
efread(&eventRec[x].eventdat2, sizeof(JE_integer), 1, level_f); |
efread(&eventRec[x].eventdat3, sizeof(JE_shortint), 1, level_f); |
efread(&eventRec[x].eventdat5, sizeof(JE_shortint), 1, level_f); |
efread(&eventRec[x].eventdat6, sizeof(JE_shortint), 1, level_f); |
efread(&eventRec[x].eventdat4, sizeof(JE_byte), 1, level_f); |
} |
eventRec[x].eventtime = 65500; /*Not needed but just in case*/ |
/*debuginfo('Level loaded.');*/ |
/*debuginfo('Loading Map');*/ |
/* MAP SHAPE LOOKUP TABLE - Each map is directly after level */ |
efread(mapSh, sizeof(JE_word), sizeof(mapSh) / sizeof(JE_word), level_f); |
for (temp = 0; temp < 3; temp++) |
{ |
for (temp2 = 0; temp2 < 128; temp2++) |
{ |
mapSh[temp][temp2] = SDL_Swap16(mapSh[temp][temp2]); |
} |
} |
/* Read Shapes.DAT */ |
sprintf(tempStr, "shapes%c.dat", tolower((unsigned char)char_shapeFile)); |
FILE *shpFile = dir_fopen_die(data_dir(), tempStr, "rb"); |
for (int z = 0; z < 600; z++) |
{ |
JE_boolean shapeBlank = fgetc(shpFile); |
if (shapeBlank) |
memset(shape, 0, sizeof(shape)); |
else |
efread(shape, sizeof(JE_byte), sizeof(shape), shpFile); |
/* Match 1 */ |
for (int x = 0; x <= 71; ++x) |
{ |
if (mapSh[0][x] == z+1) |
{ |
memcpy(megaData1.shapes[x].sh, shape, sizeof(JE_DanCShape)); |
ref[0][x] = (JE_byte *)megaData1.shapes[x].sh; |
} |
} |
/* Match 2 */ |
for (int x = 0; x <= 71; ++x) |
{ |
if (mapSh[1][x] == z+1) |
{ |
if (x != 71 && !shapeBlank) |
{ |
memcpy(megaData2.shapes[x].sh, shape, sizeof(JE_DanCShape)); |
y = 1; |
for (yy = 0; yy < (24 * 28) >> 1; yy++) |
if (shape[yy] == 0) |
y = 0; |
megaData2.shapes[x].fill = y; |
ref[1][x] = (JE_byte *)megaData2.shapes[x].sh; |
} |
else |
{ |
ref[1][x] = NULL; |
} |
} |
} |
/*Match 3*/ |
for (int x = 0; x <= 71; ++x) |
{ |
if (mapSh[2][x] == z+1) |
{ |
if (x < 70 && !shapeBlank) |
{ |
memcpy(megaData3.shapes[x].sh, shape, sizeof(JE_DanCShape)); |
y = 1; |
for (yy = 0; yy < (24 * 28) >> 1; yy++) |
if (shape[yy] == 0) |
y = 0; |
megaData3.shapes[x].fill = y; |
ref[2][x] = (JE_byte *)megaData3.shapes[x].sh; |
} |
else |
{ |
ref[2][x] = NULL; |
} |
} |
} |
} |
fclose(shpFile); |
efread(mapBuf, sizeof(JE_byte), 14 * 300, level_f); |
bufLoc = 0; /* MAP NUMBER 1 */ |
for (y = 0; y < 300; y++) |
{ |
for (x = 0; x < 14; x++) |
{ |
megaData1.mainmap[y][x] = ref[0][mapBuf[bufLoc]]; |
bufLoc++; |
} |
} |
efread(mapBuf, sizeof(JE_byte), 14 * 600, level_f); |
bufLoc = 0; /* MAP NUMBER 2 */ |
for (y = 0; y < 600; y++) |
{ |
for (x = 0; x < 14; x++) |
{ |
megaData2.mainmap[y][x] = ref[1][mapBuf[bufLoc]]; |
bufLoc++; |
} |
} |
efread(mapBuf, sizeof(JE_byte), 15 * 600, level_f); |
bufLoc = 0; /* MAP NUMBER 3 */ |
for (y = 0; y < 600; y++) |
{ |
for (x = 0; x < 15; x++) |
{ |
megaData3.mainmap[y][x] = ref[2][mapBuf[bufLoc]]; |
bufLoc++; |
} |
} |
fclose(level_f); |
/* Note: The map data is automatically calculated with the correct mapsh |
value and then the pointer is calculated using the formula (MAPSH-1)*168. |
Then, we'll automatically add S2Ofs to get the exact offset location into |
the shape table! This makes it VERY FAST! */ |
/*debuginfo('Map file done.');*/ |
/* End of find loop for LEVEL??.DAT */ |
} |
bool JE_titleScreen( JE_boolean animate ) |
{ |
bool quit = false; |
const int menunum = 7; |
unsigned int arcade_code_i[SA_ENGAGE] = { 0 }; |
JE_word waitForDemo; |
JE_byte menu = 0; |
JE_boolean redraw = true, |
fadeIn = false; |
JE_word temp; /* JE_byte temp; from varz.h will overflow in for loop */ |
play_demo = false; |
stopped_demo = false; |
redraw = true; |
fadeIn = false; |
gameLoaded = false; |
jumpSection = false; |
#ifdef WITH_NETWORK |
if (isNetworkGame) |
{ |
JE_loadPic(VGAScreen, 2, false); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
JE_dString(VGAScreen, JE_fontCenter("Waiting for other player.", SMALL_FONT_SHAPES), 140, "Waiting for other player.", SMALL_FONT_SHAPES); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
network_connect(); |
twoPlayerMode = true; |
if (thisPlayerNum == 1) |
{ |
fade_black(10); |
if (select_episode() && select_difficulty()) |
{ |
initialDifficulty = difficultyLevel; |
difficultyLevel++; /*Make it one step harder for 2-player mode!*/ |
network_prepare(PACKET_DETAILS); |
SDLNet_Write16(episodeNum, &packet_out_temp->data[4]); |
SDLNet_Write16(difficultyLevel, &packet_out_temp->data[6]); |
network_send(8); // PACKET_DETAILS |
} |
else |
{ |
network_prepare(PACKET_QUIT); |
network_send(4); // PACKET QUIT |
network_tyrian_halt(0, true); |
} |
} |
else |
{ |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
JE_dString(VGAScreen, JE_fontCenter(networkText[4-1], SMALL_FONT_SHAPES), 140, networkText[4-1], SMALL_FONT_SHAPES); |
JE_showVGA(); |
// until opponent sends details packet |
while (true) |
{ |
service_SDL_events(false); |
JE_showVGA(); |
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_DETAILS) |
break; |
network_update(); |
network_check(); |
uSDL_Delay(16); |
} |
JE_initEpisode(SDLNet_Read16(&packet_in[0]->data[4])); |
difficultyLevel = SDLNet_Read16(&packet_in[0]->data[6]); |
initialDifficulty = difficultyLevel - 1; |
fade_black(10); |
network_update(); |
} |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].cash = 0; |
player[0].items.ship = 11; // Silver Ship |
while (!network_is_sync()) |
{ |
service_SDL_events(false); |
JE_showVGA(); |
network_check(); |
uSDL_Delay(16); |
} |
} |
else |
#endif |
{ |
do |
{ |
/* Animate instead of quickly fading in */ |
if (redraw) |
{ |
play_song(SONG_TITLE); |
menu = 0; |
redraw = false; |
if (animate) |
{ |
if (fadeIn) |
{ |
fade_black(10); |
fadeIn = false; |
} |
JE_loadPic(VGAScreen, 4, false); |
draw_font_hv_shadow(VGAScreen, 2, 192, opentyrian_version, small_font, left_aligned, 15, 0, false, 1); |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
temp = moveTyrianLogoUp ? 62 : 4; |
blit_sprite(VGAScreenSeg, 11, temp, PLANET_SHAPES, 146); // tyrian logo |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255 - 16); |
if (moveTyrianLogoUp) |
{ |
for (temp = 61; temp >= 4; temp -= 2) |
{ |
setjasondelay(2); |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
blit_sprite(VGAScreenSeg, 11, temp, PLANET_SHAPES, 146); // tyrian logo |
JE_showVGA(); |
service_wait_delay(); |
} |
moveTyrianLogoUp = false; |
} |
strcpy(menuText[4], opentyrian_str); // OpenTyrian override |
/* Draw Menu Text on Screen */ |
for (int i = 0; i < menunum; ++i) |
{ |
int x = VGAScreen->w / 2, y = 104 + i * 13; |
draw_font_hv(VGAScreen, x - 1, y - 1, menuText[i], normal_font, centered, 15, -10); |
draw_font_hv(VGAScreen, x + 1, y + 1, menuText[i], normal_font, centered, 15, -10); |
draw_font_hv(VGAScreen, x + 1, y - 1, menuText[i], normal_font, centered, 15, -10); |
draw_font_hv(VGAScreen, x - 1, y + 1, menuText[i], normal_font, centered, 15, -10); |
draw_font_hv(VGAScreen, x, y, menuText[i], normal_font, centered, 15, -3); |
} |
JE_showVGA(); |
fade_palette(colors, 20, 255 - 16 + 1, 255); // fade in menu items |
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h); |
} |
} |
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h); |
// highlight selected menu item |
draw_font_hv(VGAScreen, VGAScreen->w / 2, 104 + menu * 13, menuText[menu], normal_font, centered, 15, -1); |
JE_showVGA(); |
if (trentWin) |
{ |
quit = true; |
goto trentWinsGame; |
} |
waitForDemo = 2000; |
JE_textMenuWait(&waitForDemo, false); |
if (waitForDemo == 1) |
play_demo = true; |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_UP: |
if (menu == 0) |
menu = menunum-1; |
else |
menu--; |
JE_playSampleNum(S_CURSOR); |
break; |
case SDLK_DOWN: |
if (menu == menunum-1) |
menu = 0; |
else |
menu++; |
JE_playSampleNum(S_CURSOR); |
break; |
default: |
break; |
} |
} |
for (unsigned int i = 0; i < SA_ENGAGE; i++) |
{ |
if (toupper(lastkey_char) == specialName[i][arcade_code_i[i]]) |
arcade_code_i[i]++; |
else |
arcade_code_i[i] = 0; |
if (arcade_code_i[i] > 0 && arcade_code_i[i] == strlen(specialName[i])) |
{ |
if (i+1 == SA_DESTRUCT) |
{ |
loadDestruct = true; |
} |
else if (i+1 == SA_ENGAGE) |
{ |
/* SuperTyrian */ |
JE_playSampleNum(V_DATA_CUBE); |
JE_whoa(); |
initialDifficulty = keysactive[SDLK_SCROLLOCK] ? 6 : 8; |
JE_clr256(VGAScreen); |
JE_outText(VGAScreen, 10, 10, "Cheat codes have been disabled.", 15, 4); |
if (initialDifficulty == 8) |
JE_outText(VGAScreen, 10, 20, "Difficulty level has been set to Lord of Game.", 15, 4); |
else |
JE_outText(VGAScreen, 10, 20, "Difficulty level has been set to Suicide.", 15, 4); |
JE_outText(VGAScreen, 10, 30, "It is imperative that you discover the special codes.", 15, 4); |
if (initialDifficulty == 8) |
JE_outText(VGAScreen, 10, 40, "(Next time, for an easier challenge hold down SCROLL LOCK.)", 15, 4); |
JE_outText(VGAScreen, 10, 60, "Prepare to play...", 15, 4); |
char buf[10+1+15+1]; |
snprintf(buf, sizeof(buf), "%s %s", miscTextB[4], pName[0]); |
JE_dString(VGAScreen, JE_fontCenter(buf, FONT_SHAPES), 110, buf, FONT_SHAPES); |
play_song(16); |
JE_playSampleNum(V_DANGER); |
JE_showVGA(); |
wait_noinput(true, true, true); |
wait_input(true, true, true); |
JE_initEpisode(1); |
constantDie = false; |
superTyrian = true; |
onePlayerAction = true; |
gameLoaded = true; |
difficultyLevel = initialDifficulty; |
player[0].cash = 0; |
player[0].items.ship = 13; // The Stalker 21.126 |
player[0].items.weapon[FRONT_WEAPON].id = 39; // Atomic RailGun |
} |
else |
{ |
player[0].items.ship = SAShip[i]; |
fade_black(10); |
if (select_episode() && select_difficulty()) |
{ |
/* Start special mode! */ |
fade_black(10); |
JE_loadPic(VGAScreen, 1, false); |
JE_clr256(VGAScreen); |
JE_dString(VGAScreen, JE_fontCenter(superShips[0], FONT_SHAPES), 30, superShips[0], FONT_SHAPES); |
JE_dString(VGAScreen, JE_fontCenter(superShips[i+1], SMALL_FONT_SHAPES), 100, superShips[i+1], SMALL_FONT_SHAPES); |
tempW = ships[player[0].items.ship].shipgraphic; |
if (tempW != 1) |
blit_sprite2x2(VGAScreen, 148, 70, shapes9, tempW); |
JE_showVGA(); |
fade_palette(colors, 50, 0, 255); |
wait_input(true, true, true); |
twoPlayerMode = false; |
onePlayerAction = true; |
superArcadeMode = i+1; |
gameLoaded = true; |
initialDifficulty = ++difficultyLevel; |
player[0].cash = 0; |
player[0].items.weapon[FRONT_WEAPON].id = SAWeapon[i][0]; |
player[0].items.special = SASpecialWeapon[i]; |
if (superArcadeMode == SA_NORTSHIPZ) |
{ |
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i) |
player[0].items.sidekick[i] = 24; // Companion Ship Quicksilver |
} |
} |
else |
{ |
redraw = true; |
fadeIn = true; |
} |
} |
newkey = false; |
} |
} |
lastkey_char = '\0'; |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_ESCAPE: |
quit = true; |
break; |
case SDLK_RETURN: |
JE_playSampleNum(S_SELECT); |
switch (menu) |
{ |
case 0: /* New game */ |
fade_black(10); |
if (select_gameplay()) |
{ |
if (select_episode() && select_difficulty()) |
gameLoaded = true; |
initialDifficulty = difficultyLevel; |
if (onePlayerAction) |
{ |
player[0].cash = 0; |
player[0].items.ship = 8; // Stalker |
} |
else if (twoPlayerMode) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].cash = 0; |
player[0].items.ship = 11; // Silver Ship |
difficultyLevel++; |
inputDevice[0] = 1; |
inputDevice[1] = 2; |
} |
else if (richMode) |
{ |
player[0].cash = 1000000; |
} |
else if (gameLoaded) |
{ |
// allows player to smuggle arcade/super-arcade ships into full game |
ulong initial_cash[] = { 10000, 15000, 20000, 30000 }; |
assert(episodeNum >= 1 && episodeNum <= EPISODE_AVAILABLE); |
player[0].cash = initial_cash[episodeNum-1]; |
} |
} |
fadeIn = true; |
break; |
case 1: /* Load game */ |
JE_loadScreen(); |
fadeIn = true; |
break; |
case 2: /* High scores */ |
JE_highScoreScreen(); |
fadeIn = true; |
break; |
case 3: /* Instructions */ |
JE_helpSystem(1); |
fadeIn = true; |
break; |
case 4: /* Ordering info, now OpenTyrian menu */ |
opentyrian_menu(); |
fadeIn = true; |
break; |
case 5: /* Demo */ |
play_demo = true; |
break; |
case 6: /* Quit */ |
quit = true; |
break; |
} |
redraw = true; |
break; |
default: |
break; |
} |
} |
} |
while (!(quit || gameLoaded || jumpSection || play_demo || loadDestruct)); |
trentWinsGame: |
fade_black(15); |
} |
return quit; |
} |
void intro_logos( void ) |
{ |
SDL_FillRect(VGAScreen, NULL, 0); |
fade_white(50); |
JE_loadPic(VGAScreen, 10, false); |
JE_showVGA(); |
fade_palette(colors, 50, 0, 255); |
setjasondelay(200); |
wait_delayorinput(true, true, true); |
fade_black(10); |
JE_loadPic(VGAScreen, 12, false); |
JE_showVGA(); |
fade_palette(colors, 10, 0, 255); |
setjasondelay(200); |
wait_delayorinput(true, true, true); |
fade_black(10); |
} |
void JE_readTextSync( void ) |
{ |
#if 0 // this function seems to be unnecessary |
JE_clr256(VGAScreen); |
JE_showVGA(); |
JE_loadPic(VGAScreen, 1, true); |
JE_barShade(VGAScreen, 3, 3, 316, 196); |
JE_barShade(VGAScreen, 1, 1, 318, 198); |
JE_dString(VGAScreen, 10, 160, "Waiting for other player.", SMALL_FONT_SHAPES); |
JE_showVGA(); |
/* TODO: NETWORK */ |
do |
{ |
setjasondelay(2); |
/* TODO: NETWORK */ |
wait_delay(); |
} while (0 /* TODO: NETWORK */); |
#endif |
} |
void JE_displayText( void ) |
{ |
/* Display Warning Text */ |
tempY = 55; |
if (warningRed) |
{ |
tempY = 2; |
} |
for (temp = 0; temp < levelWarningLines; temp++) |
{ |
if (!ESCPressed) |
{ |
JE_outCharGlow(10, tempY, levelWarningText[temp]); |
if (haltGame) |
{ |
JE_tyrianHalt(5); |
} |
tempY += 10; |
} |
} |
if (frameCountMax != 0) |
{ |
frameCountMax = 6; |
temp = 1; |
} else { |
temp = 0; |
} |
textGlowFont = TINY_FONT; |
tempW = 184; |
if (warningRed) |
{ |
tempW = 7 * 16 + 6; |
} |
JE_outCharGlow(JE_fontCenter(miscText[4], TINY_FONT), tempW, miscText[4]); |
do |
{ |
if (levelWarningDisplay) |
{ |
JE_updateWarning(VGAScreen); |
} |
setjasondelay(1); |
NETWORK_KEEP_ALIVE(); |
wait_delay(); |
} while (!(JE_anyButton() || (frameCountMax == 0 && temp == 1) || ESCPressed)); |
levelWarningDisplay = false; |
} |
Sint16 JE_newEnemy( int enemyOffset, Uint16 eDatI, Sint16 uniqueShapeTableI ) |
{ |
for (int i = enemyOffset; i < enemyOffset + 25; ++i) |
{ |
if (enemyAvail[i] == 1) |
{ |
enemyAvail[i] = JE_makeEnemy(&enemy[i], eDatI, uniqueShapeTableI); |
return i + 1; |
} |
} |
return 0; |
} |
uint JE_makeEnemy( struct JE_SingleEnemyType *enemy, Uint16 eDatI, Sint16 uniqueShapeTableI ) |
{ |
uint avail; |
JE_byte shapeTableI; |
if (superArcadeMode != SA_NONE && eDatI == 534) |
eDatI = 533; |
enemyShapeTables[5-1] = 21; /*Coins&Gems*/ |
enemyShapeTables[6-1] = 26; /*Two-Player Stuff*/ |
if (uniqueShapeTableI > 0) |
{ |
shapeTableI = uniqueShapeTableI; |
} |
else |
{ |
shapeTableI = enemyDat[eDatI].shapebank; |
} |
Sprite2_array *sprite2s = NULL; |
for (uint i = 0; i < 6; ++i) |
if (shapeTableI == enemyShapeTables[i]) |
sprite2s = &eShapes[i]; |
if (sprite2s != NULL) |
enemy->sprite2s = sprite2s; |
else |
// maintain buggy Tyrian behavior (use shape table value from previous enemy that occupied this index in the enemy array) |
fprintf(stderr, "warning: ignoring sprite from unloaded shape table %d\n", shapeTableI); |
enemy->enemydatofs = &enemyDat[eDatI]; |
enemy->mapoffset = 0; |
for (uint i = 0; i < 3; ++i) |
{ |
enemy->eshotmultipos[i] = 0; |
} |
enemy->enemyground = (enemyDat[eDatI].explosiontype & 1) == 0; |
enemy->explonum = enemyDat[eDatI].explosiontype >> 1; |
enemy->launchfreq = enemyDat[eDatI].elaunchfreq; |
enemy->launchwait = enemyDat[eDatI].elaunchfreq; |
enemy->launchtype = enemyDat[eDatI].elaunchtype % 1000; |
enemy->launchspecial = enemyDat[eDatI].elaunchtype / 1000; |
enemy->xaccel = enemyDat[eDatI].xaccel; |
enemy->yaccel = enemyDat[eDatI].yaccel; |
enemy->xminbounce = -10000; |
enemy->xmaxbounce = 10000; |
enemy->yminbounce = -10000; |
enemy->ymaxbounce = 10000; |
/*Far enough away to be impossible to reach*/ |
for (uint i = 0; i < 3; ++i) |
{ |
enemy->tur[i] = enemyDat[eDatI].tur[i]; |
} |
enemy->ani = enemyDat[eDatI].ani; |
enemy->animin = 1; |
switch (enemyDat[eDatI].animate) |
{ |
case 0: |
enemy->enemycycle = 1; |
enemy->aniactive = 0; |
enemy->animax = 0; |
enemy->aniwhenfire = 0; |
break; |
case 1: |
enemy->enemycycle = 0; |
enemy->aniactive = 1; |
enemy->animax = 0; |
enemy->aniwhenfire = 0; |
break; |
case 2: |
enemy->enemycycle = 1; |
enemy->aniactive = 2; |
enemy->animax = enemy->ani; |
enemy->aniwhenfire = 2; |
break; |
} |
if (enemyDat[eDatI].startxc != 0) |
enemy->ex = enemyDat[eDatI].startx + (mt_rand() % (enemyDat[eDatI].startxc * 2)) - enemyDat[eDatI].startxc + 1; |
else |
enemy->ex = enemyDat[eDatI].startx + 1; |
if (enemyDat[eDatI].startyc != 0) |
enemy->ey = enemyDat[eDatI].starty + (mt_rand() % (enemyDat[eDatI].startyc * 2)) - enemyDat[eDatI].startyc + 1; |
else |
enemy->ey = enemyDat[eDatI].starty + 1; |
enemy->exc = enemyDat[eDatI].xmove; |
enemy->eyc = enemyDat[eDatI].ymove; |
enemy->excc = enemyDat[eDatI].xcaccel; |
enemy->eycc = enemyDat[eDatI].ycaccel; |
enemy->exccw = abs(enemy->excc); |
enemy->exccwmax = enemy->exccw; |
enemy->eyccw = abs(enemy->eycc); |
enemy->eyccwmax = enemy->eyccw; |
enemy->exccadd = (enemy->excc > 0) ? 1 : -1; |
enemy->eyccadd = (enemy->eycc > 0) ? 1 : -1; |
enemy->special = false; |
enemy->iced = 0; |
if (enemyDat[eDatI].xrev == 0) |
enemy->exrev = 100; |
else if (enemyDat[eDatI].xrev == -99) |
enemy->exrev = 0; |
else |
enemy->exrev = enemyDat[eDatI].xrev; |
if (enemyDat[eDatI].yrev == 0) |
enemy->eyrev = 100; |
else if (enemyDat[eDatI].yrev == -99) |
enemy->eyrev = 0; |
else |
enemy->eyrev = enemyDat[eDatI].yrev; |
enemy->exca = (enemy->xaccel > 0) ? 1 : -1; |
enemy->eyca = (enemy->yaccel > 0) ? 1 : -1; |
enemy->enemytype = eDatI; |
for (uint i = 0; i < 3; ++i) |
{ |
if (enemy->tur[i] == 252) |
enemy->eshotwait[i] = 1; |
else if (enemy->tur[i] > 0) |
enemy->eshotwait[i] = 20; |
else |
enemy->eshotwait[i] = 255; |
} |
for (uint i = 0; i < 20; ++i) |
enemy->egr[i] = enemyDat[eDatI].egraphic[i]; |
enemy->size = enemyDat[eDatI].esize; |
enemy->linknum = 0; |
enemy->edamaged = enemyDat[eDatI].dani < 0; |
enemy->enemydie = enemyDat[eDatI].eenemydie; |
enemy->freq[1-1] = enemyDat[eDatI].freq[1-1]; |
enemy->freq[2-1] = enemyDat[eDatI].freq[2-1]; |
enemy->freq[3-1] = enemyDat[eDatI].freq[3-1]; |
enemy->edani = enemyDat[eDatI].dani; |
enemy->edgr = enemyDat[eDatI].dgr; |
enemy->edlevel = enemyDat[eDatI].dlevel; |
enemy->fixedmovey = 0; |
enemy->filter = 0x00; |
int tempValue = 0; |
if (enemyDat[eDatI].value > 1 && enemyDat[eDatI].value < 10000) |
{ |
switch (difficultyLevel) |
{ |
case -1: |
case 0: |
tempValue = enemyDat[eDatI].value * 0.75f; |
break; |
case 1: |
case 2: |
tempValue = enemyDat[eDatI].value; |
break; |
case 3: |
tempValue = enemyDat[eDatI].value * 1.125f; |
break; |
case 4: |
tempValue = enemyDat[eDatI].value * 1.5f; |
break; |
case 5: |
tempValue = enemyDat[eDatI].value * 2; |
break; |
case 6: |
tempValue = enemyDat[eDatI].value * 2.5f; |
break; |
case 7: |
case 8: |
tempValue = enemyDat[eDatI].value * 4; |
break; |
case 9: |
case 10: |
tempValue = enemyDat[eDatI].value * 8; |
break; |
} |
if (tempValue > 10000) |
tempValue = 10000; |
enemy->evalue = tempValue; |
} |
else |
{ |
enemy->evalue = enemyDat[eDatI].value; |
} |
int tempArmor = 1; |
if (enemyDat[eDatI].armor > 0) |
{ |
if (enemyDat[eDatI].armor != 255) |
{ |
switch (difficultyLevel) |
{ |
case -1: |
case 0: |
tempArmor = enemyDat[eDatI].armor * 0.5f + 1; |
break; |
case 1: |
tempArmor = enemyDat[eDatI].armor * 0.75f + 1; |
break; |
case 2: |
tempArmor = enemyDat[eDatI].armor; |
break; |
case 3: |
tempArmor = enemyDat[eDatI].armor * 1.2f; |
break; |
case 4: |
tempArmor = enemyDat[eDatI].armor * 1.5f; |
break; |
case 5: |
tempArmor = enemyDat[eDatI].armor * 1.8f; |
break; |
case 6: |
tempArmor = enemyDat[eDatI].armor * 2; |
break; |
case 7: |
tempArmor = enemyDat[eDatI].armor * 3; |
break; |
case 8: |
tempArmor = enemyDat[eDatI].armor * 4; |
break; |
case 9: |
case 10: |
tempArmor = enemyDat[eDatI].armor * 8; |
break; |
} |
if (tempArmor > 254) |
{ |
tempArmor = 254; |
} |
} |
else |
{ |
tempArmor = 255; |
} |
enemy->armorleft = tempArmor; |
avail = 0; |
enemy->scoreitem = false; |
} |
else |
{ |
avail = 2; |
enemy->armorleft = 255; |
if (enemy->evalue != 0) |
enemy->scoreitem = true; |
} |
if (!enemy->scoreitem) |
{ |
totalEnemy++; /*Destruction ratio*/ |
} |
/* indicates what to set ENEMYAVAIL to */ |
return avail; |
} |
void JE_createNewEventEnemy( JE_byte enemyTypeOfs, JE_word enemyOffset, Sint16 uniqueShapeTableI ) |
{ |
int i; |
b = 0; |
for(i = enemyOffset; i < enemyOffset + 25; i++) |
{ |
if (enemyAvail[i] == 1) |
{ |
b = i + 1; |
break; |
} |
} |
if (b == 0) |
{ |
return; |
} |
tempW = eventRec[eventLoc-1].eventdat + enemyTypeOfs; |
enemyAvail[b-1] = JE_makeEnemy(&enemy[b-1], tempW, uniqueShapeTableI); |
if (eventRec[eventLoc-1].eventdat2 != -99) |
{ |
switch (enemyOffset) |
{ |
case 0: |
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24; |
enemy[b-1].ey -= backMove2; |
break; |
case 25: |
case 75: |
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24 - 12; |
enemy[b-1].ey -= backMove; |
break; |
case 50: |
if (background3x1) |
{ |
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24 - 12; |
} else { |
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - mapX3 * 24 - 24 * 2 + 6; |
} |
enemy[b-1].ey -= backMove3; |
if (background3x1b) |
{ |
enemy[b-1].ex -= 6; |
} |
break; |
} |
enemy[b-1].ey = -28; |
if (background3x1b && enemyOffset == 50) |
{ |
enemy[b-1].ey += 4; |
} |
} |
if (smallEnemyAdjust && enemy[b-1].size == 0) |
{ |
enemy[b-1].ex -= 10; |
enemy[b-1].ey -= 7; |
} |
enemy[b-1].ey += eventRec[eventLoc-1].eventdat5; |
enemy[b-1].eyc += eventRec[eventLoc-1].eventdat3; |
enemy[b-1].linknum = eventRec[eventLoc-1].eventdat4; |
enemy[b-1].fixedmovey = eventRec[eventLoc-1].eventdat6; |
} |
void JE_eventJump( JE_word jump ) |
{ |
JE_word tempW; |
if (jump == 65535) |
{ |
curLoc = returnLoc; |
} |
else |
{ |
returnLoc = curLoc + 1; |
curLoc = jump; |
} |
tempW = 0; |
do |
{ |
tempW++; |
} |
while (!(eventRec[tempW-1].eventtime >= curLoc)); |
eventLoc = tempW - 1; |
} |
bool JE_searchFor/*enemy*/( JE_byte PLType, JE_byte* out_index ) |
{ |
int found_id = -1; |
for (int i = 0; i < 100; i++) |
{ |
if (enemyAvail[i] == 0 && enemy[i].linknum == PLType) |
{ |
found_id = i; |
if (galagaMode) |
{ |
enemy[i].evalue += enemy[i].evalue; |
} |
} |
} |
if (found_id != -1) { |
if (out_index) { |
*out_index = found_id; |
} |
return true; |
} else { |
return false; |
} |
} |
void JE_eventSystem( void ) |
{ |
switch (eventRec[eventLoc-1].eventtype) |
{ |
case 1: |
starfield_speed = eventRec[eventLoc-1].eventdat; |
break; |
case 2: |
map1YDelay = 1; |
map1YDelayMax = 1; |
map2YDelay = 1; |
map2YDelayMax = 1; |
backMove = eventRec[eventLoc-1].eventdat; |
backMove2 = eventRec[eventLoc-1].eventdat2; |
if (backMove2 > 0) |
explodeMove = backMove2; |
else |
explodeMove = backMove; |
backMove3 = eventRec[eventLoc-1].eventdat3; |
if (backMove > 0) |
stopBackgroundNum = 0; |
break; |
case 3: |
backMove = 1; |
map1YDelay = 3; |
map1YDelayMax = 3; |
backMove2 = 1; |
map2YDelay = 2; |
map2YDelayMax = 2; |
backMove3 = 1; |
break; |
case 4: |
stopBackgrounds = true; |
switch (eventRec[eventLoc-1].eventdat) |
{ |
case 0: |
case 1: |
stopBackgroundNum = 1; |
break; |
case 2: |
stopBackgroundNum = 2; |
break; |
case 3: |
stopBackgroundNum = 3; |
break; |
} |
break; |
case 5: // load enemy shape banks |
{ |
Uint8 newEnemyShapeTables[] = |
{ |
eventRec[eventLoc-1].eventdat > 0 ? eventRec[eventLoc-1].eventdat : 0, |
eventRec[eventLoc-1].eventdat2 > 0 ? eventRec[eventLoc-1].eventdat2 : 0, |
eventRec[eventLoc-1].eventdat3 > 0 ? eventRec[eventLoc-1].eventdat3 : 0, |
eventRec[eventLoc-1].eventdat4 > 0 ? eventRec[eventLoc-1].eventdat4 : 0, |
}; |
for (unsigned int i = 0; i < COUNTOF(newEnemyShapeTables); ++i) |
{ |
if (enemyShapeTables[i] != newEnemyShapeTables[i]) |
{ |
if (newEnemyShapeTables[i] > 0) |
{ |
assert(newEnemyShapeTables[i] <= COUNTOF(shapeFile)); |
JE_loadCompShapes(&eShapes[i], shapeFile[newEnemyShapeTables[i] - 1]); |
} |
else |
free_sprite2s(&eShapes[i]); |
enemyShapeTables[i] = newEnemyShapeTables[i]; |
} |
} |
} |
break; |
case 6: /* Ground Enemy */ |
JE_createNewEventEnemy(0, 25, 0); |
break; |
case 7: /* Top Enemy */ |
JE_createNewEventEnemy(0, 50, 0); |
break; |
case 8: |
starActive = false; |
break; |
case 9: |
starActive = true; |
break; |
case 10: /* Ground Enemy 2 */ |
JE_createNewEventEnemy(0, 75, 0); |
break; |
case 11: |
if (allPlayersGone || eventRec[eventLoc-1].eventdat == 1) |
reallyEndLevel = true; |
else |
if (!endLevel) |
{ |
readyToEndLevel = false; |
endLevel = true; |
levelEnd = 40; |
} |
break; |
case 12: /* Custom 4x4 Ground Enemy */ |
{ |
uint temp = 0; |
switch (eventRec[eventLoc-1].eventdat6) |
{ |
case 0: |
case 1: |
temp = 25; |
break; |
case 2: |
temp = 0; |
break; |
case 3: |
temp = 50; |
break; |
case 4: |
temp = 75; |
break; |
} |
eventRec[eventLoc-1].eventdat6 = 0; /* We use EVENTDAT6 for the background */ |
JE_createNewEventEnemy(0, temp, 0); |
JE_createNewEventEnemy(1, temp, 0); |
if (b > 0) |
enemy[b-1].ex += 24; |
JE_createNewEventEnemy(2, temp, 0); |
if (b > 0) |
enemy[b-1].ey -= 28; |
JE_createNewEventEnemy(3, temp, 0); |
if (b > 0) |
{ |
enemy[b-1].ex += 24; |
enemy[b-1].ey -= 28; |
} |
break; |
} |
case 13: |
enemiesActive = false; |
break; |
case 14: |
enemiesActive = true; |
break; |
case 15: /* Sky Enemy */ |
JE_createNewEventEnemy(0, 0, 0); |
break; |
case 16: |
if (eventRec[eventLoc-1].eventdat > 9) |
{ |
fprintf(stderr, "warning: event 16: bad event data\n"); |
} |
else |
{ |
JE_drawTextWindow(outputs[eventRec[eventLoc-1].eventdat-1]); |
soundQueue[3] = windowTextSamples[eventRec[eventLoc-1].eventdat-1]; |
} |
break; |
case 17: /* Ground Bottom */ |
JE_createNewEventEnemy(0, 25, 0); |
if (b > 0) |
{ |
enemy[b-1].ey = 190 + eventRec[eventLoc-1].eventdat5; |
} |
break; |
case 18: /* Sky Enemy on Bottom */ |
JE_createNewEventEnemy(0, 0, 0); |
if (b > 0) |
{ |
enemy[b-1].ey = 190 + eventRec[eventLoc-1].eventdat5; |
} |
break; |
case 19: /* Enemy Global Move */ |
{ |
int initial_i = 0, max_i = 0; |
bool all_enemies = false; |
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90) |
{ |
initial_i = 0; |
max_i = 100; |
all_enemies = false; |
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80]; |
} |
else |
{ |
switch (eventRec[eventLoc-1].eventdat3) |
{ |
case 0: |
initial_i = 0; |
max_i = 100; |
all_enemies = false; |
break; |
case 2: |
initial_i = 0; |
max_i = 25; |
all_enemies = true; |
break; |
case 1: |
initial_i = 25; |
max_i = 50; |
all_enemies = true; |
break; |
case 3: |
initial_i = 50; |
max_i = 75; |
all_enemies = true; |
break; |
case 99: |
initial_i = 0; |
max_i = 100; |
all_enemies = true; |
break; |
} |
} |
for (int i = initial_i; i < max_i; i++) |
{ |
if (all_enemies || enemy[i].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
if (eventRec[eventLoc-1].eventdat != -99) |
enemy[i].exc = eventRec[eventLoc-1].eventdat; |
if (eventRec[eventLoc-1].eventdat2 != -99) |
enemy[i].eyc = eventRec[eventLoc-1].eventdat2; |
if (eventRec[eventLoc-1].eventdat6 != 0) |
enemy[i].fixedmovey = eventRec[eventLoc-1].eventdat6; |
if (eventRec[eventLoc-1].eventdat6 == -99) |
enemy[i].fixedmovey = 0; |
if (eventRec[eventLoc-1].eventdat5 > 0) |
enemy[i].enemycycle = eventRec[eventLoc-1].eventdat5; |
} |
} |
break; |
} |
case 20: /* Enemy Global Accel */ |
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90) |
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80]; |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemyAvail[temp] != 1 |
&& (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4 || eventRec[eventLoc-1].eventdat4 == 0)) |
{ |
if (eventRec[eventLoc-1].eventdat != -99) |
{ |
enemy[temp].excc = eventRec[eventLoc-1].eventdat; |
enemy[temp].exccw = abs(eventRec[eventLoc-1].eventdat); |
enemy[temp].exccwmax = abs(eventRec[eventLoc-1].eventdat); |
if (eventRec[eventLoc-1].eventdat > 0) |
enemy[temp].exccadd = 1; |
else |
enemy[temp].exccadd = -1; |
} |
if (eventRec[eventLoc-1].eventdat2 != -99) |
{ |
enemy[temp].eycc = eventRec[eventLoc-1].eventdat2; |
enemy[temp].eyccw = abs(eventRec[eventLoc-1].eventdat2); |
enemy[temp].eyccwmax = abs(eventRec[eventLoc-1].eventdat2); |
if (eventRec[eventLoc-1].eventdat2 > 0) |
enemy[temp].eyccadd = 1; |
else |
enemy[temp].eyccadd = -1; |
} |
if (eventRec[eventLoc-1].eventdat5 > 0) |
{ |
enemy[temp].enemycycle = eventRec[eventLoc-1].eventdat5; |
} |
if (eventRec[eventLoc-1].eventdat6 > 0) |
{ |
enemy[temp].ani = eventRec[eventLoc-1].eventdat6; |
enemy[temp].animin = eventRec[eventLoc-1].eventdat5; |
enemy[temp].animax = 0; |
enemy[temp].aniactive = 1; |
} |
} |
} |
break; |
case 21: |
background3over = 1; |
break; |
case 22: |
background3over = 0; |
break; |
case 23: /* Sky Enemy on Bottom */ |
JE_createNewEventEnemy(0, 50, 0); |
if (b > 0) |
enemy[b-1].ey = 180 + eventRec[eventLoc-1].eventdat5; |
break; |
case 24: /* Enemy Global Animate */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
enemy[temp].aniactive = 1; |
enemy[temp].aniwhenfire = 0; |
if (eventRec[eventLoc-1].eventdat2 > 0) |
{ |
enemy[temp].enemycycle = eventRec[eventLoc-1].eventdat2; |
enemy[temp].animin = enemy[temp].enemycycle; |
} |
else |
{ |
enemy[temp].enemycycle = 0; |
} |
if (eventRec[eventLoc-1].eventdat > 0) |
enemy[temp].ani = eventRec[eventLoc-1].eventdat; |
if (eventRec[eventLoc-1].eventdat3 == 1) |
{ |
enemy[temp].animax = enemy[temp].ani; |
} |
else if (eventRec[eventLoc-1].eventdat3 == 2) |
{ |
enemy[temp].aniactive = 2; |
enemy[temp].animax = enemy[temp].ani; |
enemy[temp].aniwhenfire = 2; |
} |
} |
} |
break; |
case 25: /* Enemy Global Damage change */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
if (galagaMode) |
enemy[temp].armorleft = roundf(eventRec[eventLoc-1].eventdat * (difficultyLevel / 2)); |
else |
enemy[temp].armorleft = eventRec[eventLoc-1].eventdat; |
} |
} |
break; |
case 26: |
smallEnemyAdjust = eventRec[eventLoc-1].eventdat; |
break; |
case 27: /* Enemy Global AccelRev */ |
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90) |
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80]; |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
if (eventRec[eventLoc-1].eventdat != -99) |
enemy[temp].exrev = eventRec[eventLoc-1].eventdat; |
if (eventRec[eventLoc-1].eventdat2 != -99) |
enemy[temp].eyrev = eventRec[eventLoc-1].eventdat2; |
if (eventRec[eventLoc-1].eventdat3 != 0 && eventRec[eventLoc-1].eventdat3 < 17) |
enemy[temp].filter = eventRec[eventLoc-1].eventdat3; |
} |
} |
break; |
case 28: |
topEnemyOver = false; |
break; |
case 29: |
topEnemyOver = true; |
break; |
case 30: |
map1YDelay = 1; |
map1YDelayMax = 1; |
map2YDelay = 1; |
map2YDelayMax = 1; |
backMove = eventRec[eventLoc-1].eventdat; |
backMove2 = eventRec[eventLoc-1].eventdat2; |
explodeMove = backMove2; |
backMove3 = eventRec[eventLoc-1].eventdat3; |
break; |
case 31: /* Enemy Fire Override */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 99 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
enemy[temp].freq[1-1] = eventRec[eventLoc-1].eventdat ; |
enemy[temp].freq[2-1] = eventRec[eventLoc-1].eventdat2; |
enemy[temp].freq[3-1] = eventRec[eventLoc-1].eventdat3; |
for (temp2 = 0; temp2 < 3; temp2++) |
{ |
enemy[temp].eshotwait[temp2] = 1; |
} |
if (enemy[temp].launchtype > 0) |
{ |
enemy[temp].launchfreq = eventRec[eventLoc-1].eventdat5; |
enemy[temp].launchwait = 1; |
} |
} |
} |
break; |
case 32: // create enemy |
JE_createNewEventEnemy(0, 50, 0); |
if (b > 0) |
enemy[b-1].ey = 190; |
break; |
case 33: /* Enemy From other Enemies */ |
if (!((eventRec[eventLoc-1].eventdat == 512 || eventRec[eventLoc-1].eventdat == 513) && (twoPlayerMode || onePlayerAction || superTyrian))) |
{ |
if (superArcadeMode != SA_NONE) |
{ |
if (eventRec[eventLoc-1].eventdat == 534) |
eventRec[eventLoc-1].eventdat = 827; |
} |
else if (!superTyrian) |
{ |
const uint lives = *player[0].lives; |
if (eventRec[eventLoc-1].eventdat == 533 && (lives == 11 || (mt_rand() % 15) < lives)) |
{ |
// enemy will drop random special weapon |
eventRec[eventLoc-1].eventdat = 829 + (mt_rand() % 6); |
} |
} |
if (eventRec[eventLoc-1].eventdat == 534 && superTyrian) |
eventRec[eventLoc-1].eventdat = 828 + superTyrianSpecials[mt_rand() % 4]; |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
enemy[temp].enemydie = eventRec[eventLoc-1].eventdat; |
} |
} |
break; |
case 34: /* Start Music Fade */ |
if (firstGameOver) |
{ |
musicFade = true; |
tempVolume = tyrMusicVolume; |
} |
break; |
case 35: /* Play new song */ |
if (firstGameOver) |
{ |
play_song(eventRec[eventLoc-1].eventdat - 1); |
set_volume(tyrMusicVolume, fxVolume); |
} |
musicFade = false; |
break; |
case 36: |
readyToEndLevel = true; |
break; |
case 37: |
levelEnemyFrequency = eventRec[eventLoc-1].eventdat; |
break; |
case 38: |
curLoc = eventRec[eventLoc-1].eventdat; |
int new_event_loc = 1; |
for (tempW = 0; tempW < maxEvent; tempW++) |
{ |
if (eventRec[tempW].eventtime <= curLoc) |
{ |
new_event_loc = tempW+1 - 1; |
} |
} |
eventLoc = new_event_loc; |
break; |
case 39: /* Enemy Global Linknum Change */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat) |
enemy[temp].linknum = eventRec[eventLoc-1].eventdat2; |
} |
break; |
case 40: /* Enemy Continual Damage */ |
enemyContinualDamage = true; |
break; |
case 41: |
if (eventRec[eventLoc-1].eventdat == 0) |
{ |
memset(enemyAvail, 1, sizeof(enemyAvail)); |
} |
else |
{ |
for (x = 0; x <= 24; x++) |
enemyAvail[x] = 1; |
} |
break; |
case 42: |
background3over = 2; |
break; |
case 43: |
background2over = eventRec[eventLoc-1].eventdat; |
break; |
case 44: |
filterActive = (eventRec[eventLoc-1].eventdat > 0); |
filterFade = (eventRec[eventLoc-1].eventdat == 2); |
levelFilter = eventRec[eventLoc-1].eventdat2; |
levelBrightness = eventRec[eventLoc-1].eventdat3; |
levelFilterNew = eventRec[eventLoc-1].eventdat4; |
levelBrightnessChg = eventRec[eventLoc-1].eventdat5; |
filterFadeStart = (eventRec[eventLoc-1].eventdat6 == 0); |
break; |
case 45: /* arcade-only enemy from other enemies */ |
if (!superTyrian) |
{ |
const uint lives = *player[0].lives; |
if (eventRec[eventLoc-1].eventdat == 533 && (lives == 11 || (mt_rand() % 15) < lives)) |
{ |
eventRec[eventLoc-1].eventdat = 829 + (mt_rand() % 6); |
} |
if (twoPlayerMode || onePlayerAction) |
{ |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
enemy[temp].enemydie = eventRec[eventLoc-1].eventdat; |
} |
} |
} |
break; |
case 46: // change difficulty |
if (eventRec[eventLoc-1].eventdat3 != 0) |
damageRate = eventRec[eventLoc-1].eventdat3; |
if (eventRec[eventLoc-1].eventdat2 == 0 || twoPlayerMode || onePlayerAction) |
{ |
difficultyLevel += eventRec[eventLoc-1].eventdat; |
if (difficultyLevel < 1) |
difficultyLevel = 1; |
if (difficultyLevel > 10) |
difficultyLevel = 10; |
} |
break; |
case 47: /* Enemy Global AccelRev */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
enemy[temp].armorleft = eventRec[eventLoc-1].eventdat; |
} |
break; |
case 48: /* Background 2 Cannot be Transparent */ |
background2notTransparent = true; |
break; |
case 49: |
case 50: |
case 51: |
case 52: |
tempDat2 = eventRec[eventLoc-1].eventdat; |
eventRec[eventLoc-1].eventdat = 0; |
tempDat = eventRec[eventLoc-1].eventdat3; |
eventRec[eventLoc-1].eventdat3 = 0; |
tempDat3 = eventRec[eventLoc-1].eventdat6; |
eventRec[eventLoc-1].eventdat6 = 0; |
enemyDat[0].armor = tempDat3; |
enemyDat[0].egraphic[1-1] = tempDat2; |
switch (eventRec[eventLoc-1].eventtype - 48) |
{ |
case 1: |
temp = 25; |
break; |
case 2: |
temp = 0; |
break; |
case 3: |
temp = 50; |
break; |
case 4: |
temp = 75; |
break; |
} |
JE_createNewEventEnemy(0, temp, tempDat); |
eventRec[eventLoc-1].eventdat = tempDat2; |
eventRec[eventLoc-1].eventdat3 = tempDat; |
eventRec[eventLoc-1].eventdat6 = tempDat3; |
break; |
case 53: |
forceEvents = (eventRec[eventLoc-1].eventdat != 99); |
break; |
case 54: |
JE_eventJump(eventRec[eventLoc-1].eventdat); |
break; |
case 55: /* Enemy Global AccelRev */ |
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90) |
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80]; |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
if (eventRec[eventLoc-1].eventdat != -99) |
enemy[temp].xaccel = eventRec[eventLoc-1].eventdat; |
if (eventRec[eventLoc-1].eventdat2 != -99) |
enemy[temp].yaccel = eventRec[eventLoc-1].eventdat2; |
} |
} |
break; |
case 56: /* Ground2 Bottom */ |
JE_createNewEventEnemy(0, 75, 0); |
if (b > 0) |
enemy[b-1].ey = 190; |
break; |
case 57: |
superEnemy254Jump = eventRec[eventLoc-1].eventdat; |
break; |
case 60: /*Assign Special Enemy*/ |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
enemy[temp].special = true; |
enemy[temp].flagnum = eventRec[eventLoc-1].eventdat; |
enemy[temp].setto = (eventRec[eventLoc-1].eventdat2 == 1); |
} |
} |
break; |
case 61: // if specific flag set to specific value, skip events |
if (globalFlags[eventRec[eventLoc-1].eventdat-1] == eventRec[eventLoc-1].eventdat2) |
eventLoc += eventRec[eventLoc-1].eventdat3; |
break; |
case 62: /*Play sound effect*/ |
soundQueue[3] = eventRec[eventLoc-1].eventdat; |
break; |
case 63: // skip events if not in 2-player mode |
if (!twoPlayerMode && !onePlayerAction) |
eventLoc += eventRec[eventLoc-1].eventdat; |
break; |
case 64: |
if (!(eventRec[eventLoc-1].eventdat == 6 && twoPlayerMode && difficultyLevel > 2)) |
{ |
smoothies[eventRec[eventLoc-1].eventdat-1] = eventRec[eventLoc-1].eventdat2; |
temp = eventRec[eventLoc-1].eventdat; |
if (temp == 5) |
temp = 3; |
smoothie_data[temp-1] = eventRec[eventLoc-1].eventdat3; |
} |
break; |
case 65: |
background3x1 = (eventRec[eventLoc-1].eventdat == 0); |
break; |
case 66: /*If not on this difficulty level or higher then...*/ |
if (initialDifficulty <= eventRec[eventLoc-1].eventdat) |
eventLoc += eventRec[eventLoc-1].eventdat2; |
break; |
case 67: |
levelTimer = (eventRec[eventLoc-1].eventdat == 1); |
levelTimerCountdown = eventRec[eventLoc-1].eventdat3 * 100; |
levelTimerJumpTo = eventRec[eventLoc-1].eventdat2; |
break; |
case 68: |
randomExplosions = (eventRec[eventLoc-1].eventdat == 1); |
break; |
case 69: |
for (uint i = 0; i < COUNTOF(player); ++i) |
player[i].invulnerable_ticks = eventRec[eventLoc-1].eventdat; |
break; |
case 70: |
if (eventRec[eventLoc-1].eventdat2 == 0) |
{ /*1-10*/ |
bool found = false; |
for (temp = 1; temp <= 19; temp++) |
found = found || JE_searchFor(temp, NULL); |
if (!found) |
JE_eventJump(eventRec[eventLoc-1].eventdat); |
} |
else if (!JE_searchFor(eventRec[eventLoc-1].eventdat2, NULL) |
&& (eventRec[eventLoc-1].eventdat3 == 0 || !JE_searchFor(eventRec[eventLoc-1].eventdat3, NULL)) |
&& (eventRec[eventLoc-1].eventdat4 == 0 || !JE_searchFor(eventRec[eventLoc-1].eventdat4, NULL))) |
{ |
JE_eventJump(eventRec[eventLoc-1].eventdat); |
} |
break; |
case 71: |
if (((((intptr_t)mapYPos - (intptr_t)&megaData1.mainmap) / sizeof(JE_byte *)) * 2) <= (unsigned)eventRec[eventLoc-1].eventdat2) |
{ |
JE_eventJump(eventRec[eventLoc-1].eventdat); |
} |
break; |
case 72: |
background3x1b = (eventRec[eventLoc-1].eventdat == 1); |
break; |
case 73: |
skyEnemyOverAll = (eventRec[eventLoc-1].eventdat == 1); |
break; |
case 74: /* Enemy Global BounceParams */ |
for (temp = 0; temp < 100; temp++) |
{ |
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4) |
{ |
if (eventRec[eventLoc-1].eventdat5 != -99) |
enemy[temp].xminbounce = eventRec[eventLoc-1].eventdat5; |
if (eventRec[eventLoc-1].eventdat6 != -99) |
enemy[temp].yminbounce = eventRec[eventLoc-1].eventdat6; |
if (eventRec[eventLoc-1].eventdat != -99) |
enemy[temp].xmaxbounce = eventRec[eventLoc-1].eventdat; |
if (eventRec[eventLoc-1].eventdat2 != -99) |
enemy[temp].ymaxbounce = eventRec[eventLoc-1].eventdat2; |
} |
} |
break; |
case 75:; |
bool temp_no_clue = false; // TODO: figure out what this is doing |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemyAvail[temp] == 0 |
&& enemy[temp].eyc == 0 |
&& enemy[temp].linknum >= eventRec[eventLoc-1].eventdat |
&& enemy[temp].linknum <= eventRec[eventLoc-1].eventdat2) |
{ |
temp_no_clue = true; |
} |
} |
if (temp_no_clue) |
{ |
JE_byte enemy_i; |
do |
{ |
temp = (mt_rand() % (eventRec[eventLoc-1].eventdat2 + 1 - eventRec[eventLoc-1].eventdat)) + eventRec[eventLoc-1].eventdat; |
} |
while (!(JE_searchFor(temp, &enemy_i) && enemy[enemy_i].eyc == 0)); |
newPL[eventRec[eventLoc-1].eventdat3 - 80] = temp; |
} |
else |
{ |
newPL[eventRec[eventLoc-1].eventdat3 - 80] = 255; |
if (eventRec[eventLoc-1].eventdat4 > 0) |
{ /*Skip*/ |
curLoc = eventRec[eventLoc-1 + eventRec[eventLoc-1].eventdat4].eventtime - 1; |
eventLoc += eventRec[eventLoc-1].eventdat4 - 1; |
} |
} |
break; |
case 76: |
returnActive = true; |
break; |
case 77: |
mapYPos = &megaData1.mainmap[0][0]; |
mapYPos += eventRec[eventLoc-1].eventdat / 2; |
if (eventRec[eventLoc-1].eventdat2 > 0) |
{ |
mapY2Pos = &megaData2.mainmap[0][0]; |
mapY2Pos += eventRec[eventLoc-1].eventdat2 / 2; |
} |
else |
{ |
mapY2Pos = &megaData2.mainmap[0][0]; |
mapY2Pos += eventRec[eventLoc-1].eventdat / 2; |
} |
break; |
case 78: |
if (galagaShotFreq < 10) |
galagaShotFreq++; |
break; |
case 79: |
boss_bar[0].link_num = eventRec[eventLoc-1].eventdat; |
boss_bar[1].link_num = eventRec[eventLoc-1].eventdat2; |
break; |
case 80: // skip events if in 2-player mode |
if (twoPlayerMode) |
eventLoc += eventRec[eventLoc-1].eventdat; |
break; |
case 81: /*WRAP2*/ |
BKwrap2 = &megaData2.mainmap[0][0]; |
BKwrap2 += eventRec[eventLoc-1].eventdat / 2; |
BKwrap2to = &megaData2.mainmap[0][0]; |
BKwrap2to += eventRec[eventLoc-1].eventdat2 / 2; |
break; |
case 82: /*Give SPECIAL WEAPON*/ |
player[0].items.special = eventRec[eventLoc-1].eventdat; |
shotMultiPos[SHOT_SPECIAL] = 0; |
shotRepeat[SHOT_SPECIAL] = 0; |
shotMultiPos[SHOT_SPECIAL2] = 0; |
shotRepeat[SHOT_SPECIAL2] = 0; |
break; |
default: |
fprintf(stderr, "warning: ignoring unknown event %d\n", eventRec[eventLoc-1].eventtype); |
break; |
} |
eventLoc++; |
} |
void JE_whoa( void ) |
{ |
unsigned int i, j, color, offset, timer; |
unsigned int screenSize, topBorder, bottomBorder; |
Uint8 * TempScreen1, * TempScreen2, * TempScreenSwap; |
/* 'whoa' gets us that nifty screen fade used when you type in |
* 'engage'. We need two temporary screen buffers (char arrays can |
* work too, but these screens already exist) for our effect. |
* This could probably be a lot more efficient (there's probably a |
* way to get vgascreen as one of the temp buffers), but it's only called |
* once so don't worry about it. */ |
TempScreen1 = game_screen->pixels; |
TempScreen2 = VGAScreen2->pixels; |
screenSize = VGAScreenSeg->h * VGAScreenSeg->pitch; |
topBorder = VGAScreenSeg->pitch * 4; /* Seems an arbitrary number of lines */ |
bottomBorder = VGAScreenSeg->pitch * 7; |
/* Okay, one disadvantage to using other screens as temp buffers: they |
* need to be the right size. I doubt they'l ever be anything but 320x200, |
* but just in case, these asserts will clue in whoever stumbles across |
* the problem. You can fix it with the stack or malloc. */ |
assert( (unsigned)VGAScreen2->h * VGAScreen2->pitch >= screenSize |
&& (unsigned)game_screen->h * game_screen->pitch >= screenSize); |
/* Clear the top and bottom borders. We don't want to process |
* them and we don't want to draw them. */ |
memset((Uint8 *)VGAScreenSeg->pixels, 0, topBorder); |
memset((Uint8 *)VGAScreenSeg->pixels + screenSize - bottomBorder, 0, bottomBorder); |
/* Copy our test subject to one of the temporary buffers. Blank the other */ |
memset(TempScreen1, 0, screenSize); |
memcpy(TempScreen2, VGAScreenSeg->pixels, VGAScreenSeg->h * VGAScreenSeg->pitch); |
service_SDL_events(true); |
timer = 300; /* About 300 rounds is enough to make the screen mostly black */ |
do |
{ |
setjasondelay(1); |
/* This gets us our 'whoa' effect with pixel bleeding magic. |
* I'm willing to bet the guy who originally wrote the asm was goofing |
* around on acid and thought this looked good enough to use. */ |
for (i = screenSize - bottomBorder, j = topBorder / 2; i > 0; i--, j++) |
{ |
offset = j + i/8192 - 4; |
color = (TempScreen2[offset ] * 12 + |
TempScreen1[offset-VGAScreenSeg->pitch] + |
TempScreen1[offset-1 ] + |
TempScreen1[offset+1 ] + |
TempScreen1[offset+VGAScreenSeg->pitch]) / 16; |
TempScreen1[j] = color; |
} |
/* Now copy that mess to the buffer. */ |
memcpy((Uint8 *)VGAScreenSeg->pixels + topBorder, TempScreen1 + topBorder, screenSize - bottomBorder); |
JE_showVGA(); |
timer--; |
wait_delay(); |
/* Flip the buffer. */ |
TempScreenSwap = TempScreen1; |
TempScreen1 = TempScreen2; |
TempScreen2 = TempScreenSwap; |
} while (!(timer == 0 || JE_anyButton())); |
levelWarningLines = 4; |
} |
void JE_barX( JE_word x1, JE_word y1, JE_word x2, JE_word y2, JE_byte col ) |
{ |
fill_rectangle_xy(VGAScreen, x1, y1, x2, y1, col + 1); |
fill_rectangle_xy(VGAScreen, x1, y1 + 1, x2, y2 - 1, col ); |
fill_rectangle_xy(VGAScreen, x1, y2, x2, y2, col - 1); |
} |
void draw_boss_bar( void ) |
{ |
for (unsigned int b = 0; b < COUNTOF(boss_bar); b++) |
{ |
if (boss_bar[b].link_num == 0) |
continue; |
unsigned int armor = 256; // higher than armor max |
for (unsigned int e = 0; e < COUNTOF(enemy); e++) // find most damaged |
{ |
if (enemyAvail[e] != 1 && enemy[e].linknum == boss_bar[b].link_num) |
if (enemy[e].armorleft < armor) |
armor = enemy[e].armorleft; |
} |
if (armor > 255 || armor == 0) // boss dead? |
boss_bar[b].link_num = 0; |
else |
boss_bar[b].armor = (armor == 255) ? 254 : armor; // 255 would make the bar too long |
} |
unsigned int bars = (boss_bar[0].link_num != 0 ? 1 : 0) |
+ (boss_bar[1].link_num != 0 ? 1 : 0); |
// if only one bar left, make it the first one |
if (bars == 1 && boss_bar[0].link_num == 0) |
{ |
memcpy(&boss_bar[0], &boss_bar[1], sizeof(boss_bar_t)); |
boss_bar[1].link_num = 0; |
} |
for (unsigned int b = 0; b < bars; b++) |
{ |
unsigned int x = (bars == 2) |
? ((b == 0) ? 125 : 185) |
: ((levelTimer) ? 250 : 155); // level timer and boss bar would overlap |
JE_barX(x - 25, 7, x + 25, 12, 115); |
JE_barX(x - (boss_bar[b].armor / 10), 7, x + (boss_bar[b].armor + 5) / 10, 12, 118 + boss_bar[b].color); |
if (boss_bar[b].color > 0) |
boss_bar[b].color--; |
} |
} |
/contrib/games/opentyrian/src/tyrian2.h |
---|
0,0 → 1,70 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef TYRIAN2_H |
#define TYRIAN2_H |
#include "opentyr.h" |
#include "varz.h" |
#include "helptext.h" |
void intro_logos( void ); |
typedef struct |
{ |
Uint8 link_num; |
Uint8 armor; |
Uint8 color; |
} |
boss_bar_t; |
extern boss_bar_t boss_bar[2]; |
extern char tempStr[31]; |
extern JE_byte itemAvail[9][10], itemAvailMax[9]; |
void JE_createNewEventEnemy( JE_byte enemytypeofs, JE_word enemyoffset, Sint16 uniqueShapeTableI ); |
void JE_doNetwork( void ); |
uint JE_makeEnemy( struct JE_SingleEnemyType *enemy, Uint16 eDatI, Sint16 uniqueShapeTableI ); |
void JE_eventJump( JE_word jump ); |
void JE_whoa( void ); |
void JE_barX ( JE_word x1, JE_word y1, JE_word x2, JE_word y2, JE_byte col ); |
Sint16 JE_newEnemy( int enemyOffset, Uint16 eDatI, Sint16 uniqueShapeTableI ); |
void JE_drawEnemy( int enemyOffset ); |
void JE_starShowVGA( void ); |
void JE_main( void ); |
void JE_loadMap( void ); |
bool JE_titleScreen( JE_boolean animate ); |
void JE_readTextSync( void ); |
void JE_displayText( void ); |
bool JE_searchFor( JE_byte PLType, JE_byte* out_index ); |
void JE_eventSystem( void ); |
void draw_boss_bar( void ); |
#endif /* TYRIAN2_H */ |
/contrib/games/opentyrian/src/varz.c |
---|
0,0 → 1,1185 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "varz.h" |
#include "config.h" |
#include "editship.h" |
#include "episodes.h" |
#include "joystick.h" |
#include "lds_play.h" |
#include "loudness.h" |
#include "mainint.h" |
#include "mouse.h" |
#include "mtrand.h" |
#include "network.h" |
#include "nortsong.h" |
#include "nortvars.h" |
#include "opentyr.h" |
#include "shots.h" |
#include "sprite.h" |
#include "vga256d.h" |
#include "video.h" |
JE_integer tempDat, tempDat2, tempDat3; |
const JE_byte SANextShip[SA + 2] /* [0..SA + 1] */ = { 3, 9, 6, 2, 5, 1, 4, 3, 7 }; // 0 -> 3 -> 2 -> 6 -> 4 -> 5 -> 1 -> 9 -> 7 |
const JE_word SASpecialWeapon[SA] /* [1..SA] */ = { 7, 8, 9, 10, 11, 12, 13 }; |
const JE_word SASpecialWeaponB[SA] /* [1..SA] */ = {37, 6, 15, 40, 16, 14, 41 }; |
const JE_byte SAShip[SA] /* [1..SA] */ = { 3, 1, 5, 10, 2, 11, 12 }; |
const JE_word SAWeapon[SA][5] /* [1..SA, 1..5] */ = |
{ /* R Bl Bk G P */ |
{ 9, 31, 32, 33, 34 }, /* Stealth Ship */ |
{ 19, 8, 22, 41, 34 }, /* StormWind */ |
{ 27, 5, 20, 42, 31 }, /* Techno */ |
{ 15, 3, 28, 22, 12 }, /* Enemy */ |
{ 23, 35, 25, 14, 6 }, /* Weird */ |
{ 2, 5, 21, 4, 7 }, /* Unknown */ |
{ 40, 38, 37, 41, 36 } /* NortShip Z */ |
}; |
const JE_byte specialArcadeWeapon[PORT_NUM] /* [1..Portnum] */ = |
{ |
17,17,18,0,0,0,10,0,0,0,0,0,44,0,10,0,19,0,0,-0,0,0,0,0,0,0, |
-0,0,0,0,45,0,0,0,0,0,0,0,0,0,0,0 |
}; |
const JE_byte optionSelect[16][3][2] /* [0..15, 1..3, 1..2] */ = |
{ /* MAIN OPT FRONT */ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ { 1, 1},{16,16},{30,30} }, /*Single Shot*/ |
{ { 2, 2},{29,29},{29,20} }, /*Dual Shot*/ |
{ { 3, 3},{21,21},{12, 0} }, /*Charge Cannon*/ |
{ { 4, 4},{18,18},{16,23} }, /*Vulcan*/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ { 6, 6},{29,16},{ 0,22} }, /*Super Missile*/ |
{ { 7, 7},{19,19},{19,28} }, /*Atom Bomb*/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ {10,10},{21,21},{21,27} }, /*Mini Missile*/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ {13,13},{17,17},{13,26} }, /*MicroBomb*/ |
{ { 0, 0},{ 0, 0},{ 0, 0} }, /**/ |
{ {15,15},{15,16},{15,16} } /*Post-It*/ |
}; |
const JE_word PGR[21] /* [1..21] */ = |
{ |
4, |
1,2,3, |
41-21,57-21,73-21,89-21,105-21, |
121-21,137-21,153-21, |
151,151,151,151,73-21,73-21,1,2,4 |
/*151,151,151*/ |
}; |
const JE_byte PAni[21] /* [1..21] */ = {1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1}; |
const JE_word linkGunWeapons[38] /* [1..38] */ = |
{ |
0,0,0,0,0,0,0,0,444,445,446,447,0,448,449,0,0,0,0,0,450,451,0,506,0,564, |
445,446,447,448,449,445,446,447,448,449,450,451 |
}; |
const JE_word chargeGunWeapons[38] /* [1..38] */ = |
{ |
0,0,0,0,0,0,0,0,476,458,464,482,0,488,470,0,0,0,0,0,494,500,0,528,0,558, |
458,458,458,458,458,458,458,458,458,458,458,458 |
}; |
const JE_byte randomEnemyLaunchSounds[3] /* [1..3] */ = {13,6,26}; |
/* YKS: Twiddle cheat sheet: |
* 1: UP |
* 2: DOWN |
* 3: LEFT |
* 4: RIGHT |
* 5: UP+FIRE |
* 6: DOWN+FIRE |
* 7: LEFT+FIRE |
* 8: RIGHT+FIRE |
* 9: Release all keys (directions and fire) |
*/ |
const JE_byte keyboardCombos[26][8] /* [1..26, 1..8] */ = |
{ |
{ 2, 1, 2, 5, 137, 0, 0, 0}, /*Invulnerability*/ |
{ 4, 3, 2, 5, 138, 0, 0, 0}, /*Atom Bomb*/ |
{ 3, 4, 6, 139, 0, 0, 0, 0}, /*Seeker Bombs*/ |
{ 2, 5, 142, 0, 0, 0, 0, 0}, /*Ice Blast*/ |
{ 6, 2, 6, 143, 0, 0, 0, 0}, /*Auto Repair*/ |
{ 6, 7, 5, 8, 6, 7, 5, 112 }, /*Spin Wave*/ |
{ 7, 8, 101, 0, 0, 0, 0, 0}, /*Repulsor*/ |
{ 1, 7, 6, 146, 0, 0, 0, 0}, /*Protron Field*/ |
{ 8, 6, 7, 1, 120, 0, 0, 0}, /*Minefield*/ |
{ 3, 6, 8, 5, 121, 0, 0, 0}, /*Post-It Blast*/ |
{ 1, 2, 7, 8, 119, 0, 0, 0}, /*Drone Ship - TBC*/ |
{ 3, 4, 3, 6, 123, 0, 0, 0}, /*Repair Player 2*/ |
{ 6, 7, 5, 8, 124, 0, 0, 0}, /*Super Bomb - TBC*/ |
{ 1, 6, 125, 0, 0, 0, 0, 0}, /*Hot Dog*/ |
{ 9, 5, 126, 0, 0, 0, 0, 0}, /*Lightning UP */ |
{ 1, 7, 127, 0, 0, 0, 0, 0}, /*Lightning UP+LEFT */ |
{ 1, 8, 128, 0, 0, 0, 0, 0}, /*Lightning UP+RIGHT*/ |
{ 9, 7, 129, 0, 0, 0, 0, 0}, /*Lightning LEFT */ |
{ 9, 8, 130, 0, 0, 0, 0, 0}, /*Lightning RIGHT*/ |
{ 4, 2, 3, 5, 131, 0, 0, 0}, /*Warfly */ |
{ 3, 1, 2, 8, 132, 0, 0, 0}, /*FrontBlaster */ |
{ 2, 4, 5, 133, 0, 0, 0, 0}, /*Gerund */ |
{ 3, 4, 2, 8, 134, 0, 0, 0}, /*FireBomb */ |
{ 1, 4, 6, 135, 0, 0, 0, 0}, /*Indigo */ |
{ 1, 3, 6, 137, 0, 0, 0, 0}, /*Invulnerability [easier] */ |
{ 1, 4, 3, 4, 7, 136, 0, 0} /*D-Media Protron Drone */ |
}; |
const JE_byte shipCombosB[21] /* [1..21] */ = |
{15,16,17,18,19,20,21,22,23,24, 7, 8, 5,25,14, 4, 6, 3, 9, 2,26}; |
/*!! SUPER Tyrian !!*/ |
const JE_byte superTyrianSpecials[4] /* [1..4] */ = {1,2,4,5}; |
const JE_byte shipCombos[14][3] /* [0..12, 1..3] */ = |
{ |
{ 5, 4, 7}, /*2nd Player ship*/ |
{ 1, 2, 0}, /*USP Talon*/ |
{14, 4, 0}, /*Super Carrot*/ |
{ 4, 5, 0}, /*Gencore Phoenix*/ |
{ 6, 5, 0}, /*Gencore Maelstrom*/ |
{ 7, 8, 0}, /*MicroCorp Stalker*/ |
{ 7, 9, 0}, /*MicroCorp Stalker-B*/ |
{10, 3, 5}, /*Prototype Stalker-C*/ |
{ 5, 8, 9}, /*Stalker*/ |
{ 1, 3, 0}, /*USP Fang*/ |
{ 7,16,17}, /*U-Ship*/ |
{ 2,11,12}, /*1st Player ship*/ |
{ 3, 8,10}, /*Nort ship*/ |
{ 0, 0, 0} // Dummy entry added for Stalker 21.126 |
}; |
/*Street-Fighter Commands*/ |
JE_byte SFCurrentCode[2][21]; /* [1..2, 1..21] */ |
JE_byte SFExecuted[2]; /* [1..2] */ |
/*Special General Data*/ |
JE_byte lvlFileNum; |
JE_word maxEvent, eventLoc; |
/*JE_word maxenemies;*/ |
JE_word tempBackMove, explodeMove; /*Speed of background movement*/ |
JE_byte levelEnd; |
JE_word levelEndFxWait; |
JE_shortint levelEndWarp; |
JE_boolean endLevel, reallyEndLevel, waitToEndLevel, playerEndLevel, |
normalBonusLevelCurrent, bonusLevelCurrent, |
smallEnemyAdjust, readyToEndLevel, quitRequested; |
JE_byte newPL[10]; /* [0..9] */ /*Eventsys event 75 parameter*/ |
JE_word returnLoc; |
JE_boolean returnActive; |
JE_word galagaShotFreq; |
JE_longint galagaLife; |
JE_boolean debug = false; /*Debug Mode*/ |
Uint32 debugTime, lastDebugTime; |
JE_longint debugHistCount; |
JE_real debugHist; |
JE_word curLoc; /*Current Pixel location of background 1*/ |
JE_boolean firstGameOver, gameLoaded, enemyStillExploding; |
/* Destruction Ratio */ |
JE_word totalEnemy; |
JE_word enemyKilled; |
/* Shape/Map Data - All in one Segment! */ |
struct JE_MegaDataType1 megaData1; |
struct JE_MegaDataType2 megaData2; |
struct JE_MegaDataType3 megaData3; |
/* Secret Level Display */ |
JE_byte flash; |
JE_shortint flashChange; |
JE_byte displayTime; |
/* Demo Stuff */ |
bool play_demo = false, record_demo = false, stopped_demo = false; |
Uint8 demo_num = 0; |
FILE *demo_file = NULL; |
Uint8 demo_keys, next_demo_keys; |
Uint16 demo_keys_wait; |
/* Sound Effects Queue */ |
JE_byte soundQueue[8]; /* [0..7] */ |
/*Level Event Data*/ |
JE_boolean enemyContinualDamage; |
JE_boolean enemiesActive; |
JE_boolean forceEvents; |
JE_boolean stopBackgrounds; |
JE_byte stopBackgroundNum; |
JE_byte damageRate; /*Rate at which a player takes damage*/ |
JE_boolean background3x1; /*Background 3 enemies use Background 1 X offset*/ |
JE_boolean background3x1b; /*Background 3 enemies moved 8 pixels left*/ |
JE_boolean levelTimer; |
JE_word levelTimerCountdown; |
JE_word levelTimerJumpTo; |
JE_boolean randomExplosions; |
JE_boolean editShip1, editShip2; |
JE_boolean globalFlags[10]; /* [1..10] */ |
JE_byte levelSong; |
/* DESTRUCT game */ |
JE_boolean loadDestruct; |
/* MapView Data */ |
JE_word mapOrigin, mapPNum; |
JE_byte mapPlanet[5], mapSection[5]; /* [1..5] */ |
/* Interface Constants */ |
JE_boolean moveTyrianLogoUp; |
JE_boolean skipStarShowVGA; |
/*EnemyData*/ |
JE_MultiEnemyType enemy; |
JE_EnemyAvailType enemyAvail; /* values: 0: used, 1: free, 2: secret pick-up */ |
JE_word enemyOffset; |
JE_word enemyOnScreen; |
JE_byte enemyShapeTables[6]; /* [1..6] */ |
JE_word superEnemy254Jump; |
/*EnemyShotData*/ |
JE_boolean fireButtonHeld; |
JE_boolean enemyShotAvail[ENEMY_SHOT_MAX]; /* [1..Enemyshotmax] */ |
EnemyShotType enemyShot[ENEMY_SHOT_MAX]; /* [1..Enemyshotmax] */ |
/* Player Shot Data */ |
JE_byte zinglonDuration; |
JE_byte astralDuration; |
JE_word flareDuration; |
JE_boolean flareStart; |
JE_shortint flareColChg; |
JE_byte specialWait; |
JE_byte nextSpecialWait; |
JE_boolean spraySpecial; |
JE_byte doIced; |
JE_boolean infiniteShot; |
/*PlayerData*/ |
JE_boolean allPlayersGone; /*Both players dead and finished exploding*/ |
const uint shadowYDist = 10; |
JE_real optionSatelliteRotate; |
JE_integer optionAttachmentMove; |
JE_boolean optionAttachmentLinked, optionAttachmentReturn; |
JE_byte chargeWait, chargeLevel, chargeMax, chargeGr, chargeGrWait; |
JE_word neat; |
/*ExplosionData*/ |
explosion_type explosions[MAX_EXPLOSIONS]; /* [1..ExplosionMax] */ |
JE_integer explosionFollowAmountX, explosionFollowAmountY; |
/*Repeating Explosions*/ |
rep_explosion_type rep_explosions[MAX_REPEATING_EXPLOSIONS]; /* [1..20] */ |
/*SuperPixels*/ |
superpixel_type superpixels[MAX_SUPERPIXELS]; /* [0..MaxSP] */ |
unsigned int last_superpixel; |
/*Temporary Numbers*/ |
JE_byte temp, temp2, temp3; |
JE_word tempX, tempY; |
JE_word tempW; |
JE_boolean doNotSaveBackup; |
JE_word x, y; |
JE_integer b; |
JE_byte **BKwrap1to, **BKwrap2to, **BKwrap3to, |
**BKwrap1, **BKwrap2, **BKwrap3; |
JE_shortint specialWeaponFilter, specialWeaponFreq; |
JE_word specialWeaponWpn; |
JE_boolean linkToPlayer; |
JE_word shipGr, shipGr2; |
Sprite2_array *shipGrPtr, *shipGr2ptr; |
void JE_getShipInfo( void ) |
{ |
JE_boolean extraShip, extraShip2; |
shipGrPtr = &shapes9; |
shipGr2ptr = &shapes9; |
powerAdd = powerSys[player[0].items.generator].power; |
extraShip = player[0].items.ship > 90; |
if (extraShip) |
{ |
JE_byte base = (player[0].items.ship - 91) * 15; |
shipGr = JE_SGr(player[0].items.ship - 90, &shipGrPtr); |
player[0].armor = extraShips[base + 7]; |
} |
else |
{ |
shipGr = ships[player[0].items.ship].shipgraphic; |
player[0].armor = ships[player[0].items.ship].dmg; |
} |
extraShip2 = player[1].items.ship > 90; |
if (extraShip2) |
{ |
JE_byte base2 = (player[1].items.ship - 91) * 15; |
shipGr2 = JE_SGr(player[1].items.ship - 90, &shipGr2ptr); |
player[1].armor = extraShips[base2 + 7]; /* bug? */ |
} |
else |
{ |
shipGr2 = 0; |
player[1].armor = 10; |
} |
for (uint i = 0; i < COUNTOF(player); ++i) |
{ |
player[i].initial_armor = player[i].armor; |
uint temp = ((i == 0 && extraShip) || |
(i == 1 && extraShip2)) ? 2 : ships[player[i].items.ship].ani; |
if (temp == 0) |
{ |
player[i].shot_hit_area_x = 12; |
player[i].shot_hit_area_y = 10; |
} |
else |
{ |
player[i].shot_hit_area_x = 11; |
player[i].shot_hit_area_y = 14; |
} |
} |
} |
JE_word JE_SGr( JE_word ship, Sprite2_array **ptr ) |
{ |
const JE_word GR[15] /* [1..15] */ = {233, 157, 195, 271, 81, 0, 119, 5, 43, 81, 119, 157, 195, 233, 271}; |
JE_word tempW = extraShips[(ship - 1) * 15]; |
if (tempW > 7) |
*ptr = extraShapes; |
return GR[tempW-1]; |
} |
void JE_drawOptions( void ) |
{ |
SDL_Surface *temp_surface = VGAScreen; |
VGAScreen = VGAScreenSeg; |
Player *this_player = &player[twoPlayerMode ? 1 : 0]; |
for (uint i = 0; i < COUNTOF(this_player->sidekick); ++i) |
{ |
JE_OptionType *this_option = &options[this_player->items.sidekick[i]]; |
this_player->sidekick[i].ammo = |
this_player->sidekick[i].ammo_max = this_option->ammo; |
this_player->sidekick[i].ammo_refill_ticks = |
this_player->sidekick[i].ammo_refill_ticks_max = (105 - this_player->sidekick[i].ammo) * 4; |
this_player->sidekick[i].style = this_option->tr; |
this_player->sidekick[i].animation_enabled = (this_option->option == 1); |
this_player->sidekick[i].animation_frame = 0; |
this_player->sidekick[i].charge = 0; |
this_player->sidekick[i].charge_ticks = 20; |
// draw initial sidekick HUD |
const int y = hud_sidekick_y[twoPlayerMode ? 1 : 0][i]; |
fill_rectangle_xy(VGAScreenSeg, 284, y, 284 + 28, y + 15, 0); |
if (this_option->icongr > 0) |
blit_sprite(VGAScreenSeg, 284, y, OPTION_SHAPES, this_option->icongr - 1); // sidekick HUD icon |
draw_segmented_gauge(VGAScreenSeg, 284, y + 13, 112, 2, 2, MAX(1, this_player->sidekick[i].ammo_max / 10), this_player->sidekick[i].ammo); |
} |
VGAScreen = temp_surface; |
JE_drawOptionLevel(); |
} |
void JE_drawOptionLevel( void ) |
{ |
if (twoPlayerMode) |
{ |
for (temp = 1; temp <= 3; temp++) |
{ |
fill_rectangle_xy(VGAScreenSeg, 268, 127 + (temp - 1) * 6, 269, 127 + 3 + (temp - 1) * 6, 193 + ((player[1].items.sidekick_level - 100) == temp) * 11); |
} |
} |
} |
void JE_tyrianHalt( JE_byte code ) |
{ |
deinit_audio(); |
deinit_video(); |
deinit_joysticks(); |
/* TODO: NETWORK */ |
free_main_shape_tables(); |
free_sprite2s(&shapes6); |
for (int i = 0; i < SAMPLE_COUNT; i++) |
{ |
free(digiFx[i]); |
} |
if (code != 9) |
{ |
/* |
TODO? |
JE_drawANSI("exitmsg.bin"); |
JE_gotoXY(1,22);*/ |
JE_saveConfiguration(); |
} |
/* endkeyboard; */ |
if (code == 9) |
{ |
/* OutputString('call=file0002.EXE' + #0'); TODO? */ |
} |
if (code == 5) |
{ |
code = 0; |
} |
if (trentWin) |
{ |
printf("\n" |
"\n" |
"\n" |
"\n" |
"Sleep well, Trent, you deserve the rest.\n" |
"You now have permission to borrow my ship on your next mission.\n" |
"\n" |
"Also, you might want to try out the YESXMAS parameter.\n" |
" Type: File0001 YESXMAS\n" |
"\n" |
"You'll need the 2.1 patch, though!\n" |
"\n"); |
} |
SDL_Quit(); |
exit(code); |
} |
void JE_specialComplete( JE_byte playerNum, JE_byte specialType ) |
{ |
nextSpecialWait = 0; |
switch (special[specialType].stype) |
{ |
/*Weapon*/ |
case 1: |
if (playerNum == 1) |
b = player_shot_create(0, SHOT_SPECIAL2, player[0].x, player[0].y, mouseX, mouseY, special[specialType].wpn, playerNum); |
else |
b = player_shot_create(0, SHOT_SPECIAL2, player[1].x, player[1].y, mouseX, mouseY, special[specialType].wpn, playerNum); |
shotRepeat[SHOT_SPECIAL] = shotRepeat[SHOT_SPECIAL2]; |
break; |
/*Repulsor*/ |
case 2: |
for (temp = 0; temp < ENEMY_SHOT_MAX; temp++) |
{ |
if (!enemyShotAvail[temp]) |
{ |
if (player[0].x > enemyShot[temp].sx) |
enemyShot[temp].sxm--; |
else if (player[0].x < enemyShot[temp].sx) |
enemyShot[temp].sxm++; |
if (player[0].y > enemyShot[temp].sy) |
enemyShot[temp].sym--; |
else if (player[0].y < enemyShot[temp].sy) |
enemyShot[temp].sym++; |
} |
} |
break; |
/*Zinglon Blast*/ |
case 3: |
zinglonDuration = 50; |
shotRepeat[SHOT_SPECIAL] = 100; |
soundQueue[7] = S_SOUL_OF_ZINGLON; |
break; |
/*Attractor*/ |
case 4: |
for (temp = 0; temp < 100; temp++) |
{ |
if (enemyAvail[temp] != 1 && enemy[temp].scoreitem |
&& enemy[temp].evalue != 0) |
{ |
if (player[0].x > enemy[temp].ex) |
enemy[temp].exc++; |
else if (player[0].x < enemy[temp].ex) |
enemy[temp].exc--; |
if (player[0].y > enemy[temp].ey) |
enemy[temp].eyc++; |
else if (player[0].y < enemy[temp].ey) |
enemy[temp].eyc--; |
} |
} |
break; |
/*Flare*/ |
case 5: |
case 6: |
case 7: |
case 8: |
case 9: |
case 10: |
case 11: |
case 16: |
if (flareDuration == 0) |
flareStart = true; |
specialWeaponWpn = special[specialType].wpn; |
linkToPlayer = false; |
spraySpecial = false; |
switch (special[specialType].stype) |
{ |
case 5: |
specialWeaponFilter = 7; |
specialWeaponFreq = 2; |
flareDuration = 50; |
break; |
case 6: |
specialWeaponFilter = 1; |
specialWeaponFreq = 7; |
flareDuration = 200 + 25 * player[0].items.weapon[FRONT_WEAPON].power; |
break; |
case 7: |
specialWeaponFilter = 3; |
specialWeaponFreq = 3; |
flareDuration = 50 + 10 * player[0].items.weapon[FRONT_WEAPON].power; |
zinglonDuration = 50; |
shotRepeat[SHOT_SPECIAL] = 100; |
soundQueue[7] = S_SOUL_OF_ZINGLON; |
break; |
case 8: |
specialWeaponFilter = -99; |
specialWeaponFreq = 7; |
flareDuration = 10 + player[0].items.weapon[FRONT_WEAPON].power; |
break; |
case 9: |
specialWeaponFilter = -99; |
specialWeaponFreq = 8; |
flareDuration = 8 + 2 * player[0].items.weapon[FRONT_WEAPON].power; |
linkToPlayer = true; |
nextSpecialWait = special[specialType].pwr; |
break; |
case 10: |
specialWeaponFilter = -99; |
specialWeaponFreq = 8; |
flareDuration = 14 + 4 * player[0].items.weapon[FRONT_WEAPON].power; |
linkToPlayer = true; |
break; |
case 11: |
specialWeaponFilter = -99; |
specialWeaponFreq = special[specialType].pwr; |
flareDuration = 10 + 10 * player[0].items.weapon[FRONT_WEAPON].power; |
astralDuration = 20 + 10 * player[0].items.weapon[FRONT_WEAPON].power; |
break; |
case 16: |
specialWeaponFilter = -99; |
specialWeaponFreq = 8; |
flareDuration = temp2 * 16 + 8; |
linkToPlayer = true; |
spraySpecial = true; |
break; |
} |
break; |
case 12: |
player[playerNum-1].invulnerable_ticks = temp2 * 10; |
if (superArcadeMode > 0 && superArcadeMode <= SA) |
{ |
shotRepeat[SHOT_SPECIAL] = 250; |
b = player_shot_create(0, SHOT_SPECIAL2, player[0].x, player[0].y, mouseX, mouseY, 707, 1); |
player[0].invulnerable_ticks = 100; |
} |
break; |
case 13: |
player[0].armor += temp2 / 4 + 1; |
soundQueue[3] = S_POWERUP; |
break; |
case 14: |
player[1].armor += temp2 / 4 + 1; |
soundQueue[3] = S_POWERUP; |
break; |
case 17: // spawn left or right sidekick |
soundQueue[3] = S_POWERUP; |
if (player[0].items.sidekick[LEFT_SIDEKICK] == special[specialType].wpn) |
{ |
player[0].items.sidekick[RIGHT_SIDEKICK] = special[specialType].wpn; |
shotMultiPos[RIGHT_SIDEKICK] = 0; |
} |
else |
{ |
player[0].items.sidekick[LEFT_SIDEKICK] = special[specialType].wpn; |
shotMultiPos[LEFT_SIDEKICK] = 0; |
} |
JE_drawOptions(); |
break; |
case 18: // spawn right sidekick |
player[0].items.sidekick[RIGHT_SIDEKICK] = special[specialType].wpn; |
JE_drawOptions(); |
soundQueue[4] = S_POWERUP; |
shotMultiPos[RIGHT_SIDEKICK] = 0; |
break; |
} |
} |
void JE_doSpecialShot( JE_byte playerNum, uint *armor, uint *shield ) |
{ |
if (player[0].items.special > 0) |
{ |
if (shotRepeat[SHOT_SPECIAL] == 0 && specialWait == 0 && flareDuration < 2 && zinglonDuration < 2) |
blit_sprite2(VGAScreen, 47, 4, shapes9, 94); |
else |
blit_sprite2(VGAScreen, 47, 4, shapes9, 93); |
} |
if (shotRepeat[SHOT_SPECIAL] > 0) |
{ |
--shotRepeat[SHOT_SPECIAL]; |
} |
if (specialWait > 0) |
{ |
specialWait--; |
} |
temp = SFExecuted[playerNum-1]; |
if (temp > 0 && shotRepeat[SHOT_SPECIAL] == 0 && flareDuration == 0) |
{ |
temp2 = special[temp].pwr; |
bool can_afford = true; |
if (temp2 > 0) |
{ |
if (temp2 < 98) // costs some shield |
{ |
if (*shield >= temp2) |
*shield -= temp2; |
else |
can_afford = false; |
} |
else if (temp2 == 98) // costs all shield |
{ |
if (*shield < 4) |
can_afford = false; |
temp2 = *shield; |
*shield = 0; |
} |
else if (temp2 == 99) // costs half shield |
{ |
temp2 = *shield / 2; |
*shield = temp2; |
} |
else // costs some armor |
{ |
temp2 -= 100; |
if (*armor > temp2) |
*armor -= temp2; |
else |
can_afford = false; |
} |
} |
shotMultiPos[SHOT_SPECIAL] = 0; |
shotMultiPos[SHOT_SPECIAL2] = 0; |
if (can_afford) |
JE_specialComplete(playerNum, temp); |
SFExecuted[playerNum-1] = 0; |
JE_wipeShieldArmorBars(); |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_drawShield(); |
JE_drawArmor(); |
VGAScreen = game_screen; /* side-effect of game_screen */ |
} |
if (playerNum == 1 && player[0].items.special > 0) |
{ /*Main Begin*/ |
if (superArcadeMode > 0 && (button[2-1] || button[3-1])) |
{ |
fireButtonHeld = false; |
} |
if (!button[1-1] && !(superArcadeMode != SA_NONE && (button[2-1] || button[3-1]))) |
{ |
fireButtonHeld = false; |
} |
else if (shotRepeat[SHOT_SPECIAL] == 0 && !fireButtonHeld && !(flareDuration > 0) && specialWait == 0) |
{ |
fireButtonHeld = true; |
JE_specialComplete(playerNum, player[0].items.special); |
} |
} /*Main End*/ |
if (astralDuration > 0) |
astralDuration--; |
shotAvail[MAX_PWEAPON-1] = 0; |
if (flareDuration > 1) |
{ |
if (specialWeaponFilter != -99) |
{ |
if (levelFilter == -99 && levelBrightness == -99) |
{ |
filterActive = false; |
} |
if (!filterActive) |
{ |
levelFilter = specialWeaponFilter; |
if (levelFilter == 7) |
{ |
levelBrightness = 0; |
} |
filterActive = true; |
} |
if (mt_rand() % 2 == 0) |
flareColChg = -1; |
else |
flareColChg = 1; |
if (levelFilter == 7) |
{ |
if (levelBrightness < -6) |
{ |
flareColChg = 1; |
} |
if (levelBrightness > 6) |
{ |
flareColChg = -1; |
} |
levelBrightness += flareColChg; |
} |
} |
if ((signed)(mt_rand() % 6) < specialWeaponFreq) |
{ |
b = MAX_PWEAPON; |
if (linkToPlayer) |
{ |
if (shotRepeat[SHOT_SPECIAL] == 0) |
{ |
b = player_shot_create(0, SHOT_SPECIAL, player[0].x, player[0].y, mouseX, mouseY, specialWeaponWpn, playerNum); |
} |
} |
else |
{ |
b = player_shot_create(0, SHOT_SPECIAL, mt_rand() % 280, mt_rand() % 180, mouseX, mouseY, specialWeaponWpn, playerNum); |
} |
if (spraySpecial && b != MAX_PWEAPON) |
{ |
playerShotData[b].shotXM = (mt_rand() % 5) - 2; |
playerShotData[b].shotYM = (mt_rand() % 5) - 2; |
if (playerShotData[b].shotYM == 0) |
{ |
playerShotData[b].shotYM++; |
} |
} |
} |
flareDuration--; |
if (flareDuration == 1) |
{ |
specialWait = nextSpecialWait; |
} |
} |
else if (flareStart) |
{ |
flareStart = false; |
shotRepeat[SHOT_SPECIAL] = linkToPlayer ? 15 : 200; |
flareDuration = 0; |
if (levelFilter == specialWeaponFilter) |
{ |
levelFilter = -99; |
levelBrightness = -99; |
filterActive = false; |
} |
} |
if (zinglonDuration > 1) |
{ |
temp = 25 - abs(zinglonDuration - 25); |
JE_barBright(VGAScreen, player[0].x + 7 - temp, 0, player[0].x + 7 + temp, 184); |
JE_barBright(VGAScreen, player[0].x + 7 - temp - 2, 0, player[0].x + 7 + temp + 2, 184); |
zinglonDuration--; |
if (zinglonDuration % 5 == 0) |
{ |
shotAvail[MAX_PWEAPON-1] = 1; |
} |
} |
} |
void JE_setupExplosion( signed int x, signed int y, signed int delta_y, unsigned int type, bool fixed_position, bool follow_player ) |
{ |
const struct { |
JE_word sprite; |
JE_byte ttl; |
} explosion_data[53] /* [1..53] */ = { |
{ 144, 7 }, |
{ 120, 12 }, |
{ 190, 12 }, |
{ 209, 12 }, |
{ 152, 12 }, |
{ 171, 12 }, |
{ 133, 7 }, /*White Smoke*/ |
{ 1, 12 }, |
{ 20, 12 }, |
{ 39, 12 }, |
{ 58, 12 }, |
{ 110, 3 }, |
{ 76, 7 }, |
{ 91, 3 }, |
/*15*/ { 227, 3 }, |
{ 230, 3 }, |
{ 233, 3 }, |
{ 252, 3 }, |
{ 246, 3 }, |
/*20*/ { 249, 3 }, |
{ 265, 3 }, |
{ 268, 3 }, |
{ 271, 3 }, |
{ 236, 3 }, |
/*25*/ { 239, 3 }, |
{ 242, 3 }, |
{ 261, 3 }, |
{ 274, 3 }, |
{ 277, 3 }, |
/*30*/ { 280, 3 }, |
{ 299, 3 }, |
{ 284, 3 }, |
{ 287, 3 }, |
{ 290, 3 }, |
/*35*/ { 293, 3 }, |
{ 165, 8 }, /*Coin Values*/ |
{ 184, 8 }, |
{ 203, 8 }, |
{ 222, 8 }, |
{ 168, 8 }, |
{ 187, 8 }, |
{ 206, 8 }, |
{ 225, 10 }, |
{ 169, 10 }, |
{ 188, 10 }, |
{ 207, 20 }, |
{ 226, 14 }, |
{ 170, 14 }, |
{ 189, 14 }, |
{ 208, 14 }, |
{ 246, 14 }, |
{ 227, 14 }, |
{ 265, 14 } |
}; |
if (y > -16 && y < 190) |
{ |
for (int i = 0; i < MAX_EXPLOSIONS; i++) |
{ |
if (explosions[i].ttl == 0) |
{ |
explosions[i].x = x; |
explosions[i].y = y; |
if (type == 6) |
{ |
explosions[i].y += 12; |
explosions[i].x += 2; |
} else if (type == 98) |
{ |
type = 6; |
} |
explosions[i].sprite = explosion_data[type].sprite; |
explosions[i].ttl = explosion_data[type].ttl; |
explosions[i].follow_player = follow_player; |
explosions[i].fixed_position = fixed_position; |
explosions[i].delta_x = 0; |
explosions[i].delta_y = delta_y; |
break; |
} |
} |
} |
} |
void JE_setupExplosionLarge( JE_boolean enemyGround, JE_byte exploNum, JE_integer x, JE_integer y ) |
{ |
if (y >= 0) |
{ |
if (enemyGround) |
{ |
JE_setupExplosion(x - 6, y - 14, 0, 2, false, false); |
JE_setupExplosion(x + 6, y - 14, 0, 4, false, false); |
JE_setupExplosion(x - 6, y, 0, 3, false, false); |
JE_setupExplosion(x + 6, y, 0, 5, false, false); |
} else { |
JE_setupExplosion(x - 6, y - 14, 0, 7, false, false); |
JE_setupExplosion(x + 6, y - 14, 0, 9, false, false); |
JE_setupExplosion(x - 6, y, 0, 8, false, false); |
JE_setupExplosion(x + 6, y, 0, 10, false, false); |
} |
bool big; |
if (exploNum > 10) |
{ |
exploNum -= 10; |
big = true; |
} |
else |
{ |
big = false; |
} |
if (exploNum) |
{ |
for (int i = 0; i < MAX_REPEATING_EXPLOSIONS; i++) |
{ |
if (rep_explosions[i].ttl == 0) |
{ |
rep_explosions[i].ttl = exploNum; |
rep_explosions[i].delay = 2; |
rep_explosions[i].x = x; |
rep_explosions[i].y = y; |
rep_explosions[i].big = big; |
break; |
} |
} |
} |
} |
} |
void JE_wipeShieldArmorBars( void ) |
{ |
if (!twoPlayerMode || galagaMode) |
{ |
fill_rectangle_xy(VGAScreenSeg, 270, 137, 278, 194 - player[0].shield * 2, 0); |
} |
else |
{ |
fill_rectangle_xy(VGAScreenSeg, 270, 60 - 44, 278, 60, 0); |
fill_rectangle_xy(VGAScreenSeg, 270, 194 - 44, 278, 194, 0); |
} |
if (!twoPlayerMode || galagaMode) |
{ |
fill_rectangle_xy(VGAScreenSeg, 307, 137, 315, 194 - player[0].armor * 2, 0); |
} |
else |
{ |
fill_rectangle_xy(VGAScreenSeg, 307, 60 - 44, 315, 60, 0); |
fill_rectangle_xy(VGAScreenSeg, 307, 194 - 44, 315, 194, 0); |
} |
} |
JE_byte JE_playerDamage( JE_byte temp, |
Player *this_player ) |
{ |
int playerDamage = 0; |
soundQueue[7] = S_SHIELD_HIT; |
/* Player Damage Routines */ |
if (this_player->shield < temp) |
{ |
playerDamage = temp; |
temp -= this_player->shield; |
this_player->shield = 0; |
if (temp > 0) |
{ |
/*Through Shields - Now Armor */ |
if (this_player->armor < temp) |
{ |
temp -= this_player->armor; |
this_player->armor = 0; |
if (this_player->is_alive && !youAreCheating) |
{ |
levelTimer = false; |
this_player->is_alive = false; |
this_player->exploding_ticks = 60; |
levelEnd = 40; |
tempVolume = tyrMusicVolume; |
soundQueue[1] = S_EXPLOSION_22; |
} |
} |
else |
{ |
this_player->armor -= temp; |
soundQueue[7] = S_HULL_HIT; |
} |
} |
} |
else |
{ |
this_player->shield -= temp; |
JE_setupExplosion(this_player->x - 17, this_player->y - 12, 0, 14, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x - 5 , this_player->y - 12, 0, 15, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x + 7 , this_player->y - 12, 0, 16, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x + 19, this_player->y - 12, 0, 17, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x - 17, this_player->y + 2, 0, 18, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x + 19, this_player->y + 2, 0, 19, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x - 17, this_player->y + 16, 0, 20, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x - 5 , this_player->y + 16, 0, 21, false, !twoPlayerMode); |
JE_setupExplosion(this_player->x + 7 , this_player->y + 16, 0, 22, false, !twoPlayerMode); |
} |
JE_wipeShieldArmorBars(); |
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */ |
JE_drawShield(); |
JE_drawArmor(); |
VGAScreen = game_screen; /* side-effect of game_screen */ |
return playerDamage; |
} |
JE_word JE_portConfigs( void ) |
{ |
const uint player_index = twoPlayerMode ? 1 : 0; |
return tempW = weaponPort[player[player_index].items.weapon[REAR_WEAPON].id].opnum; |
} |
void JE_drawShield( void ) |
{ |
if (twoPlayerMode && !galagaMode) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
JE_dBar3(VGAScreen, 270, 60 + 134 * i, roundf(player[i].shield * 0.8f), 144); |
} |
else |
{ |
JE_dBar3(VGAScreen, 270, 194, player[0].shield, 144); |
if (player[0].shield != player[0].shield_max) |
{ |
const uint y = 193 - (player[0].shield_max * 2); |
JE_rectangle(VGAScreen, 270, y, 278, y, 68); /* <MXD> SEGa000 */ |
} |
} |
} |
void JE_drawArmor( void ) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
if (player[i].armor > 28) |
player[i].armor = 28; |
if (twoPlayerMode && !galagaMode) |
{ |
for (uint i = 0; i < COUNTOF(player); ++i) |
JE_dBar3(VGAScreen, 307, 60 + 134 * i, roundf(player[i].armor * 0.8f), 224); |
} |
else |
{ |
JE_dBar3(VGAScreen, 307, 194, player[0].armor, 224); |
} |
} |
void JE_doSP( JE_word x, JE_word y, JE_word num, JE_byte explowidth, JE_byte color ) /* superpixels */ |
{ |
for (temp = 0; temp < num; temp++) |
{ |
JE_real tempr = mt_rand_lt1() * (2 * M_PI); |
signed int tempy = roundf(cosf(tempr) * mt_rand_1() * explowidth); |
signed int tempx = roundf(sinf(tempr) * mt_rand_1() * explowidth); |
if (++last_superpixel >= MAX_SUPERPIXELS) |
last_superpixel = 0; |
superpixels[last_superpixel].x = tempx + x; |
superpixels[last_superpixel].y = tempy + y; |
superpixels[last_superpixel].delta_x = tempx; |
superpixels[last_superpixel].delta_y = tempy + 1; |
superpixels[last_superpixel].color = color; |
superpixels[last_superpixel].z = 15; |
} |
} |
void JE_drawSP( void ) |
{ |
for (int i = MAX_SUPERPIXELS; i--; ) |
{ |
if (superpixels[i].z) |
{ |
superpixels[i].x += superpixels[i].delta_x; |
superpixels[i].y += superpixels[i].delta_y; |
if (superpixels[i].x < (unsigned)VGAScreen->w && superpixels[i].y < (unsigned)VGAScreen->h) |
{ |
Uint8 *s = (Uint8 *)VGAScreen->pixels; /* screen pointer, 8-bit specific */ |
s += superpixels[i].y * VGAScreen->pitch; |
s += superpixels[i].x; |
*s = (((*s & 0x0f) + superpixels[i].z) >> 1) + superpixels[i].color; |
if (superpixels[i].x > 0) |
*(s - 1) = (((*(s - 1) & 0x0f) + (superpixels[i].z >> 1)) >> 1) + superpixels[i].color; |
if (superpixels[i].x < VGAScreen->w - 1u) |
*(s + 1) = (((*(s + 1) & 0x0f) + (superpixels[i].z >> 1)) >> 1) + superpixels[i].color; |
if (superpixels[i].y > 0) |
*(s - VGAScreen->pitch) = (((*(s - VGAScreen->pitch) & 0x0f) + (superpixels[i].z >> 1)) >> 1) + superpixels[i].color; |
if (superpixels[i].y < VGAScreen->h - 1u) |
*(s + VGAScreen->pitch) = (((*(s + VGAScreen->pitch) & 0x0f) + (superpixels[i].z >> 1)) >> 1) + superpixels[i].color; |
} |
superpixels[i].z--; |
} |
} |
} |
/contrib/games/opentyrian/src/varz.h |
---|
0,0 → 1,359 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef VARZ_H |
#define VARZ_H |
#include "episodes.h" |
#include "opentyr.h" |
#include "player.h" |
#include "sprite.h" |
#include <stdbool.h> |
#define SA 7 |
enum |
{ |
SA_NONE = 0, |
SA_NORTSHIPZ = 7, |
// only used for code entry |
SA_DESTRUCT = 8, |
SA_ENGAGE = 9, |
// only used in pItems[P_SUPERARCADE] |
SA_SUPERTYRIAN = 254, |
SA_ARCADE = 255 |
}; |
#define ENEMY_SHOT_MAX 60 /* 60*/ |
#define CURRENT_KEY_SPEED 1 /*Keyboard/Joystick movement rate*/ |
#define MAX_EXPLOSIONS 200 |
#define MAX_REPEATING_EXPLOSIONS 20 |
#define MAX_SUPERPIXELS 101 |
struct JE_SingleEnemyType |
{ |
JE_byte fillbyte; |
JE_integer ex, ey; /* POSITION */ |
JE_shortint exc, eyc; /* CURRENT SPEED */ |
JE_shortint exca, eyca; /* RANDOM ACCELERATION */ |
JE_shortint excc, eycc; /* FIXED ACCELERATION WAITTIME */ |
JE_shortint exccw, eyccw; |
JE_byte armorleft; |
JE_byte eshotwait[3], eshotmultipos[3]; /* [1..3] */ |
JE_byte enemycycle; |
JE_byte ani; |
JE_word egr[20]; /* [1..20] */ |
JE_byte size; |
JE_byte linknum; |
JE_byte aniactive; |
JE_byte animax; |
JE_byte aniwhenfire; |
Sprite2_array *sprite2s; |
JE_shortint exrev, eyrev; |
JE_integer exccadd, eyccadd; |
JE_byte exccwmax, eyccwmax; |
void *enemydatofs; |
JE_boolean edamaged; |
JE_word enemytype; |
JE_byte animin; |
JE_word edgr; |
JE_shortint edlevel; |
JE_shortint edani; |
JE_byte fill1; |
JE_byte filter; |
JE_integer evalue; |
JE_integer fixedmovey; |
JE_byte freq[3]; /* [1..3] */ |
JE_byte launchwait; |
JE_word launchtype; |
JE_byte launchfreq; |
JE_byte xaccel; |
JE_byte yaccel; |
JE_byte tur[3]; /* [1..3] */ |
JE_word enemydie; /* Enemy created when this one dies */ |
JE_boolean enemyground; |
JE_byte explonum; |
JE_word mapoffset; |
JE_boolean scoreitem; |
JE_boolean special; |
JE_byte flagnum; |
JE_boolean setto; |
JE_byte iced; /*Duration*/ |
JE_byte launchspecial; |
JE_integer xminbounce; |
JE_integer xmaxbounce; |
JE_integer yminbounce; |
JE_integer ymaxbounce; |
JE_byte fill[3]; /* [1..3] */ |
}; |
typedef struct JE_SingleEnemyType JE_MultiEnemyType[100]; /* [1..100] */ |
typedef JE_word JE_DanCShape[(24 * 28) / 2]; /* [1..(24*28) div 2] */ |
typedef JE_char JE_CharString[256]; /* [1..256] */ |
typedef JE_byte JE_Map1Buffer[24 * 28 * 13 * 4]; /* [1..24*28*13*4] */ |
typedef JE_byte *JE_MapType[300][14]; /* [1..300, 1..14] */ |
typedef JE_byte *JE_MapType2[600][14]; /* [1..600, 1..14] */ |
typedef JE_byte *JE_MapType3[600][15]; /* [1..600, 1..15] */ |
struct JE_EventRecType |
{ |
JE_word eventtime; |
JE_byte eventtype; |
JE_integer eventdat, eventdat2; |
JE_shortint eventdat3, eventdat5, eventdat6; |
JE_byte eventdat4; |
}; |
struct JE_MegaDataType1 |
{ |
JE_MapType mainmap; |
struct |
{ |
JE_DanCShape sh; |
} shapes[72]; /* [0..71] */ |
JE_byte tempdat1; |
/*JE_DanCShape filler;*/ |
}; |
struct JE_MegaDataType2 |
{ |
JE_MapType2 mainmap; |
struct |
{ |
JE_byte nothing[3]; /* [1..3] */ |
JE_byte fill; |
JE_DanCShape sh; |
} shapes[71]; /* [0..70] */ |
JE_byte tempdat2; |
}; |
struct JE_MegaDataType3 |
{ |
JE_MapType3 mainmap; |
struct |
{ |
JE_byte nothing[3]; /* [1..3] */ |
JE_byte fill; |
JE_DanCShape sh; |
} shapes[70]; /* [0..69] */ |
JE_byte tempdat3; |
}; |
typedef JE_byte JE_EnemyAvailType[100]; /* [1..100] */ |
typedef struct { |
JE_integer sx, sy; |
JE_integer sxm, sym; |
JE_shortint sxc, syc; |
JE_byte tx, ty; |
JE_word sgr; |
JE_byte sdmg; |
JE_byte duration; |
JE_word animate; |
JE_word animax; |
JE_byte fill[12]; |
} EnemyShotType; |
typedef struct { |
unsigned int ttl; |
signed int x, y; |
signed int delta_x, delta_y; |
bool fixed_position; |
bool follow_player; |
unsigned int sprite; |
} explosion_type; |
typedef struct { |
unsigned int delay; |
unsigned int ttl; |
unsigned int x, y; |
bool big; |
} rep_explosion_type; |
typedef struct { |
unsigned int x, y, z; |
signed int delta_x, delta_y; |
Uint8 color; |
} superpixel_type; |
extern JE_integer tempDat, tempDat2, tempDat3; |
extern const JE_byte SANextShip[SA + 2]; |
extern const JE_word SASpecialWeapon[SA]; |
extern const JE_word SASpecialWeaponB[SA]; |
extern const JE_byte SAShip[SA]; |
extern const JE_word SAWeapon[SA][5]; |
extern const JE_byte specialArcadeWeapon[PORT_NUM]; |
extern const JE_byte optionSelect[16][3][2]; |
extern const JE_word PGR[21]; |
extern const JE_byte PAni[21]; |
extern const JE_word linkGunWeapons[38]; |
extern const JE_word chargeGunWeapons[38]; |
extern const JE_byte randomEnemyLaunchSounds[3]; |
extern const JE_byte keyboardCombos[26][8]; |
extern const JE_byte shipCombosB[21]; |
extern const JE_byte superTyrianSpecials[4]; |
extern const JE_byte shipCombos[14][3]; |
extern JE_byte SFCurrentCode[2][21]; |
extern JE_byte SFExecuted[2]; |
extern JE_byte lvlFileNum; |
extern JE_word maxEvent, eventLoc; |
extern JE_word tempBackMove, explodeMove; |
extern JE_byte levelEnd; |
extern JE_word levelEndFxWait; |
extern JE_shortint levelEndWarp; |
extern JE_boolean endLevel, reallyEndLevel, waitToEndLevel, playerEndLevel, normalBonusLevelCurrent, bonusLevelCurrent, smallEnemyAdjust, readyToEndLevel, quitRequested; |
extern JE_byte newPL[10]; |
extern JE_word returnLoc; |
extern JE_boolean returnActive; |
extern JE_word galagaShotFreq; |
extern JE_longint galagaLife; |
extern JE_boolean debug; |
extern Uint32 debugTime, lastDebugTime; |
extern JE_longint debugHistCount; |
extern JE_real debugHist; |
extern JE_word curLoc; |
extern JE_boolean firstGameOver, gameLoaded, enemyStillExploding; |
extern JE_word totalEnemy; |
extern JE_word enemyKilled; |
extern struct JE_MegaDataType1 megaData1; |
extern struct JE_MegaDataType2 megaData2; |
extern struct JE_MegaDataType3 megaData3; |
extern JE_byte flash; |
extern JE_shortint flashChange; |
extern JE_byte displayTime; |
extern bool play_demo, record_demo, stopped_demo; |
extern Uint8 demo_num; |
extern FILE *demo_file; |
extern Uint8 demo_keys, next_demo_keys; |
extern Uint16 demo_keys_wait; |
extern JE_byte soundQueue[8]; |
extern JE_boolean enemyContinualDamage; |
extern JE_boolean enemiesActive; |
extern JE_boolean forceEvents; |
extern JE_boolean stopBackgrounds; |
extern JE_byte stopBackgroundNum; |
extern JE_byte damageRate; |
extern JE_boolean background3x1; |
extern JE_boolean background3x1b; |
extern JE_boolean levelTimer; |
extern JE_word levelTimerCountdown; |
extern JE_word levelTimerJumpTo; |
extern JE_boolean randomExplosions; |
extern JE_boolean editShip1, editShip2; |
extern JE_boolean globalFlags[10]; |
extern JE_byte levelSong; |
extern JE_boolean loadDestruct; |
extern JE_word mapOrigin, mapPNum; |
extern JE_byte mapPlanet[5], mapSection[5]; |
extern JE_boolean moveTyrianLogoUp; |
extern JE_boolean skipStarShowVGA; |
extern JE_MultiEnemyType enemy; |
extern JE_EnemyAvailType enemyAvail; |
extern JE_word enemyOffset; |
extern JE_word enemyOnScreen; |
extern JE_byte enemyShapeTables[6]; |
extern JE_word superEnemy254Jump; |
extern explosion_type explosions[MAX_EXPLOSIONS]; |
extern JE_integer explosionFollowAmountX, explosionFollowAmountY; |
extern JE_boolean fireButtonHeld; |
extern JE_boolean enemyShotAvail[ENEMY_SHOT_MAX]; |
extern EnemyShotType enemyShot[ENEMY_SHOT_MAX]; |
extern JE_byte zinglonDuration; |
extern JE_byte astralDuration; |
extern JE_word flareDuration; |
extern JE_boolean flareStart; |
extern JE_shortint flareColChg; |
extern JE_byte specialWait; |
extern JE_byte nextSpecialWait; |
extern JE_boolean spraySpecial; |
extern JE_byte doIced; |
extern JE_boolean infiniteShot; |
extern JE_boolean allPlayersGone; |
extern const uint shadowYDist; |
extern JE_real optionSatelliteRotate; |
extern JE_integer optionAttachmentMove; |
extern JE_boolean optionAttachmentLinked, optionAttachmentReturn; |
extern JE_byte chargeWait, chargeLevel, chargeMax, chargeGr, chargeGrWait; |
extern JE_word neat; |
extern rep_explosion_type rep_explosions[MAX_REPEATING_EXPLOSIONS]; |
extern superpixel_type superpixels[MAX_SUPERPIXELS]; |
extern unsigned int last_superpixel; |
extern JE_byte temp, temp2, temp3; |
extern JE_word tempX, tempY; |
extern JE_word tempW; |
extern JE_boolean doNotSaveBackup; |
extern JE_word x, y; |
extern JE_integer b; |
extern JE_byte **BKwrap1to, **BKwrap2to, **BKwrap3to, **BKwrap1, **BKwrap2, **BKwrap3; |
extern JE_shortint specialWeaponFilter, specialWeaponFreq; |
extern JE_word specialWeaponWpn; |
extern JE_boolean linkToPlayer; |
extern JE_word shipGr, shipGr2; |
extern Sprite2_array *shipGrPtr, *shipGr2ptr; |
static const int hud_sidekick_y[2][2] = |
{ |
{ 64, 82 }, // one player HUD |
{ 108, 126 }, // two player HUD |
}; |
void JE_getShipInfo( void ); |
JE_word JE_SGr( JE_word ship, Sprite2_array **ptr ); |
void JE_drawOptions( void ); |
void JE_tyrianHalt( JE_byte code ); /* This ends the game */ |
void JE_specialComplete( JE_byte playernum, JE_byte specialType ); |
void JE_doSpecialShot( JE_byte playernum, uint *armor, uint *shield ); |
void JE_wipeShieldArmorBars( void ); |
JE_byte JE_playerDamage( JE_byte temp, Player * ); |
void JE_setupExplosion( signed int x, signed int y, signed int delta_y, unsigned int type, bool fixed_position, bool follow_player ); |
void JE_setupExplosionLarge( JE_boolean enemyground, JE_byte explonum, JE_integer x, JE_integer y ); |
void JE_drawShield( void ); |
void JE_drawArmor( void ); |
JE_word JE_portConfigs( void ); |
/*SuperPixels*/ |
void JE_doSP( JE_word x, JE_word y, JE_word num, JE_byte explowidth, JE_byte color ); |
void JE_drawSP( void ); |
void JE_drawOptionLevel( void ); |
#endif /* VARZ_H */ |
/contrib/games/opentyrian/src/vga256d.c |
---|
0,0 → 1,161 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "vga256d.h" |
#include "config.h" // For fullscreen stuff |
#include "keyboard.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "video.h" |
#include "SDL.h" |
#include <assert.h> |
#include <ctype.h> |
#include <math.h> |
#include <stdio.h> |
#include <string.h> |
void JE_pix( SDL_Surface *surface, int x, int y, JE_byte c ) |
{ |
/* Bad things happen if we don't clip */ |
if (x < surface->pitch && y < surface->h) |
{ |
Uint8 *vga = surface->pixels; |
vga[y * surface->pitch + x] = c; |
} |
} |
void JE_pix3( SDL_Surface *surface, int x, int y, JE_byte c ) |
{ |
/* Originally impemented as several direct accesses */ |
JE_pix(surface, x, y, c); |
JE_pix(surface, x - 1, y, c); |
JE_pix(surface, x + 1, y, c); |
JE_pix(surface, x, y - 1, c); |
JE_pix(surface, x, y + 1, c); |
} |
void JE_rectangle( SDL_Surface *surface, int a, int b, int c, int d, int e ) /* x1, y1, x2, y2, color */ |
{ |
if (a < surface->pitch && b < surface->h && |
c < surface->pitch && d < surface->h) |
{ |
Uint8 *vga = surface->pixels; |
int i; |
/* Top line */ |
memset(&vga[b * surface->pitch + a], e, c - a + 1); |
/* Bottom line */ |
memset(&vga[d * surface->pitch + a], e, c - a + 1); |
/* Left line */ |
for (i = (b + 1) * surface->pitch + a; i < (d * surface->pitch + a); i += surface->pitch) |
{ |
vga[i] = e; |
} |
/* Right line */ |
for (i = (b + 1) * surface->pitch + c; i < (d * surface->pitch + c); i += surface->pitch) |
{ |
vga[i] = e; |
} |
} else { |
printf("!!! WARNING: Rectangle clipped: %d %d %d %d %d\n", a, b, c, d, e); |
} |
} |
void fill_rectangle_xy( SDL_Surface *surface, int x, int y, int x2, int y2, Uint8 color ) |
{ |
SDL_Rect rect = { x, y, x2 - x + 1, y2 - y + 1 }; |
SDL_FillRect(surface, &rect, color); |
} |
void JE_barShade( SDL_Surface *surface, int a, int b, int c, int d ) /* x1, y1, x2, y2 */ |
{ |
if (a < surface->pitch && b < surface->h && |
c < surface->pitch && d < surface->h) |
{ |
Uint8 *vga = surface->pixels; |
int i, j, width; |
width = c - a + 1; |
for (i = b * surface->pitch + a; i <= d * surface->pitch + a; i += surface->pitch) |
{ |
for (j = 0; j < width; j++) |
{ |
vga[i + j] = ((vga[i + j] & 0x0F) >> 1) | (vga[i + j] & 0xF0); |
} |
} |
} else { |
printf("!!! WARNING: Darker Rectangle clipped: %d %d %d %d\n", a,b,c,d); |
} |
} |
void JE_barBright( SDL_Surface *surface, int a, int b, int c, int d ) /* x1, y1, x2, y2 */ |
{ |
if (a < surface->pitch && b < surface->h && |
c < surface->pitch && d < surface->h) |
{ |
Uint8 *vga = surface->pixels; |
int i, j, width; |
width = c-a+1; |
for (i = b * surface->pitch + a; i <= d * surface->pitch + a; i += surface->pitch) |
{ |
for (j = 0; j < width; j++) |
{ |
JE_byte al, ah; |
al = ah = vga[i + j]; |
ah &= 0xF0; |
al = (al & 0x0F) + 2; |
if (al > 0x0F) |
{ |
al = 0x0F; |
} |
vga[i + j] = al + ah; |
} |
} |
} else { |
printf("!!! WARNING: Brighter Rectangle clipped: %d %d %d %d\n", a,b,c,d); |
} |
} |
void draw_segmented_gauge( SDL_Surface *surface, int x, int y, Uint8 color, uint segment_width, uint segment_height, uint segment_value, uint value ) |
{ |
assert(segment_width > 0 && segment_height > 0); |
const uint segments = value / segment_value, |
partial_segment = value % segment_value; |
for (uint i = 0; i < segments; ++i) |
{ |
fill_rectangle_hw(surface, x, y, segment_width, segment_height, color + 12); |
x += segment_width + 1; |
} |
if (partial_segment > 0) |
fill_rectangle_hw(surface, x, y, segment_width, segment_height, color + (12 * partial_segment / segment_value)); |
} |
/contrib/games/opentyrian/src/vga256d.h |
---|
0,0 → 1,44 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef VGA256D_H |
#define VGA256D_H |
#include "opentyr.h" |
#include "SDL.h" |
void JE_pix( SDL_Surface *surface, int x, int y, JE_byte c ); |
void JE_pix3( SDL_Surface *surface, int x, int y, JE_byte c ); |
void JE_rectangle( SDL_Surface *surface, int a, int b, int c, int d, int e ); |
void fill_rectangle_xy( SDL_Surface *, int x, int y, int x2, int y2, Uint8 color ); |
void JE_barShade( SDL_Surface *surface, int a, int b, int c, int d ); |
void JE_barBright( SDL_Surface *surface, int a, int b, int c, int d ); |
static inline void fill_rectangle_hw( SDL_Surface *surface, int x, int y, uint h, uint w, Uint8 color ) |
{ |
SDL_Rect rect = { x, y, h, w }; |
SDL_FillRect(surface, &rect, color); |
} |
void draw_segmented_gauge( SDL_Surface *surface, int x, int y, Uint8 color, uint segment_width, uint segment_height, uint segment_value, uint value ); |
#endif /* VGA256D_H */ |
/contrib/games/opentyrian/src/vga_palette.c |
---|
0,0 → 1,71 |
#include "vga_palette.h" |
// only used for the jukebox |
Palette vga_palette = |
{ |
{ 0, 0, 0}, { 0, 0, 168}, { 0, 168, 0}, { 0, 168, 168}, |
{168, 0, 0}, {168, 0, 168}, {168, 84, 0}, {168, 168, 168}, |
{ 84, 84, 84}, { 84, 84, 252}, { 84, 252, 84}, { 84, 252, 252}, |
{252, 84, 84}, {252, 84, 252}, {252, 252, 84}, {252, 252, 252}, |
{ 0, 0, 0}, { 20, 20, 20}, { 32, 32, 32}, { 44, 44, 44}, |
{ 56, 56, 56}, { 68, 68, 68}, { 80, 80, 80}, { 96, 96, 96}, |
{112, 112, 112}, {128, 128, 128}, {144, 144, 144}, {160, 160, 160}, |
{180, 180, 180}, {200, 200, 200}, {224, 224, 224}, {252, 252, 252}, |
{ 0, 0, 252}, { 64, 0, 252}, {124, 0, 252}, {188, 0, 252}, |
{252, 0, 252}, {252, 0, 188}, {252, 0, 124}, {252, 0, 64}, |
{252, 0, 0}, {252, 64, 0}, {252, 124, 0}, {252, 188, 0}, |
{252, 252, 0}, {188, 252, 0}, {124, 252, 0}, { 64, 252, 0}, |
{ 0, 252, 0}, { 0, 252, 64}, { 0, 252, 124}, { 0, 252, 188}, |
{ 0, 252, 252}, { 0, 188, 252}, { 0, 124, 252}, { 0, 64, 252}, |
{124, 124, 252}, {156, 124, 252}, {188, 124, 252}, {220, 124, 252}, |
{252, 124, 252}, {252, 124, 220}, {252, 124, 188}, {252, 124, 156}, |
{252, 124, 124}, {252, 156, 124}, {252, 188, 124}, {252, 220, 124}, |
{252, 252, 124}, {220, 252, 124}, {188, 252, 124}, {156, 252, 124}, |
{124, 252, 124}, {124, 252, 156}, {124, 252, 188}, {124, 252, 220}, |
{124, 252, 252}, {124, 220, 252}, {124, 188, 252}, {124, 156, 252}, |
{180, 180, 252}, {196, 180, 252}, {216, 180, 252}, {232, 180, 252}, |
{252, 180, 252}, {252, 180, 232}, {252, 180, 216}, {252, 180, 196}, |
{252, 180, 180}, {252, 196, 180}, {252, 216, 180}, {252, 232, 180}, |
{252, 252, 180}, {232, 252, 180}, {216, 252, 180}, {196, 252, 180}, |
{180, 252, 180}, {180, 252, 196}, {180, 252, 216}, {180, 252, 232}, |
{180, 252, 252}, {180, 232, 252}, {180, 216, 252}, {180, 196, 252}, |
{ 0, 0, 112}, { 28, 0, 112}, { 56, 0, 112}, { 84, 0, 112}, |
{112, 0, 112}, {112, 0, 84}, {112, 0, 56}, {112, 0, 28}, |
{112, 0, 0}, {112, 28, 0}, {112, 56, 0}, {112, 84, 0}, |
{112, 112, 0}, { 84, 112, 0}, { 56, 112, 0}, { 28, 112, 0}, |
{ 0, 112, 0}, { 0, 112, 28}, { 0, 112, 56}, { 0, 112, 84}, |
{ 0, 112, 112}, { 0, 84, 112}, { 0, 56, 112}, { 0, 28, 112}, |
{ 56, 56, 112}, { 68, 56, 112}, { 84, 56, 112}, { 96, 56, 112}, |
{112, 56, 112}, {112, 56, 96}, {112, 56, 84}, {112, 56, 68}, |
{112, 56, 56}, {112, 68, 56}, {112, 84, 56}, {112, 96, 56}, |
{112, 112, 56}, { 96, 112, 56}, { 84, 112, 56}, { 68, 112, 56}, |
{ 56, 112, 56}, { 56, 112, 68}, { 56, 112, 84}, { 56, 112, 96}, |
{ 56, 112, 112}, { 56, 96, 112}, { 56, 84, 112}, { 56, 68, 112}, |
{ 80, 80, 112}, { 88, 80, 112}, { 96, 80, 112}, {104, 80, 112}, |
{112, 80, 112}, {112, 80, 104}, {112, 80, 96}, {112, 80, 88}, |
{112, 80, 80}, {112, 88, 80}, {112, 96, 80}, {112, 104, 80}, |
{112, 112, 80}, {104, 112, 80}, { 96, 112, 80}, { 88, 112, 80}, |
{ 80, 112, 80}, { 80, 112, 88}, { 80, 112, 96}, { 80, 112, 104}, |
{ 80, 112, 112}, { 80, 104, 112}, { 80, 96, 112}, { 80, 88, 112}, |
{ 0, 0, 64}, { 16, 0, 64}, { 32, 0, 64}, { 48, 0, 64}, |
{ 64, 0, 64}, { 64, 0, 48}, { 64, 0, 32}, { 64, 0, 16}, |
{ 64, 0, 0}, { 64, 16, 0}, { 64, 32, 0}, { 64, 48, 0}, |
{ 64, 64, 0}, { 48, 64, 0}, { 32, 64, 0}, { 16, 64, 0}, |
{ 0, 64, 0}, { 0, 64, 16}, { 0, 64, 32}, { 0, 64, 48}, |
{ 0, 64, 64}, { 0, 48, 64}, { 0, 32, 64}, { 0, 16, 64}, |
{ 32, 32, 64}, { 40, 32, 64}, { 48, 32, 64}, { 56, 32, 64}, |
{ 64, 32, 64}, { 64, 32, 56}, { 64, 32, 48}, { 64, 32, 40}, |
{ 64, 32, 32}, { 64, 40, 32}, { 64, 48, 32}, { 64, 56, 32}, |
{ 64, 64, 32}, { 56, 64, 32}, { 48, 64, 32}, { 40, 64, 32}, |
{ 32, 64, 32}, { 32, 64, 40}, { 32, 64, 48}, { 32, 64, 56}, |
{ 32, 64, 64}, { 32, 56, 64}, { 32, 48, 64}, { 32, 40, 64}, |
{ 44, 44, 64}, { 48, 44, 64}, { 52, 44, 64}, { 60, 44, 64}, |
{ 64, 44, 64}, { 64, 44, 60}, { 64, 44, 52}, { 64, 44, 48}, |
{ 64, 44, 44}, { 64, 48, 44}, { 64, 52, 44}, { 64, 60, 44}, |
{ 64, 64, 44}, { 60, 64, 44}, { 52, 64, 44}, { 48, 64, 44}, |
{ 44, 64, 44}, { 44, 64, 48}, { 44, 64, 52}, { 44, 64, 60}, |
{ 44, 64, 64}, { 44, 60, 64}, { 44, 52, 64}, { 44, 48, 64}, |
{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, |
{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} |
}; |
/contrib/games/opentyrian/src/vga_palette.h |
---|
0,0 → 1,8 |
#ifndef VGA_PALETTE_H |
#define VGA_PALETTE_H |
#include "palette.h" |
extern Palette vga_palette; |
#endif // VGA_PALETTE_H |
/contrib/games/opentyrian/src/video.c |
---|
0,0 → 1,204 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "video.h" |
#include "keyboard.h" |
#include "opentyr.h" |
#include "palette.h" |
#include "video_scale.h" |
#include <assert.h> |
#include <stdbool.h> |
#include <stdio.h> |
#include <stdlib.h> |
bool fullscreen_enabled = false; |
SDL_Surface *VGAScreen, *VGAScreenSeg; |
SDL_Surface *VGAScreen2; |
SDL_Surface *game_screen; |
static ScalerFunction scaler_function; |
void init_video( void ) |
{ |
SDL_ShowCursor(0); |
if (SDL_WasInit(SDL_INIT_VIDEO)) |
return; |
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) |
{ |
fprintf(stderr, "error: failed to initialize SDL video: %s\n", SDL_GetError()); |
exit(1); |
} |
SDL_WM_SetCaption("OpenTyrian", NULL); |
VGAScreen = VGAScreenSeg = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0); |
VGAScreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0); |
game_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0); |
SDL_FillRect(VGAScreen, NULL, 0); |
if (!init_scaler(scaler, fullscreen_enabled) && // try desired scaler and desired fullscreen state |
!init_any_scaler(fullscreen_enabled) && // try any scaler in desired fullscreen state |
!init_any_scaler(!fullscreen_enabled)) // try any scaler in other fullscreen state |
{ |
fprintf(stderr, "error: failed to initialize any supported video mode\n"); |
exit(EXIT_FAILURE); |
} |
} |
int can_init_scaler( unsigned int new_scaler, bool fullscreen ) |
{ |
if (new_scaler >= scalers_count) |
return false; |
int w = scalers[new_scaler].width, |
h = scalers[new_scaler].height; |
int flags = SDL_SWSURFACE | SDL_HWPALETTE | (fullscreen ? SDL_FULLSCREEN : 0); |
// test each bitdepth |
for (uint bpp = 32; bpp > 0; bpp -= 8) |
{ |
uint temp_bpp = SDL_VideoModeOK(w, h, bpp, flags); |
if ((temp_bpp == 32 && scalers[new_scaler].scaler32) || |
(temp_bpp == 16 && scalers[new_scaler].scaler16) || |
(temp_bpp == 8 && scalers[new_scaler].scaler8 )) |
{ |
return temp_bpp; |
} |
else if (temp_bpp == 24 && scalers[new_scaler].scaler32) |
{ |
// scalers don't support 24 bpp because it's a pain |
// so let SDL handle the conversion |
return 32; |
} |
} |
return 0; |
} |
bool init_scaler( unsigned int new_scaler, bool fullscreen ) |
{ |
int w = scalers[new_scaler].width, |
h = scalers[new_scaler].height; |
int bpp = can_init_scaler(new_scaler, fullscreen); |
int flags = SDL_SWSURFACE | SDL_HWPALETTE | (fullscreen ? SDL_FULLSCREEN : 0); |
if (bpp == 0) |
return false; |
#ifdef _KOLIBRI |
bpp=16; // DEBUG |
#endif |
SDL_Surface *const surface = SDL_SetVideoMode(w, h, bpp, flags); |
if (surface == NULL) |
{ |
fprintf(stderr, "error: failed to initialize %s video mode %dx%dx%d: %s\n", fullscreen ? "fullscreen" : "windowed", w, h, bpp, SDL_GetError()); |
return false; |
} |
w = surface->w; |
h = surface->h; |
#ifdef _KOLIBRI |
uSDL_SetWinCenter(w,h); |
#endif |
//bpp = surface->format->BitsPerPixel; |
printf("initialized video: %dx%dx%d %s\n", w, h, bpp, fullscreen ? "fullscreen" : "windowed"); |
scaler = new_scaler; |
fullscreen_enabled = fullscreen; |
switch (bpp) |
{ |
case 32: |
scaler_function = scalers[scaler].scaler32; |
break; |
case 16: |
scaler_function = scalers[scaler].scaler16; |
break; |
case 8: |
scaler_function = scalers[scaler].scaler8; |
break; |
default: |
scaler_function = NULL; |
break; |
} |
if (scaler_function == NULL) |
{ |
assert(false); |
return false; |
} |
input_grab(input_grab_enabled); |
JE_showVGA(); |
return true; |
} |
bool can_init_any_scaler( bool fullscreen ) |
{ |
for (int i = scalers_count - 1; i >= 0; --i) |
if (can_init_scaler(i, fullscreen) != 0) |
return true; |
return false; |
} |
bool init_any_scaler( bool fullscreen ) |
{ |
// attempts all scalers from last to first |
for (int i = scalers_count - 1; i >= 0; --i) |
if (init_scaler(i, fullscreen)) |
return true; |
return false; |
} |
void deinit_video( void ) |
{ |
SDL_FreeSurface(VGAScreenSeg); |
SDL_FreeSurface(VGAScreen2); |
SDL_FreeSurface(game_screen); |
SDL_QuitSubSystem(SDL_INIT_VIDEO); |
} |
void JE_clr256( SDL_Surface * screen) |
{ |
memset(screen->pixels, 0, screen->pitch * screen->h); |
} |
void JE_showVGA( void ) { scale_and_flip(VGAScreen); } |
void scale_and_flip( SDL_Surface *src_surface ) |
{ |
assert(src_surface->format->BitsPerPixel == 8); |
SDL_Surface *dst_surface = SDL_GetVideoSurface(); |
assert(scaler_function != NULL); |
scaler_function(src_surface, dst_surface); |
SDL_Flip(dst_surface); |
} |
/contrib/games/opentyrian/src/video.h |
---|
0,0 → 1,49 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef VIDEO_H |
#define VIDEO_H |
#include "opentyr.h" |
#include "SDL.h" |
#define vga_width 320 |
#define vga_height 200 |
extern bool fullscreen_enabled; |
extern SDL_Surface *VGAScreen, *VGAScreenSeg; |
extern SDL_Surface *game_screen; |
extern SDL_Surface *VGAScreen2; |
void init_video( void ); |
int can_init_scaler( unsigned int new_scaler, bool fullscreen ); |
bool init_scaler( unsigned int new_scaler, bool fullscreen ); |
bool can_init_any_scaler( bool fullscreen ); |
bool init_any_scaler( bool fullscreen ); |
void deinit_video( void ); |
void JE_clr256( SDL_Surface * ); |
void JE_showVGA( void ); |
void scale_and_flip( SDL_Surface * ); |
#endif /* VIDEO_H */ |
/contrib/games/opentyrian/src/video_scale.c |
---|
0,0 → 1,437 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2010 The OpenTyrian Development Team |
* |
* Scale2x, Scale3x |
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "video_scale.h" |
#include "palette.h" |
#include "video.h" |
#include <assert.h> |
static void no_scale( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void nn_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void nn_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void scale2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void scale2x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void scale3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static void scale3x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
void hq2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
void hq3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
void hq4x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
uint scaler; |
const struct Scalers scalers[] = |
{ |
#if defined(TARGET_GP2X) || defined(TARGET_DINGUX) |
{ 320, 240, no_scale, nn_16, nn_32, "None" }, |
#else |
{ 1 * vga_width, 1 * vga_height, no_scale, nn_16, nn_32, "None" }, |
{ 2 * vga_width, 2 * vga_height, NULL, nn_16, nn_32, "2x" }, |
{ 2 * vga_width, 2 * vga_height, NULL, scale2x_16, scale2x_32, "Scale2x" }, |
{ 2 * vga_width, 2 * vga_height, NULL, NULL, hq2x_32, "hq2x" }, |
{ 3 * vga_width, 3 * vga_height, NULL, nn_16, nn_32, "3x" }, |
{ 3 * vga_width, 3 * vga_height, NULL, scale3x_16, scale3x_32, "Scale3x" }, |
{ 3 * vga_width, 3 * vga_height, NULL, NULL, hq3x_32, "hq3x" }, |
{ 4 * vga_width, 4 * vga_height, NULL, nn_16, nn_32, "4x" }, |
{ 4 * vga_width, 4 * vga_height, NULL, NULL, hq4x_32, "hq4x" }, |
#endif |
}; |
const uint scalers_count = COUNTOF(scalers); |
void set_scaler_by_name( const char *name ) |
{ |
for (uint i = 0; i < scalers_count; ++i) |
{ |
if (strcmp(name, scalers[i].name) == 0) |
{ |
scaler = i; |
break; |
} |
} |
} |
#if defined(TARGET_GP2X) || defined(TARGET_DINGUX) |
#define VGA_CENTERED |
#endif |
void no_scale( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, |
*dst = dst_surface->pixels; |
#ifdef VGA_CENTERED |
size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch; |
memset(dst, 0, blank); |
dst += blank; |
#endif |
memcpy(dst, src, src_surface->pitch * src_surface->h); |
#ifdef VGA_CENTERED |
dst += src_surface->pitch * src_surface->h; |
memset(dst, 0, blank); |
#endif |
} |
void nn_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width, // src_surface->w |
scale = dst_surface->w / width; |
assert(scale == dst_surface->h / height); |
#ifdef VGA_CENTERED |
size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch; |
memset(dst, 0, blank); |
dst += blank; |
#endif |
for (int y = height; y > 0; y--) |
{ |
src_temp = src; |
dst_temp = dst; |
for (int x = width; x > 0; x--) |
{ |
for (int z = scale; z > 0; z--) |
{ |
*(Uint32 *)dst = rgb_palette[*src]; |
dst += dst_Bpp; |
} |
src++; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + dst_pitch; |
for (int z = scale; z > 1; z--) |
{ |
memcpy(dst, dst_temp, dst_pitch); |
dst += dst_pitch; |
} |
} |
#ifdef VGA_CENTERED |
memset(dst, 0, blank); |
#endif |
} |
void nn_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 2; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width, // src_surface->w |
scale = dst_surface->w / width; |
assert(scale == dst_surface->h / height); |
#ifdef VGA_CENTERED |
size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch; |
memset(dst, 0, blank); |
dst += blank; |
#endif |
for (int y = height; y > 0; y--) |
{ |
src_temp = src; |
dst_temp = dst; |
for (int x = width; x > 0; x--) |
{ |
for (int z = scale; z > 0; z--) |
{ |
*(Uint16 *)dst = rgb_palette[*src]; |
dst += dst_Bpp; |
} |
src++; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + dst_pitch; |
for (int z = scale; z > 1; z--) |
{ |
memcpy(dst, dst_temp, dst_pitch); |
dst += dst_pitch; |
} |
} |
#ifdef VGA_CENTERED |
memset(dst, 0, blank); |
#endif |
} |
void scale2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint32 E0, E1, E2, E3, B, D, E, F, H; |
for (int y = 0; y < height; y++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (y > 0) ? -src_pitch : 0; |
nextline = (y < height - 1) ? src_pitch : 0; |
for (int x = 0; x < width; x++) |
{ |
B = rgb_palette[*(src + prevline)]; |
D = rgb_palette[*(x > 0 ? src - 1 : src)]; |
E = rgb_palette[*src]; |
F = rgb_palette[*(x < width - 1 ? src + 1 : src)]; |
H = rgb_palette[*(src + nextline)]; |
if (B != H && D != F) { |
E0 = D == B ? D : E; |
E1 = B == F ? F : E; |
E2 = D == H ? D : E; |
E3 = H == F ? F : E; |
} else { |
E0 = E1 = E2 = E3 = E; |
} |
*(Uint32 *)dst = E0; |
*(Uint32 *)(dst + dst_Bpp) = E1; |
*(Uint32 *)(dst + dst_pitch) = E2; |
*(Uint32 *)(dst + dst_pitch + dst_Bpp) = E3; |
src++; |
dst += 2 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 2 * dst_pitch; |
} |
} |
void scale2x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 2; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint16 E0, E1, E2, E3, B, D, E, F, H; |
for (int y = 0; y < height; y++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (y > 0) ? -src_pitch : 0; |
nextline = (y < height - 1) ? src_pitch : 0; |
for (int x = 0; x < width; x++) |
{ |
B = rgb_palette[*(src + prevline)]; |
D = rgb_palette[*(x > 0 ? src - 1 : src)]; |
E = rgb_palette[*src]; |
F = rgb_palette[*(x < width - 1 ? src + 1 : src)]; |
H = rgb_palette[*(src + nextline)]; |
if (B != H && D != F) { |
E0 = D == B ? D : E; |
E1 = B == F ? F : E; |
E2 = D == H ? D : E; |
E3 = H == F ? F : E; |
} else { |
E0 = E1 = E2 = E3 = E; |
} |
*(Uint16 *)dst = E0; |
*(Uint16 *)(dst + dst_Bpp) = E1; |
*(Uint16 *)(dst + dst_pitch) = E2; |
*(Uint16 *)(dst + dst_pitch + dst_Bpp) = E3; |
src++; |
dst += 2 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 2 * dst_pitch; |
} |
} |
void scale3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint32 E0, E1, E2, E3, E4, E5, E6, E7, E8, A, B, C, D, E, F, G, H, I; |
for (int y = 0; y < height; y++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (y > 0) ? -src_pitch : 0; |
nextline = (y < height - 1) ? src_pitch : 0; |
for (int x = 0; x < width; x++) |
{ |
A = rgb_palette[*(src + prevline - (x > 0 ? 1 : 0))]; |
B = rgb_palette[*(src + prevline)]; |
C = rgb_palette[*(src + prevline + (x < width - 1 ? 1 : 0))]; |
D = rgb_palette[*(src - (x > 0 ? 1 : 0))]; |
E = rgb_palette[*src]; |
F = rgb_palette[*(src + (x < width - 1 ? 1 : 0))]; |
G = rgb_palette[*(src + nextline - (x > 0 ? 1 : 0))]; |
H = rgb_palette[*(src + nextline)]; |
I = rgb_palette[*(src + nextline + (x < width - 1 ? 1 : 0))]; |
if (B != H && D != F) { |
E0 = D == B ? D : E; |
E1 = (D == B && E != C) || (B == F && E != A) ? B : E; |
E2 = B == F ? F : E; |
E3 = (D == B && E != G) || (D == H && E != A) ? D : E; |
E4 = E; |
E5 = (B == F && E != I) || (H == F && E != C) ? F : E; |
E6 = D == H ? D : E; |
E7 = (D == H && E != I) || (H == F && E != G) ? H : E; |
E8 = H == F ? F : E; |
} else { |
E0 = E1 = E2 = E3 = E4 = E5 = E6 = E7 = E8 = E; |
} |
*(Uint32 *)dst = E0; |
*(Uint32 *)(dst + dst_Bpp) = E1; |
*(Uint32 *)(dst + 2 * dst_Bpp) = E2; |
*(Uint32 *)(dst + dst_pitch) = E3; |
*(Uint32 *)(dst + dst_pitch + dst_Bpp) = E4; |
*(Uint32 *)(dst + dst_pitch + 2 * dst_Bpp) = E5; |
*(Uint32 *)(dst + 2 * dst_pitch) = E6; |
*(Uint32 *)(dst + 2 * dst_pitch + dst_Bpp) = E7; |
*(Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = E8; |
src++; |
dst += 3 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 3 * dst_pitch; |
} |
} |
void scale3x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 2; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint16 E0, E1, E2, E3, E4, E5, E6, E7, E8, A, B, C, D, E, F, G, H, I; |
for (int y = 0; y < height; y++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (y > 0) ? -src_pitch : 0; |
nextline = (y < height - 1) ? src_pitch : 0; |
for (int x = 0; x < width; x++) |
{ |
A = rgb_palette[*(src + prevline - (x > 0 ? 1 : 0))]; |
B = rgb_palette[*(src + prevline)]; |
C = rgb_palette[*(src + prevline + (x < width - 1 ? 1 : 0))]; |
D = rgb_palette[*(src - (x > 0 ? 1 : 0))]; |
E = rgb_palette[*src]; |
F = rgb_palette[*(src + (x < width - 1 ? 1 : 0))]; |
G = rgb_palette[*(src + nextline - (x > 0 ? 1 : 0))]; |
H = rgb_palette[*(src + nextline)]; |
I = rgb_palette[*(src + nextline + (x < width - 1 ? 1 : 0))]; |
if (B != H && D != F) { |
E0 = D == B ? D : E; |
E1 = (D == B && E != C) || (B == F && E != A) ? B : E; |
E2 = B == F ? F : E; |
E3 = (D == B && E != G) || (D == H && E != A) ? D : E; |
E4 = E; |
E5 = (B == F && E != I) || (H == F && E != C) ? F : E; |
E6 = D == H ? D : E; |
E7 = (D == H && E != I) || (H == F && E != G) ? H : E; |
E8 = H == F ? F : E; |
} else { |
E0 = E1 = E2 = E3 = E4 = E5 = E6 = E7 = E8 = E; |
} |
*(Uint16 *)dst = E0; |
*(Uint16 *)(dst + dst_Bpp) = E1; |
*(Uint16 *)(dst + 2 * dst_Bpp) = E2; |
*(Uint16 *)(dst + dst_pitch) = E3; |
*(Uint16 *)(dst + dst_pitch + dst_Bpp) = E4; |
*(Uint16 *)(dst + dst_pitch + 2 * dst_Bpp) = E5; |
*(Uint16 *)(dst + 2 * dst_pitch) = E6; |
*(Uint16 *)(dst + 2 * dst_pitch + dst_Bpp) = E7; |
*(Uint16 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = E8; |
src++; |
dst += 3 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 3 * dst_pitch; |
} |
} |
/contrib/games/opentyrian/src/video_scale.h |
---|
0,0 → 1,42 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2010 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef VIDEO_SCALE_H |
#define VIDEO_SCALE_H |
#include "opentyr.h" |
#include "SDL.h" |
typedef void (*ScalerFunction)( SDL_Surface *dst, SDL_Surface *src ); |
struct Scalers |
{ |
int width, height; |
ScalerFunction scaler8, scaler16, scaler32; |
const char *name; |
}; |
extern uint scaler; |
extern const struct Scalers scalers[]; |
extern const uint scalers_count; |
void set_scaler_by_name( const char *name ); |
#endif /* VIDEO_SCALE_H */ |
/contrib/games/opentyrian/src/video_scale_hqNx.c |
---|
0,0 → 1,11895 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2010 The OpenTyrian Development Team |
* |
* hq2x, hq3x, hq4x |
* Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "palette.h" |
#include "video.h" |
void interp1(Uint32 *pc, Uint32 c1, Uint32 c2); |
void interp2(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
void interp3(Uint32 *pc, Uint32 c1, Uint32 c2); |
void interp4(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
void interp5(Uint32 *pc, Uint32 c1, Uint32 c2); |
void interp6(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
void interp7(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
void interp8(Uint32 *pc, Uint32 c1, Uint32 c2); |
void interp9(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
void interp10(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3); |
bool diff(unsigned int w1, unsigned int w2); |
void hq2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
void hq3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
void hq4x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ); |
static int YUV1, YUV2; |
const int Ymask = 0x00FF0000; |
const int Umask = 0x0000FF00; |
const int Vmask = 0x000000FF; |
const int trY = 0x00300000; |
const int trU = 0x00000700; |
const int trV = 0x00000006; |
inline void interp1(Uint32 *pc, Uint32 c1, Uint32 c2) |
{ |
*pc = (c1*3+c2) >> 2; |
} |
inline void interp2(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
*pc = (c1*2+c2+c3) >> 2; |
} |
inline void interp3(Uint32 *pc, Uint32 c1, Uint32 c2) |
{ |
//*((int*)pc) = (c1*7+c2)/8; |
*((int*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) + |
(((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3; |
} |
inline void interp4(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
//*((int*)pc) = (c1*2+(c2+c3)*7)/16; |
*((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*7 ) & 0x000FF000) + |
(((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*7 ) & 0x0FF00FF0)) >> 4; |
} |
inline void interp5(Uint32 *pc, Uint32 c1, Uint32 c2) |
{ |
*pc = (c1+c2) >> 1; |
} |
inline void interp6(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
//*pc = (c1*5+c2*2+c3)/8; |
*pc = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) + |
(((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; |
} |
inline void interp7(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
//*pc = (c1*6+c2+c3)/8; |
*pc = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) + |
(((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; |
} |
inline void interp8(Uint32 *pc, Uint32 c1, Uint32 c2) |
{ |
//*pc = (c1*5+c2*3)/8; |
*pc = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*3 ) & 0x0007F800) + |
(((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*3 ) & 0x07F807F8)) >> 3; |
} |
inline void interp9(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
//*pc = (c1*2+(c2+c3)*3)/8; |
*pc = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*3 ) & 0x0007F800) + |
(((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*3 ) & 0x07F807F8)) >> 3; |
} |
inline void interp10(Uint32 *pc, Uint32 c1, Uint32 c2, Uint32 c3) |
{ |
//*pc = (c1*14+c2+c3)/16; |
*pc = ((((c1 & 0x00FF00)*14 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x000FF000) + |
(((c1 & 0xFF00FF)*14 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x0FF00FF0)) >> 4; |
} |
inline bool diff(unsigned int w1, unsigned int w2) |
{ |
Uint32 YUV1 = yuv_palette[w1]; |
Uint32 YUV2 = yuv_palette[w2]; |
return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || |
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || |
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); |
} |
#define PIXEL00_0 *(Uint32 *)dst = c[5]; |
#define PIXEL00_10 interp1((Uint32 *)dst, c[5], c[1]); |
#define PIXEL00_11 interp1((Uint32 *)dst, c[5], c[4]); |
#define PIXEL00_12 interp1((Uint32 *)dst, c[5], c[2]); |
#define PIXEL00_20 interp2((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_21 interp2((Uint32 *)dst, c[5], c[1], c[2]); |
#define PIXEL00_22 interp2((Uint32 *)dst, c[5], c[1], c[4]); |
#define PIXEL00_60 interp6((Uint32 *)dst, c[5], c[2], c[4]); |
#define PIXEL00_61 interp6((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_70 interp7((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_90 interp9((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_100 interp10((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL01_0 *(Uint32 *)(dst + dst_Bpp) = c[5]; |
#define PIXEL01_10 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[3]); |
#define PIXEL01_11 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[2]); |
#define PIXEL01_12 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[6]); |
#define PIXEL01_20 interp2((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL01_21 interp2((Uint32 *)(dst + dst_Bpp), c[5], c[3], c[6]); |
#define PIXEL01_22 interp2((Uint32 *)(dst + dst_Bpp), c[5], c[3], c[2]); |
#define PIXEL01_60 interp6((Uint32 *)(dst + dst_Bpp), c[5], c[6], c[2]); |
#define PIXEL01_61 interp6((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL01_70 interp7((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL01_90 interp9((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL01_100 interp10((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL10_0 *(Uint32 *)(dst + dst_pitch) = c[5]; |
#define PIXEL10_10 interp1((Uint32 *)(dst + dst_pitch), c[5], c[7]); |
#define PIXEL10_11 interp1((Uint32 *)(dst + dst_pitch), c[5], c[8]); |
#define PIXEL10_12 interp1((Uint32 *)(dst + dst_pitch), c[5], c[4]); |
#define PIXEL10_20 interp2((Uint32 *)(dst + dst_pitch), c[5], c[8], c[4]); |
#define PIXEL10_21 interp2((Uint32 *)(dst + dst_pitch), c[5], c[7], c[4]); |
#define PIXEL10_22 interp2((Uint32 *)(dst + dst_pitch), c[5], c[7], c[8]); |
#define PIXEL10_60 interp6((Uint32 *)(dst + dst_pitch), c[5], c[4], c[8]); |
#define PIXEL10_61 interp6((Uint32 *)(dst + dst_pitch), c[5], c[8], c[4]); |
#define PIXEL10_70 interp7((Uint32 *)(dst + dst_pitch), c[5], c[8], c[4]); |
#define PIXEL10_90 interp9((Uint32 *)(dst + dst_pitch), c[5], c[8], c[4]); |
#define PIXEL10_100 interp10((Uint32 *)(dst + dst_pitch), c[5], c[8], c[4]); |
#define PIXEL11_0 *(Uint32 *)(dst + dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL11_10 interp1((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[9]); |
#define PIXEL11_11 interp1((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6]); |
#define PIXEL11_12 interp1((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL11_20 interp2((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL11_21 interp2((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[9], c[8]); |
#define PIXEL11_22 interp2((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[9], c[6]); |
#define PIXEL11_60 interp6((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[8], c[6]); |
#define PIXEL11_61 interp6((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL11_70 interp7((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL11_90 interp9((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL11_100 interp10((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[6], c[8]); |
void hq2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint32 w[10]; |
Uint32 c[10]; |
// +----+----+----+ |
// | | | | |
// | w1 | w2 | w3 | |
// +----+----+----+ |
// | | | | |
// | w4 | w5 | w6 | |
// +----+----+----+ |
// | | | | |
// | w7 | w8 | w9 | |
// +----+----+----+ |
for (int j = 0; j < height; j++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (j > 0) ? -width : 0; |
nextline = (j < height - 1) ? width : 0; |
for (int i = 0; i < width; i++) |
{ |
w[2] = *(src + prevline); |
w[5] = *src; |
w[8] = *(src + nextline); |
if (i > 0) |
{ |
w[1] = *(src + prevline - 1); |
w[4] = *(src - 1); |
w[7] = *(src + nextline - 1); |
} else { |
w[1] = w[2]; |
w[4] = w[5]; |
w[7] = w[8]; |
} |
if (i < width - 1) |
{ |
w[3] = *(src + prevline + 1); |
w[6] = *(src + 1); |
w[9] = *(src + nextline + 1); |
} else { |
w[3] = w[2]; |
w[6] = w[5]; |
w[9] = w[8]; |
} |
int pattern = 0; |
int flag = 1; |
YUV1 = yuv_palette[w[5]]; |
for (int k=1; k<=9; k++) |
{ |
if (k==5) continue; |
if ( w[k] != w[5] ) |
{ |
YUV2 = yuv_palette[w[k]]; |
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || |
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || |
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) |
pattern |= flag; |
} |
flag <<= 1; |
} |
for (int k=1; k<=9; k++) |
c[k] = rgb_palette[w[k]] & 0xfcfcfcfc; // hq2x has a nasty inability to accept more than 6 bits for each component |
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 (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_20 |
PIXEL11_21 |
break; |
} |
case 80: |
case 81: |
{ |
PIXEL00_20 |
PIXEL01_22 |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 72: |
case 76: |
{ |
PIXEL00_21 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 10: |
case 138: |
{ |
if (diff(w[4], w[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 (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_20 |
PIXEL11_21 |
break; |
} |
case 208: |
case 209: |
{ |
PIXEL00_20 |
PIXEL01_22 |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 104: |
case 108: |
{ |
PIXEL00_21 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 11: |
case 139: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_21 |
PIXEL10_22 |
PIXEL11_20 |
break; |
} |
case 19: |
case 51: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_11 |
PIXEL01_10 |
} |
else |
{ |
PIXEL00_60 |
PIXEL01_90 |
} |
PIXEL10_20 |
PIXEL11_21 |
break; |
} |
case 146: |
case 178: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
PIXEL11_12 |
} |
else |
{ |
PIXEL01_90 |
PIXEL11_61 |
} |
PIXEL10_20 |
break; |
} |
case 84: |
case 85: |
{ |
PIXEL00_20 |
if (diff(w[6], w[8])) |
{ |
PIXEL01_11 |
PIXEL11_10 |
} |
else |
{ |
PIXEL01_60 |
PIXEL11_90 |
} |
PIXEL10_21 |
break; |
} |
case 112: |
case 113: |
{ |
PIXEL00_20 |
PIXEL01_22 |
if (diff(w[6], w[8])) |
{ |
PIXEL10_12 |
PIXEL11_10 |
} |
else |
{ |
PIXEL10_61 |
PIXEL11_90 |
} |
break; |
} |
case 200: |
case 204: |
{ |
PIXEL00_21 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
PIXEL11_11 |
} |
else |
{ |
PIXEL10_90 |
PIXEL11_60 |
} |
break; |
} |
case 73: |
case 77: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_12 |
PIXEL10_10 |
} |
else |
{ |
PIXEL00_61 |
PIXEL10_90 |
} |
PIXEL01_20 |
PIXEL11_22 |
break; |
} |
case 42: |
case 170: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
PIXEL10_11 |
} |
else |
{ |
PIXEL00_90 |
PIXEL10_60 |
} |
PIXEL01_21 |
PIXEL11_20 |
break; |
} |
case 14: |
case 142: |
{ |
if (diff(w[4], w[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 (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_22 |
PIXEL11_21 |
break; |
} |
case 82: |
case 214: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 88: |
case 248: |
{ |
PIXEL00_21 |
PIXEL01_22 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 74: |
case 107: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_21 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 27: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_10 |
PIXEL10_22 |
PIXEL11_21 |
break; |
} |
case 86: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_21 |
PIXEL11_10 |
break; |
} |
case 216: |
{ |
PIXEL00_21 |
PIXEL01_22 |
PIXEL10_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 106: |
{ |
PIXEL00_10 |
PIXEL01_21 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 30: |
{ |
PIXEL00_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_22 |
PIXEL11_21 |
break; |
} |
case 210: |
{ |
PIXEL00_22 |
PIXEL01_10 |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 120: |
{ |
PIXEL00_21 |
PIXEL01_22 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_10 |
break; |
} |
case 75: |
{ |
if (diff(w[4], w[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 (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_11 |
PIXEL11_21 |
break; |
} |
case 83: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 92: |
{ |
PIXEL00_21 |
PIXEL01_11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 202: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
PIXEL01_21 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
PIXEL11_11 |
break; |
} |
case 78: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
PIXEL11_22 |
break; |
} |
case 154: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_22 |
PIXEL11_12 |
break; |
} |
case 114: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 89: |
{ |
PIXEL00_12 |
PIXEL01_22 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 90: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 55: |
case 23: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_11 |
PIXEL01_0 |
} |
else |
{ |
PIXEL00_60 |
PIXEL01_90 |
} |
PIXEL10_20 |
PIXEL11_21 |
break; |
} |
case 182: |
case 150: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
PIXEL11_12 |
} |
else |
{ |
PIXEL01_90 |
PIXEL11_61 |
} |
PIXEL10_20 |
break; |
} |
case 213: |
case 212: |
{ |
PIXEL00_20 |
if (diff(w[6], w[8])) |
{ |
PIXEL01_11 |
PIXEL11_0 |
} |
else |
{ |
PIXEL01_60 |
PIXEL11_90 |
} |
PIXEL10_21 |
break; |
} |
case 241: |
case 240: |
{ |
PIXEL00_20 |
PIXEL01_22 |
if (diff(w[6], w[8])) |
{ |
PIXEL10_12 |
PIXEL11_0 |
} |
else |
{ |
PIXEL10_61 |
PIXEL11_90 |
} |
break; |
} |
case 236: |
case 232: |
{ |
PIXEL00_21 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
PIXEL11_11 |
} |
else |
{ |
PIXEL10_90 |
PIXEL11_60 |
} |
break; |
} |
case 109: |
case 105: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_12 |
PIXEL10_0 |
} |
else |
{ |
PIXEL00_61 |
PIXEL10_90 |
} |
PIXEL01_20 |
PIXEL11_22 |
break; |
} |
case 171: |
case 43: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
PIXEL10_11 |
} |
else |
{ |
PIXEL00_90 |
PIXEL10_60 |
} |
PIXEL01_21 |
PIXEL11_20 |
break; |
} |
case 143: |
case 15: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
PIXEL01_12 |
} |
else |
{ |
PIXEL00_90 |
PIXEL01_61 |
} |
PIXEL10_22 |
PIXEL11_20 |
break; |
} |
case 124: |
{ |
PIXEL00_21 |
PIXEL01_11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_10 |
break; |
} |
case 203: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_21 |
PIXEL10_10 |
PIXEL11_11 |
break; |
} |
case 62: |
{ |
PIXEL00_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_11 |
PIXEL11_21 |
break; |
} |
case 211: |
{ |
PIXEL00_11 |
PIXEL01_10 |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 118: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_12 |
PIXEL11_10 |
break; |
} |
case 217: |
{ |
PIXEL00_12 |
PIXEL01_22 |
PIXEL10_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 110: |
{ |
PIXEL00_10 |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 155: |
{ |
if (diff(w[4], w[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 (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 158: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_22 |
PIXEL11_12 |
break; |
} |
case 234: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
PIXEL01_21 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_11 |
break; |
} |
case 242: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 59: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_11 |
PIXEL11_21 |
break; |
} |
case 121: |
{ |
PIXEL00_12 |
PIXEL01_22 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 87: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 79: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
PIXEL11_22 |
break; |
} |
case 122: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 94: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 218: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 91: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[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 (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_11 |
PIXEL11_12 |
break; |
} |
case 115: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 93: |
{ |
PIXEL00_12 |
PIXEL01_11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_10 |
} |
else |
{ |
PIXEL11_70 |
} |
break; |
} |
case 206: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
PIXEL11_11 |
break; |
} |
case 205: |
case 201: |
{ |
PIXEL00_12 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_10 |
} |
else |
{ |
PIXEL10_70 |
} |
PIXEL11_11 |
break; |
} |
case 174: |
case 46: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_10 |
} |
else |
{ |
PIXEL00_70 |
} |
PIXEL01_12 |
PIXEL10_11 |
PIXEL11_20 |
break; |
} |
case 179: |
case 147: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_10 |
} |
else |
{ |
PIXEL01_70 |
} |
PIXEL10_20 |
PIXEL11_12 |
break; |
} |
case 117: |
case 116: |
{ |
PIXEL00_20 |
PIXEL01_11 |
PIXEL10_12 |
if (diff(w[6], w[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 (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_10 |
break; |
} |
case 219: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_10 |
PIXEL10_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 125: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_12 |
PIXEL10_0 |
} |
else |
{ |
PIXEL00_61 |
PIXEL10_90 |
} |
PIXEL01_11 |
PIXEL11_10 |
break; |
} |
case 221: |
{ |
PIXEL00_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL01_11 |
PIXEL11_0 |
} |
else |
{ |
PIXEL01_60 |
PIXEL11_90 |
} |
PIXEL10_10 |
break; |
} |
case 207: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
PIXEL01_12 |
} |
else |
{ |
PIXEL00_90 |
PIXEL01_61 |
} |
PIXEL10_10 |
PIXEL11_11 |
break; |
} |
case 238: |
{ |
PIXEL00_10 |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
PIXEL11_11 |
} |
else |
{ |
PIXEL10_90 |
PIXEL11_60 |
} |
break; |
} |
case 190: |
{ |
PIXEL00_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
PIXEL11_12 |
} |
else |
{ |
PIXEL01_90 |
PIXEL11_61 |
} |
PIXEL10_11 |
break; |
} |
case 187: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
PIXEL10_11 |
} |
else |
{ |
PIXEL00_90 |
PIXEL10_60 |
} |
PIXEL01_10 |
PIXEL11_12 |
break; |
} |
case 243: |
{ |
PIXEL00_11 |
PIXEL01_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL10_12 |
PIXEL11_0 |
} |
else |
{ |
PIXEL10_61 |
PIXEL11_90 |
} |
break; |
} |
case 119: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_11 |
PIXEL01_0 |
} |
else |
{ |
PIXEL00_60 |
PIXEL01_90 |
} |
PIXEL10_12 |
PIXEL11_10 |
break; |
} |
case 237: |
case 233: |
{ |
PIXEL00_12 |
PIXEL01_20 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
PIXEL11_11 |
break; |
} |
case 175: |
case 47: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
PIXEL01_12 |
PIXEL10_11 |
PIXEL11_20 |
break; |
} |
case 183: |
case 151: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_20 |
PIXEL11_12 |
break; |
} |
case 245: |
case 244: |
{ |
PIXEL00_20 |
PIXEL01_11 |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 250: |
{ |
PIXEL00_10 |
PIXEL01_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 123: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_10 |
break; |
} |
case 95: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_10 |
PIXEL11_10 |
break; |
} |
case 222: |
{ |
PIXEL00_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 252: |
{ |
PIXEL00_21 |
PIXEL01_11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 249: |
{ |
PIXEL00_12 |
PIXEL01_22 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 235: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_21 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
PIXEL11_11 |
break; |
} |
case 111: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_22 |
break; |
} |
case 63: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_11 |
PIXEL11_21 |
break; |
} |
case 159: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_22 |
PIXEL11_12 |
break; |
} |
case 215: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_21 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 246: |
{ |
PIXEL00_22 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 254: |
{ |
PIXEL00_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 253: |
{ |
PIXEL00_12 |
PIXEL01_11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 251: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
PIXEL01_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 239: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
PIXEL01_12 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
PIXEL11_11 |
break; |
} |
case 127: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_20 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_20 |
} |
PIXEL11_10 |
break; |
} |
case 191: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_11 |
PIXEL11_12 |
break; |
} |
case 223: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_20 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_10 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_20 |
} |
break; |
} |
case 247: |
{ |
PIXEL00_11 |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
PIXEL10_12 |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
case 255: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_0 |
} |
else |
{ |
PIXEL00_100 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_0 |
} |
else |
{ |
PIXEL01_100 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL10_0 |
} |
else |
{ |
PIXEL10_100 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL11_0 |
} |
else |
{ |
PIXEL11_100 |
} |
break; |
} |
} |
src++; |
dst += 2 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 2 * dst_pitch; |
} |
} |
#define PIXEL00_1M interp1((Uint32 *)dst, c[5], c[1]); |
#define PIXEL00_1U interp1((Uint32 *)dst, c[5], c[2]); |
#define PIXEL00_1L interp1((Uint32 *)dst, c[5], c[4]); |
#define PIXEL00_2 interp2((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_4 interp4((Uint32 *)dst, c[5], c[4], c[2]); |
#define PIXEL00_5 interp5((Uint32 *)dst, c[4], c[2]); |
#define PIXEL00_C *(Uint32 *)dst = c[5]; |
#define PIXEL01_1 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[2]); |
#define PIXEL01_3 interp3((Uint32 *)(dst + dst_Bpp), c[5], c[2]); |
#define PIXEL01_6 interp1((Uint32 *)(dst + dst_Bpp), c[2], c[5]); |
#define PIXEL01_C *(Uint32 *)(dst + dst_Bpp) = c[5]; |
#define PIXEL02_1M interp1((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[3]); |
#define PIXEL02_1U interp1((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2]); |
#define PIXEL02_1R interp1((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL02_2 interp2((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL02_4 interp4((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL02_5 interp5((Uint32 *)(dst + 2 * dst_Bpp), c[2], c[6]); |
#define PIXEL02_C *(Uint32 *)(dst + 2 * dst_Bpp) = c[5]; |
#define PIXEL10_1 interp1((Uint32 *)(dst + dst_pitch), c[5], c[4]); |
#define PIXEL10_3 interp3((Uint32 *)(dst + dst_pitch), c[5], c[4]); |
#define PIXEL10_6 interp1((Uint32 *)(dst + dst_pitch), c[4], c[5]); |
#define PIXEL10_C *(Uint32 *)(dst + dst_pitch) = c[5]; |
#define PIXEL11 *(Uint32 *)(dst + dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL12_1 interp1((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL12_3 interp3((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL12_6 interp1((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[6], c[5]); |
#define PIXEL12_C *(Uint32 *)(dst + dst_pitch + 2 * dst_Bpp) = c[5]; |
#define PIXEL20_1M interp1((Uint32 *)(dst + 2 * dst_pitch), c[5], c[7]); |
#define PIXEL20_1D interp1((Uint32 *)(dst + 2 * dst_pitch), c[5], c[8]); |
#define PIXEL20_1L interp1((Uint32 *)(dst + 2 * dst_pitch), c[5], c[4]); |
#define PIXEL20_2 interp2((Uint32 *)(dst + 2 * dst_pitch), c[5], c[8], c[4]); |
#define PIXEL20_4 interp4((Uint32 *)(dst + 2 * dst_pitch), c[5], c[8], c[4]); |
#define PIXEL20_5 interp5((Uint32 *)(dst + 2 * dst_pitch), c[8], c[4]); |
#define PIXEL20_C *(Uint32 *)(dst + 2 * dst_pitch) = c[5]; |
#define PIXEL21_1 interp1((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL21_3 interp3((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL21_6 interp1((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[8], c[5]); |
#define PIXEL21_C *(Uint32 *)(dst + 2 * dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL22_1M interp1((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[9]); |
#define PIXEL22_1D interp1((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[8]); |
#define PIXEL22_1R interp1((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL22_2 interp2((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL22_4 interp4((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL22_5 interp5((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[6], c[8]); |
#define PIXEL22_C *(Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = c[5]; |
void hq3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint32 w[10]; |
Uint32 c[10]; |
// +----+----+----+ |
// | | | | |
// | w1 | w2 | w3 | |
// +----+----+----+ |
// | | | | |
// | w4 | w5 | w6 | |
// +----+----+----+ |
// | | | | |
// | w7 | w8 | w9 | |
// +----+----+----+ |
for (int j = 0; j < height; j++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (j > 0) ? -width : 0; |
nextline = (j < height - 1) ? width : 0; |
for (int i = 0; i < width; i++) |
{ |
w[2] = *(src + prevline); |
w[5] = *src; |
w[8] = *(src + nextline); |
if (i>0) |
{ |
w[1] = *(src + prevline - 1); |
w[4] = *(src - 1); |
w[7] = *(src + nextline - 1); |
} else { |
w[1] = w[2]; |
w[4] = w[5]; |
w[7] = w[8]; |
} |
if (i < width - 1) |
{ |
w[3] = *(src + prevline + 1); |
w[6] = *(src + 1); |
w[9] = *(src + nextline + 1); |
} else { |
w[3] = w[2]; |
w[6] = w[5]; |
w[9] = w[8]; |
} |
int pattern = 0; |
int flag = 1; |
YUV1 = yuv_palette[w[5]]; |
for (int k=1; k<=9; k++) |
{ |
if (k==5) continue; |
if ( w[k] != w[5] ) |
{ |
YUV2 = yuv_palette[w[k]]; |
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || |
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || |
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) |
pattern |= flag; |
} |
flag <<= 1; |
} |
for (int k=1; k<=9; k++) |
c[k] = rgb_palette[w[k]] & 0xfcfcfcfc; // hq3x has a nasty inability to accept more than 6 bits for each component |
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_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 2: |
case 34: |
case 130: |
case 162: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 16: |
case 17: |
case 48: |
case 49: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 64: |
case 65: |
case 68: |
case 69: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 8: |
case 12: |
case 136: |
case 140: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 3: |
case 35: |
case 131: |
case 163: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 6: |
case 38: |
case 134: |
case 166: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 20: |
case 21: |
case 52: |
case 53: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 144: |
case 145: |
case 176: |
case 177: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 192: |
case 193: |
case 196: |
case 197: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 96: |
case 97: |
case 100: |
case 101: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 40: |
case 44: |
case 168: |
case 172: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 9: |
case 13: |
case 137: |
case 141: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 18: |
case 50: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_1M |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 80: |
case 81: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_1M |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 72: |
case 76: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_1M |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 10: |
case 138: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 66: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 24: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 7: |
case 39: |
case 135: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 148: |
case 149: |
case 180: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 224: |
case 228: |
case 225: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 41: |
case 169: |
case 45: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 22: |
case 54: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 208: |
case 209: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 104: |
case 108: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 11: |
case 139: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 19: |
case 51: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL12_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL01_6 |
PIXEL02_5 |
PIXEL12_1 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 146: |
case 178: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_1M |
PIXEL12_C |
PIXEL22_1D |
} |
else |
{ |
PIXEL01_1 |
PIXEL02_5 |
PIXEL12_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
break; |
} |
case 84: |
case 85: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL02_1U |
PIXEL12_C |
PIXEL21_C |
PIXEL22_1M |
} |
else |
{ |
PIXEL02_2 |
PIXEL12_6 |
PIXEL21_1 |
PIXEL22_5 |
} |
PIXEL00_2 |
PIXEL01_1 |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
break; |
} |
case 112: |
case 113: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
} |
else |
{ |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_6 |
PIXEL22_5 |
} |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
break; |
} |
case 200: |
case 204: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
} |
else |
{ |
PIXEL10_1 |
PIXEL20_5 |
PIXEL21_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
break; |
} |
case 73: |
case 77: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_1U |
PIXEL10_C |
PIXEL20_1M |
PIXEL21_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL10_6 |
PIXEL20_5 |
PIXEL21_1 |
} |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
PIXEL22_1M |
break; |
} |
case 42: |
case 170: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL10_C |
PIXEL20_1D |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_1 |
PIXEL10_6 |
PIXEL20_2 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 14: |
case 142: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_6 |
PIXEL02_2 |
PIXEL10_1 |
} |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 67: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 70: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 28: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 152: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 194: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 98: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 56: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 25: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 26: |
case 31: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL10_3 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL11 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 82: |
case 214: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 88: |
case 248: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL22_4 |
} |
break; |
} |
case 74: |
case 107: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
} |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 27: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 86: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 216: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 106: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 30: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 210: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 120: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 75: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 29: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 198: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 184: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 99: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 57: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 71: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 156: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 226: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 60: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 195: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 102: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 153: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 58: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 83: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 92: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 202: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 78: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 154: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 114: |
{ |
PIXEL00_1M |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 89: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 90: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 55: |
case 23: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL01_6 |
PIXEL02_5 |
PIXEL12_1 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 182: |
case 150: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
PIXEL22_1D |
} |
else |
{ |
PIXEL01_1 |
PIXEL02_5 |
PIXEL12_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_2 |
PIXEL21_1 |
break; |
} |
case 213: |
case 212: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL02_1U |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL02_2 |
PIXEL12_6 |
PIXEL21_1 |
PIXEL22_5 |
} |
PIXEL00_2 |
PIXEL01_1 |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
break; |
} |
case 241: |
case 240: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_6 |
PIXEL22_5 |
} |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
break; |
} |
case 236: |
case 232: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
PIXEL22_1R |
} |
else |
{ |
PIXEL10_1 |
PIXEL20_5 |
PIXEL21_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
break; |
} |
case 109: |
case 105: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_1U |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL10_6 |
PIXEL20_5 |
PIXEL21_1 |
} |
PIXEL01_1 |
PIXEL02_2 |
PIXEL11 |
PIXEL12_1 |
PIXEL22_1M |
break; |
} |
case 171: |
case 43: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
PIXEL20_1D |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_1 |
PIXEL10_6 |
PIXEL20_2 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 143: |
case 15: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_6 |
PIXEL02_2 |
PIXEL10_1 |
} |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 124: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 203: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 62: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 211: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 118: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 217: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 110: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 155: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 188: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 185: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 61: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 157: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 103: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 227: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 230: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 199: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 220: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 158: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 234: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1M |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1R |
break; |
} |
case 242: |
{ |
PIXEL00_1M |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1L |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 59: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 121: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 87: |
{ |
PIXEL00_1L |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1M |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 79: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1R |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 122: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 94: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_C |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 218: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 91: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 229: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 167: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 173: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 181: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 186: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 115: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 93: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 206: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 205: |
case 201: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_1M |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 174: |
case 46: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_1M |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 179: |
case 147: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_1M |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 117: |
case 116: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_1M |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 189: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 231: |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_1 |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 126: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 219: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
PIXEL10_3 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 125: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL00_1U |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL10_6 |
PIXEL20_5 |
PIXEL21_1 |
} |
PIXEL01_1 |
PIXEL02_1U |
PIXEL11 |
PIXEL12_C |
PIXEL22_1M |
break; |
} |
case 221: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL02_1U |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL02_2 |
PIXEL12_6 |
PIXEL21_1 |
PIXEL22_5 |
} |
PIXEL00_1U |
PIXEL01_1 |
PIXEL10_C |
PIXEL11 |
PIXEL20_1M |
break; |
} |
case 207: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_6 |
PIXEL02_2 |
PIXEL10_1 |
} |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 238: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
PIXEL22_1R |
} |
else |
{ |
PIXEL10_1 |
PIXEL20_5 |
PIXEL21_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1R |
PIXEL11 |
PIXEL12_1 |
break; |
} |
case 190: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
PIXEL22_1D |
} |
else |
{ |
PIXEL01_1 |
PIXEL02_5 |
PIXEL12_6 |
PIXEL22_2 |
} |
PIXEL00_1M |
PIXEL10_C |
PIXEL11 |
PIXEL20_1D |
PIXEL21_1 |
break; |
} |
case 187: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
PIXEL20_1D |
} |
else |
{ |
PIXEL00_5 |
PIXEL01_1 |
PIXEL10_6 |
PIXEL20_2 |
} |
PIXEL02_1M |
PIXEL11 |
PIXEL12_C |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 243: |
{ |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_1 |
PIXEL20_2 |
PIXEL21_6 |
PIXEL22_5 |
} |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_1M |
PIXEL10_1 |
PIXEL11 |
break; |
} |
case 119: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL00_1L |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL01_6 |
PIXEL02_5 |
PIXEL12_1 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL20_1L |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 237: |
case 233: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_2 |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 175: |
case 47: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_2 |
break; |
} |
case 183: |
case 151: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_2 |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 245: |
case 244: |
{ |
PIXEL00_2 |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 250: |
{ |
PIXEL00_1M |
PIXEL01_C |
PIXEL02_1M |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL22_4 |
} |
break; |
} |
case 123: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
} |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 95: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL10_3 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL11 |
PIXEL20_1M |
PIXEL21_C |
PIXEL22_1M |
break; |
} |
case 222: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 252: |
{ |
PIXEL00_1M |
PIXEL01_1 |
PIXEL02_1U |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 249: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL22_4 |
} |
break; |
} |
case 235: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
} |
PIXEL02_1M |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 111: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 63: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1M |
break; |
} |
case 159: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL10_3 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 215: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 246: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 254: |
{ |
PIXEL00_1M |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_4 |
} |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_4 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL21_3 |
PIXEL22_2 |
} |
break; |
} |
case 253: |
{ |
PIXEL00_1U |
PIXEL01_1 |
PIXEL02_1U |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 251: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL01_3 |
} |
PIXEL02_1M |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL10_C |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL10_3 |
PIXEL20_2 |
PIXEL21_3 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL12_C |
PIXEL22_C |
} |
else |
{ |
PIXEL12_3 |
PIXEL22_4 |
} |
break; |
} |
case 239: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
PIXEL02_1R |
PIXEL10_C |
PIXEL11 |
PIXEL12_1 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
PIXEL22_1R |
break; |
} |
case 127: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL01_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_2 |
PIXEL01_3 |
PIXEL10_3 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL02_4 |
PIXEL12_3 |
} |
PIXEL11 |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
PIXEL21_C |
} |
else |
{ |
PIXEL20_4 |
PIXEL21_3 |
} |
PIXEL22_1M |
break; |
} |
case 191: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
PIXEL20_1D |
PIXEL21_1 |
PIXEL22_1D |
break; |
} |
case 223: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
PIXEL10_C |
} |
else |
{ |
PIXEL00_4 |
PIXEL10_3 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL01_C |
PIXEL02_C |
PIXEL12_C |
} |
else |
{ |
PIXEL01_3 |
PIXEL02_2 |
PIXEL12_3 |
} |
PIXEL11 |
PIXEL20_1M |
if (diff(w[6], w[8])) |
{ |
PIXEL21_C |
PIXEL22_C |
} |
else |
{ |
PIXEL21_3 |
PIXEL22_4 |
} |
break; |
} |
case 247: |
{ |
PIXEL00_1L |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_1 |
PIXEL11 |
PIXEL12_C |
PIXEL20_1L |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
case 255: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL00_C |
} |
else |
{ |
PIXEL00_2 |
} |
PIXEL01_C |
if (diff(w[2], w[6])) |
{ |
PIXEL02_C |
} |
else |
{ |
PIXEL02_2 |
} |
PIXEL10_C |
PIXEL11 |
PIXEL12_C |
if (diff(w[8], w[4])) |
{ |
PIXEL20_C |
} |
else |
{ |
PIXEL20_2 |
} |
PIXEL21_C |
if (diff(w[6], w[8])) |
{ |
PIXEL22_C |
} |
else |
{ |
PIXEL22_2 |
} |
break; |
} |
} |
src++; |
dst += 3 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 3 * dst_pitch; |
} |
} |
#define PIXEL4_00_0 *(Uint32 *)(dst) = c[5]; |
#define PIXEL4_00_11 interp1((Uint32 *)(dst), c[5], c[4]); |
#define PIXEL4_00_12 interp1((Uint32 *)(dst), c[5], c[2]); |
#define PIXEL4_00_20 interp2((Uint32 *)(dst), c[5], c[2], c[4]); |
#define PIXEL4_00_50 interp5((Uint32 *)(dst), c[2], c[4]); |
#define PIXEL4_00_80 interp8((Uint32 *)(dst), c[5], c[1]); |
#define PIXEL4_00_81 interp8((Uint32 *)(dst), c[5], c[4]); |
#define PIXEL4_00_82 interp8((Uint32 *)(dst), c[5], c[2]); |
#define PIXEL4_01_0 *(Uint32 *)(dst + dst_Bpp) = c[5]; |
#define PIXEL4_01_10 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[1]); |
#define PIXEL4_01_12 interp1((Uint32 *)(dst + dst_Bpp), c[5], c[2]); |
#define PIXEL4_01_14 interp1((Uint32 *)(dst + dst_Bpp), c[2], c[5]); |
#define PIXEL4_01_21 interp2((Uint32 *)(dst + dst_Bpp), c[2], c[5], c[4]); |
#define PIXEL4_01_31 interp3((Uint32 *)(dst + dst_Bpp), c[5], c[4]); |
#define PIXEL4_01_50 interp5((Uint32 *)(dst + dst_Bpp), c[2], c[5]); |
#define PIXEL4_01_60 interp6((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[4]); |
#define PIXEL4_01_61 interp6((Uint32 *)(dst + dst_Bpp), c[5], c[2], c[1]); |
#define PIXEL4_01_82 interp8((Uint32 *)(dst + dst_Bpp), c[5], c[2]); |
#define PIXEL4_01_83 interp8((Uint32 *)(dst + dst_Bpp), c[2], c[4]); |
#define PIXEL4_02_0 *(Uint32 *)(dst + 2 * dst_Bpp) = c[5]; |
#define PIXEL4_02_10 interp1((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[3]); |
#define PIXEL4_02_11 interp1((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_02_13 interp1((Uint32 *)(dst + 2 * dst_Bpp), c[2], c[5]); |
#define PIXEL4_02_21 interp2((Uint32 *)(dst + 2 * dst_Bpp), c[2], c[5], c[6]); |
#define PIXEL4_02_32 interp3((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_02_50 interp5((Uint32 *)(dst + 2 * dst_Bpp), c[2], c[5]); |
#define PIXEL4_02_60 interp6((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL4_02_61 interp6((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2], c[3]); |
#define PIXEL4_02_81 interp8((Uint32 *)(dst + 2 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_02_83 interp8((Uint32 *)(dst + 2 * dst_Bpp), c[2], c[6]); |
#define PIXEL4_03_0 *(Uint32 *)(dst + 3 * dst_Bpp) = c[5]; |
#define PIXEL4_03_11 interp1((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_03_12 interp1((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_03_20 interp2((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[2], c[6]); |
#define PIXEL4_03_50 interp5((Uint32 *)(dst + 3 * dst_Bpp), c[2], c[6]); |
#define PIXEL4_03_80 interp8((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[3]); |
#define PIXEL4_03_81 interp8((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_03_82 interp8((Uint32 *)(dst + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_10_0 *(Uint32 *)(dst + dst_pitch) = c[5]; |
#define PIXEL4_10_10 interp1((Uint32 *)(dst + dst_pitch ), c[5], c[1]); |
#define PIXEL4_10_11 interp1((Uint32 *)(dst + dst_pitch ), c[5], c[4]); |
#define PIXEL4_10_13 interp1((Uint32 *)(dst + dst_pitch ), c[4], c[5]); |
#define PIXEL4_10_21 interp2((Uint32 *)(dst + dst_pitch ), c[4], c[5], c[2]); |
#define PIXEL4_10_32 interp3((Uint32 *)(dst + dst_pitch ), c[5], c[2]); |
#define PIXEL4_10_50 interp5((Uint32 *)(dst + dst_pitch ), c[4], c[5]); |
#define PIXEL4_10_60 interp6((Uint32 *)(dst + dst_pitch ), c[5], c[4], c[2]); |
#define PIXEL4_10_61 interp6((Uint32 *)(dst + dst_pitch ), c[5], c[4], c[1]); |
#define PIXEL4_10_81 interp8((Uint32 *)(dst + dst_pitch ), c[5], c[4]); |
#define PIXEL4_10_83 interp8((Uint32 *)(dst + dst_pitch ), c[4], c[2]); |
#define PIXEL4_11_0 *(Uint32 *)(dst + dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL4_11_30 interp3((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[1]); |
#define PIXEL4_11_31 interp3((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[4]); |
#define PIXEL4_11_32 interp3((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[2]); |
#define PIXEL4_11_70 interp7((Uint32 *)(dst + dst_pitch + dst_Bpp), c[5], c[4], c[2]); |
#define PIXEL4_12_0 *(Uint32 *)(dst + dst_pitch + 2 * dst_Bpp) = c[5]; |
#define PIXEL4_12_30 interp3((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[3]); |
#define PIXEL4_12_31 interp3((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_12_32 interp3((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_12_70 interp7((Uint32 *)(dst + dst_pitch + 2 * dst_Bpp), c[5], c[6], c[2]); |
#define PIXEL4_13_0 *(Uint32 *)(dst + dst_pitch + 3 * dst_Bpp) = c[5]; |
#define PIXEL4_13_10 interp1((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[3]); |
#define PIXEL4_13_12 interp1((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_13_14 interp1((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[6], c[5]); |
#define PIXEL4_13_21 interp2((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[6], c[5], c[2]); |
#define PIXEL4_13_31 interp3((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[2]); |
#define PIXEL4_13_50 interp5((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[6], c[5]); |
#define PIXEL4_13_60 interp6((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[6], c[2]); |
#define PIXEL4_13_61 interp6((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[6], c[3]); |
#define PIXEL4_13_82 interp8((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_13_83 interp8((Uint32 *)(dst + dst_pitch + 3 * dst_Bpp), c[6], c[2]); |
#define PIXEL4_20_0 *(Uint32 *)(dst + 2 * dst_pitch) = c[5]; |
#define PIXEL4_20_10 interp1((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[7]); |
#define PIXEL4_20_12 interp1((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[4]); |
#define PIXEL4_20_14 interp1((Uint32 *)(dst + 2 * dst_pitch ), c[4], c[5]); |
#define PIXEL4_20_21 interp2((Uint32 *)(dst + 2 * dst_pitch ), c[4], c[5], c[8]); |
#define PIXEL4_20_31 interp3((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[8]); |
#define PIXEL4_20_50 interp5((Uint32 *)(dst + 2 * dst_pitch ), c[4], c[5]); |
#define PIXEL4_20_60 interp6((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[4], c[8]); |
#define PIXEL4_20_61 interp6((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[4], c[7]); |
#define PIXEL4_20_82 interp8((Uint32 *)(dst + 2 * dst_pitch ), c[5], c[4]); |
#define PIXEL4_20_83 interp8((Uint32 *)(dst + 2 * dst_pitch ), c[4], c[8]); |
#define PIXEL4_21_0 *(Uint32 *)(dst + 2 * dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL4_21_30 interp3((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[7]); |
#define PIXEL4_21_31 interp3((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL4_21_32 interp3((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[4]); |
#define PIXEL4_21_70 interp7((Uint32 *)(dst + 2 * dst_pitch + dst_Bpp), c[5], c[4], c[8]); |
#define PIXEL4_22_0 *(Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = c[5]; |
#define PIXEL4_22_30 interp3((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[9]); |
#define PIXEL4_22_31 interp3((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_22_32 interp3((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[8]); |
#define PIXEL4_22_70 interp7((Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL4_23_0 *(Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp) = c[5]; |
#define PIXEL4_23_10 interp1((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[9]); |
#define PIXEL4_23_11 interp1((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_23_13 interp1((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[6], c[5]); |
#define PIXEL4_23_21 interp2((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[6], c[5], c[8]); |
#define PIXEL4_23_32 interp3((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[8]); |
#define PIXEL4_23_50 interp5((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[6], c[5]); |
#define PIXEL4_23_60 interp6((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[6], c[8]); |
#define PIXEL4_23_61 interp6((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[6], c[9]); |
#define PIXEL4_23_81 interp8((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_23_83 interp8((Uint32 *)(dst + 2 * dst_pitch + 3 * dst_Bpp), c[6], c[8]); |
#define PIXEL4_30_0 *(Uint32 *)(dst + 3 * dst_pitch) = c[5]; |
#define PIXEL4_30_11 interp1((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[8]); |
#define PIXEL4_30_12 interp1((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[4]); |
#define PIXEL4_30_20 interp2((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[8], c[4]); |
#define PIXEL4_30_50 interp5((Uint32 *)(dst + 3 * dst_pitch ), c[8], c[4]); |
#define PIXEL4_30_80 interp8((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[7]); |
#define PIXEL4_30_81 interp8((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[8]); |
#define PIXEL4_30_82 interp8((Uint32 *)(dst + 3 * dst_pitch ), c[5], c[4]); |
#define PIXEL4_31_0 *(Uint32 *)(dst + 3 * dst_pitch + dst_Bpp) = c[5]; |
#define PIXEL4_31_10 interp1((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[7]); |
#define PIXEL4_31_11 interp1((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL4_31_13 interp1((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[8], c[5]); |
#define PIXEL4_31_21 interp2((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[8], c[5], c[4]); |
#define PIXEL4_31_32 interp3((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[4]); |
#define PIXEL4_31_50 interp5((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[8], c[5]); |
#define PIXEL4_31_60 interp6((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[8], c[4]); |
#define PIXEL4_31_61 interp6((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[8], c[7]); |
#define PIXEL4_31_81 interp8((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[5], c[8]); |
#define PIXEL4_31_83 interp8((Uint32 *)(dst + 3 * dst_pitch + dst_Bpp), c[8], c[4]); |
#define PIXEL4_32_0 *(Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp) = c[5]; |
#define PIXEL4_32_10 interp1((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[9]); |
#define PIXEL4_32_12 interp1((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[8]); |
#define PIXEL4_32_14 interp1((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[8], c[5]); |
#define PIXEL4_32_21 interp2((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[8], c[5], c[6]); |
#define PIXEL4_32_31 interp3((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_32_50 interp5((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[8], c[5]); |
#define PIXEL4_32_60 interp6((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[8], c[6]); |
#define PIXEL4_32_61 interp6((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[8], c[9]); |
#define PIXEL4_32_82 interp8((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[5], c[8]); |
#define PIXEL4_32_83 interp8((Uint32 *)(dst + 3 * dst_pitch + 2 * dst_Bpp), c[8], c[6]); |
#define PIXEL4_33_0 *(Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp) = c[5]; |
#define PIXEL4_33_11 interp1((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_33_12 interp1((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[8]); |
#define PIXEL4_33_20 interp2((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[8], c[6]); |
#define PIXEL4_33_50 interp5((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[8], c[6]); |
#define PIXEL4_33_80 interp8((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[9]); |
#define PIXEL4_33_81 interp8((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[6]); |
#define PIXEL4_33_82 interp8((Uint32 *)(dst + 3 * dst_pitch + 3 * dst_Bpp), c[5], c[8]); |
void hq4x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface ) |
{ |
Uint8 *src = src_surface->pixels, *src_temp, |
*dst = dst_surface->pixels, *dst_temp; |
int src_pitch = src_surface->pitch, |
dst_pitch = dst_surface->pitch; |
const int dst_Bpp = 4; // dst_surface->format->BytesPerPixel |
const int height = vga_height, // src_surface->h |
width = vga_width; // src_surface->w |
int prevline, nextline; |
Uint32 w[10]; |
Uint32 c[10]; |
// +----+----+----+ |
// | | | | |
// | w1 | w2 | w3 | |
// +----+----+----+ |
// | | | | |
// | w4 | w5 | w6 | |
// +----+----+----+ |
// | | | | |
// | w7 | w8 | w9 | |
// +----+----+----+ |
for (int j = 0; j < height; j++) |
{ |
src_temp = src; |
dst_temp = dst; |
prevline = (j > 0) ? -width : 0; |
nextline = (j < height - 1) ? width : 0; |
for (int i = 0; i < width; i++) |
{ |
w[2] = *(src + prevline); |
w[5] = *src; |
w[8] = *(src + nextline); |
if (i>0) |
{ |
w[1] = *(src + prevline - 1); |
w[4] = *(src - 1); |
w[7] = *(src + nextline - 1); |
} else { |
w[1] = w[2]; |
w[4] = w[5]; |
w[7] = w[8]; |
} |
if (i < width - 1) |
{ |
w[3] = *(src + prevline + 1); |
w[6] = *(src + 1); |
w[9] = *(src + nextline + 1); |
} else { |
w[3] = w[2]; |
w[6] = w[5]; |
w[9] = w[8]; |
} |
int pattern = 0; |
int flag = 1; |
YUV1 = yuv_palette[w[5]]; |
for (int k=1; k<=9; k++) |
{ |
if (k==5) continue; |
if ( w[k] != w[5] ) |
{ |
YUV2 = yuv_palette[w[k]]; |
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || |
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || |
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) |
pattern |= flag; |
} |
flag <<= 1; |
} |
for (int k=1; k<=9; k++) |
c[k] = rgb_palette[w[k]] & 0xfcfcfcfc; // hq4x has a nasty inability to accept more than 6 bits for each component |
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: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 2: |
case 34: |
case 130: |
case 162: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 16: |
case 17: |
case 48: |
case 49: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 64: |
case 65: |
case 68: |
case 69: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 8: |
case 12: |
case 136: |
case 140: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 3: |
case 35: |
case 131: |
case 163: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 6: |
case 38: |
case 134: |
case 166: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 20: |
case 21: |
case 52: |
case 53: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 144: |
case 145: |
case 176: |
case 177: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 192: |
case 193: |
case 196: |
case 197: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 96: |
case 97: |
case 100: |
case 101: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 40: |
case 44: |
case 168: |
case 172: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 9: |
case 13: |
case 137: |
case 141: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 18: |
case 50: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_12_0 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 80: |
case 81: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_61 |
PIXEL4_21_30 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 72: |
case 76: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_21_0 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 10: |
case 138: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
PIXEL4_11_0 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 66: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 24: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 7: |
case 39: |
case 135: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 148: |
case 149: |
case 180: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 224: |
case 228: |
case 225: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 41: |
case 169: |
case 45: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 22: |
case 54: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 208: |
case 209: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 104: |
case 108: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 11: |
case 139: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 19: |
case 51: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_00_12 |
PIXEL4_01_14 |
PIXEL4_02_83 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_21 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 146: |
case 178: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_23_32 |
PIXEL4_33_82 |
} |
else |
{ |
PIXEL4_02_21 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_83 |
PIXEL4_23_13 |
PIXEL4_33_11 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
break; |
} |
case 84: |
case 85: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_03_81 |
PIXEL4_13_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_03_12 |
PIXEL4_13_14 |
PIXEL4_22_70 |
PIXEL4_23_83 |
PIXEL4_32_21 |
PIXEL4_33_50 |
} |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 112: |
case 113: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_70 |
PIXEL4_23_21 |
PIXEL4_30_11 |
PIXEL4_31_13 |
PIXEL4_32_83 |
PIXEL4_33_50 |
} |
break; |
} |
case 200: |
case 204: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
} |
else |
{ |
PIXEL4_20_21 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_83 |
PIXEL4_32_14 |
PIXEL4_33_12 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
break; |
} |
case 73: |
case 77: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL4_00_82 |
PIXEL4_10_32 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_00_11 |
PIXEL4_10_13 |
PIXEL4_20_83 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_21 |
} |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 42: |
case 170: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_20_31 |
PIXEL4_30_81 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_21 |
PIXEL4_10_83 |
PIXEL4_11_70 |
PIXEL4_20_14 |
PIXEL4_30_12 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 14: |
case 142: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_83 |
PIXEL4_02_13 |
PIXEL4_03_11 |
PIXEL4_10_21 |
PIXEL4_11_70 |
} |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 67: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 70: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 28: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 152: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 194: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 98: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 56: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 25: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 26: |
case 31: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 82: |
case 214: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 88: |
case 248: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
break; |
} |
case 74: |
case 107: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_61 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 27: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 86: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 216: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 106: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 30: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 210: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 120: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 75: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 29: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 198: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 184: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 99: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 57: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 71: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 156: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 226: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 60: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 195: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 102: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 153: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 58: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 83: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_61 |
PIXEL4_21_30 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 92: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 202: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_61 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 78: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 154: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 114: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
PIXEL4_30_82 |
PIXEL4_31_32 |
break; |
} |
case 89: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 90: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 55: |
case 23: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_00_12 |
PIXEL4_01_14 |
PIXEL4_02_83 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_21 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 182: |
case 150: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_23_32 |
PIXEL4_33_82 |
} |
else |
{ |
PIXEL4_02_21 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_83 |
PIXEL4_23_13 |
PIXEL4_33_11 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
break; |
} |
case 213: |
case 212: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_03_81 |
PIXEL4_13_31 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_03_12 |
PIXEL4_13_14 |
PIXEL4_22_70 |
PIXEL4_23_83 |
PIXEL4_32_21 |
PIXEL4_33_50 |
} |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 241: |
case 240: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_22_70 |
PIXEL4_23_21 |
PIXEL4_30_11 |
PIXEL4_31_13 |
PIXEL4_32_83 |
PIXEL4_33_50 |
} |
break; |
} |
case 236: |
case 232: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_70 |
PIXEL4_13_60 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
PIXEL4_32_31 |
PIXEL4_33_81 |
} |
else |
{ |
PIXEL4_20_21 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_83 |
PIXEL4_32_14 |
PIXEL4_33_12 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
break; |
} |
case 109: |
case 105: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL4_00_82 |
PIXEL4_10_32 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_00_11 |
PIXEL4_10_13 |
PIXEL4_20_83 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_21 |
} |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 171: |
case 43: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_20_31 |
PIXEL4_30_81 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_21 |
PIXEL4_10_83 |
PIXEL4_11_70 |
PIXEL4_20_14 |
PIXEL4_30_12 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 143: |
case 15: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_0 |
PIXEL4_11_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_83 |
PIXEL4_02_13 |
PIXEL4_03_11 |
PIXEL4_10_21 |
PIXEL4_11_70 |
} |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 124: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 203: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 62: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 211: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 118: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 217: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 110: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 155: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 188: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 185: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 61: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 157: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 103: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 227: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 230: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 199: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 220: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
break; |
} |
case 158: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_12_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 234: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_61 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 242: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_82 |
PIXEL4_31_32 |
break; |
} |
case 59: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_11_0 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 121: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 87: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_0 |
PIXEL4_20_61 |
PIXEL4_21_30 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 79: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_11_0 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 122: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 94: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_12_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 218: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
break; |
} |
case 91: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_11_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 229: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 167: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 173: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 181: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 186: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 115: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
PIXEL4_30_82 |
PIXEL4_31_32 |
break; |
} |
case 93: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
break; |
} |
case 206: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 205: |
case 201: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
} |
else |
{ |
PIXEL4_20_12 |
PIXEL4_21_0 |
PIXEL4_30_20 |
PIXEL4_31_11 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 174: |
case 46: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_10_10 |
PIXEL4_11_30 |
} |
else |
{ |
PIXEL4_00_20 |
PIXEL4_01_12 |
PIXEL4_10_11 |
PIXEL4_11_0 |
} |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 179: |
case 147: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
} |
else |
{ |
PIXEL4_02_11 |
PIXEL4_03_20 |
PIXEL4_12_0 |
PIXEL4_13_12 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 117: |
case 116: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
} |
else |
{ |
PIXEL4_22_0 |
PIXEL4_23_11 |
PIXEL4_32_12 |
PIXEL4_33_20 |
} |
PIXEL4_30_82 |
PIXEL4_31_32 |
break; |
} |
case 189: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 231: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 126: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 219: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 125: |
{ |
if (diff(w[8], w[4])) |
{ |
PIXEL4_00_82 |
PIXEL4_10_32 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_00_11 |
PIXEL4_10_13 |
PIXEL4_20_83 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_21 |
} |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 221: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_03_81 |
PIXEL4_13_31 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_03_12 |
PIXEL4_13_14 |
PIXEL4_22_70 |
PIXEL4_23_83 |
PIXEL4_32_21 |
PIXEL4_33_50 |
} |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 207: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_0 |
PIXEL4_11_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_83 |
PIXEL4_02_13 |
PIXEL4_03_11 |
PIXEL4_10_21 |
PIXEL4_11_70 |
} |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_31 |
PIXEL4_23_81 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 238: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
PIXEL4_32_31 |
PIXEL4_33_81 |
} |
else |
{ |
PIXEL4_20_21 |
PIXEL4_21_70 |
PIXEL4_30_50 |
PIXEL4_31_83 |
PIXEL4_32_14 |
PIXEL4_33_12 |
} |
PIXEL4_22_31 |
PIXEL4_23_81 |
break; |
} |
case 190: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_23_32 |
PIXEL4_33_82 |
} |
else |
{ |
PIXEL4_02_21 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_83 |
PIXEL4_23_13 |
PIXEL4_33_11 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
break; |
} |
case 187: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_20_31 |
PIXEL4_30_81 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_21 |
PIXEL4_10_83 |
PIXEL4_11_70 |
PIXEL4_20_14 |
PIXEL4_30_12 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 243: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_82 |
PIXEL4_21_32 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_22_70 |
PIXEL4_23_21 |
PIXEL4_30_11 |
PIXEL4_31_13 |
PIXEL4_32_83 |
PIXEL4_33_50 |
} |
break; |
} |
case 119: |
{ |
if (diff(w[2], w[6])) |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_00_12 |
PIXEL4_01_14 |
PIXEL4_02_83 |
PIXEL4_03_50 |
PIXEL4_12_70 |
PIXEL4_13_21 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 237: |
case 233: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_60 |
PIXEL4_03_20 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_70 |
PIXEL4_13_60 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_31 |
PIXEL4_23_81 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 175: |
case 47: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_70 |
PIXEL4_23_60 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_60 |
PIXEL4_33_20 |
break; |
} |
case 183: |
case 151: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_60 |
PIXEL4_21_70 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_20 |
PIXEL4_31_60 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 245: |
case 244: |
{ |
PIXEL4_00_20 |
PIXEL4_01_60 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_60 |
PIXEL4_11_70 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 250: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
break; |
} |
case 123: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_10 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 95: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_80 |
PIXEL4_31_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 222: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 252: |
{ |
PIXEL4_00_80 |
PIXEL4_01_61 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_31 |
PIXEL4_13_31 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 249: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_61 |
PIXEL4_03_80 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
break; |
} |
case 235: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_61 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_31 |
PIXEL4_23_81 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 111: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_32 |
PIXEL4_13_82 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_61 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 63: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_61 |
PIXEL4_33_80 |
break; |
} |
case 159: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_80 |
PIXEL4_31_61 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 215: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_61 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 246: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_61 |
PIXEL4_11_30 |
PIXEL4_12_0 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 254: |
{ |
PIXEL4_00_80 |
PIXEL4_01_10 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_10 |
PIXEL4_11_30 |
PIXEL4_12_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 253: |
{ |
PIXEL4_00_82 |
PIXEL4_01_82 |
PIXEL4_02_81 |
PIXEL4_03_81 |
PIXEL4_10_32 |
PIXEL4_11_32 |
PIXEL4_12_31 |
PIXEL4_13_31 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_0 |
PIXEL4_23_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 251: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_10 |
PIXEL4_03_80 |
PIXEL4_11_0 |
PIXEL4_12_30 |
PIXEL4_13_10 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
break; |
} |
case 239: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
PIXEL4_02_32 |
PIXEL4_03_82 |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_32 |
PIXEL4_13_82 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_31 |
PIXEL4_23_81 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
PIXEL4_32_31 |
PIXEL4_33_81 |
break; |
} |
case 127: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_02_0 |
PIXEL4_03_0 |
PIXEL4_13_0 |
} |
else |
{ |
PIXEL4_02_50 |
PIXEL4_03_50 |
PIXEL4_13_50 |
} |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_20_0 |
PIXEL4_30_0 |
PIXEL4_31_0 |
} |
else |
{ |
PIXEL4_20_50 |
PIXEL4_30_50 |
PIXEL4_31_50 |
} |
PIXEL4_21_0 |
PIXEL4_22_30 |
PIXEL4_23_10 |
PIXEL4_32_10 |
PIXEL4_33_80 |
break; |
} |
case 191: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_31 |
PIXEL4_21_31 |
PIXEL4_22_32 |
PIXEL4_23_32 |
PIXEL4_30_81 |
PIXEL4_31_81 |
PIXEL4_32_82 |
PIXEL4_33_82 |
break; |
} |
case 223: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
PIXEL4_01_0 |
PIXEL4_10_0 |
} |
else |
{ |
PIXEL4_00_50 |
PIXEL4_01_50 |
PIXEL4_10_50 |
} |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_10 |
PIXEL4_21_30 |
PIXEL4_22_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_23_0 |
PIXEL4_32_0 |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_23_50 |
PIXEL4_32_50 |
PIXEL4_33_50 |
} |
PIXEL4_30_80 |
PIXEL4_31_10 |
break; |
} |
case 247: |
{ |
PIXEL4_00_81 |
PIXEL4_01_31 |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_10_81 |
PIXEL4_11_31 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_82 |
PIXEL4_21_32 |
PIXEL4_22_0 |
PIXEL4_23_0 |
PIXEL4_30_82 |
PIXEL4_31_32 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
case 255: |
{ |
if (diff(w[4], w[2])) |
{ |
PIXEL4_00_0 |
} |
else |
{ |
PIXEL4_00_20 |
} |
PIXEL4_01_0 |
PIXEL4_02_0 |
if (diff(w[2], w[6])) |
{ |
PIXEL4_03_0 |
} |
else |
{ |
PIXEL4_03_20 |
} |
PIXEL4_10_0 |
PIXEL4_11_0 |
PIXEL4_12_0 |
PIXEL4_13_0 |
PIXEL4_20_0 |
PIXEL4_21_0 |
PIXEL4_22_0 |
PIXEL4_23_0 |
if (diff(w[8], w[4])) |
{ |
PIXEL4_30_0 |
} |
else |
{ |
PIXEL4_30_20 |
} |
PIXEL4_31_0 |
PIXEL4_32_0 |
if (diff(w[6], w[8])) |
{ |
PIXEL4_33_0 |
} |
else |
{ |
PIXEL4_33_20 |
} |
break; |
} |
} |
src++; |
dst += 4 * dst_Bpp; |
} |
src = src_temp + src_pitch; |
dst = dst_temp + 4 * dst_pitch; |
} |
} |
// kate: tab-width 4; vim: set noet: |
/contrib/games/opentyrian/src/xmas.c |
---|
0,0 → 1,100 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#include "xmas.h" |
#include "font.h" |
#include "keyboard.h" |
#include "palette.h" |
#include "setup.h" |
#include "sprite.h" |
#include "video.h" |
#include <stdio.h> |
#include <time.h> |
bool xmas = false; |
bool xmas_time( void ) |
{ |
time_t now = time(NULL); |
return localtime(&now)->tm_mon == 11; |
} |
bool xmas_prompt( void ) |
{ |
const char *prompt[] = |
{ |
"Christmas has been detected.", |
"Activate Christmas?", |
}; |
const char *choice[] = |
{ |
"Yes", |
"No", |
}; |
set_palette(palettes[0], 0, 255); |
for (uint i = 0; i < COUNTOF(prompt); ++i) |
draw_font_hv(VGAScreen, 320 / 2, 85 + 15 * i, prompt[i], normal_font, centered, (i % 2) ? 2 : 4, -2); |
uint selection = 0; |
bool decided = false, quit = false; |
while (!decided) |
{ |
for (uint i = 0; i < COUNTOF(choice); ++i) |
draw_font_hv(VGAScreen, 320 / 2 - 20 + 40 * i, 120, choice[i], normal_font, centered, 15, (selection == i) ? -2 : -4); |
JE_showVGA(); |
JE_word temp = 0; |
JE_textMenuWait(&temp, false); |
if (newkey) |
{ |
switch (lastkey_sym) |
{ |
case SDLK_LEFT: |
if (selection == 0) |
selection = 2; |
selection--; |
break; |
case SDLK_RIGHT: |
selection++; |
selection %= 2; |
break; |
case SDLK_RETURN: |
decided = true; |
break; |
case SDLK_ESCAPE: |
decided = true; |
quit = true; |
break; |
default: |
break; |
} |
} |
} |
fade_black(10); |
return (selection == 0 && quit == false); |
} |
/contrib/games/opentyrian/src/xmas.h |
---|
0,0 → 1,30 |
/* |
* OpenTyrian: A modern cross-platform port of Tyrian |
* Copyright (C) 2007-2009 The OpenTyrian Development Team |
* |
* This program is free software; you can redistribute it and/or |
* modify it under the terms of the GNU General Public License |
* as published by the Free Software Foundation; either version 2 |
* of the License, or (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License |
* along with this program; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
*/ |
#ifndef XMAS_H |
#define XMAS_H |
#include <stdbool.h> |
extern bool xmas; |
bool xmas_time( void ); |
bool xmas_prompt( void ); |
#endif /* XMAS_H */ |