pax_global_header00006660000000000000000000000064134144026410014511gustar00rootroot0000000000000052 comment=04fccb288f012d69c14d7d10504125c7553b5a92 openjazz-20190106/000077500000000000000000000000001341440264100136155ustar00rootroot00000000000000openjazz-20190106/.gitattributes000066400000000000000000000001341341440264100165060ustar00rootroot00000000000000* text=auto *.txt text *.cpp text *.h text configure.ac text Makefile text Makefile.* text openjazz-20190106/.gitignore000066400000000000000000000005271341440264100156110ustar00rootroot00000000000000*.o openjazz OpenJazz openjazz.cfg *.exe # psp *.elf *.prx PARAM.SFO EBOOT.PBP # 3ds *.3dsx *.smdh *.d /build/ .DS_Store # autotools /build-aux/ .deps/ .dirstamp Makefile.in aclocal.m4 /autom4te.cache/ config.log config.status configure # distribution openjazz-*.tar.* OpenJazz-*.zip # generated documentation /doc/html /unix/OpenJazz.6 openjazz-20190106/Makefile000066400000000000000000000013731341440264100152610ustar00rootroot00000000000000# OpenJazz makefile include openjazz.mk # Sane defaults CXX ?= g++ CXXFLAGS ?= -g -Wall -O2 CXXFLAGS += -DSCALE # Network support CXXFLAGS += -DUSE_SOCKETS # Needed under Windows #LIBS += -lws2_32 # SDL CXXFLAGS += $(shell sdl-config --cflags) LIBS += $(shell sdl-config --libs) # music library: modplug, xmp MUSICLIB ?= modplug MUSICLIB_CFLAGS ?= $(shell pkg-config --silence-errors --cflags lib$(MUSICLIB)) MUSICLIB_LIBS ?= $(shell pkg-config --silence-errors --libs lib$(MUSICLIB)) ifneq ($(MUSICLIB_LIBS),) CXXFLAGS += -DUSE_$(MUSICLIB) $(MUSICLIB_CFLAGS) LIBS += $(MUSICLIB_LIBS) endif LIBS += -lm -lz OpenJazz: $(OBJS) $(CXX) -o OpenJazz $(LDFLAGS) $(OBJS) $(LIBS) %.o: %.cpp $(CXX) $(CXXFLAGS) -Isrc -c $< -o $@ clean: rm -f OpenJazz $(OBJS) openjazz-20190106/Makefile.3ds000066400000000000000000000172431341440264100157540ustar00rootroot00000000000000#--------------------------------------------------------------------------------- .SUFFIXES: #--------------------------------------------------------------------------------- ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif TOPDIR ?= $(CURDIR) include $(DEVKITARM)/3ds_rules #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed # SOURCES is a list of directories containing source code # DATA is a list of directories containing data files # INCLUDES is a list of directories containing header files # # NO_SMDH: if set to anything, no SMDH file is generated. # ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) # APP_TITLE is the name of the app stored in the SMDH file (Optional) # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) # ICON is the filename of the icon (.png), relative to the project folder. # If not set, it attempts to use one of the following (in this order): # - .png # - icon.png # - /default_icon.png #--------------------------------------------------------------------------------- TARGET := OpenJazz BUILD := build SOURCES := src src/game src/io src/io/gfx src/jj1bonuslevel \ src/jj1bonuslevel/jj1bonuslevelplayer src/jj1level \ src/jj1level/jj1event src/jj1level/jj1levelplayer src/jj1planet \ src/jj1scene src/jj2level src/jj2level/jj2event \ src/jj2level/jj2levelplayer src/level src/menu src/player DATA := data INCLUDES := src #ROMFS := romfs APP_TITLE := OpenJazz #APP_DESCRIPTION:= APP_AUTHOR := AlisterT & carstene1ns #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft CFLAGS := -g -Wall -O2 -mword-relocations \ -fomit-frame-pointer -ffunction-sections \ $(ARCH) CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DUSE_XMP -DDATAPATH=\"sdmc:/3ds/OJ/\" CXXFLAGS := $(CFLAGS) -frtti -fexceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LIBS := -lSDL -lxmp -lcitro3d -lctru -lz -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- LIBDIRS := $(CTRULIB) $(CURDIR)/deps #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional # rules for different file extensions #--------------------------------------------------------------------------------- ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- export OUTPUT := $(CURDIR)/$(TARGET) export TOPDIR := $(CURDIR) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- ifeq ($(strip $(CPPFILES)),) #--------------------------------------------------------------------------------- export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- export OFILES := $(addsuffix .o,$(BINFILES)) \ $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ -I$(CURDIR)/$(BUILD) export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) ifeq ($(strip $(ICON)),) icons := $(wildcard *.png) ifneq (,$(findstring $(TARGET).png,$(icons))) export APP_ICON := $(TOPDIR)/$(TARGET).png else ifneq (,$(findstring icon.png,$(icons))) export APP_ICON := $(TOPDIR)/icon.png endif endif else export APP_ICON := $(TOPDIR)/$(ICON) endif ifeq ($(strip $(NO_SMDH)),) export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh endif ifneq ($(ROMFS),) export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) endif .PHONY: $(BUILD) clean all #--------------------------------------------------------------------------------- all: $(BUILD) $(BUILD): @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.3ds #--------------------------------------------------------------------------------- clean: @echo clean ... @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf #--------------------------------------------------------------------------------- else DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- ifeq ($(strip $(NO_SMDH)),) $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh else $(OUTPUT).3dsx : $(OUTPUT).elf endif $(OUTPUT).elf : $(OFILES) #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- %.bin.o : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) #--------------------------------------------------------------------------------- # rules for assembling GPU shaders #--------------------------------------------------------------------------------- define shader-as $(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@))) picasso -o $(CURBIN) $1 bin2s $(CURBIN) | $(AS) -o $@ echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h endef %.shbin.o : %.v.pica %.g.pica @echo $(notdir $^) @$(call shader-as,$^) %.shbin.o : %.v.pica @echo $(notdir $<) @$(call shader-as,$<) %.shbin.o : %.shlist @echo $(notdir $<) @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file))) -include $(DEPENDS) #--------------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------------- openjazz-20190106/Makefile.am000066400000000000000000000070411341440264100156530ustar00rootroot00000000000000dist_pkgdata_DATA = openjazz.000 EXTRA_DIST = gpl.txt licenses.txt README.md desktopdir = $(datadir)/applications dist_desktop_DATA = unix/OpenJazz.desktop appicondir = $(datadir)/icons/hicolor/scalable/apps dist_appicon_DATA = unix/OpenJazz.svg appicon_fallbackdir = $(datadir)/icons/hicolor/48x48/apps dist_appicon_fallback_DATA = unix/OpenJazz.png bin_PROGRAMS = OpenJazz OpenJazz_CPPFLAGS = \ -DUSE_SOCKETS \ -DSCALE \ -I${srcdir}/src OpenJazz_CXXFLAGS = \ ${HOST_CFLAGS} \ ${SDL_CFLAGS} \ ${LIBMODPLUG_CFLAGS} \ ${LIBXMP_CFLAGS} \ ${ZLIB_CFLAGS} OpenJazz_LDADD = \ ${SDL_LIBS} \ ${LIBMODPLUG_LIBS} \ ${LIBXMP_LIBS} \ ${ZLIB_LIBS} \ ${NET_LIBS} \ ${HOST_LIBS} OpenJazz_SOURCES = \ src/game/clientgame.cpp \ src/game/game.cpp \ src/game/game.h \ src/game/gamemode.cpp \ src/game/gamemode.h \ src/game/localgame.cpp \ src/game/servergame.cpp \ src/io/controls.cpp \ src/io/controls.h \ src/io/file.cpp \ src/io/file.h \ src/io/gfx/anim.cpp \ src/io/gfx/anim.h \ src/io/gfx/font.cpp \ src/io/gfx/font.h \ src/io/gfx/paletteeffects.cpp \ src/io/gfx/paletteeffects.h \ src/io/gfx/scale2x/getopt.cpp \ src/io/gfx/scale2x/pixel.cpp \ src/io/gfx/scale2x/pixel.h \ src/io/gfx/scale2x/portable.h \ src/io/gfx/scale2x/scale2x.cpp \ src/io/gfx/scale2x/scale2x.h \ src/io/gfx/scale2x/scale3x.cpp \ src/io/gfx/scale2x/scale3x.h \ src/io/gfx/scale2x/scalebit.cpp \ src/io/gfx/scale2x/scalebit.h \ src/io/gfx/scale2x/simple2x.cpp \ src/io/gfx/sprite.cpp \ src/io/gfx/sprite.h \ src/io/gfx/video.cpp \ src/io/gfx/video.h \ src/io/network.cpp \ src/io/network.h \ src/io/sound.cpp \ src/io/sound.h \ src/jj1bonuslevel/jj1bonuslevel.cpp \ src/jj1bonuslevel/jj1bonuslevel.h \ src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.cpp \ src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.h \ src/jj1level/jj1bullet.cpp \ src/jj1level/jj1bullet.h \ src/jj1level/jj1demolevel.cpp \ src/jj1level/jj1event/jj1bridge.cpp \ src/jj1level/jj1event/jj1event.cpp \ src/jj1level/jj1event/jj1event.h \ src/jj1level/jj1event/jj1guardians.cpp \ src/jj1level/jj1event/jj1guardians.h \ src/jj1level/jj1event/jj1standardevent.cpp \ src/jj1level/jj1level.cpp \ src/jj1level/jj1levelframe.cpp \ src/jj1level/jj1level.h \ src/jj1level/jj1levelload.cpp \ src/jj1level/jj1levelplayer/jj1bird.cpp \ src/jj1level/jj1levelplayer/jj1bird.h \ src/jj1level/jj1levelplayer/jj1levelplayer.cpp \ src/jj1level/jj1levelplayer/jj1levelplayerframe.cpp \ src/jj1level/jj1levelplayer/jj1levelplayer.h \ src/jj1planet/jj1planet.cpp \ src/jj1planet/jj1planet.h \ src/jj1scene/jj1scene.cpp \ src/jj1scene/jj1scene.h \ src/jj1scene/jj1sceneload.cpp \ src/jj2level/jj2event/jj2event.cpp \ src/jj2level/jj2event/jj2eventframe.cpp \ src/jj2level/jj2event/jj2event.h \ src/jj2level/jj2layer.cpp \ src/jj2level/jj2level.cpp \ src/jj2level/jj2levelframe.cpp \ src/jj2level/jj2level.h \ src/jj2level/jj2levelload.cpp \ src/jj2level/jj2levelplayer/jj2levelplayer.cpp \ src/jj2level/jj2levelplayer/jj2levelplayerframe.cpp \ src/jj2level/jj2levelplayer/jj2levelplayer.h \ src/level/level.cpp \ src/level/level.h \ src/level/levelplayer.cpp \ src/level/levelplayer.h \ src/level/movable.cpp \ src/level/movable.h \ src/loop.h \ src/main.cpp \ src/menu/gamemenu.cpp \ src/menu/mainmenu.cpp \ src/menu/menu.cpp \ src/menu/menu.h \ src/menu/plasma.cpp \ src/menu/plasma.h \ src/menu/setupmenu.cpp \ src/OpenJazz.h \ src/platforms/wiz.cpp \ src/platforms/wiz.h \ src/player/player.cpp \ src/player/player.h \ src/setup.cpp \ src/setup.h \ src/util.cpp \ src/util.h openjazz-20190106/Makefile.psp000066400000000000000000000045011341440264100160560ustar00rootroot00000000000000# OpenJazz PSP Port Makefile TARGET = OpenJazz OBJS = \ src/game/clientgame.o src/game/game.o src/game/gamemode.o \ src/game/localgame.o src/game/servergame.o \ src/io/gfx/anim.o src/io/gfx/font.o src/io/gfx/paletteeffects.o \ src/io/gfx/sprite.o src/io/gfx/video.o \ src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \ src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.o \ src/jj1bonuslevel/jj1bonuslevel.o \ src/jj1level/jj1event/jj1bridge.o src/jj1level/jj1event/jj1event.o \ src/jj1level/jj1event/jj1guardians.o \ src/jj1level/jj1event/jj1standardevent.o \ src/jj1level/jj1levelplayer/jj1bird.o \ src/jj1level/jj1levelplayer/jj1levelplayer.o \ src/jj1level/jj1levelplayer/jj1levelplayerframe.o \ src/jj1level/jj1bullet.o src/jj1level/jj1demolevel.o \ src/jj1level/jj1level.o src/jj1level/jj1levelframe.o \ src/jj1level/jj1levelload.o \ src/jj1planet/jj1planet.o \ src/jj1scene/jj1scene.o src/jj1scene/jj1sceneload.o \ src/jj2level/jj2event/jj2event.o src/jj2level/jj2event/jj2eventframe.o \ src/jj2level/jj2levelplayer/jj2levelplayer.o \ src/jj2level/jj2levelplayer/jj2levelplayerframe.o \ src/jj2level/jj2layer.o src/jj2level/jj2level.o \ src/jj2level/jj2levelframe.o src/jj2level/jj2levelload.o \ src/level/level.o src/level/movable.o src/level/levelplayer.o \ src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \ src/menu/plasma.o src/menu/setupmenu.o \ src/player/player.o \ src/main.o src/setup.o src/util.o # src/io/gfx/scale2x/getopt.o src/io/gfx/scale2x/pixel.o \ # src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \ # src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \ PSPSDK=$(shell psp-config --pspsdk-path) PSPPREFIX=$(shell psp-config --psp-prefix) CFLAGS = -g -O2 -G0 -Wall -I$(PSPPREFIX)/include/SDL \ -Isrc -DPSP -DUSE_XMP LIBS = -lSDL -lxmp -lm -lz -lGL -lstdc++ \ -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm \ -lpspvfpu -lpsprtc -lpspaudio -lpsputility -lpspirkeyb -lpsppower BUILD_PRX = 1 #ENCRYPT = 1 #PSP_LARGE_MEMORY = 1 #PSP_FW_VERSION = 330 EXTRA_TARGETS = EBOOT.PBP PSP_EBOOT_TITLE = Jazz Jackrabbit (OpenJazz) #PSP_EBOOT_ICON = "psp_icon.png" # (144x80) #PSP_EBOOT_PIC1 = "psp_background.png" # (480x272) include $(PSPSDK)/lib/build.mak # silent building %.o: %.cpp @echo "[CXX] $<" @$(CXX) $(CXXFLAGS) -c $< -o $@ openjazz-20190106/README.md000066400000000000000000000073611341440264100151030ustar00rootroot00000000000000 # OpenJazz - http://www.alister.eu/jazz/oj/ ## About ### OpenJazz is a free, open-source version of the classic Jazz Jackrabbitт„Ђ games. OpenJazz can be compiled on a wide range of operating systems, including Windows, macOS, GNU/Linux and *BSD. Also ports are available for some homebrew platforms, for example Wii and PSP. To play, you will need the files from one of the original games. With the demise of DOS-based operating systems, it has become necessary to use emulators to play old DOS games. Jazz Jackrabbitт„Ђ deserves more - and would benefit greatly from new features. ### Jazz Jackrabbitт„Ђ is a PC platform game. Produced by Epic Games (then Epic MegaGames), it was first released in 1994. The fast-paced, colourful gameplay proved popular, and the game won PC Format's Arcade Game of the Year award. Many people still fondly recall the shareware versions. ## History OpenJazz was started on the 23rd of August, 2005, by Alister Thomson. Academic pressures put the project on hold until late December 2005. The source code was released on the 25th, and the first version with a degree of playability was released on the 15th of January. Since then, a variety of ports have been released by other people. More academic pressures meant there were few updates over the following few years, but in 2009 a multiplayer version was released. ## License OpenJazz is available under the GNU General Public License version 2 or later, see `licenses.txt` for additional information. ## Controls `Enter` to choose a menu option, `Escape` to go back to the previous menu. `F9` to view in-game statistics, `P` to pause. `Alt` + `Enter` switches between full-screen and windowed mode. The other controls are configurable via the "setup options" menu. By default, the controls are as follows: - Left and right arrow keys to move left and right. - Under Windows, `Alt Gr (right Alt)` to jump and the `Space bar` to shoot. - Under Linux, the `Space bar` to jump and `left Alt` to shoot. - `Right Ctrl` to change weapon. Additionally, most game controllers and joysticks that SDL recognizes can be used. However, not all axes or buttons may be available. ## Building Needed: - SDL 1.2.x library (https://libsdl.org/). Optional: - SDL_net 1.2.x library (https://www.libsdl.org/projects/SDL_net/) - xmp 4.x.x library (http://xmp.sourceforge.net/) - ModPlug library (http://modplug-xmms.sourceforge.net/) OpenJazz ships a basic Makefile that may be used and adapted to the specific needs of the user or platform where it shall run. For network play, you need a platform which natively provides sockets or use SDL_net, then either define `USE_SOCKETS` or `USE_SDL_NET` in the Makefile. On the Windows platform, the socket library (`-lws2_32`) is needed while linking. For music support, you either need ModPlug or xmp. Then define `USE_MODPLUG` or `USE_XMP` in the Makefile. ModPlug needs to be patched to properly support looping tracks, otherwise there will be a small gap in the playback, xmp does not have this problem (no patching needed). For UNIX systems also an autoconf script is provided, used like this: ./configure # `--help` lists options make [install] Further (partly outdated) instructions are available at: http://www.alister.eu/jazz/oj/build.php ### other options - `DATAPATH` - use a fixed path for data files - `HOMEDIR` - use the user's home directory for data files - `SCALE` - enable scaling of the video output (i.e. Scale2X...) - `FULLSCREEN_ONLY` - disable window mode, useful for console ports ## Running Execute `OpenJazz`, depending on the platform and compile time options, the data files are expected to be under different paths (see above). You can also specifiy a game folder as command line argument. ## Author Alister Thomson (alister_j_t at yahoo dot com) openjazz-20190106/configure.ac000066400000000000000000000031101341440264100160760ustar00rootroot00000000000000AC_INIT([openjazz], [0], [https://github.com/AlisterT/openjazz/issues], [openjazz], [http://www.alister.eu/jazz/oj/]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects tar-pax no-dist-gzip dist-xz]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CANONICAL_HOST AC_PROG_CXX AC_PROG_CXXCPP PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([SDL], [sdl]) PKG_CHECK_MODULES([LIBXMP], [libxmp], [AC_DEFINE(USE_XMP, [1], [Enable XMP Music])], [ PKG_CHECK_MODULES([LIBMODPLUG], [libmodplug], [AC_DEFINE(USE_MODPLUG, [1], [Enable ModPlug Music])], [ AC_MSG_WARN([No music library found. OpenJazz will run, but music will be silent.]) ]) ]) PKG_CHECK_MODULES([ZLIB], [zlib]) AS_CASE([$host], [*-*-mingw*], [NET_LIBS="-lws2_32" OJ_HOST="MinGW (Windows)"], [*-haiku*], [HOST_CFLAGS="-D_BSD_SOURCE" HOST_LIBS="-lbe" NET_LIBS="-lnetwork" OJ_HOST="Haiku"], [arm-none-linux-gnueabi], [HOST_CFLAGS="-DPANDORA -fsigned-char" HOST_LIBS="-lts" OJ_HOST="Pandora"], [arm-gph-linux-gnueabi], [HOST_CFLAGS="-DCAANOO -fsigned-char" OJ_HOST="GP2X Caanoo"], [arm-openwiz-linux-gnu], [HOST_CFLAGS="-DWIZ -fsigned-char" OJ_HOST="GP2X Wiz"], [arm-open2x-linux], [HOST_CFLAGS="-DGP2X -fsigned-char" OJ_HOST="GP2X"], [mipsel-linux*], [HOST_CFLAGS="-DDINGOO" OJ_HOST="Dingoo"], [armv7l-unknown-linux-gnueabihf], [HOST_CFLAGS="-DGAMESHELL" OJ_HOST="GameShell"]) AC_SUBST(HOST_CFLAGS) AC_SUBST(HOST_LIBS) AC_SUBST(NET_LIBS) AC_CONFIG_FILES([Makefile]) AC_OUTPUT AS_IF([test "x$OJ_HOST" != "x"],[ echo "" echo "Detected Platform: $OJ_HOST. If this is wrong, please open a bug report!" echo "" ]) openjazz-20190106/doc/000077500000000000000000000000001341440264100143625ustar00rootroot00000000000000openjazz-20190106/doc/Doxyfile000066400000000000000000000264271341440264100161030ustar00rootroot00000000000000# Doxyfile 1.8.14 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = OpenJazz PROJECT_NUMBER = PROJECT_BRIEF = "Open Source Jazz Jackrabbit Engine" PROJECT_LOGO = OpenJazz.png OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES TOC_INCLUDE_HEADINGS = 0 AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO GROUP_NESTED_COMPOUNDS = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_PACKAGE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_AS_ERROR = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ../src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.cpp *.h RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 110 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 200 HTML_TIMESTAMP = YES HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = YES HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO EXTERNAL_SEARCH = NO SEARCHENGINE_URL = SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = LATEX_EXTRA_STYLESHEET = LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = RTF_SOURCE_CODE = NO #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = MAN_LINKS = NO #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration options related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = svg INTERACTIVE_SVG = YES DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = PLANTUML_JAR_PATH = PLANTUML_CFG_FILE = PLANTUML_INCLUDE_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES openjazz-20190106/doc/OpenJazz.png000066400000000000000000000023311341440264100166270ustar00rootroot00000000000000‰PNG  IHDRP7›рЭO IDATxкэлxФXрYœmлЖmлЖmлЖmлЖmеЖл8sѓщЌ—Mv“^ч}нХ,Т‡б•БŒ…РфВОœ%Ъ{R%mв.uђ‰<)—ШŽ2ГфP‘№щ1№aЅM&ћШkb ђЕœ$s–ЙР7…~ˆГИх ЦФ—GeщQ[  хL&$ћd–QU хGa™єЩ^’Ыtrr”ИТ И[&ЬdŠrƒАТо“Љ3U ‚м+L‰ЏdкLH 'з Sц#™8 !LЉG$—к ,/Ў0ХOe&я„)gЩ|i,№TaЉќсЗї‹рМї0lБПМNл‘pƒiрЧTтЫЉ*Рt2$ŒЊ§P8ї|{% јзcЭxїП Лs?81”Иaš МH…ЕќЛ>„5E€ќocf§эяРr–+щљЎф*^ ‰ЅGhЊk8{vУЃ;ріюyЁЪri(pWЁЉю}сn2,mlлЏЇШ%оš†Ÿšp–П_'\0žqx+oюH/чN)VЌ@EYx<є6l0оёЬKА 0‚5*YрЪB=ЛТеGw К№7‡ЁР“+YрБBOНLfМј Ќ>ZЩo5Й”0p‡>ИIxX[Є…IU% |бфR6‡3Nˆ0Љ' и‹Т‰Аi7NЅ ќифRъЯ€ &;š7.а—)+Uр7&—ђѕХNКРЮЦp„ъ2Qрw$_`е™™)аќ%ЌН,Nвvь;K/aЃ…ˆНМй|I•ЗЄ/˜~–"З Mœмм‚фТЊHЛЙЊ2Е"§СНЩНŒПИ>s+вц›rю‚№З€wy{єРѕgGЕMЙH;>ПV>ЦђŠ!Тя.Ж3!@!ЪЮ„w„Оuw рэУŽЋРп†ХœyyCX›Ѓkv‡UBoџSЛMљѓ!ИтћвKМс+иСЌ‘^КќЗрކхM/žаРc‰ьвfC№Р[)F(nМ|ќXсд а\žЧЃž_—œAЇ ]l~PЩ@ѕyАmћяKчcšсдŸЛ”ыЌУ Ьџк§^џБМ…eHhhлФk†#Ќ:іНРоЕ і4!ТAсtТ=;`=№.ьк3`…уƒDi.ТЗП§ж‘џЅМ%ЄQhШ“iёo!pŠ0.ю,pv@0АwF8q^і8‡љПx хIYMЦ‡А Ыeb #xЪ=Еу{ašЙ˜—ћ у_џLкdXXЂ] Œš“‹ТkхМК:ЪЈ8НэK\Щq–ѓ*ї€AR}‚e#ŽсrАЫy•oHIэ)О­8˜aАœWй-sТ Љ=Щ<Ф„яoŒСŸЪx•ŽЌ ƒЄyšУ]2!РйЅF˜0WЖA24б†3ЩЧТ„єЪ0HЇzqBЙFaŒо—y`žЌN6ф*ђЁАDmražЌOweN6ЇФ6Y.Щ—rLœІ зќЭ„ыŽ?LИО4ў зœRЖ•+хEљVZЅ]ЊфmЙC‘Й%‡џkЦ2–Бќ њеѓЌuЮэчIENDЎB`‚openjazz-20190106/gpl.txt000066400000000000000000000432541341440264100151500ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. openjazz-20190106/licenses.txt000066400000000000000000000112101341440264100161560ustar00rootroot00000000000000================================================================================ OpenJazz ================================================================================ The OpenJazz source code is available from http://alister.eu/jazz/oj/ and the code repository lives at https://github.com/AlisterT/openjazz Copyright (c) 2005-2018 Alister Thomson Menu plasma effect Copyright (c) 2010 Alireza Nejati This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You 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 St, Fifth Floor, Boston, MA 02110-1301 USA ================================================================================ libmodplug ================================================================================ ModPlug-XMMS and libmodplug are now in the public domain. ================================================================================ libxmp ================================================================================ 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 ================================================================================ Scale2x ================================================================================ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ================================================================================ SDL ================================================================================ The Simple DirectMedia Layer (SDL for short) is a cross-platfrom library designed to make it easy to write multi-media software, such as games and emulators. The Simple DirectMedia Layer library source code is available from: http://www.libsdl.org/ This library is distributed under the terms of the GNU LGPL license: http://www.gnu.org/copyleft/lesser.html ================================================================================ zlib ================================================================================ Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler openjazz-20190106/openjazz.000000066400000000000000000000015611341440264100157010ustar00rootroot00000000000000oPќ…§EP/™вŠж‹§ў‹WўE/–в‰ижŠPў‘W§•в‰ижˆў•W§/“в‰и懧˜Wў‘в‰иж†/ў›WEв‰иж…ўWEв‰иж„/ўŸWќв‰ижƒўЁWŽв‰ижƒPЂWўв‰иж/ўŒWў]ˆ…‰^XW§в‰иж§ŒWd‰‡Ž\ўŒW/Œв‰иж/ŒW\‹‰X‹W§‹в‰ижE‹W\ސ‰XŠWў/‹в‰ижўŠW\‰‹WP‹в‰ижŠWX‘ˆŠW§‹в‰ижPŠWˆ’X‰WўŠв‰ижќ‰Wў‰“^ŠWŠв‰и槉WX“ˆŠW/Šв‰и槉WXŽ“‰ŠWŠв‰и槉WXŽ“‰ŠWŠв‰и槉WX“ˆŠW/Šв‰ижќŠW‰’_ŠWŠв‰ижPŠW\’X‰WўŠв‰ижŠWўŽ‘\ŠW§‹в‰ижўŠW_Ž‰‹W;ж‰в‰ижE‹W^‰XŠWўзи‰ж‰ижŒW^‹‰ў‹WvиивˆŠивќŒWX‰Ž†^Wзƒив†жŠив/ўWX^ˆƒ‰\]ўWv…ивƒжŠижƒЂWўз‡ижжив„§ЁWг—и…§ŸW;—ив‡ўW;—ижˆ§›WEж–ижŠE˜Wў/ж”ижŒ§”WўEƒж’иж§WўE†вжŽижв’/E§ў‰Wў§ŠвжŠижв—/P„EP/Žвв„жвв‹openjazz-20190106/openjazz.mk000066400000000000000000000031101341440264100160010ustar00rootroot00000000000000 OBJS = \ src/game/clientgame.o src/game/game.o src/game/gamemode.o \ src/game/localgame.o src/game/servergame.o \ src/io/gfx/anim.o src/io/gfx/font.o src/io/gfx/paletteeffects.o \ src/io/gfx/sprite.o src/io/gfx/video.o \ src/io/gfx/scale2x/getopt.o src/io/gfx/scale2x/pixel.o \ src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \ src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \ src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \ src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.o \ src/jj1bonuslevel/jj1bonuslevel.o \ src/jj1level/jj1event/jj1bridge.o src/jj1level/jj1event/jj1event.o \ src/jj1level/jj1event/jj1guardians.o \ src/jj1level/jj1event/jj1standardevent.o \ src/jj1level/jj1levelplayer/jj1bird.o \ src/jj1level/jj1levelplayer/jj1levelplayer.o \ src/jj1level/jj1levelplayer/jj1levelplayerframe.o \ src/jj1level/jj1bullet.o src/jj1level/jj1demolevel.o \ src/jj1level/jj1level.o src/jj1level/jj1levelframe.o \ src/jj1level/jj1levelload.o \ src/jj1planet/jj1planet.o \ src/jj1scene/jj1scene.o src/jj1scene/jj1sceneload.o \ src/jj2level/jj2event/jj2event.o src/jj2level/jj2event/jj2eventframe.o \ src/jj2level/jj2levelplayer/jj2levelplayer.o \ src/jj2level/jj2levelplayer/jj2levelplayerframe.o \ src/jj2level/jj2layer.o src/jj2level/jj2level.o \ src/jj2level/jj2levelframe.o src/jj2level/jj2levelload.o \ src/level/level.o src/level/movable.o src/level/levelplayer.o \ src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \ src/menu/plasma.o src/menu/setupmenu.o \ src/player/player.o \ src/main.o src/setup.o src/util.o openjazz-20190106/src/000077500000000000000000000000001341440264100144045ustar00rootroot00000000000000openjazz-20190106/src/OpenJazz.h000066400000000000000000000052551341440264100163240ustar00rootroot00000000000000 /** * * @file OpenJazz.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 3rd February 2009: Created menu.h from parts of OpenJazz.h * - 3rd February 2009: Created file.h from parts of OpenJazz.h * - 3rd February 2009: Created font.h from parts of OpenJazz.h * - 4th February 2009: Created palette.h from parts of OpenJazz.h * - 2nd March 2009: Created network.h from parts of OpenJazz.h * - 2nd June 2009: Created sound.h from parts of OpenJazz.h * - 3rd June 2009: Created network.h from parts of OpenJazz.h * - 13th July 2009: Created controls.h from parts of OpenJazz.h * - 13th July 2009: Created graphics.h from parts of OpenJazz.h * - 30th April 2010: Created util.h from parts of OpenJazz.h * - 30th April 2010: Created loop.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _OPENJAZZ_H #define _OPENJAZZ_H #ifndef EXTERN #define EXTERN extern #endif // Constants // Numbers in -10 exponent fixed point #define FE 128 #define FQ 256 #define FH 512 #define F1 1024 #define F2 2048 #define F4 4096 #define F8 8192 #define F10 10240 #define F12 12288 #define F16 16384 #define F20 20480 #define F24 24576 #define F32 32768 #define F36 36864 #define F40 40960 #define F80 81920 #define F64 65536 #define F100 102400 #define F160 163840 #define F192 196608 // Standard string length #define STRING_LENGTH 32 // Return values #define E_N_OTHER -(0x26) #define E_N_DISCONNECT -(0x25) #define E_N_CONNECT -(0x24) #define E_N_ADDRESS -(0x23) #define E_N_LISTEN -(0x22) #define E_N_BIND -(0x21) #define E_N_SOCKET -(0x20) #define E_DATA -(0x15) #define E_VERSION -(0x14) #define E_TIMEOUT -(0x13) #define E_DEMOTYPE -(0x12) #define E_FILE -(0x11) #define E_VIDEO -(0x10) #define E_RETURN -(0x02) #define E_QUIT -(0x01) #define E_NONE 0 // Macros // For fixed-point operations #define FTOI(x) ((x) >> 10) ///< Fixed to Int #define ITOF(x) ((x) << 10) ///< Int to Fixed #define MUL(x, y) (((x) * (y)) >> 10) ///< multiplication #define DIV(x, y) (((x) << 10) / (y)) ///< division // Datatype typedef int fixed; ///< Custom fixed-point data type #endif openjazz-20190106/src/game/000077500000000000000000000000001341440264100153155ustar00rootroot00000000000000openjazz-20190106/src/game/clientgame.cpp000066400000000000000000000234341341440264100201370ustar00rootroot00000000000000 /** * * @file clientgame.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 18th July 2009: Created clientgame.cpp from parts of game.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "game.h" #include "gamemode.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/network.h" #include "player/player.h" #include "loop.h" #include "setup.h" #include "util.h" #include /** * Create game client * * @param address Address of the server to which to connect */ ClientGame::ClientGame (char* address) { unsigned char buffer[BUFFER_LENGTH]; unsigned int timeout; int count, ret; GameModeType modeType; sock = net->join(address); if (sock < 0) throw sock; // Tee hee hee hee hee. // Receive initialisation message count = 0; timeout = globalTicks + T_SCHECK + T_TIMEOUT; // Wait for whole message to arrive while (count < MTL_G_PROPS) { if (loop(NORMAL_LOOP) == E_QUIT) { net->close(sock); throw E_QUIT; } if (controls.release(C_ESCAPE)) { net->close(sock); throw E_RETURN; } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); fontmn2->showString("WAITING FOR REPLY", canvasW >> 2, (canvasH >> 1) - 16); ret = net->recv(sock, buffer + count, MTL_G_PROPS - count); if (ret > 0) count += ret; if (globalTicks > timeout) { net->close(sock); throw E_TIMEOUT; } } // Make sure message is valid if (buffer[1] != MT_G_PROPS) { net->close(sock); throw E_DATA; } else if (buffer[2] != 1) { net->close(sock); throw E_VERSION; } printf("Connected to server (version %d).\n", buffer[2]); // Copy game parameters modeType = GameModeType(buffer[3]); difficulty = buffer[4]; maxPlayers = buffer[5]; nPlayers = buffer[6]; clientID = buffer[7]; printf("Game mode %d, difficulty %d, %d of %d players.\n", modeType, difficulty, nPlayers, maxPlayers); if (nPlayers > maxPlayers) { net->close(sock); throw E_DATA; } mode = createMode(modeType); if (!mode) { net->close(sock); throw E_DATA; } // Create players nPlayers = 0; players = new Player[maxPlayers]; // Download the level from the server levelFile = createString(LEVEL_FILE); file = NULL; ret = setLevel(NULL); if (ret < 0) { net->close(sock); if (file) delete file; delete mode; throw ret; } // Add a new player to the game buffer[0] = MTL_G_PJOIN + strlen(setup.characterName); buffer[1] = MT_G_PJOIN; buffer[2] = clientID; buffer[3] = 0; // Player's number, assigned by the server buffer[4] = 0; // Player's team, assigned by the server memcpy(buffer + 5, setup.characterCols, 4); memcpy(buffer + 9, setup.characterName, strlen(setup.characterName) + 1); send(buffer); // Wait for acknowledgement localPlayer = NULL; while (!localPlayer) { if (loop(NORMAL_LOOP) == E_QUIT) { net->close(sock); if (file) delete file; delete mode; throw E_QUIT; } if (controls.release(C_ESCAPE)) { net->close(sock); if (file) delete file; delete mode; throw E_RETURN; } video.clearScreen(0); fontmn2->showString("JOINING GAME", canvasW >> 2, (canvasH >> 1) - 16); ret = step(0); if (ret < 0) { net->close(sock); if (file) delete file; delete mode; throw ret; } } return; } /** * Disconnect and destroy client */ ClientGame::~ClientGame () { net->close(sock); if (file) delete file; delete mode; return; } /** * Set the next level and receive level data from server * * @param fileName The file name of the next level * * @return Error code */ int ClientGame::setLevel (char* fileName) { (void)fileName; int ret; video.setPalette(menuPalette); // Wait for level data to start arriving while (!file && levelFile) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_RETURN; SDL_Delay(T_MENU_FRAME); video.clearScreen(0); fontmn2->showString("WAITING FOR SERVER", canvasW >> 2, (canvasH >> 1) - 16); ret = step(0); if (ret < 0) return ret; } // Wait for level data to finish arriving while (file && levelFile) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_RETURN; SDL_Delay(T_MENU_FRAME); video.clearScreen(0); fontmn2->showString("downloaded", canvasW >> 2, (canvasH >> 1) - 16); fontmn2->showNumber(file->tell(), (canvasW >> 2) + 56, canvasH >> 1); fontmn2->showString("bytes", (canvasW >> 2) + 64, canvasH >> 1); ret = step(0); if (ret < 0) return ret; } return E_NONE; } /** * Send data to server * * @param buffer Data to send. First byte indicates length. */ void ClientGame::send (unsigned char* buffer) { net->send(sock, buffer); return; } /** * Game iteration * * @param ticks Current time * * @return Error code */ int ClientGame::step (unsigned int ticks) { unsigned char sendBuffer[BUFFER_LENGTH]; int length, count; bool firstMessage; // Receive data from server if (received == 0) { // Not currently receiving a message // See if there is a new message to receive length = net->recv(sock, recvBuffer, 1); if (length > 0) received++; } if (received > 0) { // Currently receiving a message // See if there is any more data length = net->recv(sock, recvBuffer + received, recvBuffer[0] - received); if (length > 0) received += length; // See if the whole message has arrived if (received >= recvBuffer[0]) { switch (recvBuffer[1] & MCMASK) { case MC_GAME: if (recvBuffer[1] == MT_G_LEVEL) { if (!file) { // Not already storing level data, so open the file try { file = new File(levelFile, true); } catch (int e) { return e; } firstMessage = true; } else firstMessage = false; file->seek((recvBuffer[2] << 8) + recvBuffer[3], true); for (count = 4; count < recvBuffer[0]; count++) file->storeChar(recvBuffer[count]); // If a zero-length block has been sent, it is the last if (recvBuffer[0] == MTL_G_LEVEL) { if (firstMessage) { // If the last message was also the first, // then the run of levels has ended delete[] levelFile; levelFile = NULL; } delete file; file = NULL; } break; } if ((recvBuffer[1] == MT_G_PJOIN) && (recvBuffer[3] < maxPlayers)) { printf("Player %d joined the game.\n", recvBuffer[3]); // Add the new player, and any that have been missed for (count = nPlayers; count <= recvBuffer[3]; count++) { players[count].init(this, (char *)recvBuffer + 9, recvBuffer + 5, recvBuffer[4]); addLevelPlayer(players + count); printf("Player %d joined team %d.\n", count, recvBuffer[4]); } nPlayers = count; if (recvBuffer[2] == clientID) localPlayer = players + recvBuffer[3]; } if ((recvBuffer[1] == MT_G_PQUIT) && (recvBuffer[2] < nPlayers)) { printf("Player %d left the game.\n", recvBuffer[2]); // Remove the player players[recvBuffer[2]].deinit(); // If necessary, move more recent players for (count = recvBuffer[2]; count < nPlayers; count++) memcpy(players + count, players + count + 1, sizeof(Player)); // Clear duplicate pointers memset(players + nPlayers, 0, sizeof(Player)); } if (recvBuffer[1] == MT_G_CHECK) { checkX = recvBuffer[2]; checkY = recvBuffer[3]; if (recvBuffer[0] > 4) { checkX += recvBuffer[4] << 8; checkY += recvBuffer[5] << 8; } } if (recvBuffer[1] == MT_G_SCORE) { for (count = 0; count < nPlayers; count++) { if (players[count].getTeam() == recvBuffer[2]) players[count].teamScore++; } } if (recvBuffer[1] == MT_G_LTYPE) { levelType = (LevelType)recvBuffer[2]; } break; case MC_LEVEL: if (baseLevel) baseLevel->receive(recvBuffer); break; case MC_PLAYER: if (recvBuffer[2] < maxPlayers) players[recvBuffer[2]].receive(recvBuffer); break; } received = 0; } } if (ticks >= checkTime) { // Check for disconnection if (!(net->isConnected(sock))) { if (file) delete file; file = NULL; return E_N_DISCONNECT; } checkTime = ticks + T_CCHECK; } if (localPlayer && (ticks >= sendTime)) { // Update server sendBuffer[0] = MTL_P_TEMP; sendBuffer[1] = MT_P_TEMP; sendBuffer[2] = 0; localPlayer->send(sendBuffer); send(sendBuffer); sendTime = ticks + T_CSEND; } return E_NONE; } /** * Ask server to award team a point * * @param team Team to receive point */ void ClientGame::score (unsigned char team) { unsigned char buffer[MTL_G_SCORE]; // Inform server buffer[0] = MTL_G_SCORE; buffer[1] = MT_G_SCORE; buffer[2] = team; send(buffer); return; } /** * Ask server to approve new checkpoint * * @param gridX X-coordinate (in tiles) of the checkpoint * @param gridY Y-coordinate (in tiles) of the checkpoint */ void ClientGame::setCheckpoint (int gridX, int gridY) { unsigned char buffer[MTL_G_CHECK]; buffer[0] = MTL_G_CHECK; buffer[1] = MT_G_CHECK; buffer[2] = gridX & 0xFF; buffer[3] = gridY & 0xFF; buffer[4] = (gridX >> 8) & 0xFF; buffer[5] = (gridY >> 8) & 0xFF; send(buffer); return; } openjazz-20190106/src/game/game.cpp000066400000000000000000000163161341440264100167410ustar00rootroot00000000000000 /** * * @file game.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 3rd June 2009: Created network.cpp from parts of game.cpp * - 18th July 2009: Created servergame.cpp from parts of game.cpp * - 18th July 2009: Created clientgame.cpp from parts of game.cpp * - 3rd October 2010: Created localgame.cpp from parts of game.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "game.h" #include "gamemode.h" #include "io/gfx/video.h" #include "io/sound.h" #include "jj1bonuslevel/jj1bonuslevel.h" #include "jj1level/jj1level.h" #include "jj1planet/jj1planet.h" #include "jj2level/jj2level.h" #include "player/player.h" #include "util.h" #include /** * Create base game */ Game::Game () { levelFile = NULL; levelType = LT_JJ1; players = NULL; baseLevel = NULL; return; } /** * Destroy game */ Game::~Game () { if (levelFile) delete[] levelFile; if (players) delete[] players; localPlayer = NULL; return; } /** * Check the if a file name corresponds to a type * * @param fileName The name of the file * @param type The type identifier in lower case characters * @param typeLength The length of the type identifier string * * @return Whether or not the file name corresponds to the type */ bool Game::isFileType (const char *fileName, const char *type, int typeLength) { int i; for (i = 0; i < typeLength; i++) { if ((fileName[i] != type[i]) && (fileName[i] != type[i] - 32)) return false; } return true; } /** * Create a new game mode * * @param modeType The mode to create * * @return The new game mode (NULL on failure) */ GameMode* Game::createMode (GameModeType modeType) { switch (modeType) { case M_SINGLE: return new SingleGameMode(); case M_COOP: return new CoopGameMode(); case M_BATTLE: return new BattleGameMode(); case M_TEAMBATTLE: return new TeamBattleGameMode(); case M_RACE: return new RaceGameMode(); } return NULL; } /** * Get the game's mode * * @return The game's mode */ GameMode* Game::getMode () { return mode; } /** * Get the game's difficulty * * @return The game's difficulty */ int Game::getDifficulty () { return difficulty; } /** * Set the game's difficulty */ void Game::setDifficulty (int diff) { difficulty = diff; return; } /** * Play a level. * * @return Error code */ int Game::playLevel (char* fileName, bool intro, bool checkpoint) { bool multiplayer; int ret; multiplayer = (mode->getMode() != M_SINGLE); if (isFileType(fileName, "macro", 5)) { // Load and play the level try { baseLevel = level = new JJ1DemoLevel(this, fileName); } catch (int e) { return e; } ret = level->play(); delete level; baseLevel = level = NULL; } else if (levelType == LT_JJ1BONUS) { JJ1BonusLevel *bonus; try { baseLevel = bonus = new JJ1BonusLevel(this, fileName, multiplayer); } catch (int e) { return e; } ret = bonus->play(); delete bonus; baseLevel = NULL; } else if (levelType == LT_JJ2) { try { baseLevel = jj2Level = new JJ2Level(this, fileName, checkpoint, multiplayer); } catch (int e) { return e; } ret = jj2Level->play(); delete jj2Level; baseLevel = jj2Level = NULL; } else { try { baseLevel = level = new JJ1Level(this, fileName, checkpoint, multiplayer); } catch (int e) { return e; } if (intro) { JJ1Planet *planet; char *planetFileName = NULL; planetFileName = createFileName("PLANET", level->getWorld()); try { planet = new JJ1Planet(planetFileName, planetId); } catch (int e) { planet = NULL; } delete[] planetFileName; if (planet) { if (planet->play() == E_QUIT) { delete planet; delete level; return E_QUIT; } planetId = planet->getId(); delete planet; } } ret = level->play(); delete level; baseLevel = level = NULL; } return ret; } /** * Determine the type of the specified level file. * * @return Level type */ LevelType Game::getLevelType (const char* fileName) { int length; length = strlen(fileName); if ((length > 4) && isFileType(fileName + length - 4, ".j2l", 4)) return LT_JJ2; if (isFileType(fileName, "bonusmap", 8)) return LT_JJ1BONUS; return LT_JJ1; } /** * Play a level. * * @return Error code */ int Game::playLevel (char* fileName) { levelType = getLevelType(fileName); return playLevel(fileName, false, false); } /** * Play the game * * @return Error code */ int Game::play () { bool multiplayer; bool checkpoint; int ret; multiplayer = (mode->getMode() != M_SINGLE); checkpoint = false; planetId = -1; // Play the level(s) while (true) { if (!levelFile) return E_NONE; sendTime = checkTime = 0; // Load and play the level ret = playLevel(levelFile, !multiplayer, checkpoint); if (ret <= 0) return ret; if (levelFile && isFileType(levelFile, "bonusmap", 8)) { if (ret == WON) { char *fileName; // Go to next level fileName = createFileName("BONUSMAP", (levelFile[10] * 10) + levelFile[11] - 527); setLevel(fileName); delete[] fileName; } } else { if (ret == WON) { // Won the level // Do not use old level's checkpoint coordinates checkpoint = false; } else { // Lost the level if (!localPlayer->getLives()) return E_NONE; // Use checkpoint coordinates checkpoint = true; } } } return E_NONE; } /** * Move the viewport towards the exit sign * * @param change Distance to move */ void Game::view (int change) { if (TTOF(checkX) > viewX + (canvasW << 9) + change) viewX += change; else if (TTOF(checkX) < viewX + (canvasW << 9) - change) viewX -= change; if (TTOF(checkY) > viewY + (canvasH << 9) + change) viewY += change; else if (TTOF(checkY) < viewY + (canvasH << 9) - change) viewY -= change; return; } /** * Make a player restart the level from the beginning/last checkpoint * * @param player Player to reset */ void Game::resetPlayer (Player *player) { player->reset(checkX, checkY); return; } /** * Create a level player * * @param player Player for which to create the level player */ void Game::addLevelPlayer (Player *player) { int count; if (level) { Anim* pAnims[JJ1PANIMS]; for (count = 0; count < JJ1PANIMS; count++) pAnims[count] = level->getPlayerAnim(count); player->createLevelPlayer(levelType, pAnims, NULL, checkX, checkY); } else if (jj2Level) { Anim* pAnims[JJ2PANIMS]; Anim* pFlippedAnims[JJ2PANIMS]; for (count = 0; count < JJ2PANIMS; count++) { pAnims[count] = jj2Level->getPlayerAnim(0, count, false); pFlippedAnims[count] = jj2Level->getPlayerAnim(0, count, true); } player->createLevelPlayer(levelType, pAnims, pFlippedAnims, checkX, checkY); } return; } openjazz-20190106/src/game/game.h000066400000000000000000000137501341440264100164050ustar00rootroot00000000000000 /** * * @file game.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 2nd March 2009: Created network.h from parts of OpenJazz.h * - 9th February 2009: Renamed network.h to game.h * - 2nd August 2009: Created gamemode.h from parts of game.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _GAME_H #define _GAME_H #include "gamemode.h" #include "io/network.h" #include "level/level.h" // Constants // Time intervals #define T_SSEND 20 #define T_SCHECK 1000 #define T_CSEND 10 #define T_CCHECK 1000 // Message categories and types #define MCMASK 0xF0 #define MC_GAME 0x00 #define MC_LEVEL 0x10 #define MC_PLAYER 0x20 #define MT_G_PROPS 0x00 /* Game properties */ #define MT_G_PJOIN 0x01 /* New player joined */ #define MT_G_PQUIT 0x02 /* Player left */ #define MT_G_LEVEL 0x03 /* Level data */ #define MT_G_CHECK 0x04 #define MT_G_SCORE 0x05 /* Team scored a roast/lap/etc. */ #define MT_G_LTYPE 0x06 /* Level type */ #define MT_L_PROP 0x10 /* Level property */ #define MT_L_GRID 0x11 /* Change to gridElement */ #define MT_L_STAGE 0x12 /* Change in level stage */ #define MT_P_ANIMS 0x20 /* Player animations */ #define MT_P_TEMP 0x21 /* Temporary player properties, e.g. position */ // Minimum message lengths, including header #define MTL_G_PROPS 8 #define MTL_G_PJOIN 10 #define MTL_G_PQUIT 3 #define MTL_G_LEVEL 4 /* + amount of level data */ #define MTL_G_CHECK 6 #define MTL_G_SCORE 3 #define MTL_G_LTYPE 3 #define MTL_L_PROP 5 #define MTL_L_GRID 8 #define MTL_L_STAGE 3 #define MTL_P_ANIMS 3 /* + PANIMS, BPANIMS, or 1 (for JJ2) */ #define MTL_P_TEMP 46 #define BUFFER_LENGTH 255 /* Should always be big enough to hold any message */ // Classes class Anim; class File; /// Base class for game handling classes class Game { private: int planetId; ///< ID of last planet approach sequence bool isFileType (const char *fileName, const char *type, int typeLength); protected: GameMode* mode; ///< Mode-specific management Level* baseLevel; ///< Current level char* levelFile; ///< Current level's file name LevelType levelType; ///< Current level's type int difficulty; ///< Difficulty setting (0 = easy, 1 = medium, 2 = hard, 3 = turbo (hard in JJ2 levels)) unsigned int sendTime; ///< The next time data will be sent unsigned int checkTime; ///< The next time a connection/disconnection will be dealt with short int checkX; ///< X-coordinate of the level checkpoint short int checkY; ///< Y-coordinate of the level checkpoint Game (); GameMode* createMode (GameModeType modeType); LevelType getLevelType (const char* fileName); int playLevel (char *fileName, bool intro, bool checkpoint); void addLevelPlayer (Player *player); public: virtual ~Game (); GameMode* getMode (); int getDifficulty (); void setDifficulty (int diff); int playLevel (char *fileName); virtual int setLevel (char *fileName) = 0; int play (); void view (int change); virtual void send (unsigned char *buffer) = 0; virtual int step (unsigned int ticks) = 0; virtual void score (unsigned char team) = 0; virtual void setCheckpoint (int gridX, int gridY) = 0; void resetPlayer (Player *player); }; /// Game handling for single-player local play class LocalGame : public Game { public: LocalGame (const char *firstLevel, int gameDifficulty); ~LocalGame (); int setLevel (char *fileName); void send (unsigned char *buffer); int step (unsigned int ticks); void score (unsigned char team); void setCheckpoint (int gridX, int gridY); }; /// Game handling for multiplayer servers class ServerGame : public Game { private: int clientStatus[MAX_CLIENTS]; /**< Array of client statuses -2: Connected and operational -1: Not connected >=0: Number of bytes of the level that have been sent */ int clientPlayer[MAX_CLIENTS]; ///< Array of client player indexes int clientSock[MAX_CLIENTS]; ///< Array of client sockets unsigned char recvBuffers[MAX_CLIENTS][BUFFER_LENGTH]; ///< Array of buffers containing data received from clients int received[MAX_CLIENTS]; ///< Array containing the amount of data received from each client unsigned char *levelData; ///< Contents of the current level file int levelSize; ///< Size of the current level file int sock; ///< Server socket public: ServerGame (GameModeType mode, char *firstLevel, int gameDifficulty); ~ServerGame (); int setLevel (char *fileName); void send (unsigned char *buffer); int step (unsigned int ticks); void score (unsigned char team); void setCheckpoint (int gridX, int gridY); }; /// Game handling for multiplayer clients class ClientGame : public Game { private: File *file; ///< File to which the incoming level will be written unsigned char recvBuffer[BUFFER_LENGTH]; ///< Buffer containing data received from server int received; ///< Amount of data received from server int clientID; ///< Client's index on the server int maxPlayers; ///< The maximum number of players in the game int sock; ///< Client socket public: ClientGame (char *address); ~ClientGame (); int setLevel (char *fileName); void send (unsigned char *buffer); int step (unsigned int ticks); void score (unsigned char team); void setCheckpoint (int gridX, int gridY); }; #endif openjazz-20190106/src/game/gamemode.cpp000066400000000000000000000132031341440264100175760ustar00rootroot00000000000000 /** * * @file gamemode.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 18th July 2009: Created servergame.cpp from parts of game.cpp * - 2nd August 2009: Created gamemode.cpp from parts of servergame.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "game.h" #include "gamemode.h" #include "io/gfx/font.h" #include "player/player.h" /** * Destroy game mode */ GameMode::~GameMode () { } /** * Outcome of player being hit * * @param source Player responsible for the hit * @param victim Player victim of the hit * * @return Whether or not the hit should result in energy loss (true) */ bool GameMode::hit (Player *source, Player *victim) { (void)source; (void)victim; return true; } /** * Outcome of player being killed * * @param game The current game * @param source Player responsible for the kill * @param victim Player victim of the kill * * @return Whether or not the player should be be killed (true) */ bool GameMode::kill (Game* game, Player *source, Player *victim) { if (source && (victim == localPlayer)) game->score(source->getTeam()); return true; } /** * Outcome of level being completed * * @param game The current game * @param player Player that has completed level * @param gridX X-coordinate (in tiles) of finishing position * @param gridY Y-coordinate (in tiles) of finishing position * * @return Whether or not the level should end (true) */ bool GameMode::endOfLevel (Game* game, Player *player, int gridX, int gridY) { (void)player; game->setCheckpoint(gridX, gridY); return true; } /** * Outcome of time running out */ void GameMode::outOfTime () { return; } /** * Get the game mode type * * @return Game mode type (M_SINGLE) */ GameModeType SingleGameMode::getMode () { return M_SINGLE; } /** * Choose a team for a new player * * @return New player's team (0) */ unsigned char SingleGameMode::chooseTeam () { return 0; } /** * Draw the player's team's score (not in single-player mode) * * @param font Font to use to draw score */ void SingleGameMode::drawScore (Font* font) { (void)font; return; } /** * Choose a team for a new player * * @return New player's team (0) */ unsigned char CooperativeGameMode::chooseTeam () { // All players are on the same team return 0; } /** * Draw the player's team's score (not in cooperative mode) * * @param font Font to use to draw score */ void CooperativeGameMode::drawScore (Font* font) { (void)font; // Do nothing return; } /** * Choose a team for a new player * * @return New player's team (unique) */ unsigned char FreeForAllGameMode::chooseTeam () { // Every player is on a separate team int count; unsigned char team; team = 1; // Find a team number higher than any other for (count = nPlayers - 1; count >= 0; count--) { if (players[count].getTeam() > team) team = players[count].getTeam() + 1; } return team; } /** * Draw the player's team's score * * @param font Font to use to draw score */ void FreeForAllGameMode::drawScore (Font* font) { font->showNumber(localPlayer->teamScore, 64, 4); return; } /** * Choose a team for a new player * * @return New player's team (0 or 1) */ unsigned char TeamGameMode::chooseTeam () { // Players are split between two teams int count, difference; // Calculate team imbalance difference = 0; for (count = 0; count < nPlayers; count++) { if (players[count].getTeam()) difference++; else difference--; } // Assign to the team with the least players if (difference >= 0) return 0; return 1; } /** * Draw the player's team's score * * @param font Font to use to draw score */ void TeamGameMode::drawScore (Font* font) { font->showNumber(localPlayer->teamScore, 64, 4); return; } /** * Get the game mode type * * @return Game mode type (M_COOP) */ GameModeType CoopGameMode::getMode () { return M_COOP; } /** * Get the game mode type * * @return Game mode type (M_BATTLE) */ GameModeType BattleGameMode::getMode () { return M_BATTLE; } /** * Get the game mode type * * @return Game mode type (M_TEAMBATTLE) */ GameModeType TeamBattleGameMode::getMode () { return M_TEAMBATTLE; } /** * Get the game mode type * * @return Game mode type (M_RACE) */ GameModeType RaceGameMode::getMode () { return M_RACE; } /** * Outcome of player being hit * * @param source Player responsible for the hit * @param victim Player victim of the hit * * @return Whether or not the hit should result in energy loss (false) */ bool RaceGameMode::hit (Player *source, Player *victim) { (void)source; (void)victim; return false; } /** * Outcome of level being completed * * @param game The current game * @param player Player that has completed level * @param gridX X-coordinate (in tiles) of finishing position * @param gridY Y-coordinate (in tiles) of finishing position * * @return Whether or not the level should end (false) */ bool RaceGameMode::endOfLevel (Game* game, Player *player, int gridX, int gridY) { (void)gridX; (void)gridY; if (player == localPlayer) game->score(localPlayer->getTeam()); game->resetPlayer(player); return false; } openjazz-20190106/src/game/gamemode.h000066400000000000000000000060411341440264100172450ustar00rootroot00000000000000 /** * * @file gamemode.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 2nd March 2009: Created network.h from parts of OpenJazz.h * - 9th February 2009: Renamed network.h to game.h * - 2nd August 2009: Created gamemode.h from parts of game.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _GAMEMODE_H #define _GAMEMODE_H // Constants #define MAX_PLAYERS (MAX_CLIENTS + 1) // Enum /// Game mode identifier enum GameModeType { M_SINGLE = 0, ///< Single-player mode M_COOP = 1, ///< Co-operative mode M_BATTLE = 2, ///< Battle mode M_TEAMBATTLE = 3, ///< Team battle mode M_RACE = 4 ///< Race mode }; // Classes class Font; class Game; class Player; /// Game mode base class class GameMode { public: virtual ~GameMode (); virtual GameModeType getMode () = 0; virtual unsigned char chooseTeam () = 0; virtual void drawScore (Font* font) = 0; virtual bool hit (Player *source, Player *victim); virtual bool kill (Game* game, Player *source, Player *victim); virtual bool endOfLevel (Game* game, Player *player, int gridX, int gridY); virtual void outOfTime (); }; /// Single-player game mode class SingleGameMode : public GameMode { public: GameModeType getMode (); unsigned char chooseTeam (); void drawScore (Font* font); }; /// Co-operative game mode base class class CooperativeGameMode : public GameMode { public: unsigned char chooseTeam (); virtual void drawScore (Font* font); }; /// Free-for-all game mode base class class FreeForAllGameMode : public GameMode { public: unsigned char chooseTeam (); virtual void drawScore (Font* font); }; /// Team-based game mode base class class TeamGameMode : public GameMode { public: unsigned char chooseTeam (); virtual void drawScore (Font* font); }; /// Co-operative game mode class CoopGameMode : public CooperativeGameMode { public: GameModeType getMode (); }; /// Battle game mode class BattleGameMode : public FreeForAllGameMode { private: int targetKills; ///< Number of kills required for a player to win public: GameModeType getMode (); }; /// Team battle game mode class TeamBattleGameMode : public TeamGameMode { private: int targetKills; ///< Number of kills required for a team to win public: GameModeType getMode (); }; /// Race game mode class RaceGameMode : public FreeForAllGameMode { private: int targetLaps; ///< Number of laps required for a player to win public: GameModeType getMode (); bool hit (Player *source, Player *victim); bool endOfLevel (Game* game, Player *player, int gridX, int gridY); }; #endif openjazz-20190106/src/game/localgame.cpp000066400000000000000000000054301341440264100177470ustar00rootroot00000000000000 /** * * @file localgame.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 3rd June 2009: Created network.cpp from parts of game.cpp * - 18th July 2009: Created servergame.cpp from parts of game.cpp * - 18th July 2009: Created clientgame.cpp from parts of game.cpp * - 3rd October 2010: Created localgame.cpp from parts of game.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "game.h" #include "gamemode.h" #include "player/player.h" #include "setup.h" #include "util.h" /** * Create a single-player local game * * @param firstLevel File name of the first level to play * @param gameDifficulty Difficulty setting */ LocalGame::LocalGame (const char *firstLevel, int gameDifficulty) { levelFile = createString(firstLevel); levelType = getLevelType(firstLevel); difficulty = gameDifficulty; mode = new SingleGameMode(); // Create the player nPlayers = 1; localPlayer = players = new Player[1]; localPlayer->init(this, setup.characterName, NULL, 0); return; } /** * Destroy local game */ LocalGame::~LocalGame () { delete mode; return; } /** * Set the next level * * @param fileName The file name of the next level * * @return Error code */ int LocalGame::setLevel (char *fileName) { if (levelFile) delete[] levelFile; if (fileName) { levelFile = createString(fileName); levelType = getLevelType(fileName); } else levelFile = NULL; return E_NONE; } /** * No data is sent in local games * * @param buffer Data that will not be sent. First byte indicates length. */ void LocalGame::send (unsigned char *buffer) { (void)buffer; // Do nothing return; } /** * Game iteration - nothing to be done in local games * * @param ticks Current time * * @return Error code */ int LocalGame::step (unsigned int ticks) { (void)ticks; // Do nothing return E_NONE; } /** * No points are assigned to teams in local games * * @param team Team to receive point */ void LocalGame::score (unsigned char team) { (void)team; // Do nothing return; } /** * Set the checkpoint * * @param gridX X-coordinate (in tiles) of the checkpoint * @param gridY Y-coordinate (in tiles) of the checkpoint */ void LocalGame::setCheckpoint (int gridX, int gridY) { checkX = gridX; checkY = gridY; return; } openjazz-20190106/src/game/servergame.cpp000066400000000000000000000263211341440264100201650ustar00rootroot00000000000000 /** * * @file servergame.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 18th July 2009: Created servergame.cpp from parts of game.cpp * - 2nd August 2009: Created gamemode.cpp from parts of servergame.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "game.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/network.h" #include "player/player.h" #include "setup.h" #include "util.h" #include /** * Create game server * * @param modeType Game mode * @param firstLevel File name of the first level to play * @param gameDifficulty Difficulty setting */ ServerGame::ServerGame (GameModeType modeType, char* firstLevel, int gameDifficulty) { int count; // Create the server sock = net->host(); if (sock < 0) throw sock; // Tee hee. Throw sock. // Create the players nPlayers = 1; localPlayer = players = new Player[MAX_PLAYERS]; localPlayer->init(this, setup.characterName, setup.characterCols, 0); for (count = 0; count < MAX_CLIENTS; count++) clientPlayer[count] = clientStatus[count] = -1; // Copy the first level into memory levelFile = NULL; levelData = NULL; count = setLevel(firstLevel); if (count < 0) { net->close(sock); if (levelData) delete[] levelData; throw count; } difficulty = gameDifficulty; mode = createMode(modeType); return; } /** * Disconnect clients and destroy server */ ServerGame::~ServerGame () { int count; for (count = 0; count < MAX_CLIENTS; count++) { if (clientStatus[count] != -1) net->close(clientSock[count]); } net->close(sock); if (levelData) delete[] levelData; delete mode; return; } /** * Set the next level and load it into memory * * @param fileName The file name of the next level * * @return Error code */ int ServerGame::setLevel (char* fileName) { File* file; int count; if (levelFile) delete[] levelFile; if (levelData) delete[] levelData; // The new level will be sent to all clients for (count = 0; count < MAX_CLIENTS; count++) { if (clientStatus[count] != -1) clientStatus[count] = 0; } if (!fileName) { levelFile = NULL; levelData = NULL; return E_NONE; } try { file = new File(fileName, false); } catch (int e) { levelFile = NULL; levelData = NULL; return e; } levelFile = createString(fileName); // Load the entire file into memory levelSize = file->getSize(); levelData = file->loadBlock(levelSize); delete file; levelType = getLevelType(fileName); if (levelType != LT_JJ1) return E_NONE; // Modify the extension section to match the actual extension count = levelSize - 5; while (levelData[count - 1] != 3) count--; levelData[count] = fileName[strlen(fileName) - 3]; levelData[count + 1] = fileName[strlen(fileName) - 2]; levelData[count + 2] = fileName[strlen(fileName) - 1]; return E_NONE; } /** * Send data to clients * * @param buffer Data to send. First byte indicates length. */ void ServerGame::send (unsigned char* buffer) { int count; for (count = 0; count < MAX_CLIENTS; count++) { // Send data to client, unless the data concerns the client's player // Each client is solely responsible for its player's state if ((clientStatus[count] != -1) && (((buffer[1] & MCMASK) != MC_PLAYER) || (buffer[2] != clientPlayer[count]))) net->send(clientSock[count], buffer); } return; } /** * Game iteration * * @param ticks Current time * * @return Error code */ int ServerGame::step (unsigned int ticks) { unsigned char sendBuffer[BUFFER_LENGTH]; int count, pcount, length; for (count = 0; count < MAX_CLIENTS; count++) { if (clientStatus[count] >= 0) { if (clientStatus[count] == 0) { // Send level type sendBuffer[0] = MTL_G_LTYPE; sendBuffer[1] = MT_G_LTYPE; sendBuffer[2] = levelType; net->send(clientSock[count], sendBuffer); } // Client is connected, but not operational // Send a chunk of the level length = levelSize - clientStatus[count]; if (length > 251) length = 251; sendBuffer[0] = MTL_G_LEVEL + length; sendBuffer[1] = MT_G_LEVEL; sendBuffer[2] = clientStatus[count] >> 8; sendBuffer[3] = clientStatus[count] & 255; memcpy(sendBuffer + 4, levelData + clientStatus[count], length); length = net->send(clientSock[count], sendBuffer); // Client is operational if the whole level has been sent // Otherwise, keep sending data if (length == MTL_G_LEVEL) clientStatus[count] = -2; else if (length > 0) clientStatus[count] += length - MTL_G_LEVEL; } if ((clientStatus[count] == -2) && (received[count] == 0)) { // Client is operational, but not currently receiving a message // See if there is a new message to receive length = net->recv(clientSock[count], recvBuffers[count], 1); if (length > 0) received[count]++; } if ((clientStatus[count] == -2) && (received[count] > 0)) { // Currently receiving a message // See if there is any more data length = net->recv(clientSock[count], recvBuffers[count] + received[count], recvBuffers[count][0] - received[count]); if (length > 0) received[count] += length; // See if the whole message has arrived if (received[count] >= recvBuffers[count][0]) { switch (recvBuffers[count][1] & MCMASK) { case MC_GAME: if ((recvBuffers[count][1] == MT_G_PJOIN) && (clientPlayer[count] == -1)) { printf("Player %d (client %d) joined the game.\n", nPlayers, count); // Set up the new player recvBuffers[count][4] = mode->chooseTeam(); players[nPlayers].init(this, (char *)(recvBuffers[count]) + 9, recvBuffers[count] + 5, recvBuffers[count][4]); addLevelPlayer(players + nPlayers); printf("Player %d joined team %d.\n", nPlayers, recvBuffers[count][4]); recvBuffers[count][3] = clientPlayer[count] = nPlayers; nPlayers++; } if (recvBuffers[count][1] == MT_G_CHECK) { checkX = recvBuffers[count][2]; checkY = recvBuffers[count][3]; if (recvBuffers[count][0] > 4) { checkX += recvBuffers[count][4] << 8; checkY += recvBuffers[count][5] << 8; } } if (recvBuffers[count][1] == MT_G_SCORE) { for (pcount = 0; pcount < nPlayers; pcount++) { if (players[pcount].getTeam() == recvBuffers[count][2]) players[pcount].teamScore++; } } break; case MC_LEVEL: baseLevel->receive(recvBuffers[count]); break; case MC_PLAYER: if (clientPlayer[count] != -1) { // Assign player byte based on sender recvBuffers[count][2] = clientPlayer[count]; players[clientPlayer[count]].receive(recvBuffers[count]); } break; } // Update clients send(recvBuffers[count]); received[count] = 0; } } if (ticks >= checkTime) { if ((clientStatus[count] == -1) && levelData) { // Client is not connected // Check for new connection clientSock[count] = net->accept(sock); if (clientSock[count] != -1) { printf("Client %d connected.\n", count); clientPlayer[count] = -1; received[count] = 0; // Incorporate the new client // Send data sendBuffer[0] = MTL_G_PROPS; sendBuffer[1] = MT_G_PROPS; sendBuffer[2] = 1; // Server version sendBuffer[3] = mode->getMode(); sendBuffer[4] = difficulty; sendBuffer[5] = MAX_PLAYERS; sendBuffer[6] = nPlayers; // Number of players sendBuffer[7] = count; // Client's clientID net->send(clientSock[count], sendBuffer); // Initiate sending of level data clientStatus[count] = 0; // Inform the new client of the checkpoint sendBuffer[0] = MTL_G_CHECK; sendBuffer[1] = MT_G_CHECK; sendBuffer[2] = checkX & 0xFF; sendBuffer[3] = checkY & 0xFF; sendBuffer[4] = (checkX >> 8) & 0xFF; sendBuffer[5] = (checkY >> 8) & 0xFF; net->send(clientSock[count], sendBuffer); // Inform the new client of the existing players sendBuffer[1] = MT_G_PJOIN; for (pcount = 0; pcount < nPlayers; pcount++) { sendBuffer[0] = MTL_G_PJOIN + strlen(players[pcount].getName()); sendBuffer[2] = count; sendBuffer[3] = pcount; sendBuffer[4] = players[pcount].getTeam(); memcpy(sendBuffer + 5, players[pcount].getCols(), PCOLOURS); memcpy(sendBuffer + 9, players[pcount].getName(), strlen(players[pcount].getName()) + 1); net->send(clientSock[count], sendBuffer); } } } else { // Client is connected // Check for disconnection if (!(net->isConnected(clientSock[count]))) { printf("Client %d disconnected (code: %d).\n", count, net->getError()); // Disconnect client net->close(clientSock[count]); clientStatus[count] = -1; if (clientPlayer[count] != -1) { // Remove the client's player printf("Player %d (client %d) left the game.\n", clientPlayer[count], count); nPlayers--; players[clientPlayer[count]].deinit(); // If necessary, move more recent players for (pcount = clientPlayer[count]; pcount < nPlayers; pcount++) memcpy(players + pcount, players + pcount + 1, sizeof(Player)); // Clear duplicate pointers memset(players + nPlayers, 0, sizeof(Player)); // Inform remaining clients that the player has left sendBuffer[0] = MTL_G_PQUIT; sendBuffer[1] = MT_G_PQUIT; sendBuffer[2] = clientPlayer[count]; send(sendBuffer); clientPlayer[count] = -1; } } } } } if (ticks >= checkTime) checkTime = ticks + T_SCHECK; if (ticks >= sendTime) { // Update clients sendBuffer[0] = MTL_P_TEMP; sendBuffer[1] = MT_P_TEMP; for (count = 0; count < nPlayers; count++) { sendBuffer[2] = count; players[count].send(sendBuffer); send(sendBuffer); } sendTime = ticks + T_SSEND; } return E_NONE; } /** * Assign point to team and inform clients * * @param team Team to receive point */ void ServerGame::score (unsigned char team) { unsigned char buffer[MTL_G_SCORE]; int count; // Inform clients buffer[0] = MTL_G_SCORE; buffer[1] = MT_G_SCORE; buffer[2] = team; send(buffer); // Update self for (count = 0; count < nPlayers; count++) { if (players[count].getTeam() == team) players[count].teamScore++; } return; } /** * Set the checkpoint and inform clients * * @param gridX X-coordinate (in tiles) of the checkpoint * @param gridY Y-coordinate (in tiles) of the checkpoint */ void ServerGame::setCheckpoint (int gridX, int gridY) { unsigned char buffer[MTL_G_CHECK]; buffer[0] = MTL_G_CHECK; buffer[1] = MT_G_CHECK; buffer[2] = gridX & 0xFF; buffer[3] = gridY & 0xFF; buffer[4] = (gridX >> 8) & 0xFF; buffer[5] = (gridY >> 8) & 0xFF; send(buffer); checkX = gridX; checkY = gridY; return; } openjazz-20190106/src/io/000077500000000000000000000000001341440264100150135ustar00rootroot00000000000000openjazz-20190106/src/io/controls.cpp000077500000000000000000000363601341440264100173750ustar00rootroot00000000000000 /** * * @file controls.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed main.c to main.cpp * - 13th July 2009: Created controls.cpp from parts of main.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with input. * */ #include "controls.h" #include "gfx/video.h" #include "loop.h" #define DEFAULT_KEY_UP (SDLK_UP) #define DEFAULT_KEY_DOWN (SDLK_DOWN) #define DEFAULT_KEY_LEFT (SDLK_LEFT) #define DEFAULT_KEY_RIGHT (SDLK_RIGHT) #if defined (_WIN32) #define DEFAULT_KEY_JUMP (SDLK_RALT) #define DEFAULT_KEY_SWIM (SDLK_RALT) #define DEFAULT_KEY_FIRE (SDLK_SPACE) #define DEFAULT_KEY_CHANGE (SDLK_RCTRL) #define DEFAULT_KEY_ENTER (SDLK_RETURN) #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) #define DEFAULT_KEY_STATS (SDLK_F9) #define DEFAULT_KEY_PAUSE (SDLK_p) #define DEFAULT_KEY_YES (SDLK_y) #define DEFAULT_KEY_NO (SDLK_n) #elif defined(DINGOO) #define DEFAULT_KEY_JUMP (SDLK_LCTRL) #define DEFAULT_KEY_SWIM (SDLK_LCTRL) #define DEFAULT_KEY_FIRE (SDLK_LALT) #define DEFAULT_KEY_CHANGE (SDLK_LSHIFT) #define DEFAULT_KEY_ENTER (SDLK_LCTRL) #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) #define DEFAULT_KEY_STATS (SDLK_TAB) #define DEFAULT_KEY_PAUSE (SDLK_RETURN) #define DEFAULT_KEY_YES (SDLK_LCTRL) #define DEFAULT_KEY_NO (SDLK_LALT) #elif defined (ANDROID) #define DEFAULT_KEY_JUMP (SDLK_SPACE) #define DEFAULT_KEY_SWIM (SDLK_SPACE) #define DEFAULT_KEY_FIRE (SDLK_LALT) #define DEFAULT_KEY_CHANGE (SDLK_RETURN) #define DEFAULT_KEY_ENTER (SDLK_SPACE) #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) #define DEFAULT_KEY_STATS (SDLK_F9) #define DEFAULT_KEY_PAUSE (SDLK_p) #define DEFAULT_KEY_YES (SDLK_y) #define DEFAULT_KEY_NO (SDLK_n) #elif defined (_3DS) #define DEFAULT_KEY_JUMP (SDLK_a) #define DEFAULT_KEY_SWIM (SDLK_b) #define DEFAULT_KEY_FIRE (SDLK_x) #define DEFAULT_KEY_CHANGE (SDLK_y) #define DEFAULT_KEY_ENTER (SDLK_RETURN) #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) #define DEFAULT_KEY_STATS (SDLK_l) #define DEFAULT_KEY_PAUSE (SDLK_r) #define DEFAULT_KEY_YES (SDLK_y) #define DEFAULT_KEY_NO (SDLK_n) #elif defined(GAMESHELL) #define DEFAULT_KEY_JUMP (SDLK_j) /* A button */ #define DEFAULT_KEY_SWIM (SDLK_j) /* A button */ #define DEFAULT_KEY_FIRE (SDLK_k) /* B button */ #define DEFAULT_KEY_CHANGE (SDLK_o) /* Y button */ #define DEFAULT_KEY_ENTER (SDLK_RETURN) /* START button */ #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) /* MENU button */ #define DEFAULT_KEY_STATS (SDLK_SPACE) /* SELECT button */ #define DEFAULT_KEY_PAUSE (SDLK_p) #define DEFAULT_KEY_YES (SDLK_y) #define DEFAULT_KEY_NO (SDLK_n) #else #define DEFAULT_KEY_JUMP (SDLK_SPACE) #define DEFAULT_KEY_SWIM (SDLK_SPACE) #define DEFAULT_KEY_FIRE (SDLK_LALT) #define DEFAULT_KEY_CHANGE (SDLK_RCTRL) #define DEFAULT_KEY_ENTER (SDLK_RETURN) #define DEFAULT_KEY_ESCAPE (SDLK_ESCAPE) #define DEFAULT_KEY_STATS (SDLK_F9) #define DEFAULT_KEY_PAUSE (SDLK_p) #define DEFAULT_KEY_YES (SDLK_y) #define DEFAULT_KEY_NO (SDLK_n) #endif #if defined(GP2X) || defined(WIZ) #define DEFAULT_BUTTON_UP (0) #define DEFAULT_BUTTON_DOWN (4) #define DEFAULT_BUTTON_LEFT (2) #define DEFAULT_BUTTON_RIGHT (6) #define DEFAULT_BUTTON_JUMP (12) /* A */ #define DEFAULT_BUTTON_SWIM (12) /* A */ #define DEFAULT_BUTTON_FIRE (14) /* X */ #define DEFAULT_BUTTON_CHANGE (15) /* Y */ #define DEFAULT_BUTTON_ESCAPE (10) /* L */ #define DEFAULT_BUTTON_ENTER (11) /* R */ #define DEFAULT_BUTTON_PAUSE (8) /* Start */ #define DEFAULT_BUTTON_STATS (9) /* Select */ #define DEFAULT_BUTTON_YES (-1) #define DEFAULT_BUTTON_NO (-1) #elif defined(CAANOO) #define DEFAULT_BUTTON_UP (11) /* Directional dummies for Caanoo (not used) */ #define DEFAULT_BUTTON_DOWN (12) #define DEFAULT_BUTTON_LEFT (13) #define DEFAULT_BUTTON_RIGHT (14) #define DEFAULT_BUTTON_JUMP (0) /* A? */ #define DEFAULT_BUTTON_SWIM (0) /* A? */ #define DEFAULT_BUTTON_FIRE (1) /* X? */ #define DEFAULT_BUTTON_CHANGE (3) /* Y? */ #define DEFAULT_BUTTON_ESCAPE (6) /* Home */ #define DEFAULT_BUTTON_ENTER (5) /* R? */ #define DEFAULT_BUTTON_PAUSE (9) /* Help 2 */ #define DEFAULT_BUTTON_STATS (8) /* Help 1 */ #define DEFAULT_BUTTON_YES (-1) #define DEFAULT_BUTTON_NO (-1) #elif defined(PSP) #define DEFAULT_BUTTON_UP (8) #define DEFAULT_BUTTON_DOWN (6) #define DEFAULT_BUTTON_LEFT (7) #define DEFAULT_BUTTON_RIGHT (9) #define DEFAULT_BUTTON_JUMP (2) #define DEFAULT_BUTTON_SWIM (2) #define DEFAULT_BUTTON_FIRE (3) #define DEFAULT_BUTTON_CHANGE (0) #define DEFAULT_BUTTON_ENTER (5) #define DEFAULT_BUTTON_ESCAPE (4) #define DEFAULT_BUTTON_STATS (10) #define DEFAULT_BUTTON_PAUSE (11) #define DEFAULT_BUTTON_YES (-1) #define DEFAULT_BUTTON_NO (-1) #else #define DEFAULT_BUTTON_UP (-1) #define DEFAULT_BUTTON_DOWN (-1) #define DEFAULT_BUTTON_LEFT (-1) #define DEFAULT_BUTTON_RIGHT (-1) #define DEFAULT_BUTTON_JUMP (1) #define DEFAULT_BUTTON_SWIM (1) #define DEFAULT_BUTTON_FIRE (0) #define DEFAULT_BUTTON_CHANGE (3) #define DEFAULT_BUTTON_ENTER (0) #define DEFAULT_BUTTON_ESCAPE (-1) #define DEFAULT_BUTTON_STATS (-1) #define DEFAULT_BUTTON_PAUSE (-1) #define DEFAULT_BUTTON_YES (-1) #define DEFAULT_BUTTON_NO (-1) #endif /** * Set up the default controls. */ Controls::Controls () { int count; keys[C_UP].key = DEFAULT_KEY_UP; keys[C_DOWN].key = DEFAULT_KEY_DOWN; keys[C_LEFT].key = DEFAULT_KEY_LEFT; keys[C_RIGHT].key = DEFAULT_KEY_RIGHT; keys[C_JUMP].key = DEFAULT_KEY_JUMP; keys[C_SWIM].key = DEFAULT_KEY_SWIM; keys[C_FIRE].key = DEFAULT_KEY_FIRE; keys[C_CHANGE].key = DEFAULT_KEY_CHANGE; keys[C_ENTER].key = DEFAULT_KEY_ENTER; keys[C_ESCAPE].key = DEFAULT_KEY_ESCAPE; keys[C_STATS].key = DEFAULT_KEY_STATS; keys[C_PAUSE].key = DEFAULT_KEY_PAUSE; keys[C_YES].key = DEFAULT_KEY_YES; keys[C_NO].key = DEFAULT_KEY_NO; buttons[C_UP].button = DEFAULT_BUTTON_UP; buttons[C_DOWN].button = DEFAULT_BUTTON_DOWN; buttons[C_LEFT].button = DEFAULT_BUTTON_LEFT; buttons[C_RIGHT].button = DEFAULT_BUTTON_RIGHT; buttons[C_JUMP].button = DEFAULT_BUTTON_JUMP; buttons[C_SWIM].button = DEFAULT_BUTTON_SWIM; buttons[C_FIRE].button = DEFAULT_BUTTON_FIRE; buttons[C_CHANGE].button = DEFAULT_BUTTON_CHANGE; buttons[C_ENTER].button = DEFAULT_BUTTON_ENTER; buttons[C_ESCAPE].button = DEFAULT_BUTTON_ESCAPE; buttons[C_STATS].button = DEFAULT_BUTTON_STATS; buttons[C_PAUSE].button = DEFAULT_BUTTON_PAUSE; axes[C_UP].axis = 1; axes[C_UP].direction = false; axes[C_DOWN].axis = 1; axes[C_DOWN].direction = true; axes[C_LEFT].axis = 0; axes[C_LEFT].direction = false; axes[C_RIGHT].axis = 0; axes[C_RIGHT].direction = true; axes[C_JUMP].axis = -1; axes[C_SWIM].axis = -1; axes[C_FIRE].axis = -1; axes[C_CHANGE].axis = -1; axes[C_ENTER].axis = -1; axes[C_ESCAPE].axis = -1; axes[C_STATS].axis = -1; axes[C_PAUSE].axis = -1; axes[C_YES].axis = -1; axes[C_NO].axis = -1; for (count = 0; count < CONTROLS; count++) { keys[count].pressed = false; buttons[count].pressed = false; axes[count].pressed = false; controls[count].time = 0; controls[count].state = false; } cursorPressed = false; cursorReleased = false; return; } /** * Set the key to use for the specified control. * * @param control The control * @param key The key to use */ void Controls::setKey (int control, int key) { keys[control].key = key; keys[control].pressed = false; return; } /** * Set the button to use for the specified control. * * @param control The control * @param button The button to use */ void Controls::setButton (int control, int button) { buttons[control].button = button; buttons[control].pressed = false; return; } /** * Set the axis and direction to use for the specified control. * * @param control The control * @param axis The axis to use * @param direction Whether or not to use positive axis values */ void Controls::setAxis (int control, int axis, bool direction) { axes[control].axis = axis; axes[control].direction = direction; axes[control].pressed = false; return; } /** * Get the key being used for the specified control. * * @param control The control * * @return The key being used */ int Controls::getKey (int control) { return keys[control].key; } /** * Get the button being used for the specified control. * * @param control The control * * @return The button being used */ int Controls::getButton (int control) { return buttons[control].button; } /** * Get the axis being used for the specified control. * * @param control The control * * @return The axis being used */ int Controls::getAxis (int control) { return axes[control].axis; } /** * Get the direction of the axis being used for the specified control. * * @param control The control * * @return True if positive values of the axis are being used */ int Controls::getAxisDirection (int control) { return axes[control].direction; } /** * Set the position and state of the cursor. * * @param x The x-coordinate of the cursor * @param y The y-coordinate of the cursor * @param pressed The state of the cursor */ void Controls::setCursor(int x, int y, bool pressed) { cursorX = x; cursorY = y; cursorPressed = pressed; cursorReleased = !pressed; return; } /** * Update controls based on a system event. * * @param event The system event. Non-input events will be ignored * @param type Type of loop. Normal, typing, or input configuration * * @return Error code */ int Controls::update (SDL_Event *event, LoopType type) { int count; count = CONTROLS; switch (event->type) { case SDL_KEYDOWN: if (type == SET_KEY_LOOP) return event->key.keysym.sym; for (count = 0; count < CONTROLS; count++) if (event->key.keysym.sym == keys[count].key) keys[count].pressed = true; if (type == TYPING_LOOP) return event->key.keysym.sym; break; case SDL_KEYUP: for (count = 0; count < CONTROLS; count++) if (event->key.keysym.sym == keys[count].key) keys[count].pressed = false; break; case SDL_JOYBUTTONDOWN: if (type == SET_JOYSTICK_LOOP) return JOYSTICKB | event->jbutton.button; for (count = 0; count < CONTROLS; count++) if (event->jbutton.button == buttons[count].button) buttons[count].pressed = true; break; case SDL_JOYBUTTONUP: for (count = 0; count < CONTROLS; count++) if (event->jbutton.button == buttons[count].button) buttons[count].pressed = false; break; case SDL_JOYAXISMOTION: if (type == SET_JOYSTICK_LOOP) { if (event->jaxis.value < -16384) return JOYSTICKANEG | event->jaxis.axis; else if (event->jaxis.value > 16384) return JOYSTICKAPOS | event->jaxis.axis; } for (count = 0; count < CONTROLS; count++) if (event->jaxis.axis == axes[count].axis) { if (!axes[count].direction && (event->jaxis.value < -16384)) axes[count].pressed = true; else if (axes[count].direction && (event->jaxis.value > 16384)) axes[count].pressed = true; else axes[count].pressed = false; } break; case SDL_MOUSEMOTION: if (event->motion.state & SDL_BUTTON(1)) { setCursor(event->motion.x, event->motion.y, true); } break; case SDL_MOUSEBUTTONDOWN: if (event->button.button == SDL_BUTTON_LEFT) { setCursor(event->button.x, event->button.y, true); } else if (event->button.button == 4) { wheelUp++; } else if (event->button.button == 5) { wheelDown++; } break; case SDL_MOUSEBUTTONUP: if (event->button.button == SDL_BUTTON_LEFT) { setCursor(event->button.x, event->button.y, false); } break; } return E_NONE; } /** * Process input iteration. * * Called once per game iteration. Updates input. */ void Controls::loop () { int count; // Apply controls to universal control tracking for (count = 0; count < CONTROLS; count++) controls[count].state = (controls[count].time < globalTicks) && (keys[count].pressed || buttons[count].pressed || axes[count].pressed); if (wheelUp) { controls[C_UP].state = true; wheelUp--; } if (wheelDown) { controls[C_DOWN].state = true; wheelDown--; } return; } /** * Determine whether or not the specified control is being used. * * @param control The control * * @return True if the control is being used */ bool Controls::getState (int control) { return controls[control].state; } /** * If it's being used, release the specified control. * * @param control The control * * @return True if the control was being used */ bool Controls::release (int control) { if (!controls[control].state) return false; controls[control].time = globalTicks + T_KEY; controls[control].state = false; return true; } /** * Get the position of the cursor, and determine whether or not it's being used. * * @param x Is set to the x-coordinate of the cursor * @param y Is set to the y-coordinate of the cursor * * @return True if the cursor was being used */ bool Controls::getCursor (int& x, int& y) { #ifdef SCALE int scaleFactor = video.getScaleFactor(); x = cursorX / scaleFactor; y = cursorY / scaleFactor; #else x = cursorX; y = cursorY; #endif return cursorPressed || cursorReleased; } /** * Determine whether or not the cursor has been released. * * @return True if the cursor has been released */ bool Controls::wasCursorReleased () { if (cursorReleased) { cursorReleased = false; return true; } return false; } openjazz-20190106/src/io/controls.h000066400000000000000000000056211341440264100170330ustar00rootroot00000000000000 /** * * @file controls.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 13th July 2009: Created controls.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _INPUT_H #define _INPUT_H #include "loop.h" #include "OpenJazz.h" #include // Constants // Indexes for the keys / buttons / axes player controls arrays #define C_UP 0 #define C_DOWN 1 #define C_LEFT 2 #define C_RIGHT 3 #define C_JUMP 4 #define C_SWIM 5 #define C_FIRE 6 #define C_CHANGE 7 /* Change weapon */ #define C_ENTER 8 #define C_ESCAPE 9 #define C_STATS 10 #define C_PAUSE 11 #define C_YES 12 #define C_NO 13 // Size of those arrays #define CONTROLS 14 // Time interval #define T_KEY 200 // Class /// Keeps track of all control input class Controls { private: struct { int key; ///< Keyboard key bool pressed; ///< Whether or not the key is pressed } keys[CONTROLS]; struct { int button; ///< Joystick button bool pressed; ///< Whether or not the button is pressed } buttons[CONTROLS]; struct { int axis; ///< Joystick axis bool direction; ///< Axis direction bool pressed; ///< Whether or not the axis is pressed in the given direction } axes[CONTROLS]; struct { unsigned int time; ///< The time from which the control will respond to being pressed bool state; ///< Whether or not the control is being used } controls[CONTROLS]; int cursorX; ///< X-coordinate of the cursor int cursorY; ///< Y-coordinate of the cursor bool cursorPressed; ///< Whether or not the cursor is being pressed bool cursorReleased; ///< Whether or not the cursor has been released int wheelUp; ///< How many times the wheel has been scrolled upwards int wheelDown; ///< How many times the wheel has been scrolled downwards void setCursor (int x, int y, bool pressed); public: Controls (); void setKey (int control, int key); void setButton (int control, int button); void setAxis (int control, int axis, bool direction); int getKey (int control); int getButton (int control); int getAxis (int control); int getAxisDirection (int control); int update (SDL_Event *event, LoopType type); void loop (); bool getState (int control); bool release (int control); bool getCursor (int& x, int& y); bool wasCursorReleased (); }; // Variable EXTERN Controls controls; #endif openjazz-20190106/src/io/file.cpp000066400000000000000000000253631341440264100164470ustar00rootroot00000000000000 /** * * @file file.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed util.c to util.cpp * - 3rd February 2009: Created file.cpp from parts of util.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with files. * */ #include "file.h" #include "io/gfx/video.h" #include "util.h" #include #include #ifndef _WIN32 #define UPPERCASE_FILENAMES #define LOWERCASE_FILENAMES #endif /** * Try opening a file from the available paths. * * @param name File name * @param write Whether or not the file can be written to */ File::File (const char* name, bool write) { Path* path; path = firstPath; while (path) { if (open(path->path, name, write)) return; path = path->next; } log("Could not open file", name); throw E_FILE; } /** * Delete the file object. */ File::~File () { fclose(file); #ifdef VERBOSE log("Closed file", filePath); #endif delete[] filePath; return; } /** * Try opening a file from the given path * * @param path Directory path * @param name File name * @param write Whether or not the file can be written to */ bool File::open (const char* path, const char* name, bool write) { #if defined(UPPERCASE_FILENAMES) || defined(LOWERCASE_FILENAMES) int count; #endif // Create the file path for the given directory filePath = createString(path, name); // Open the file from the path file = fopen(filePath, write ? "wb": "rb"); #ifdef UPPERCASE_FILENAMES if (!file) { // Convert the file name to upper case for (count = strlen(path); filePath[count]; count++) { if ((filePath[count] >= 97) && (filePath[count] <= 122)) filePath[count] -= 32; } // Open the file from the path file = fopen(filePath, write ? "wb": "rb"); } #endif #ifdef LOWERCASE_FILENAMES if (!file) { // Convert the file name to lower case for (count = strlen(path); filePath[count]; count++) { if ((filePath[count] >= 65) && (filePath[count] <= 90)) filePath[count] += 32; } // Open the file from the path file = fopen(filePath, write ? "wb": "rb"); } #endif if (file) { LOG("Opened file", filePath); return true; } delete[] filePath; return false; } /** * Get the size of the file. * * @return The size of the file */ int File::getSize () { int pos, size; pos = ftell(file); fseek(file, 0, SEEK_END); size = ftell(file); fseek(file, pos, SEEK_SET); return size; } /** * Get the current read/write location within the file. * * @return The current location */ int File::tell () { return ftell(file); } /** * Set the read/write location within the file. * * @param offset The new offset * @param reset Whether to offset from the current location or the start of the file */ void File::seek (int offset, bool reset) { fseek(file, offset, reset ? SEEK_SET: SEEK_CUR); return; } /** * Load an unsigned char from the file. * * @return The value read */ unsigned char File::loadChar () { return fgetc(file); } void File::storeChar (unsigned char val) { fputc(val, file); return; } /** * Load an unsigned short int from the file. * * @return The value read */ unsigned short int File::loadShort () { unsigned short int val; val = fgetc(file); val += fgetc(file) << 8; return val; } /** * Load an unsigned short int with an upper limit from the file. * * @return The value read */ unsigned short int File::loadShort (unsigned short int max) { unsigned short int val; val = loadShort(); if (val > max) { logError("Oversized value in file", filePath); return max; } return val; } void File::storeShort (unsigned short int val) { fputc(val & 255, file); fputc(val >> 8, file); return; } /** * Load a signed int from the file. * * @return The value read */ signed int File::loadInt () { unsigned int val; val = fgetc(file); val += fgetc(file) << 8; val += fgetc(file) << 16; val += fgetc(file) << 24; return *((signed int *)&val); } void File::storeInt (signed int val) { unsigned int uval; uval = *((unsigned int *)&val); fputc(uval & 255, file); fputc((uval >> 8) & 255, file); fputc((uval >> 16) & 255, file); fputc(uval >> 24, file); return; } /** * Load a block of uncompressed data from the file. * * @param length The length of the block * * @return Buffer containing the block of data */ unsigned char * File::loadBlock (int length) { unsigned char *buffer; buffer = new unsigned char[length]; fread(buffer, 1, length, file); return buffer; } /** * Load a block of RLE compressed data from the file. * * @param length The length of the uncompressed block * * @return Buffer containing the uncompressed data */ unsigned char* File::loadRLE (int length) { unsigned char* buffer; int rle, pos, byte, count, next; // Determine the offset that follows the block next = fgetc(file); next += fgetc(file) << 8; next += ftell(file); buffer = new unsigned char[length]; pos = 0; while (pos < length) { rle = fgetc(file); if (rle & 128) { byte = fgetc(file); for (count = 0; count < (rle & 127); count++) { buffer[pos++] = byte; if (pos >= length) break; } } else if (rle) { for (count = 0; count < rle; count++) { buffer[pos++] = fgetc(file); if (pos >= length) break; } } else buffer[pos++] = fgetc(file); } fseek(file, next, SEEK_SET); return buffer; } /** * Skip past a block of RLE compressed data in the file. */ void File::skipRLE () { int next; next = fgetc(file); next += fgetc(file) << 8; fseek(file, next, SEEK_CUR); return; } /** * Load a block of LZ compressed data from the file. * * @param compressedLength The length of the compressed block * @param length The length of the uncompressed block * * @return Buffer containing the uncompressed data */ unsigned char* File::loadLZ (int compressedLength, int length) { unsigned char* compressedBuffer; unsigned char* buffer; compressedBuffer = loadBlock(compressedLength); buffer = new unsigned char[length]; uncompress(buffer, (unsigned long int *)&length, compressedBuffer, compressedLength); delete[] compressedBuffer; return buffer; } /** * Load a string from the file. * * @return The new string */ char * File::loadString () { char *string; int length, count; length = fgetc(file); if (length) { string = new char[length + 1]; fread(string, 1, length, file); } else { // If the length is not given, assume it is an 8.3 file name string = new char[13]; for (count = 0; count < 9; count++) { string[count] = fgetc(file); if (string[count] == '.') { string[++count] = fgetc(file); string[++count] = fgetc(file); string[++count] = fgetc(file); count++; break; } } length = count; } string[length] = 0; return string; } /** * Load RLE compressed graphical data from the file. * * @param width The width of the image to load * @param height The height of the image to load * * @return SDL surface containing the loaded image */ SDL_Surface* File::loadSurface (int width, int height) { SDL_Surface* surface; unsigned char* pixels; pixels = loadRLE(width * height); surface = createSurface(pixels, width, height); delete[] pixels; return surface; } /** * Load a block of scrambled pixel data from the file. * * @param length The length of the block * * @return Buffer containing the de-scrambled data */ unsigned char* File::loadPixels (int length) { unsigned char* pixels; unsigned char* sorted; int count; sorted = new unsigned char[length]; pixels = loadBlock(length); // Rearrange pixels in correct order for (count = 0; count < length; count++) { sorted[count] = pixels[(count >> 2) + ((count & 3) * (length >> 2))]; } delete[] pixels; return sorted; } /** * Load a block of scrambled and masked pixel data from the file. * * @param length The length of the block * @param key The transparent pixel value * * @return Buffer containing the de-scrambled data */ unsigned char* File::loadPixels (int length, int key) { unsigned char* pixels; unsigned char* sorted; unsigned char mask = 0; int count; sorted = new unsigned char[length]; pixels = new unsigned char[length]; // Read the mask // Each mask pixel is either 0 or 1 // Four pixels are packed into the lower end of each byte for (count = 0; count < length; count++) { if (!(count & 3)) mask = fgetc(file); pixels[count] = (mask >> (count & 3)) & 1; } // Pixels are loaded if the corresponding mask pixel is 1, otherwise // the transparent index is used. Pixels are scrambled, so the mask // has to be scrambled the same way. for (count = 0; count < length; count++) { sorted[(count >> 2) + ((count & 3) * (length >> 2))] = pixels[count]; } // Read pixels according to the scrambled mask for (count = 0; count < length; count++) { // Use the transparent pixel pixels[count] = key; if (sorted[count] == 1) { // The unmasked portions are transparent, so no masked // portion should be transparent. while (pixels[count] == key) pixels[count] = fgetc(file); } } // Rearrange pixels in correct order for (count = 0; count < length; count++) { sorted[count] = pixels[(count >> 2) + ((count & 3) * (length >> 2))]; } delete[] pixels; return sorted; } /** * Load a palette from the file. * * @param palette The palette to be filled with loaded colours * @param rle Whether or not the palette data is RLE-encoded */ void File::loadPalette (SDL_Color* palette, bool rle) { unsigned char* buffer; int count; if (rle) buffer = loadRLE(768); else buffer = loadBlock(768); for (count = 0; count < 256; count++) { // Palette entries are 6-bit // Shift them upwards to 8-bit, and fill in the lower 2 bits palette[count].r = (buffer[count * 3] << 2) + (buffer[count * 3] >> 4); palette[count].g = (buffer[(count * 3) + 1] << 2) + (buffer[(count * 3) + 1] >> 4); palette[count].b = (buffer[(count * 3) + 2] << 2) + (buffer[(count * 3) + 2] >> 4); } delete[] buffer; return; } /** * Create a new directory path object. * * @param newNext Next path * @param newPath The new path */ Path::Path (Path* newNext, char* newPath) { next = newNext; path = newPath; return; } /** * Delete the directory path object. */ Path::~Path () { if (next) delete next; delete[] path; return; } openjazz-20190106/src/io/file.h000066400000000000000000000040511341440264100161030ustar00rootroot00000000000000 /** * * @file file.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 3rd February 2009: Created file.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _FILE_H #define _FILE_H #include "OpenJazz.h" #include #include // Classes /// File i/o class File { private: FILE* file; char* filePath; bool open (const char* path, const char* name, bool write); public: File (const char* name, bool write); ~File (); int getSize (); void seek (int offset, bool reset); int tell (); unsigned char loadChar (); void storeChar (unsigned char val); unsigned short int loadShort (); unsigned short int loadShort (unsigned short int max); void storeShort (unsigned short int val); signed int loadInt (); void storeInt (signed int val); unsigned char* loadBlock (int length); unsigned char* loadRLE (int length); void skipRLE (); unsigned char* loadLZ (int compressedLength, int length); char* loadString (); SDL_Surface* loadSurface (int width, int height); unsigned char* loadPixels (int length); unsigned char* loadPixels (int length, int key); void loadPalette (SDL_Color* palette, bool rle = true); }; /// Directory path class Path { public: Path* next; ///< Next path to check char* path; ///< Path Path (Path* newNext, char* newPath); ~Path (); }; // Variable EXTERN Path* firstPath; ///< Paths to files #endif openjazz-20190106/src/io/gfx/000077500000000000000000000000001341440264100155775ustar00rootroot00000000000000openjazz-20190106/src/io/gfx/anim.cpp000066400000000000000000000140121341440264100172250ustar00rootroot00000000000000 /** * * @file anim.cpp * * Part of the OpenJazz project * * @par History * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp * - 26th July 2009: Created anim.cpp from parts of sprite.cpp * * @par Licence * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "anim.h" #include "sprite.h" #include "jj1level/jj1level.h" /** * Create empty animation. */ Anim::Anim () { sprites = new Sprite *[19]; xOffsets = new signed char[19]; yOffsets = new signed char[19]; frame = 0; yOffset = 0; return; } /** * Delete animation. */ Anim::~Anim () { delete[] sprites; delete[] xOffsets; delete[] yOffsets; return; } /** * Set overall animation data. * * @param length Number of frames * @param sX Bullet generation x-coordinate * @param sY Bullet generation y-coordinate * @param aX Accessory animation x-coordinate * @param aY Accessory animation y-coordinate * @param a Accessory animation index * @param y Vertical offset */ void Anim::setData (int length, signed char sX, signed char sY, signed char aX, signed char aY, unsigned char a, signed char y) { if (length > 19) { delete[] sprites; delete[] xOffsets; delete[] yOffsets; sprites = new Sprite *[length]; xOffsets = new signed char[length]; yOffsets = new signed char[length]; } frames = length; shootX = sX; shootY = sY; accessoryX = aX; accessoryY = aY; accessory = a; yOffset = y; return; } /** * Set current frame. * * @param nextFrame The frame to use * @param looping Whether the animation should stop at the end or loop */ void Anim::setFrame (int nextFrame, bool looping) { if (looping) frame = nextFrame % frames; else frame = (nextFrame >= frames)? frames - 1: nextFrame; return; } /** * Set the data for the current frame. * * @param sprite Sprite to use * @param x Horizontal offset * @param y Vertical offset */ void Anim::setFrameData (Sprite *sprite, signed char x, signed char y) { sprites[frame] = sprite; xOffsets[frame] = x; yOffsets[frame] = y; return; } /** * Determine the width of the current frame. * * @return The width of the current frame */ int Anim::getWidth () { return sprites[frame]->getWidth(); } /** * Determine the height of the current frame. * * @return The height of the current frame */ int Anim::getHeight () { return sprites[frame]->getHeight(); } /** * Determine the length of the animation. * * @return The length of the animation */ int Anim::getLength () { return frames; } /** * Determine the bullet generation x-coordinate of the current frame. * * @return The bullet generation x-coordinate */ fixed Anim::getShootX () { return ITOF(shootX + xOffsets[frame]) << 2; } /** * Determine the bullet generation y-coordinate of the current frame. * * @return The bullet generation y-coordinate */ fixed Anim::getShootY () { return ITOF(shootY + yOffsets[frame]); } /** * Determine the accessory bullet generation x-coordinate of the current frame. * * @return The accessory bullet generation x-coordinate */ fixed Anim::getAccessoryShootX () { return ITOF(shootX + accessoryX + xOffsets[frame]) << 2; } /** * Determine the accessory bullet generation y-coordinate of the current frame. * * @return The accessory bullet generation y-coordinate */ fixed Anim::getAccessoryShootY () { return ITOF(shootY + accessoryY + yOffsets[frame]); } /** * Determine the vertical offset. * * @return The vertical offset */ fixed Anim::getOffset () { return -ITOF(yOffset); } /** * Determine the horizontal offset of the current frame. * * @return The horizontal offset */ fixed Anim::getXOffset () { return ITOF(sprites[frame]->getXOffset() + (xOffsets[frame] << 2) + 1); } /** * Determine the vertical offset of the current frame. * * @return The vertical offset */ fixed Anim::getYOffset () { return ITOF(sprites[frame]->getYOffset() + yOffsets[frame] + 1); } /** * Draw current frame. * * @param x X-coordinate at which to draw * @param y Y-coordinate at which to draw * @param accessories Number of accessory animations to draw */ void Anim::draw (fixed x, fixed y, int accessories) { Anim* anim; sprites[frame]->draw( FTOI(x) + (xOffsets[frame] << 2), FTOI(y) + yOffsets[frame] - yOffset); if (accessories && accessory) { anim = level->getAnim(accessory); anim->setFrame(frame, true); anim->draw( x + ITOF(accessoryX << 2), y + ITOF(accessoryY - yOffset) - anim->getOffset(), accessories - 1); } return; } /** * Draw current frame scaled. * * @param x X-coordinate at which to draw * @param y Y-coordinate at which to draw * @param scale Scaling factor */ void Anim::drawScaled (fixed x, fixed y, fixed scale) { // Used to draw bonus level player, so no offset sprites[frame]->drawScaled(FTOI(x), FTOI(y), scale); return; } /** * Set the current frame's palette. * * @param palette The new palette to use * @param start The first entry to use * @param amount The number of entries to use */ void Anim::setPalette (SDL_Color *palette, int start, int amount) { sprites[frame]->setPalette(palette, start, amount); return; } /** * Turn the whole of the current frame a single colour. * * @param index The index of the colour to use */ void Anim::flashPalette (int index) { sprites[frame]->flashPalette(index); return; } /** * Restore the current frame's original palette. */ void Anim::restorePalette () { sprites[frame]->restorePalette(); return; } openjazz-20190106/src/io/gfx/anim.h000066400000000000000000000050521341440264100166760ustar00rootroot00000000000000 /** * * @file anim.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 19th March 2009: Created sprite.h from parts of level.h * - 26th July 2009: Created anim.h from parts of sprite.h * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _ANIM_H #define _ANIM_H #include "OpenJazz.h" #include // Classes class Sprite; /// Animation class Anim { private: Sprite** sprites; ///< Sprite images signed char* xOffsets; ///< Horizontal offsets for each frame signed char* yOffsets; ///< Vertical offsets for each frame signed char shootX; ///< Bullet generation x-coordinate signed char shootY; ///< Bullet generation y-coordinate signed char accessoryX; ///< Accessory animation x-coordinate signed char accessoryY; ///< Accessory animation y-coordinate signed char yOffset; ///< Vertical offset unsigned char frames; ///< Number of frames unsigned char frame; ///< Current frame unsigned char accessory; ///< Number of an animation that is an accessory to this animation ///< Most of the time accessories are used with guardians. public: Anim (); ~Anim (); void setData (int length, signed char sX, signed char sY, signed char aX, signed char aY, unsigned char a, signed char y); void setFrame (int nextFrame, bool looping); void setFrameData (Sprite *frameSprite, signed char x, signed char y); int getWidth (); int getHeight (); int getLength (); fixed getShootX (); fixed getShootY (); fixed getAccessoryShootX (); fixed getAccessoryShootY (); fixed getOffset (); fixed getXOffset (); fixed getYOffset (); void draw (fixed x, fixed y, int accessories = 7); void drawScaled (fixed x, fixed y, fixed scale); void setPalette (SDL_Color *palette, int start, int amount); void flashPalette (int index); void restorePalette (); }; #endif openjazz-20190106/src/io/gfx/font.cpp000066400000000000000000000304031341440264100172510ustar00rootroot00000000000000 /** * * @file font.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created font.c * - 3rd February 2009: Renamed font.c to font.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading, displaying and freeing of screen fonts. * */ #include "../file.h" #include "font.h" #include "video.h" #include /** * Load a font from the given .0FN file. * * @param fileName Name of an .0FN file */ Font::Font (const char* fileName) { File* file; unsigned char* pixels; unsigned char* blank; int fileSize; int count, size, width, height; // Load font from a font file try { file = new File(fileName, false); } catch (int e) { throw e; } fileSize = file->getSize(); nCharacters = 128; file->seek(20, true); lineHeight = file->loadChar() << 1; // Create blank character data blank = new unsigned char[3]; memset(blank, 0, 3); // Load characters for (count = 0; count < 128; count++) { if (file->tell() >= fileSize) { nCharacters = count; break; } size = file->loadShort(); if (size > 4) { pixels = file->loadRLE(size); width = pixels[0]; width += pixels[1] << 8; height = pixels[2]; height += pixels[3] << 8; if (size - 4 >= width * height) characters[count] = createSurface(pixels + 4, width, height); else characters[count] = createSurface(blank, 3, 1); delete[] pixels; } else characters[count] = createSurface(blank, 3, 1); SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 0); } delete[] blank; delete file; // Create ASCII->font map for (count = 0; count < 33; count++) map[count] = 0; map[33] = 107; // ! map[34] = 116; // " map[35] = 0; // # map[36] = 63; // $ map[37] = 0; // % map[38] = 0; // & map[39] = 115; // ' map[40] = 111; // ( map[41] = 112; // ) map[42] = 0; // * map[43] = 105; // + map[44] = 101; // , map[45] = 104; // - map[46] = 102; // . map[47] = 108; // / for (count = 48; count < 58; count++) map[count] = count + 5; // Numbers map[58] = 114; // : map[59] = 113; // ; map[60] = 0; // < map[61] = 106; // = map[62] = 0; // > map[63] = 103; // ? map[64] = 0; // @ for (count = 65; count < 91; count++) map[count] = count - 38; // Upper-case letters for (; count < 97; count++) map[count] = 0; for (; count < 123; count++) map[count] = count - 96; // Lower-case letters for (; count < 128; count++) map[count] = 0; for (count = 0; count < 128; count++) { if (map[count] >= nCharacters) map[count] = 0; } return; } /** * Create a font from the panel pixel data. * * @param pixels Panel pixel data * @param big Whether to use the small or the big font */ Font::Font (unsigned char* pixels, bool big) { unsigned char* chrPixels; int count, y; if (big) lineHeight = 8; else lineHeight = 7; chrPixels = new unsigned char[8 * lineHeight]; for (count = 0; count < 40; count++) { for (y = 0; y < lineHeight; y++) memcpy(chrPixels + (y * 8), pixels + (count * 8) + (y * SW), 8); characters[count] = createSurface(chrPixels, 8, lineHeight); if (big) SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 31); } nCharacters= 40; delete[] chrPixels; // Create ASCII->font map if (big) { // Goes " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-:." for (count = 0; count < 45; count++) map[count] = 0; map[count++] = 37; map[count++] = 39; for (; count < 48; count++) map[count] = 0; for (; count < 58; count++) map[count] = count - 47; // Numbers map[count++] = 38; for (; count < 65; count++) map[count] = 0; for (; count < 91; count++) map[count] = count - 54; // Upper-case letters for (; count < 97; count++) map[count] = 0; for (; count < 123; count++) map[count] = count - 86; // Lower-case letters for (; count < 128; count++) map[count] = 0; } else { // Goes " 0123456789oo" (where oo = infinity) // Use :; to represent the infinity symbol for (count = 0; count < 48; count++) map[count] = 0; for (; count < 60; count++) map[count] = count - 47; // Numbers and :; for (; count < 128; count++) map[count] = 0; } return; } /** * Load a font from a .000 file. * * @param bonus whether to use FONTS.000 or BONUS.000 */ Font::Font (bool bonus) { File* file; unsigned char* pixels; int fileSize; int count, width, height; // Load font from FONTS.000 or BONUS.000 try { file = new File(bonus? "BONUS.000": "FONTS.000", false); } catch (int e) { throw e; } fileSize = file->getSize(); nCharacters = file->loadShort(256); if (bonus) { count = file->loadShort(); nCharacters -= count; // Skip sprites for (; count > 0; count--) { file->seek(4, false); width = file->loadShort(); if (width == 0xFFFF) width = 0; file->seek((width << 2) + file->loadShort(), false); } } // Load characters for (count = 0; count < nCharacters; count++) { if (file->tell() >= fileSize) { nCharacters = count; break; } width = file->loadShort(SW); height = file->loadShort(SH); if (bonus) width = (width + 3) & ~3; else width <<= 2; file->seek(4, false); pixels = file->loadPixels(width * height); characters[count] = createSurface(pixels, width, height); SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 254); delete[] pixels; } delete file; lineHeight = characters[0]->h; // Create blank character data pixels = new unsigned char[3]; memset(pixels, 254, 3); characters[nCharacters] = createSurface(pixels, 3, 1); SDL_SetColorKey(characters[nCharacters], SDL_SRCCOLORKEY, 254); delete[] pixels; // Create ASCII->font map count = 0; if (bonus) { for (; count < 42; count++) map[count] = nCharacters; map[count++] = 37; // * for (; count < 46; count++) map[count] = nCharacters; map[count++] = 39; // . map[count++] = 38; // / for (; count < 59; count++) map[count] = count - 22; // Numbers and : } else { for (; count < 37; count++) map[count] = nCharacters; map[count++] = 36; // % for (; count < 48; count++) map[count] = nCharacters; for (; count < 58; count++) map[count] = count - 22; // Numbers } for (; count < 65; count++) map[count] = nCharacters; for (; count < 91; count++) map[count] = count - 65; // Upper-case letters for (; count < 97; count++) map[count] = nCharacters; for (; count < 123; count++) map[count] = count - 97; // Lower-case letters for (; count < 128; count++) map[count] = nCharacters; nCharacters++; for (count = 0; count < 128; count++) { if (map[count] >= nCharacters) map[count] = 0; } return; } /** * Delete the font. */ Font::~Font () { int count; for (count = 0; count < nCharacters; count++) SDL_FreeSurface(characters[count]); return; } /** * Draw a string using the font. * * @param string The string to draw * @param x The x-coordinate at which to draw the string * @param y The y-coordinate at which to draw the string * * @return The x-coordinate of the end of the string */ int Font::showString (const char* string, int x, int y) { SDL_Surface* surface; SDL_Rect dst; unsigned int count; int xOffset, yOffset; // Determine the position at which to draw the first character xOffset = x; yOffset = y; // Go through each character of the string for (count = 0; string[count]; count++) { if (string[count] == '\n') { xOffset = x; yOffset += lineHeight; } else { // Determine the character's position on the screen dst.y = yOffset; dst.x = xOffset; // Determine the character's surface surface = characters[int(map[int(string[count])])]; // Draw the character to the screen SDL_BlitSurface(surface, NULL, canvas, &dst); xOffset += surface->w + 2; } } return xOffset; } /** * Draw a JJ1 cutscene string using the font. * * @param string The JJ1 cutstring to draw * @param x The x-coordinate at which to draw the string * @param y The y-coordinate at which to draw the string * * @return The x-coordinate of the end of the string */ int Font::showSceneString (const unsigned char* string, int x, int y) { SDL_Surface* surface; SDL_Rect dst; unsigned int count; int offset; // Determine the position at which to draw the first character offset = x; // Go through each character of the string for (count = 0; string[count]; count++) { // Determine the character's position on the screen dst.y = y; dst.x = offset; // Determine the character's surface if (string[count] < nCharacters) surface = characters[int(string[count])]; else surface = characters[0]; // Draw the character to the screen SDL_BlitSurface(surface, NULL, canvas, &dst); offset += surface->w + 1; } return offset; } /** * Draw a number using the font. * * @param n The number to draw * @param x The x-coordinate at which to draw the number * @param y The y-coordinate at which to draw the number * * @return The x-coordinate of the end of the number */ void Font::showNumber (int n, int x, int y) { SDL_Surface *surface; SDL_Rect dst; int count, offset; // n being 0 is a special case. It must not be considered to be a trailing // zero, as these are not displayed. if (!n) { // Determine 0's surface surface = characters[int(map[int('0')])]; // Determine 0's position on the screen dst.y = y; dst.x = x - surface->w; // Draw 0 to the screen SDL_BlitSurface(surface, NULL, canvas, &dst); return; } // Determine the length of the number to be drawn if (n > 0) count = n; else count = -n; // Determine the position at which to draw the lowest digit offset = x; while (count) { // Determine the digit's surface surface = characters[int(map['0' + (count % 10)])]; offset -= surface->w; // Determine the digit's position on the screen dst.y = y; dst.x = offset; // Draw the digit to the screen SDL_BlitSurface(surface, NULL, canvas, &dst); count /= 10; } // If needed, draw the negative sign if (n < 0) { // Determine the negative sign's surface surface = characters[int(map[int('-')])]; // Determine the negative sign's position on the screen dst.y = y; dst.x = offset - surface->w; // Draw the negative sign to the screen SDL_BlitSurface(surface, NULL, canvas, &dst); } return; } /** * Map a range of palette indices to another range * * @param start Start of original range * @param length Span of original range * @param newStart Start of new range * @param newLength Span of new range */ void Font::mapPalette (int start, int length, int newStart, int newLength) { SDL_Color palette[256]; int count; for (count = 0; count < length; count++) palette[count].r = palette[count].g = palette[count].b = (count * newLength / length) + newStart; for (count = 0; count < nCharacters; count++) SDL_SetPalette(characters[count], SDL_LOGPAL, palette, start, length); return; } /** * Restore a palette to its original state. */ void Font::restorePalette () { int count; for (count = 0; count < nCharacters; count++) video.restoreSurfacePalette(characters[count]); return; } /** * Get the height of a single line of any text. * * @return The height */ int Font::getHeight () { return lineHeight; } /** * Get the width of a single line of a given string. * * @param string The string to measure * * @return The width */ int Font::getStringWidth (const char *string) { int count; int stringWidth = 0; // Go through each character of the string for (count = 0; string[count]; count++) { // Only get the width of the first line if (string[count] == '\n') return stringWidth; stringWidth += characters[int(map[int(string[count])])]->w + 2; } return stringWidth; } /** * Get the width of a single line of a given JJ1 cutscene string. * * @param string The string to measure * * @return The width */ int Font::getSceneStringWidth (const unsigned char *string) { int count; int stringWidth = 0; // Go through each character of the string for (count = 0; string[count]; count++) { if (string[count] < nCharacters) stringWidth += characters[int(string[count])]->w + 1; else stringWidth += characters[0]->w + 1; } return stringWidth; } openjazz-20190106/src/io/gfx/font.h000066400000000000000000000037431341440264100167250ustar00rootroot00000000000000 /** * * @file font.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 3rd February 2009: Created font.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _FONT_H #define _FONT_H #include "OpenJazz.h" #include // Classes class File; /// Font class Font { private: SDL_Surface *characters[128]; ///< Symbol images int nCharacters; ///< Number of symbols unsigned char lineHeight; ///< Vertical spacing of displayed characters char map[128]; ///< Maps ASCII values to symbol indices public: Font (const char *fileName); Font (unsigned char *pixels, bool big); Font (bool bonus); ~Font (); int showString (const char *s, int x, int y); int showSceneString (const unsigned char *s, int x, int y); void showNumber (int n, int x, int y); void mapPalette (int start, int length, int newStart, int newLength); void restorePalette (); int getHeight (); int getStringWidth (const char *string); int getSceneStringWidth (const unsigned char *string); }; // Variables EXTERN Font *font2; /** Taken from .0FN file name */ EXTERN Font *fontbig; /** Taken from .0FN file name */ EXTERN Font *fontiny; /** Taken from .0FN file name */ EXTERN Font *fontmn1; /** Taken from .0FN file name */ EXTERN Font *fontmn2; /** Taken from .0FN file name */ EXTERN Font *panelBigFont; /** Found in PANEL.000 */ EXTERN Font *panelSmallFont; /** Found in PANEL.000 */ #endif openjazz-20190106/src/io/gfx/paletteeffects.cpp000066400000000000000000000367521341440264100213160ustar00rootroot00000000000000 /** * * @file paletteeffects.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed main.c to main.cpp and util.c to util.cpp * - 4th February 2009: Created palette.cpp from parts of main.cpp and util.cpp * - 1st August 2009: Renamed palette.cpp to paletteeffects.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "paletteeffects.h" #include "video.h" #include "jj1level/jj1level.h" #include "jj2level/jj2level.h" #include "level/levelplayer.h" #include "player/player.h" #include /** * Create a new palette effect. * * @param nextPE The next palette effect */ PaletteEffect::PaletteEffect (PaletteEffect* nextPE) { next = nextPE; return; } /** * Delete the palette effect. */ PaletteEffect::~PaletteEffect () { if (next) delete next; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void PaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); return; } /** * Create a new white-in palette effect. * * @param newDuration The length of time the effect will last * @param nextPE The next palette effect */ WhiteInPaletteEffect::WhiteInPaletteEffect (int newDuration, PaletteEffect* nextPE) : PaletteEffect (nextPE) { duration = newDuration; whiteness = F1 + FH; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void WhiteInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); if (whiteness > F1) { memset(shownPalette, 255, sizeof(SDL_Color) * 256); whiteness -= ITOF(mspf) / duration; } else if (whiteness > 0) { for (count = 0; count < 256; count++) { shownPalette[count].r = 255 - FTOI((255 - shownPalette[count].r) * (F1 - whiteness)); shownPalette[count].g = 255 - FTOI((255 - shownPalette[count].g) * (F1 - whiteness)); shownPalette[count].b = 255 - FTOI((255 - shownPalette[count].b) * (F1 - whiteness)); } whiteness -= ITOF(mspf) / duration; } if (direct) video.changePalette(shownPalette, 0, 256); return; } /** * Create a new fade-in palette effect. * * @param newDuration The length of time the effect will last * @param nextPE The next palette effect */ FadeInPaletteEffect::FadeInPaletteEffect (int newDuration, PaletteEffect* nextPE) : PaletteEffect (nextPE) { duration = newDuration; blackness = F1 + FH; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void FadeInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); if (blackness > F1) { memset(shownPalette, 0, sizeof(SDL_Color) * 256); blackness -= ITOF(mspf) / duration; } else if (blackness > 0) { for (count = 0; count < 256; count++) { shownPalette[count].r = FTOI(shownPalette[count].r * (F1 - blackness)); shownPalette[count].g = FTOI(shownPalette[count].g * (F1 - blackness)); shownPalette[count].b = FTOI(shownPalette[count].b * (F1 - blackness)); } blackness -= ITOF(mspf) / duration; } if (direct) video.changePalette(shownPalette, 0, 256); return; } /** * Create a new white-out palette effect. * * @param newDuration The length of time the effect will last * @param nextPE The next palette effect */ WhiteOutPaletteEffect::WhiteOutPaletteEffect (int newDuration, PaletteEffect* nextPE) : PaletteEffect (nextPE) { duration = newDuration; whiteness = 0; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void WhiteOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); if (whiteness > F1) { memset(shownPalette, 255, sizeof(SDL_Color) * 256); } else if (whiteness > 0) { for (count = 0; count < 256; count++) { shownPalette[count].r = 255 - FTOI((255 - shownPalette[count].r) * (F1 - whiteness)); shownPalette[count].g = 255 - FTOI((255 - shownPalette[count].g) * (F1 - whiteness)); shownPalette[count].b = 255 - FTOI((255 - shownPalette[count].b) * (F1 - whiteness)); } whiteness += ITOF(mspf) / duration; } else whiteness += ITOF(mspf) / duration; if (direct) video.changePalette(shownPalette, 0, 256); return; } /** * Create a new fade-out palette effect. * * @param newDuration The length of time the effect will last * @param nextPE The next palette effect */ FadeOutPaletteEffect::FadeOutPaletteEffect (int newDuration, PaletteEffect* nextPE) : PaletteEffect (nextPE) { duration = newDuration; blackness = -(F2 + F1); return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void FadeOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); if (blackness > F1) { memset(shownPalette, 0, sizeof(SDL_Color) * 256); } else if (blackness > 0) { for (count = 0; count < 256; count++) { shownPalette[count].r = FTOI(shownPalette[count].r * (F1 - blackness)); shownPalette[count].g = FTOI(shownPalette[count].g * (F1 - blackness)); shownPalette[count].b = FTOI(shownPalette[count].b * (F1 - blackness)); } blackness += ITOF(mspf) / duration; } else blackness += ITOF(mspf) / duration; if (direct) video.changePalette(shownPalette, 0, 256); return; } /** * Create a new flash-to-colour palette effect. * * @param newRed The red component of the colour * @param newGreen The green component of the colour * @param newBlue The blue component of the colour * @param newDuration The length of time the effect will last * @param nextPE The next palette effect */ FlashPaletteEffect::FlashPaletteEffect (unsigned char newRed, unsigned char newGreen, unsigned char newBlue, int newDuration, PaletteEffect* nextPE) : PaletteEffect (nextPE) { duration = newDuration; progress = -F1; red = newRed; green = newGreen; blue = newBlue; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void FlashPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); if (progress < 0) { for (count = 0; count < 256; count++) { shownPalette[count].r = FTOI((shownPalette[count].r * -progress) + (red * (progress + F1))); shownPalette[count].g = FTOI((shownPalette[count].g * -progress) + (green * (progress + F1))); shownPalette[count].b = FTOI((shownPalette[count].b * -progress) + (blue * (progress + F1))); } progress += ITOF(mspf) / duration; } else if (progress < F1) { for (count = 0; count < 256; count++) { shownPalette[count].r = FTOI((shownPalette[count].r * progress) + (red * (F1 - progress))); shownPalette[count].g = FTOI((shownPalette[count].g * progress) + (green * (F1 - progress))); shownPalette[count].b = FTOI((shownPalette[count].b * progress) + (blue * (F1 - progress))); } progress += ITOF(mspf) / duration; } if (direct) video.changePalette(shownPalette, 0, 256); return; } /** * Create a new colour rotation palette effect. * * @param newFirst The first palette index to be affected * @param newAmount The number of palette indices to be affected * @param newSpeed The speed of he rotation * @param nextPE The next palette effect */ RotatePaletteEffect::RotatePaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect * nextPE) : PaletteEffect (nextPE) { first = newFirst; amount = newAmount; speed = newSpeed; position = 0; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void RotatePaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { SDL_Color* currentPalette; int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); currentPalette = video.getPalette(); for (count = 0; count < amount; count++) { memcpy(shownPalette + first + count, currentPalette + first + ((count + FTOI(position)) % amount), sizeof(SDL_Color)); } position -= (mspf * speed) >> 10; while (position < 0) position += ITOF(amount); if (direct) video.changePalette(shownPalette + first, first, amount); return; } /** * Create a new parallaxing sky background palette effect. * * @param newFirst The first palette index to be affected * @param newAmount The number of palette indices to be affected * @param newSpeed The relative speed of the background * @param newSkyPalette Palette containing the sky's colours * @param nextPE The next palette effect */ SkyPaletteEffect::SkyPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, SDL_Color* newSkyPalette, PaletteEffect* nextPE) : PaletteEffect (nextPE) { skyPalette = newSkyPalette; first = newFirst; amount = newAmount; speed = newSpeed; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void SkyPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { int position, count, y; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); position = viewY + ((canvasH - 33) << 9) - F4; y = ((canvasH - 34) / 100) + 1; count = (((position * speed) / y) >> 20) % 255; if (direct) { if (count > 255 - amount) { video.changePalette(skyPalette + count, first, 255 - count); video.changePalette(skyPalette, first + (255 - count), count + amount - 255); } else { video.changePalette(skyPalette + count, first, amount); } } else { if (count > 255 - amount) { memcpy(shownPalette + first, skyPalette + count, sizeof(SDL_Color) * (255 - count)); memcpy(shownPalette + first + (255 - count), skyPalette, sizeof(SDL_Color) * (count + amount - 255)); } else { memcpy(shownPalette + first, skyPalette + count, sizeof(SDL_Color) * amount); } } return; } /** * Create a new 2D parallaxing background palette effect. * * @param newFirst The first palette index to be affected * @param newAmount The number of palette indices to be affected * @param newSpeed The relative speed of the background * @param nextPE The next palette effect */ P2DPaletteEffect::P2DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE) : PaletteEffect (nextPE) { first = newFirst; amount = newAmount; speed = newSpeed; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void P2DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { SDL_Color* currentPalette; int count, x, y, j; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); currentPalette = video.getPalette(); x = FTOI(((256 * 32) - FTOI(viewX)) * speed); y = FTOI(((64 * 32) - FTOI(viewY)) * speed); for (count = 0; count < amount >> 3; count++) { for (j = 0; j < 8; j++) { memcpy(shownPalette + first + (count << 3) + j, currentPalette + first + (((count + y) % 8) << 3) + ((j + x) % 8), sizeof(SDL_Color)); } } if (direct) video.changePalette(shownPalette + first, first, amount); return; } /** * Create a new 1D parallaxing background palette effect. * * @param newFirst The first palette index to be affected * @param newAmount The number of palette indices to be affected * @param newSpeed The relative speed of the background * @param nextPE The next palette effect */ P1DPaletteEffect::P1DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE) : PaletteEffect (nextPE) { first = newFirst; amount = newAmount; speed = newSpeed; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void P1DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { SDL_Color* currentPalette; fixed position; int count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); currentPalette = video.getPalette(); position = viewX + viewY; for (count = 0; count < amount; count++) { memcpy(shownPalette + first + count, currentPalette + first + ((count + (amount - 1 - (FTOI(MUL(position, speed)) % amount))) % amount), sizeof(SDL_Color)); } if (direct) video.changePalette(shownPalette + first, first, amount); return; } /** * Create a new water palette effect. * * @param newDepth Water depth * @param nextPE The next palette effect */ WaterPaletteEffect::WaterPaletteEffect (fixed newDepth, PaletteEffect* nextPE) : PaletteEffect (nextPE) { depth = newDepth; return; } /** * Apply the palette effect. * * @param shownPalette The palette the effect will be applied to * @param direct Whether or not to apply the effect directly * @param mspf Ticks per frame */ void WaterPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) { SDL_Color* currentPalette; int position, count; // Apply the next palette effect if (next) next->apply(shownPalette, direct, mspf); currentPalette = video.getPalette(); if (level) position = localPlayer->getLevelPlayer()->getY() - level->getWaterLevel(); else if (jj2Level) position = localPlayer->getLevelPlayer()->getY() - jj2Level->getWaterLevel(); else return; if (position <= 0) return; if (position < depth) { for (count = 0; count < 256; count++) { shownPalette[count].r = FTOI(currentPalette[count].r * (1023 - DIV(position, depth))); shownPalette[count].g = FTOI(currentPalette[count].g * (1023 - DIV(position, depth))); shownPalette[count].b = FTOI(currentPalette[count].b * (1023 - DIV(position, depth))); } } else memset(shownPalette, 0, sizeof(SDL_Color) * 256); if (direct) video.changePalette(shownPalette, 0, 256); return; } openjazz-20190106/src/io/gfx/paletteeffects.h000066400000000000000000000130311341440264100207440ustar00rootroot00000000000000 /** * * @file paletteeffects.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 4th February 2009: Created palette.h from parts of OpenJazz.h * - 1st August 2009: Renamed palette.h to paletteeffects.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PALETTE_H #define _PALETTE_H #include "OpenJazz.h" #include // Constants // Types of palette effect #define PE_FADE 0 /* Fades to black, then remains black */ #define PE_ROTATE 1 /* Cyclical colour animation */ // Level background palette effects #define PE_SKY 2 /* Transfers the appropriate section of the background palette to the main palette */ #define PE_2D 8 /* Real parallaxing background */ #define PE_1D 9 /* Diagonal lines parallaxing background */ #define PE_WATER 11 /* The deeper below water, the darker it gets */ // Class /// Palette effect base class class PaletteEffect { protected: PaletteEffect* next; ///< Next effect to use public: PaletteEffect (PaletteEffect* nextPE); virtual ~PaletteEffect (); virtual void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Dissolve from white palette effect class WhiteInPaletteEffect : public PaletteEffect { private: int duration; ///< Number of milliseconds the effect lasts fixed whiteness; public: WhiteInPaletteEffect (int newDuration, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Fade in palette effect class FadeInPaletteEffect : public PaletteEffect { private: int duration; ///< Number of milliseconds the effect lasts fixed blackness; public: FadeInPaletteEffect (int newDuration, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Dissolve to white palette effect class WhiteOutPaletteEffect : public PaletteEffect { private: int duration; ///< Number of milliseconds the effect lasts fixed whiteness; public: WhiteOutPaletteEffect (int newDuration, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Fade out palette effect class FadeOutPaletteEffect : public PaletteEffect { private: int duration; ///< Number of milliseconds the effect lasts fixed blackness; public: FadeOutPaletteEffect (int newDuration, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Flash colour (dissolve to it and back again) palette effect class FlashPaletteEffect : public PaletteEffect { private: int duration; ///< Number of milliseconds the effect lasts fixed progress; unsigned char red, green, blue; ///< Flash colour public: FlashPaletteEffect (unsigned char newRed, unsigned char newGreen, unsigned char newBlue, int newDuration, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Entry rotation palette effect class RotatePaletteEffect : public PaletteEffect { private: unsigned char first; ///< The first palette index affected int amount; ///< The number of (consecutive) palette indices affected fixed speed; ///< Rotations per second fixed position; public: RotatePaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Sky palette palette effect class SkyPaletteEffect : public PaletteEffect { private: SDL_Color* skyPalette; unsigned char first; ///< The first palette index affected int amount; ///< The number of (consecutive) palette indices affected fixed speed; ///< Relative Y speed - as in Jazz 2 public: SkyPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, SDL_Color* newSkyPalette, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// 2D parallaxing background palette effect class P2DPaletteEffect : public PaletteEffect { private: unsigned char first; ///< The first palette index affected int amount; ///< The number of (consecutive) palette indices affected fixed speed; ///< Relative X & Y speed - as in Jazz 2 public: P2DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// 1D parallaxing background palette effect class P1DPaletteEffect : public PaletteEffect { private: unsigned char first; ///< The first palette index affected int amount; ///< The number of (consecutive) palette indices affected fixed speed; ///< Relative X & Y speed - as in Jazz 2 public: P1DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; /// Underwater darkening palette effect class WaterPaletteEffect : public PaletteEffect { private: fixed depth; ///< Number of pixels between water surface and total darkness public: WaterPaletteEffect (fixed newDepth, PaletteEffect* nextPE); void apply (SDL_Color* shownPalette, bool direct, int mspf); }; #endif openjazz-20190106/src/io/gfx/scale2x/000077500000000000000000000000001341440264100171405ustar00rootroot00000000000000openjazz-20190106/src/io/gfx/scale2x/getopt.cpp000066400000000000000000000050651341440264100211540ustar00rootroot00000000000000/* * This file is part of the Advance project. * * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This source is extracted from the DJGPP LIBC library */ #define unconst(var, type) ((type)(var)) /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include int opterr = 1, optind = 1, optopt = 0; char *optarg = 0; #define BADCH (int)'?' #define EMSG "" int getopt(int nargc, char *const nargv[], char *ostr) { static const char *place = EMSG; /* option letter processing */ char *oli; /* option letter list index */ char *p; if (!*place) { if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; return(EOF); } if (place[1] && *++place == '-') { ++optind; place = EMSG; return(EOF); } } if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) { /* * if the user didn't specify '-' as an option, * assume it means EOF. */ if (optopt == (int)'-') return EOF; if (!*place) ++optind; if (opterr) { if (!(p = strrchr(*nargv, '/'))) p = *nargv; else ++p; fprintf(stderr, "%s: illegal option -- %c\n", p, optopt); } return BADCH; } if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; } else { /* need an argument */ if (*place) /* no white space */ optarg = unconst(place, char *); else if (nargc <= ++optind) { /* no arg */ place = EMSG; if (!(p = strrchr(*nargv, '/'))) p = *nargv; else ++p; if (opterr) fprintf(stderr, "%s: option requires an argument -- %c\n", p, optopt); return BADCH; } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } return optopt; /* dump back option letter */ } openjazz-20190106/src/io/gfx/scale2x/pixel.cpp000066400000000000000000000032131341440264100207640ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * Copyright (C) 2003 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "pixel.h" pixel_t pixel_get(int x, int y, const unsigned char* pix, unsigned slice, unsigned pixel, unsigned dx, unsigned dy, int opt_tes) { const unsigned char* p; unsigned i; pixel_t v; if (opt_tes) { if (x < 0) x += dx; if ((unsigned int)x >= dx) x -= dx; if (y < 0) y += dy; if ((unsigned int)y >= dy) y -= dy; } else { if (x < 0) x = 0; if ((unsigned int)x >= dx) x = dx - 1; if (y < 0) y = 0; if ((unsigned int)y >= dy) y = dy - 1; } p = pix + (y * slice) + (x * pixel); v = 0; for(i=0;i> (i*8); } } openjazz-20190106/src/io/gfx/scale2x/pixel.h000066400000000000000000000021471341440264100204360ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * Copyright (C) 2003 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __PIXEL_H #define __PIXEL_H typedef unsigned long long pixel_t; pixel_t pixel_get(int x, int y, const unsigned char* pix, unsigned slice, unsigned pixel, unsigned dx, unsigned dy, int opt_tes); void pixel_put(int x, int y, unsigned char* pix, unsigned slice, unsigned pixel, unsigned dx, unsigned dy, pixel_t v); #endif openjazz-20190106/src/io/gfx/scale2x/portable.h000066400000000000000000000023221341440264100211200ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * Copyright (C) 2001, 2002, 2003 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __PORTABLE_H #define __PORTABLE_H #if HAVE_CONFIG_H #include #endif /* ------------------------------------------------------------------------ */ /* getopt */ #if HAVE_GETOPT_H #include #endif #if HAVE_UNISTD_H #include #endif #if !HAVE_GETOPT int getopt(int argc, char * const *argv, const char *options); extern char *optarg; extern int optind, opterr, optopt; #endif #endif openjazz-20190106/src/io/gfx/scale2x/scale2x.cpp000066400000000000000000001221111341440264100212030ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file contains a C and MMX implementation of the Scale2x effect. * * You can find an high level description of the effect at : * * http://scale2x.sourceforge.net/ * * Alternatively at the previous license terms, you are allowed to use this * code in your program with these conditions: * - the program is not used in commercial activities. * - the whole source code of the program is released with the binary. * - derivative works of the program are allowed. */ #include "scale2x.h" #include /***************************************************************************/ /* Scale2x C implementation */ /** * Define the macro USE_SCALE_RANDOMWRITE to enable * an optimized version which writes memory in random order. * This version is a little faster if you write in system memory. * But it's a lot slower if you write in video memory. * So, enable it only if you are sure to never write directly in video memory. */ /* #define USE_SCALE_RANDOMWRITE */ #ifdef USE_SCALE_RANDOMWRITE static inline void scale2x_8_def_whole(scale2x_uint8* restrict dst0, scale2x_uint8* restrict dst1, const scale2x_uint8* restrict src0, const scale2x_uint8* restrict src1, const scale2x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } } #endif static inline void scale2x_8_def_border(scale2x_uint8* restrict dst, const scale2x_uint8* restrict src0, const scale2x_uint8* restrict src1, const scale2x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } static inline void scale2x_8_def_center(scale2x_uint8* restrict dst, const scale2x_uint8* restrict src0, const scale2x_uint8* restrict src1, const scale2x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } #ifdef USE_SCALE_RANDOMWRITE static inline void scale2x_16_def_whole(scale2x_uint16* restrict dst0, scale2x_uint16* restrict dst1, const scale2x_uint16* restrict src0, const scale2x_uint16* restrict src1, const scale2x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } } #endif static inline void scale2x_16_def_border(scale2x_uint16* restrict dst, const scale2x_uint16* restrict src0, const scale2x_uint16* restrict src1, const scale2x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } static inline void scale2x_16_def_center(scale2x_uint16* restrict dst, const scale2x_uint16* restrict src0, const scale2x_uint16* restrict src1, const scale2x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } #ifdef USE_SCALE_RANDOMWRITE static inline void scale2x_32_def_whole(scale2x_uint32* restrict dst0, scale2x_uint32* restrict dst1, const scale2x_uint32* restrict src0, const scale2x_uint32* restrict src1, const scale2x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 2; dst1 += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; } } #endif static inline void scale2x_32_def_border(scale2x_uint32* restrict dst, const scale2x_uint32* restrict src0, const scale2x_uint32* restrict src1, const scale2x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; dst[1] = src1[0] == src0[0] ? src0[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } static inline void scale2x_32_def_center(scale2x_uint32* restrict dst, const scale2x_uint32* restrict src0, const scale2x_uint32* restrict src1, const scale2x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } ++src0; ++src1; ++src2; dst += 2; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; } } /** * Scale by a factor of 2 a row of pixels of 8 bits. * The function is implemented in C. * The pixels over the left and right borders are assumed of the same color of * the pixels on the border. * Note that the implementation is optimized to write data sequentially to * maximize the bandwidth on video memory. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst1, src0, src1, src2, count); #else scale2x_8_def_border(dst0, src0, src1, src2, count); scale2x_8_def_border(dst1, src2, src1, src0, count); #endif } /** * Scale by a factor of 2 a row of pixels of 16 bits. * This function operates like scale2x_8_def() but for 16 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst1, src0, src1, src2, count); #else scale2x_16_def_border(dst0, src0, src1, src2, count); scale2x_16_def_border(dst1, src2, src1, src0, count); #endif } /** * Scale by a factor of 2 a row of pixels of 32 bits. * This function operates like scale2x_8_def() but for 32 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst1, src0, src1, src2, count); #else scale2x_32_def_border(dst0, src0, src1, src2, count); scale2x_32_def_border(dst1, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x3 a row of pixels of 8 bits. * \note Like scale2x_8_def(); */ void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst2, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); #else scale2x_8_def_border(dst0, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); scale2x_8_def_border(dst2, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x3 a row of pixels of 16 bits. * \note Like scale2x_16_def(); */ void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst2, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); #else scale2x_16_def_border(dst0, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); scale2x_16_def_border(dst2, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x3 a row of pixels of 32 bits. * \note Like scale2x_32_def(); */ void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst2, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); #else scale2x_32_def_border(dst0, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); scale2x_32_def_border(dst2, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x4 a row of pixels of 8 bits. * \note Like scale2x_8_def(); */ void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_8_def_whole(dst0, dst3, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); scale2x_8_def_center(dst2, src0, src1, src2, count); #else scale2x_8_def_border(dst0, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); scale2x_8_def_center(dst2, src0, src1, src2, count); scale2x_8_def_border(dst3, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x4 a row of pixels of 16 bits. * \note Like scale2x_16_def(); */ void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_16_def_whole(dst0, dst3, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); scale2x_16_def_center(dst2, src0, src1, src2, count); #else scale2x_16_def_border(dst0, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); scale2x_16_def_center(dst2, src0, src1, src2, count); scale2x_16_def_border(dst3, src2, src1, src0, count); #endif } /** * Scale by a factor of 2x4 a row of pixels of 32 bits. * \note Like scale2x_32_def(); */ void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale2x_32_def_whole(dst0, dst3, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); scale2x_32_def_center(dst2, src0, src1, src2, count); #else scale2x_32_def_border(dst0, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); scale2x_32_def_center(dst2, src0, src1, src2, count); scale2x_32_def_border(dst3, src2, src1, src0, count); #endif } /***************************************************************************/ /* Scale2x MMX implementation */ #if defined(__GNUC__) && defined(__i386__) /* * Apply the Scale2x effect at a single row. * This function must be called only by the other scale2x functions. * * Considering the pixel map : * * ABC (src0) * DEF (src1) * GHI (src2) * * this functions compute 2 new pixels in substitution of the source pixel E * like this map : * * ab (dst) * * with these variables : * * ¤t -> E * ¤t_left -> D * ¤t_right -> F * ¤t_upper -> B * ¤t_lower -> H * * %0 -> current_upper * %1 -> current * %2 -> current_lower * %3 -> dst * %4 -> counter * * %mm0 -> *current_left * %mm1 -> *current_next * %mm2 -> tmp0 * %mm3 -> tmp1 * %mm4 -> tmp2 * %mm5 -> tmp3 * %mm6 -> *current_upper * %mm7 -> *current */ static inline void scale2x_8_mmx_border(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { assert(count >= 16); assert(count % 8 == 0); /* always do the first and last run */ count -= 2*8; __asm__ __volatile__( /* first run */ /* set the current, current_pre, current_next registers */ "movq 0(%1), %%mm0\n" "movq 0(%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psllq $56, %%mm0\n" "psllq $56, %%mm1\n" "psrlq $56, %%mm0\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $8, %%mm2\n" "psrlq $8, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqb %%mm6, %%mm2\n" "pcmpeqb %%mm6, %%mm4\n" "pcmpeqb (%2), %%mm3\n" "pcmpeqb (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqb %%mm1, %%mm2\n" "pcmpeqb %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklbw %%mm4, %%mm2\n" "punpckhbw %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" /* central runs */ "shrl $3, %4\n" "jz 1f\n" "0:\n" /* set the current, current_pre, current_next registers */ "movq -8(%1), %%mm0\n" "movq (%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psrlq $56, %%mm0\n" "psllq $56, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $8, %%mm2\n" "psrlq $8, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqb %%mm6, %%mm2\n" "pcmpeqb %%mm6, %%mm4\n" "pcmpeqb (%2), %%mm3\n" "pcmpeqb (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqb %%mm1, %%mm2\n" "pcmpeqb %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklbw %%mm4, %%mm2\n" "punpckhbw %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" "decl %4\n" "jnz 0b\n" "1:\n" /* final run */ /* set the current, current_pre, current_next registers */ "movq (%1), %%mm1\n" "movq (%1), %%mm7\n" "movq -8(%1), %%mm0\n" "psrlq $56, %%mm1\n" "psrlq $56, %%mm0\n" "psllq $56, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $8, %%mm2\n" "psrlq $8, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqb %%mm6, %%mm2\n" "pcmpeqb %%mm6, %%mm4\n" "pcmpeqb (%2), %%mm3\n" "pcmpeqb (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqb %%mm1, %%mm2\n" "pcmpeqb %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklbw %%mm4, %%mm2\n" "punpckhbw %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) : : "cc" ); } static inline void scale2x_16_mmx_border(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { assert(count >= 8); assert(count % 4 == 0); /* always do the first and last run */ count -= 2*4; __asm__ __volatile__( /* first run */ /* set the current, current_pre, current_next registers */ "movq 0(%1), %%mm0\n" "movq 0(%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psllq $48, %%mm0\n" "psllq $48, %%mm1\n" "psrlq $48, %%mm0\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $16, %%mm2\n" "psrlq $16, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqw %%mm6, %%mm2\n" "pcmpeqw %%mm6, %%mm4\n" "pcmpeqw (%2), %%mm3\n" "pcmpeqw (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqw %%mm1, %%mm2\n" "pcmpeqw %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklwd %%mm4, %%mm2\n" "punpckhwd %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" /* central runs */ "shrl $2, %4\n" "jz 1f\n" "0:\n" /* set the current, current_pre, current_next registers */ "movq -8(%1), %%mm0\n" "movq (%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psrlq $48, %%mm0\n" "psllq $48, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $16, %%mm2\n" "psrlq $16, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqw %%mm6, %%mm2\n" "pcmpeqw %%mm6, %%mm4\n" "pcmpeqw (%2), %%mm3\n" "pcmpeqw (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqw %%mm1, %%mm2\n" "pcmpeqw %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklwd %%mm4, %%mm2\n" "punpckhwd %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" "decl %4\n" "jnz 0b\n" "1:\n" /* final run */ /* set the current, current_pre, current_next registers */ "movq (%1), %%mm1\n" "movq (%1), %%mm7\n" "movq -8(%1), %%mm0\n" "psrlq $48, %%mm1\n" "psrlq $48, %%mm0\n" "psllq $48, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $16, %%mm2\n" "psrlq $16, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqw %%mm6, %%mm2\n" "pcmpeqw %%mm6, %%mm4\n" "pcmpeqw (%2), %%mm3\n" "pcmpeqw (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqw %%mm1, %%mm2\n" "pcmpeqw %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpcklwd %%mm4, %%mm2\n" "punpckhwd %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) : : "cc" ); } static inline void scale2x_32_mmx_border(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { assert(count >= 4); assert(count % 2 == 0); /* always do the first and last run */ count -= 2*2; __asm__ __volatile__( /* first run */ /* set the current, current_pre, current_next registers */ "movq 0(%1), %%mm0\n" "movq 0(%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psllq $32, %%mm0\n" "psllq $32, %%mm1\n" "psrlq $32, %%mm0\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $32, %%mm2\n" "psrlq $32, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqd %%mm6, %%mm2\n" "pcmpeqd %%mm6, %%mm4\n" "pcmpeqd (%2), %%mm3\n" "pcmpeqd (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqd %%mm1, %%mm2\n" "pcmpeqd %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpckldq %%mm4, %%mm2\n" "punpckhdq %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" /* central runs */ "shrl $1, %4\n" "jz 1f\n" "0:\n" /* set the current, current_pre, current_next registers */ "movq -8(%1), %%mm0\n" "movq (%1), %%mm7\n" "movq 8(%1), %%mm1\n" "psrlq $32, %%mm0\n" "psllq $32, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $32, %%mm2\n" "psrlq $32, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqd %%mm6, %%mm2\n" "pcmpeqd %%mm6, %%mm4\n" "pcmpeqd (%2), %%mm3\n" "pcmpeqd (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqd %%mm1, %%mm2\n" "pcmpeqd %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpckldq %%mm4, %%mm2\n" "punpckhdq %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" /* next */ "addl $8, %0\n" "addl $8, %1\n" "addl $8, %2\n" "addl $16, %3\n" "decl %4\n" "jnz 0b\n" "1:\n" /* final run */ /* set the current, current_pre, current_next registers */ "movq (%1), %%mm1\n" "movq (%1), %%mm7\n" "movq -8(%1), %%mm0\n" "psrlq $32, %%mm1\n" "psrlq $32, %%mm0\n" "psllq $32, %%mm1\n" "movq %%mm7, %%mm2\n" "movq %%mm7, %%mm3\n" "psllq $32, %%mm2\n" "psrlq $32, %%mm3\n" "por %%mm2, %%mm0\n" "por %%mm3, %%mm1\n" /* current_upper */ "movq (%0), %%mm6\n" /* compute the upper-left pixel for dst on %%mm2 */ /* compute the upper-right pixel for dst on %%mm4 */ "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "movq %%mm0, %%mm3\n" "movq %%mm1, %%mm5\n" "pcmpeqd %%mm6, %%mm2\n" "pcmpeqd %%mm6, %%mm4\n" "pcmpeqd (%2), %%mm3\n" "pcmpeqd (%2), %%mm5\n" "pandn %%mm2, %%mm3\n" "pandn %%mm4, %%mm5\n" "movq %%mm0, %%mm2\n" "movq %%mm1, %%mm4\n" "pcmpeqd %%mm1, %%mm2\n" "pcmpeqd %%mm0, %%mm4\n" "pandn %%mm3, %%mm2\n" "pandn %%mm5, %%mm4\n" "movq %%mm2, %%mm3\n" "movq %%mm4, %%mm5\n" "pand %%mm6, %%mm2\n" "pand %%mm6, %%mm4\n" "pandn %%mm7, %%mm3\n" "pandn %%mm7, %%mm5\n" "por %%mm3, %%mm2\n" "por %%mm5, %%mm4\n" /* set *dst */ "movq %%mm2, %%mm3\n" "punpckldq %%mm4, %%mm2\n" "punpckhdq %%mm4, %%mm3\n" "movq %%mm2, (%3)\n" "movq %%mm3, 8(%3)\n" : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) : : "cc" ); } /** * Scale by a factor of 2 a row of pixels of 8 bits. * This is a very fast MMX implementation. * The implementation uses a combination of cmp/and/not operations to * completly remove the need of conditional jumps. This trick give the * major speed improvement. * Also, using the 8 bytes MMX registers more than one pixel are computed * at the same time. * Before calling this function you must ensure that the currenct CPU supports * the MMX instruction set. After calling it you must be sure to call the EMMS * instruction before any floating-point operation. * The pixels over the left and right borders are assumed of the same color of * the pixels on the border. * Note that the implementation is optimized to write data sequentially to * maximize the bandwidth on video memory. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. It must * be at least 16 and a multiple of 8. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { if (count % 8 != 0 || count < 16) { scale2x_8_def(dst0, dst1, src0, src1, src2, count); } else { scale2x_8_mmx_border(dst0, src0, src1, src2, count); scale2x_8_mmx_border(dst1, src2, src1, src0, count); } } /** * Scale by a factor of 2 a row of pixels of 16 bits. * This function operates like scale2x_8_mmx() but for 16 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. It must * be at least 8 and a multiple of 4. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { if (count % 4 != 0 || count < 8) { scale2x_16_def(dst0, dst1, src0, src1, src2, count); } else { scale2x_16_mmx_border(dst0, src0, src1, src2, count); scale2x_16_mmx_border(dst1, src2, src1, src0, count); } } /** * Scale by a factor of 2 a row of pixels of 32 bits. * This function operates like scale2x_8_mmx() but for 32 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. It must * be at least 4 and a multiple of 2. * \param dst0 First destination row, double length in pixels. * \param dst1 Second destination row, double length in pixels. */ void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { if (count % 2 != 0 || count < 4) { scale2x_32_def(dst0, dst1, src0, src1, src2, count); } else { scale2x_32_mmx_border(dst0, src0, src1, src2, count); scale2x_32_mmx_border(dst1, src2, src1, src0, count); } } /** * Scale by a factor of 2x3 a row of pixels of 8 bits. * This function operates like scale2x_8_mmx() but with an expansion * factor of 2x3 instead of 2x2. */ void scale2x3_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { if (count % 8 != 0 || count < 16) { scale2x3_8_def(dst0, dst1, dst2, src0, src1, src2, count); } else { scale2x_8_mmx_border(dst0, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); scale2x_8_mmx_border(dst2, src2, src1, src0, count); } } /** * Scale by a factor of 2x3 a row of pixels of 16 bits. * This function operates like scale2x_16_mmx() but with an expansion * factor of 2x3 instead of 2x2. */ void scale2x3_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { if (count % 4 != 0 || count < 8) { scale2x3_16_def(dst0, dst1, dst2, src0, src1, src2, count); } else { scale2x_16_mmx_border(dst0, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); scale2x_16_mmx_border(dst2, src2, src1, src0, count); } } /** * Scale by a factor of 2x3 a row of pixels of 32 bits. * This function operates like scale2x_32_mmx() but with an expansion * factor of 2x3 instead of 2x2. */ void scale2x3_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { if (count % 2 != 0 || count < 4) { scale2x3_32_def(dst0, dst1, dst2, src0, src1, src2, count); } else { scale2x_32_mmx_border(dst0, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); scale2x_32_mmx_border(dst2, src2, src1, src0, count); } } /** * Scale by a factor of 2x4 a row of pixels of 8 bits. * This function operates like scale2x_8_mmx() but with an expansion * factor of 2x4 instead of 2x2. */ void scale2x4_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { if (count % 8 != 0 || count < 16) { scale2x4_8_def(dst0, dst1, dst2, dst3, src0, src1, src2, count); } else { scale2x_8_mmx_border(dst0, src0, src1, src2, count); scale2x_8_def_center(dst1, src0, src1, src2, count); scale2x_8_def_center(dst2, src0, src1, src2, count); scale2x_8_mmx_border(dst3, src2, src1, src0, count); } } /** * Scale by a factor of 2x4 a row of pixels of 16 bits. * This function operates like scale2x_16_mmx() but with an expansion * factor of 2x4 instead of 2x2. */ void scale2x4_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { if (count % 4 != 0 || count < 8) { scale2x4_16_def(dst0, dst1, dst2, dst3, src0, src1, src2, count); } else { scale2x_16_mmx_border(dst0, src0, src1, src2, count); scale2x_16_def_center(dst1, src0, src1, src2, count); scale2x_16_def_center(dst2, src0, src1, src2, count); scale2x_16_mmx_border(dst3, src2, src1, src0, count); } } /** * Scale by a factor of 2x4 a row of pixels of 32 bits. * This function operates like scale2x_32_mmx() but with an expansion * factor of 2x4 instead of 2x2. */ void scale2x4_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { if (count % 2 != 0 || count < 4) { scale2x4_32_def(dst0, dst1, dst2, dst3, src0, src1, src2, count); } else { scale2x_32_mmx_border(dst0, src0, src1, src2, count); scale2x_32_def_center(dst1, src0, src1, src2, count); scale2x_32_def_center(dst2, src0, src1, src2, count); scale2x_32_mmx_border(dst3, src2, src1, src0, count); } } #endif openjazz-20190106/src/io/gfx/scale2x/scale2x.h000066400000000000000000000107601341440264100206560ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __SCALE2X_H #define __SCALE2X_H #define restrict typedef unsigned char scale2x_uint8; typedef unsigned short scale2x_uint16; typedef unsigned scale2x_uint32; void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); void scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); void scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); #if defined(__GNUC__) && defined(__i386__) void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); void scale2x3_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x3_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x3_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); void scale2x4_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count); void scale2x4_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count); void scale2x4_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count); /** * End the use of the MMX instructions. * This function must be called before using any floating-point operations. */ static inline void scale2x_mmx_emms(void) { __asm__ __volatile__ ( "emms" ); } #endif #endif openjazz-20190106/src/io/gfx/scale2x/scale3x.cpp000066400000000000000000000571631341440264100212220ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file contains a C and MMX implementation of the Scale2x effect. * * You can find an high level description of the effect at : * * http://scale2x.sourceforge.net/ * * Alternatively at the previous license terms, you are allowed to use this * code in your program with these conditions: * - the program is not used in commercial activities. * - the whole source code of the program is released with the binary. * - derivative works of the program are allowed. */ #include "scale3x.h" #include /***************************************************************************/ /* Scale3x C implementation */ /** * Define the macro USE_SCALE_RANDOMWRITE to enable * an optimized version which writes memory in random order. * This version is a little faster if you write in system memory. * But it's a lot slower if you write in video memory. * So, enable it only if you are sure to never write directly in video memory. */ /* #define USE_SCALE_RANDOMWRITE */ #ifdef USE_SCALE_RANDOMWRITE static inline void scale3x_8_def_whole(scale3x_uint8* restrict dst0, scale3x_uint8* restrict dst1, scale3x_uint8* restrict dst2, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0]; dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[0]; dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } } #endif static inline void scale3x_8_def_border(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } static inline void scale3x_8_def_center(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } #ifdef USE_SCALE_RANDOMWRITE static inline void scale3x_16_def_whole(scale3x_uint16* restrict dst0, scale3x_uint16* restrict dst1, scale3x_uint16* restrict dst2, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0]; dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[0]; dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } } #endif static inline void scale3x_16_def_border(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } static inline void scale3x_16_def_center(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } #ifdef USE_SCALE_RANDOMWRITE static inline void scale3x_32_def_whole(scale3x_uint32* restrict dst0, scale3x_uint32* restrict dst1, scale3x_uint32* restrict dst2, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst0[0] = src1[0]; dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[0]; dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } ++src0; ++src1; ++src2; dst0 += 3; dst1 += 3; dst2 += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst0[2] = src1[0]; dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst1[1] = src1[0]; dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; dst2[2] = src1[0]; } else { dst0[0] = src1[0]; dst0[1] = src1[0]; dst0[2] = src1[0]; dst1[0] = src1[0]; dst1[1] = src1[0]; dst1[2] = src1[0]; dst2[0] = src1[0]; dst2[1] = src1[0]; dst2[2] = src1[0]; } } #endif static inline void scale3x_32_def_border(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = src1[0]; dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[1] == src0[0] ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; dst[2] = src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } static inline void scale3x_32_def_center(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count) { assert(count >= 2); /* first pixel */ if (src0[0] != src2[0] && src1[0] != src1[1]) { dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; /* central pixels */ count -= 2; while (count) { if (src0[0] != src2[0] && src1[-1] != src1[1]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } ++src0; ++src1; ++src2; dst += 3; --count; } /* last pixel */ if (src0[0] != src2[0] && src1[-1] != src1[0]) { dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; dst[1] = src1[0]; dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; } else { dst[0] = src1[0]; dst[1] = src1[0]; dst[2] = src1[0]; } } /** * Scale by a factor of 3 a row of pixels of 8 bits. * The function is implemented in C. * The pixels over the left and right borders are assumed of the same color of * the pixels on the border. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, triple length in pixels. * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count); #else scale3x_8_def_border(dst0, src0, src1, src2, count); scale3x_8_def_center(dst1, src0, src1, src2, count); scale3x_8_def_border(dst2, src2, src1, src0, count); #endif } /** * Scale by a factor of 3 a row of pixels of 16 bits. * This function operates like scale3x_8_def() but for 16 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, triple length in pixels. * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count); #else scale3x_16_def_border(dst0, src0, src1, src2, count); scale3x_16_def_center(dst1, src0, src1, src2, count); scale3x_16_def_border(dst2, src2, src1, src0, count); #endif } /** * Scale by a factor of 3 a row of pixels of 32 bits. * This function operates like scale3x_8_def() but for 32 bits pixels. * \param src0 Pointer at the first pixel of the previous row. * \param src1 Pointer at the first pixel of the current row. * \param src2 Pointer at the first pixel of the next row. * \param count Length in pixels of the src0, src1 and src2 rows. * It must be at least 2. * \param dst0 First destination row, triple length in pixels. * \param dst1 Second destination row, triple length in pixels. * \param dst2 Third destination row, triple length in pixels. */ void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) { #ifdef USE_SCALE_RANDOMWRITE scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count); #else scale3x_32_def_border(dst0, src0, src1, src2, count); scale3x_32_def_center(dst1, src0, src1, src2, count); scale3x_32_def_border(dst2, src2, src1, src0, count); #endif } openjazz-20190106/src/io/gfx/scale2x/scale3x.h000066400000000000000000000030111341440264100206460ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __SCALE3X_H #define __SCALE3X_H #define restrict typedef unsigned char scale3x_uint8; typedef unsigned short scale3x_uint16; typedef unsigned scale3x_uint32; void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count); void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count); void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count); #endif openjazz-20190106/src/io/gfx/scale2x/scalebit.cpp000066400000000000000000000450731341440264100214430ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * Copyright (C) 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file contains an example implementation of the Scale effect * applyed to a generic bitmap. * * You can find an high level description of the effect at : * * http://scale2x.sourceforge.net/ * * Alternatively at the previous license terms, you are allowed to use this * code in your program with these conditions: * - the program is not used in commercial activities. * - the whole source code of the program is released with the binary. * - derivative works of the program are allowed. */ #include "scale2x.h" #include "scale3x.h" #include #include #define SSDST(bits, num) (scale2x_uint##bits *)dst##num #define SSSRC(bits, num) (const scale2x_uint##bits *)src##num /** * Apply the Scale2x effect on a group of rows. Used internally. */ static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) { switch (pixel) { #if defined(__GNUC__) && defined(__i386__) case 1 : scale2x_8_mmx(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x_16_mmx(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x_32_mmx(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #else case 1 : scale2x_8_def(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x_16_def(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x_32_def(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #endif } } /** * Apply the Scale2x3 effect on a group of rows. Used internally. */ static inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) { switch (pixel) { #if defined(__GNUC__) && defined(__i386__) case 1 : scale2x3_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x3_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x3_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #else case 1 : scale2x3_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x3_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x3_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #endif } } /** * Apply the Scale2x4 effect on a group of rows. Used internally. */ static inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) { switch (pixel) { #if defined(__GNUC__) && defined(__i386__) case 1 : scale2x4_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x4_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x4_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #else case 1 : scale2x4_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale2x4_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale2x4_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; #endif } } /** * Apply the Scale3x effect on a group of rows. Used internally. */ static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) { switch (pixel) { case 1 : scale3x_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break; case 2 : scale3x_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break; case 4 : scale3x_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break; } } /** * Apply the Scale4x effect on a group of rows. Used internally. */ static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) { stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row); stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row); } #define SCDST(i) (dst+(i)*dst_slice) #define SCSRC(i) (src+(i)*src_slice) #define SCMID(i) (mid[(i)]) /** * Apply the Scale2x effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 2x2 times the size of the source bitmap. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; unsigned count; assert(height >= 2); count = height; stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); dst = SCDST(2); count -= 2; while (count) { stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(2); src = SCSRC(1); --count; } stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width); #if defined(__GNUC__) && defined(__i386__) scale2x_mmx_emms(); #endif } /** * Apply the Scale2x3 effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 2x3 times the size of the source bitmap. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; unsigned count; assert(height >= 2); count = height; stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); dst = SCDST(3); count -= 2; while (count) { stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(3); src = SCSRC(1); --count; } stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width); #if defined(__GNUC__) && defined(__i386__) scale2x_mmx_emms(); #endif } /** * Apply the Scale2x4 effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 2x4 times the size of the source bitmap. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; unsigned count; assert(height >= 2); count = height; stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); dst = SCDST(4); count -= 2; while (count) { stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(4); src = SCSRC(1); --count; } stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width); #if defined(__GNUC__) && defined(__i386__) scale2x_mmx_emms(); #endif } /** * Apply the Scale3x effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 3x3 times the size of the source bitmap. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; unsigned count; assert(height >= 2); count = height; stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); dst = SCDST(3); count -= 2; while (count) { stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); dst = SCDST(3); src = SCSRC(1); --count; } stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width); } /** * Apply the Scale4x effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 4x4 times the size of the source bitmap. * \note This function requires also a small buffer bitmap used internally to store * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel, * and a vertical size of 6 rows. The memory of this buffer must not be allocated * in video memory because it's also read and not only written. Generally * a heap (malloc) or a stack (alloca) buffer is the best choice. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_mid Pointer at the first pixel of the buffer bitmap. * \param mid_slice Size in bytes of a buffer bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned char* dst = (unsigned char*)void_dst; const unsigned char* src = (const unsigned char*)void_src; unsigned count; unsigned char* mid[6]; assert(height >= 4); count = height; /* set the 6 buffer pointers */ mid[0] = (unsigned char*)void_mid; mid[1] = mid[0] + mid_slice; mid[2] = mid[1] + mid_slice; mid[3] = mid[2] + mid_slice; mid[4] = mid[3] + mid_slice; mid[5] = mid[4] + mid_slice; stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width); stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width); dst = SCDST(4); stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width); dst = SCDST(4); count -= 4; while (count) { unsigned char* tmp; stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width); stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width); dst = SCDST(4); src = SCSRC(1); tmp = SCMID(0); /* shift by 2 position */ SCMID(0) = SCMID(2); SCMID(2) = SCMID(4); SCMID(4) = tmp; tmp = SCMID(1); SCMID(1) = SCMID(3); SCMID(3) = SCMID(5); SCMID(5) = tmp; --count; } stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width); stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width); dst = SCDST(4); stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width); #if defined(__GNUC__) && defined(__i386__) scale2x_mmx_emms(); #endif } /** * Apply the Scale4x effect on a bitmap. * The destination bitmap is filled with the scaled version of the source bitmap. * The source bitmap isn't modified. * The destination bitmap must be manually allocated before calling the function, * note that the resulting size is exactly 4x4 times the size of the source bitmap. * \note This function operates like ::scale4x_buf() but the intermediate buffer is * automatically allocated in the stack. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { unsigned mid_slice; void* mid; mid_slice = 2 * pixel * width; /* required space for 1 row buffer */ mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */ mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */ if (!mid) return; scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height); free(mid); } /** * Check if the scale implementation is applicable at the given arguments. * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. * \return * - -1 on precondition violated. * - 0 on success. */ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height) { if (pixel != 1 && pixel != 2 && pixel != 4) return -1; switch (scale) { case 202 : case 203 : case 204 : case 2 : case 303 : case 3 : if (height < 2) return -1; break; case 404 : case 4 : if (height < 4) return -1; break; default: return -1; } if (width < 2) return -1; return 0; } /** * Apply the Scale effect on a bitmap. * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x(). * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { switch (scale) { case 202 : case 2 : scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 203 : scale2x3(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 204 : scale2x4(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 303 : case 3 : scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 404 : case 4 : scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; } } openjazz-20190106/src/io/gfx/scale2x/scalebit.h000066400000000000000000000033371341440264100211050ustar00rootroot00000000000000/* * This file is part of the Scale2x project. * * Copyright (C) 2003 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file contains an example implementation of the Scale effect * applyed to a generic bitmap. * * You can find an high level description of the effect at : * * http://scale2x.sourceforge.net/ * * Alternatively at the previous license terms, you are allowed to use this * code in your program with these conditions: * - the program is not used in commercial activities. * - the whole source code of the program is released with the binary. * - derivative works of the program are allowed. */ #ifndef __SCALEBIT_H #define __SCALEBIT_H int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height); void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height); void Simple2x(unsigned char *srcPtr, unsigned int srcPitch, unsigned char *deltaPtr, unsigned char *dstPtr, unsigned int dstPitch, int width, int height); #endif openjazz-20190106/src/io/gfx/scale2x/simple2x.cpp000066400000000000000000000056711341440264100214200ustar00rootroot00000000000000// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA 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, or(at your option) // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* * Code adapted To openjazz by Pickle (from Openbor adapted by SX * simple2x.c - Trying to scale 2x. * * */ #include "scalebit.h" void Simple2x(unsigned char *srcPtr, unsigned int srcPitch, unsigned char *deltaPtr, unsigned char *dstPtr, unsigned int dstPitch, int width, int height) { (void)deltaPtr; unsigned char *nextLine, *finish; nextLine = dstPtr + dstPitch; do { unsigned char *bP = (unsigned char *) srcPtr; unsigned char *dP = (unsigned char *) dstPtr; unsigned char *nL = (unsigned char *) nextLine; unsigned char currentPixel; finish = (unsigned char *) bP + ((width+2) << 1); currentPixel = *bP++; do { #ifdef BIG_ENDIAN unsigned char color = currentPixel >> 16; #else unsigned char color = currentPixel & 0xffff; #endif color = color | (color << 16); *(dP) = color; *(nL) = color; //#ifdef BIG_ENDIAN // color = currentPixel & 0xffff; //#else // color = currentPixel >> 16; //#endif color = color| (color << 16); *(dP + 1) = color; *(nL + 1) = color; currentPixel = *bP++; dP += 2; nL += 2; } while ((unsigned char *) bP < finish); srcPtr += srcPitch; dstPtr += dstPitch << 1; nextLine += dstPitch << 1; } while (--height); } void Simple2x32(unsigned char *srcPtr, unsigned int srcPitch, unsigned char *deltaPtr, unsigned char *dstPtr, unsigned int dstPitch, int width, int height) { (void)deltaPtr; unsigned char *nextLine, *finish; nextLine = dstPtr + dstPitch; do { unsigned int *bP = (unsigned int *) srcPtr; unsigned int *dP = (unsigned int *) dstPtr; unsigned int *nL = (unsigned int *) nextLine; unsigned int currentPixel; finish = (unsigned char *) bP + ((width+1) << 2); currentPixel = *bP++; do { unsigned int color = currentPixel; *(dP) = color; *(dP+1) = color; *(nL) = color; *(nL + 1) = color; currentPixel = *bP++; dP += 2; nL += 2; } while ((unsigned char *) bP < finish); srcPtr += srcPitch; dstPtr += dstPitch << 1; nextLine += dstPitch << 1; } while (--height); } openjazz-20190106/src/io/gfx/sprite.cpp000066400000000000000000000123031341440264100176100ustar00rootroot00000000000000 /** * * @file sprite.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp * - 26th July 2009: Created anim.cpp from parts of sprite.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "video.h" #include "sprite.h" /** * Create a sprite. */ Sprite::Sprite () { pixels = NULL; xOffset = 0; yOffset = 0; return; } /** * Delete the sprite. */ Sprite::~Sprite () { if (pixels) SDL_FreeSurface(pixels); return; } /** * Make the sprite blank. */ void Sprite::clearPixels () { unsigned char data; if (pixels) SDL_FreeSurface(pixels); data = 0; pixels = createSurface(&data, 1, 1); SDL_SetColorKey(pixels, SDL_SRCCOLORKEY, 0); return; } void Sprite::setOffset (short int x, short int y) { xOffset = x; yOffset = y; return; } /** * Set new pixel data for the sprite. * * @param data The new pixel data * @param width The width of the sprite image * @param height The height of the sprite image * @param key The transparent pixel value */ void Sprite::setPixels (unsigned char *data, int width, int height, unsigned char key) { if (pixels) SDL_FreeSurface(pixels); pixels = createSurface(data, width, height); SDL_SetColorKey(pixels, SDL_SRCCOLORKEY, key); return; } /** * Get the width of the sprite. * * @return The width */ int Sprite::getWidth () { return pixels->w; } /** * Get the height of the sprite. * * @return The height */ int Sprite::getHeight() { return pixels->h; } /** * Get the horizontal offset of the sprite. * * @return The horizontal offset */ int Sprite::getXOffset () { return xOffset; } /** * Get the vertical offset of the sprite. * * @return The vertical offset */ int Sprite::getYOffset () { return yOffset; } /** * Set the sprite's palette, or a portion thereof. * * @param palette New palette * @param start First colour to change * @param amount Number of colours to change */ void Sprite::setPalette (SDL_Color *palette, int start, int amount) { SDL_SetPalette(pixels, SDL_LOGPAL, palette + start, start, amount); return; } /** * Map the whole of the sprite's palette to one index. * * @param index The index to use */ void Sprite::flashPalette (int index) { SDL_Color palette[256]; int count; for (count = 0; count < 256; count++) palette[count].r = palette[count].g = palette[count].b = index; SDL_SetPalette(pixels, SDL_LOGPAL, palette, 0, 256); return; } /** * Restore the sprite's palette to its original state. */ void Sprite::restorePalette () { video.restoreSurfacePalette(pixels); return; } /** * Draw the sprite * * @param x The x-coordinate at which to draw the sprite * @param y The y-coordinate at which to draw the sprite * @param includeOffsets Whether or not to include the sprite's offsets */ void Sprite::draw (int x, int y, bool includeOffsets) { SDL_Rect dst; dst.x = x; dst.y = y; if (includeOffsets) { dst.x += xOffset; dst.y += yOffset; } SDL_BlitSurface(pixels, NULL, canvas, &dst); return; } /** * Draw the sprite scaled * * @param x The x-coordinate at which to draw the sprite * @param y The y-coordinate at which to draw the sprite * @param scale The amount by which to scale the sprite */ void Sprite::drawScaled (int x, int y, fixed scale) { unsigned char* srcRow; unsigned char* dstRow; unsigned char pixel, key; int width, height, fullWidth, fullHeight; int dstX, dstY; int srcX, srcY; key = pixels->format->colorkey; fullWidth = FTOI(pixels->w * scale); if (x < -(fullWidth >> 1)) return; // Off-screen if (x + (fullWidth >> 1) > canvasW) width = canvasW + (fullWidth >> 1) - x; else width = fullWidth; fullHeight = FTOI(pixels->h * scale); if (y < -(fullHeight >> 1)) return; // Off-screen if (y + (fullHeight >> 1) > canvasH) height = canvasH + (fullHeight >> 1) - y; else height = fullHeight; if (SDL_MUSTLOCK(canvas)) SDL_LockSurface(canvas); if (y < (fullHeight >> 1)) { srcY = (fullHeight >> 1) - y; dstY = 0; } else { srcY = 0; dstY = y - (fullHeight >> 1); } while (srcY < height) { srcRow = ((unsigned char *)(pixels->pixels)) + (pixels->pitch * DIV(srcY, scale)); dstRow = ((unsigned char *)(canvas->pixels)) + (canvas->pitch * dstY); if (x < (fullWidth >> 1)) { srcX = (fullWidth >> 1) - x; dstX = 0; } else { srcX = 0; dstX = x - (fullWidth >> 1); } while (srcX < width) { pixel = srcRow[DIV(srcX, scale)]; if (pixel != key) dstRow[dstX] = pixel; srcX++; dstX++; } srcY++; dstY++; } if (SDL_MUSTLOCK(canvas)) SDL_UnlockSurface(canvas); return; } openjazz-20190106/src/io/gfx/sprite.h000066400000000000000000000030011341440264100172500ustar00rootroot00000000000000 /** * * @file sprite.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 19th March 2009: Created sprite.h from parts of level.h * - 26th July 2009: Created anim.h from parts of sprite.h * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _SPRITE_H #define _SPRITE_H #include "OpenJazz.h" #include // Class /// Sprite class Sprite { private: SDL_Surface* pixels; ///< Sprite image short int xOffset; ///< Horizontal offset short int yOffset; ///< Vertical offset public: Sprite (); ~Sprite (); void clearPixels (); void setOffset (short int x, short int y); void setPixels (unsigned char* data, int width, int height, unsigned char key); int getWidth (); int getHeight (); int getXOffset (); int getYOffset (); void draw (int x, int y, bool includeOffsets = true); void drawScaled (int x, int y, fixed scale); void setPalette (SDL_Color* palette, int start, int amount); void flashPalette (int index); void restorePalette (); }; #endif openjazz-20190106/src/io/gfx/video.cpp000077500000000000000000000243271341440264100174240ustar00rootroot00000000000000 /** * * @file video.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed util.c to util.cpp * - 13th July 2009: Created graphics.cpp from parts of util.cpp * - 26th July 2009: Renamed graphics.cpp to video.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Contains graphics utility functions. * */ #include "paletteeffects.h" #include "video.h" #ifdef SCALE #include "io/gfx/scale2x/scalebit.h" #endif #include "util.h" #include /** * Creates a surface. * * @param pixels Pixel data to copy into the surface. Can be NULL. * @param width Width of the pixel data and of the surface to be created * @param height Height of the pixel data and of the surface to be created * * @return The completed surface */ SDL_Surface* createSurface (unsigned char * pixels, int width, int height) { SDL_Surface *ret; int y; // Create the surface ret = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 8, 0, 0, 0, 0); // Set the surface's palette video.restoreSurfacePalette(ret); if (pixels) { // Upload pixel data to the surface if (SDL_MUSTLOCK(ret)) SDL_LockSurface(ret); for (y = 0; y < height; y++) memcpy(((unsigned char *)(ret->pixels)) + (ret->pitch * y), pixels + (width * y), width); if (SDL_MUSTLOCK(ret)) SDL_UnlockSurface(ret); } return ret; } /** * Create the video output object. */ Video::Video () { int count; screen = NULL; #ifdef SCALE scaleFactor = 1; #endif // Generate the logical palette for (count = 0; count < 256; count++) logicalPalette[count].r = logicalPalette[count].g = logicalPalette[count].b = count; currentPalette = logicalPalette; return; } /** * Find the maximum horizontal and vertical resolutions. */ void Video::findMaxResolution () { #ifdef NO_RESIZE maxW = DEFAULT_SCREEN_WIDTH; maxH = DEFAULT_SCREEN_HEIGHT; #else SDL_Rect **resolutions; int count; resolutions = SDL_ListModes(NULL, fullscreen? FULLSCREEN_FLAGS: WINDOWED_FLAGS); if (resolutions == (SDL_Rect **)(-1)) { maxW = MAX_SCREEN_WIDTH; maxH = MAX_SCREEN_HEIGHT; } else { maxW = SW; maxH = SH; for (count = 0; resolutions[count] != NULL; count++) { if (resolutions[count]->w > maxW) maxW = resolutions[count]->w; if (resolutions[count]->h > maxH) maxH = resolutions[count]->h; } if (maxW > MAX_SCREEN_WIDTH) maxW = MAX_SCREEN_WIDTH; if (maxH > MAX_SCREEN_HEIGHT) maxH = MAX_SCREEN_HEIGHT; } #endif return; } /** * Initialise video output. * * @param width Width of the window or screen * @param height Height of the window or screen * @param startFullscreen Whether or not to start in full-screen mode * * @return Success */ bool Video::init (int width, int height, bool startFullscreen) { fullscreen = startFullscreen; if (fullscreen) SDL_ShowCursor(SDL_DISABLE); if (!reset(width, height)) { logError("Could not set video mode", SDL_GetError()); return false; } SDL_WM_SetCaption("OpenJazz", NULL); findMaxResolution(); return true; } /** * Sets the size of the video window or the resolution of the screen. * * @param width New width of the window or screen * @param height New height of the window or screen * * @return Success */ bool Video::reset (int width, int height) { screenW = width; screenH = height; #ifdef SCALE if (canvas != screen) SDL_FreeSurface(canvas); #endif #ifdef NO_RESIZE screen = SDL_SetVideoMode(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 8, FULLSCREEN_FLAGS); #else screen = SDL_SetVideoMode(screenW, screenH, 8, fullscreen? FULLSCREEN_FLAGS: WINDOWED_FLAGS); #endif if (!screen) return false; #ifdef SCALE // Check that the scale will fit in the current resolution while ( ((screenW/SW < scaleFactor) || (screenH/SH < scaleFactor)) && (scaleFactor > 1) ) { scaleFactor--; } if (scaleFactor > 1) { canvasW = screenW / scaleFactor; canvasH = screenH / scaleFactor; canvas = createSurface(NULL, canvasW, canvasH); } else #endif { canvasW = screenW; canvasH = screenH; canvas = screen; } #if !defined(WIZ) && !defined(GP2X) expose(); #endif /* A real 8-bit display is quite likely if the user has the right video card, the right video drivers, the right version of DirectX/whatever, and the right version of SDL. In other words, it's not likely enough. If a real palette is assumed when a) there really is a real palette, there will be an extremely small speed gain. b) the palette is emulated, there will be a HUGE speed loss. Therefore, assume the palette is emulated. */ /// @todo Find a better way to determine if palette is emulated fakePalette = true; return true; } /** * Sets the display palette. * * @param palette The new palette */ void Video::setPalette (SDL_Color *palette) { // Make palette changes invisible until the next draw. Hopefully. clearScreen(SDL_MapRGB(screen->format, 0, 0, 0)); flip(0, NULL); SDL_SetPalette(screen, SDL_PHYSPAL, palette, 0, 256); currentPalette = palette; return; } /** * Returns the current display palette. * * @return The current display palette */ SDL_Color* Video::getPalette () { return currentPalette; } /** * Sets some colours of the display palette. * * @param palette The palette containing the new colours * @param first The index of the first colour in both the display palette and the specified palette * @param amount The number of colours */ void Video::changePalette (SDL_Color *palette, unsigned char first, unsigned int amount) { SDL_SetPalette(screen, SDL_PHYSPAL, palette, first, amount); return; } /** * Restores a surface's palette. * * @param surface Surface with a modified palette */ void Video::restoreSurfacePalette (SDL_Surface* surface) { SDL_SetPalette(surface, SDL_LOGPAL, logicalPalette, 0, 256); return; } /** * Returns the maximum possible screen width. * * @return The maximum width */ int Video::getMaxWidth () { return maxW; } /** * Returns the maximum possible screen height. * * @return The maximum height */ int Video::getMaxHeight () { return maxH; } /** * Returns the current width of the window or screen. * * @return The width */ int Video::getWidth () { return screenW; } /** * Returns the current height of the window or screen. * * @return The height */ int Video::getHeight () { return screenH; } #ifdef SCALE /** * Returns the current scaling factor. * * @return The scaling factor */ int Video::getScaleFactor () { return scaleFactor; } /** * Sets the scaling factor. * * @param newScaleFactor The new scaling factor */ int Video::setScaleFactor (int newScaleFactor) { if ((SW * newScaleFactor <= screenW) && (SH * newScaleFactor <= screenH)) { scaleFactor = newScaleFactor; if (screen) reset(screenW, screenH); } return scaleFactor; } #endif #ifndef FULLSCREEN_ONLY /** * Determines whether or not full-screen mode is being used. * * @return Whether or not full-screen mode is being used */ bool Video::isFullscreen () { return fullscreen; } #endif /** * Refresh display palette. */ void Video::expose () { SDL_SetPalette(screen, SDL_LOGPAL, logicalPalette, 0, 256); SDL_SetPalette(screen, SDL_PHYSPAL, currentPalette, 0, 256); return; } /** * Update video based on a system event. * * @param event The system event. Events not affecting video will be ignored */ void Video::update (SDL_Event *event) { #if !defined(FULLSCREEN_ONLY) || !defined(NO_RESIZE) switch (event->type) { #ifndef FULLSCREEN_ONLY case SDL_KEYDOWN: // If Alt + Enter has been pressed, switch between windowed and full-screen mode. if ((event->key.keysym.sym == SDLK_RETURN) && (event->key.keysym.mod & KMOD_ALT)) { fullscreen = !fullscreen; if (fullscreen) SDL_ShowCursor(SDL_DISABLE); reset(screenW, screenH); if (!fullscreen) SDL_ShowCursor(SDL_ENABLE); findMaxResolution(); } break; #endif #ifndef NO_RESIZE case SDL_VIDEORESIZE: reset(event->resize.w, event->resize.h); break; #endif case SDL_VIDEOEXPOSE: expose(); break; } #endif return; } /** * Draw graphics to screen. * * @param mspf Ticks per frame * @param paletteEffects Palette effects to use */ void Video::flip (int mspf, PaletteEffect* paletteEffects) { SDL_Color shownPalette[256]; #ifdef SCALE if (canvas != screen) { // Copy everything that has been drawn so far scale(scaleFactor, screen->pixels, screen->pitch, canvas->pixels, canvas->pitch, screen->format->BytesPerPixel, canvas->w, canvas->h); } #endif // Apply palette effects if (paletteEffects) { /* If the palette is being emulated, compile all palette changes and apply them all at once. If the palette is being used directly, apply all palette effects directly. */ if (fakePalette) { memcpy(shownPalette, currentPalette, sizeof(SDL_Color) * 256); paletteEffects->apply(shownPalette, false, mspf); SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette, 0, 256); } else { paletteEffects->apply(shownPalette, true, mspf); } } // Show what has been drawn SDL_Flip(screen); return; } /** * Fill the screen with a colour. * * @param index Index of the colour to use */ void Video::clearScreen (int index) { #if defined(CAANOO) || defined(WIZ) || defined(GP2X) || defined(GAMESHELL) // always 240 lines cleared to black memset(video.screen->pixels, index, 320*240); #else SDL_FillRect(canvas, NULL, index); #endif return; } /** * Fill a specified rectangle of the screen with a colour. * * @param x X-coordinate of the left side of the rectangle * @param y Y-coordinate of the top of the rectangle * @param width Width of the rectangle * @param height Height of the rectangle * @param index Index of the colour to use */ void drawRect (int x, int y, int width, int height, int index) { SDL_Rect dst; dst.x = x; dst.y = y; dst.w = width; dst.h = height; SDL_FillRect(canvas, &dst, index); return; } openjazz-20190106/src/io/gfx/video.h000077500000000000000000000101361341440264100170620ustar00rootroot00000000000000 /** * * @file video.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 13th July 2009: Created graphics.h from parts of OpenJazz.h * - 26th July 2009: Renamed graphics.h to video.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _VIDEO_H #define _VIDEO_H #include "paletteeffects.h" #include // Constants // Original screen dimensions #define SW 320 #define SH 200 #define MIN_SCALE 1 #ifdef SCALE #define MAX_SCALE 4 #else #define MAX_SCALE 1 #endif // Maximum screen dimensions #define MAX_SCREEN_WIDTH (32 * 256 * MAX_SCALE) #define MAX_SCREEN_HEIGHT (32 * 64 * MAX_SCALE) #define WINDOWED_FLAGS (SDL_RESIZABLE | SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE) #if defined(CAANOO) || defined(WIZ) || defined(GP2X) || defined(GAMESHELL) #define DEFAULT_SCREEN_WIDTH 320 #define DEFAULT_SCREEN_HEIGHT 240 #define FULLSCREEN_ONLY #define NO_RESIZE #define FULLSCREEN_FLAGS (SDL_FULLSCREEN | SDL_SWSURFACE | SDL_HWPALETTE) #elif defined(DINGOO) #define DEFAULT_SCREEN_WIDTH 320 #define DEFAULT_SCREEN_HEIGHT 240 #define FULLSCREEN_ONLY #define NO_RESIZE #define FULLSCREEN_FLAGS 0 #elif defined(PSP) #define DEFAULT_SCREEN_WIDTH 480 #define DEFAULT_SCREEN_HEIGHT 272 #define FULLSCREEN_ONLY #define NO_RESIZE #define FULLSCREEN_FLAGS (SDL_FULLSCREEN | SDL_SWSURFACE | SDL_HWPALETTE) #elif defined(_3DS) #define DEFAULT_SCREEN_WIDTH 400 #define DEFAULT_SCREEN_HEIGHT 240 #define FULLSCREEN_ONLY #define NO_RESIZE #define FULLSCREEN_FLAGS (SDL_SWSURFACE | SDL_TOPSCR | SDL_CONSOLEBOTTOM) #else #define DEFAULT_SCREEN_WIDTH SW #define DEFAULT_SCREEN_HEIGHT SH #define FULLSCREEN_FLAGS (SDL_FULLSCREEN | SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE) #endif // Time interval #define T_MENU_FRAME 20 // Class /// Video output class Video { private: SDL_Surface* screen; ///< Output surface // Palettes SDL_Color* currentPalette; ///< Current palette SDL_Color logicalPalette[256]; ///< Logical palette (greyscale) bool fakePalette; ///< Whether or not the palette mode is being emulated int maxW; ///< Largest possible width int maxH; ///< Largest possible height int screenW; ///< Real width int screenH; ///< Real height #ifdef SCALE int scaleFactor; ///< Scaling factor #endif bool fullscreen; ///< Full-screen mode void findMaxResolution (); void expose (); public: Video (); bool init (int width, int height, bool startFullscreen); bool reset (int width, int height); void setPalette (SDL_Color *palette); SDL_Color* getPalette (); void changePalette (SDL_Color *palette, unsigned char first, unsigned int amount); void restoreSurfacePalette (SDL_Surface *surface); int getMaxWidth (); int getMaxHeight (); int getWidth (); int getHeight (); #ifdef SCALE int getScaleFactor (); int setScaleFactor (int newScaleFactor); #endif #ifndef FULLSCREEN_ONLY bool isFullscreen (); #endif void update (SDL_Event *event); void flip (int mspf, PaletteEffect* paletteEffects); void clearScreen (int index); }; // Variables EXTERN SDL_Surface* canvas; ///< Surface used for drawing EXTERN int canvasW; ///< Drawing surface width EXTERN int canvasH; ///< Drawing surface height EXTERN Video video; ///< Video output // Functions EXTERN SDL_Surface* createSurface (unsigned char* pixels, int width, int height); EXTERN void drawRect (int x, int y, int width, int height, int index); #endif openjazz-20190106/src/io/network.cpp000066400000000000000000000167001341440264100172140ustar00rootroot00000000000000 /** * * @file network.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c and menu.c * - 3rd of February 2009: Renamed level.c to level.cpp and menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 3rd June 2009: Created network.cpp from parts of game.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with a platform-specific networking API. * * On most platforms, USE_SOCKETS should be defined. * */ #include "controls.h" #include "gfx/font.h" #include "gfx/video.h" #include "network.h" #include "loop.h" #include "util.h" #ifdef USE_SOCKETS #ifdef _WIN32 #include #define ioctl ioctlsocket #define socklen_t int #define EWOULDBLOCK WSAEWOULDBLOCK #define MSG_NOSIGNAL 0 #else #include #include #include #include #include #include #include #endif #ifdef __APPLE__ #define MSG_NOSIGNAL 0 #endif #elif defined USE_SDL_NET #include #endif #ifdef __HAIKU__ #include #endif /** * Initialise networking. */ Network::Network () { #ifdef USE_SOCKETS #ifdef _WIN32 WSADATA WSAData; // Start Windows Sockets WSAStartup(MAKEWORD(1, 0), &WSAData); #endif #elif defined USE_SDL_NET SDLNet_Init(); #endif return; } /** * De-initialise networking. */ Network::~Network () { #ifdef USE_SOCKETS #ifdef _WIN32 // Shut down Windows Sockets WSACleanup(); #endif #elif defined USE_SDL_NET SDLNet_Quit(); #endif return; } /** * Open a host connection. * * @return Connection socket or error code */ int Network::host () { #ifdef USE_SOCKETS sockaddr_in sockAddr; int sock, nonblock; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) return E_N_SOCKET; // Make the socket non-blocking nonblock = 1; ioctl(sock, FIONBIO, (u_long *)&nonblock); memset(&sockAddr, 0, sizeof(sockaddr_in)); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = INADDR_ANY; sockAddr.sin_port = htons(NET_PORT); if (bind(sock, (sockaddr *)&sockAddr, sizeof(sockaddr_in))) { close(sock); return E_N_BIND; } if (listen(sock, MAX_CLIENTS) == -1) { close(sock); return E_N_LISTEN; } return sock; #elif defined USE_SDL_NET ipAddress.port = NET_PORT; ipAddress.host = 0; socket = SDLNet_TCP_Open(&ipAddress); if (socket == NULL) return E_N_SOCKET; return (int)socket; #else return E_N_OTHER; #endif } /** * Open a client connection to the specified server. * * @param address Address of the server * * @return Connection socket or error code */ int Network::join (char *address) { #ifdef USE_SOCKETS sockaddr_in sockAddr; fd_set writefds; timeval timeouttv; unsigned int timeout; int sock, con; // Create socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) return E_N_SOCKET; // Make socket non-blocking con = 1; ioctl(sock, FIONBIO, (u_long *)&con); // Connect to server memset(&sockAddr, 0, sizeof(sockaddr_in)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(NET_PORT); #ifdef _WIN32 sockAddr.sin_addr.s_addr = inet_addr(address); #else if (inet_aton(address, &(sockAddr.sin_addr)) == 0) return E_N_ADDRESS; #endif // Initiate connection con = connect(sock, (sockaddr *)&sockAddr, sizeof(sockAddr)); // If the connection completed, return if (con == 0) return sock; // Wait for connection to complete con = 0; timeout = globalTicks + T_TIMEOUT; while (!con) { if (loop(NORMAL_LOOP) == E_QUIT) { close(sock); return E_QUIT; } if (controls.release(C_ESCAPE)) { close(sock); return E_RETURN; } video.clearScreen(0); fontmn2->showString("CONNECTING TO SERVER", canvasW >> 2, (canvasH >> 1) - 16); FD_ZERO(&writefds); FD_SET(sock, &writefds); timeouttv.tv_sec = 0; timeouttv.tv_usec = T_MENU_FRAME; con = select(sock + 1, NULL, &writefds, NULL, &timeouttv); if (con == -1) { log("Could not connect to server - code", getError()); close(sock); return E_N_CONNECT; } if (globalTicks > timeout) { close(sock); return E_TIMEOUT; } } return sock; #elif defined USE_SDL_NET video.clearScreen(0); fontmn2->showString("CONNECTING TO SERVER", canvasW >> 2, (canvasH >> 1) - 16); loop(NORMAL_LOOP); ipAddress.port = NET_PORT; ipAddress.host = inet_addr(address); socket = SDLNet_TCP_Open(&ipAddress); if (socket == NULL) return -1; return (int)socket; #else return E_N_OTHER; #endif } /** * Accept a connection to a client * * @param sock The host connection socket * * @return Client connection socket, or -1 for no connection */ int Network::accept (int sock) { #ifdef USE_SOCKETS sockaddr_in sockAddr; int clientSocket, length; length = sizeof(sockaddr_in); clientSocket = ::accept(sock, (sockaddr *)&sockAddr, (socklen_t *)&length); if (clientSocket != -1) { // Make the socket non-blocking length = 1; ioctl(clientSocket, FIONBIO, (u_long *)&length); } return clientSocket; #elif defined USE_SDL_NET clientSocket = SDLNet_TCP_Accept((TCPsocket)sock); if (clientSocket == NULL) return -1; return (int)&clientSocket; #else return -1; #endif } /** * Close a connection. * * @param sock The connection socket */ void Network::close (int sock) { #ifdef USE_SOCKETS #ifdef _WIN32 closesocket(sock); #else ::close(sock); #endif #elif defined USE_SDL_NET SDLNet_TCP_Close((TCPsocket)sock); #endif return; } /** * Send data over the specified connection. * * @param sock Connection socket * @param buffer Data to be sent * * @return Number of bytes sent, or -1 for failure */ int Network::send (int sock, unsigned char *buffer) { #ifdef USE_SOCKETS return ::send(sock, (char *)buffer, buffer[0], MSG_NOSIGNAL); #elif defined USE_SDL_NET return SDLNet_TCP_Send((TCPsocket)sock, (char *)buffer, buffer[0]); #else return 0; #endif } /** * Receive data from the specified connection. * * @param sock Connection socket * @param buffer Buffer to receive data * @param length The size of the buffer, in bytes * * @return Number of bytes received, or -1 for failure */ int Network::recv (int sock, unsigned char *buffer, int length) { #ifdef USE_SOCKETS return ::recv(sock, (char *)buffer, length, MSG_NOSIGNAL); #elif defined USE_SDL_NET return SDLNet_TCP_Recv((TCPsocket)sock, buffer, length); #else return 0; #endif } /** * Check if a given socket is connected. * * @param sock The socket * * @return True if connected */ bool Network::isConnected (int sock) { #ifdef USE_SOCKETS int length; char buffer; // Check for incoming data length = ::recv(sock, &buffer, 1, MSG_PEEK | MSG_NOSIGNAL); // Still connected if data was received or if there was no data to receive return (length != -1) || (getError() == EWOULDBLOCK); #elif defined USE_SDL_NET return SDLNet_SocketReady((TCPsocket)sock); #else return false; #endif } /** * Get the last error code. * * @return Network library error code */ int Network::getError () { #ifdef USE_SOCKETS #ifdef _WIN32 return WSAGetLastError(); #else return errno; #endif #elif defined USE_SDL_NET return (int)SDLNet_GetError(); #else return 0; #endif } openjazz-20190106/src/io/network.h000066400000000000000000000030611341440264100166550ustar00rootroot00000000000000 /** * * @file network.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 3rd June 2009: Created network.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _NETWORK_H #define _NETWORK_H #include "OpenJazz.h" #ifdef USE_SDL_NET #include #endif // Constants // Defaults #if defined(DINGOO) #define NET_ADDRESS "10.1.0.1" #else #define NET_ADDRESS "192.168.0.1" #endif #define NET_PORT 10052 // Timeout interval #define T_TIMEOUT 30000 // Client limit #define MAX_CLIENTS 31 // Level file #define LEVEL_FILE "openjazz.tmp" // Class /// Networking class Network { public: #ifdef USE_SDL_NET TCPsocket socket; TCPsocket clientSocket; IPaddress ipAddress; SDLNet_SocketSet socketset; #endif Network (); ~Network (); int host (); int join (char *address); int accept (int sock); void close (int sock); int send (int sock, unsigned char *buffer); int recv (int sock, unsigned char *buffer, int length); bool isConnected (int sock); int getError (); }; // Variables EXTERN char *netAddress; /// Server address EXTERN Network *net; #endif openjazz-20190106/src/io/sound.cpp000066400000000000000000000265731341440264100166640ustar00rootroot00000000000000 /** * * @file sound.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created sound.c * - 3rd February 2009: Renamed sound.c to sound.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading, playing and freeing of music and sound effects. * * For music, USE_MODPLUG or USE_XMP must be defined. * */ #include "file.h" #include "sound.h" #include "util.h" #include // support for the default Makefile #ifdef USE_modplug #define USE_MODPLUG #endif #ifdef USE_xmp #define USE_XMP #endif // make sure we only have one music library available #if defined(USE_MODPLUG) && defined(USE_XMP) #error "You can either use libxmp or libmodplug, not both!" #endif #if defined(USE_MODPLUG) #ifdef _WIN32 #include #else #include #endif #elif defined(USE_XMP) #include #endif #if defined(__SYMBIAN32__) || defined(_3DS) || defined(PSP) #define SOUND_FREQ 22050 #else #define SOUND_FREQ 44100 #endif #if defined(USE_MODPLUG) #ifdef __SYMBIAN32__ #define MUSIC_RESAMPLEMODE MODPLUG_RESAMPLE_LINEAR #define MUSIC_FLAGS MODPLUG_ENABLE_MEGABASS #elif defined(CAANOO) || defined(WIZ) || defined(GP2X) || defined(DINGOO) || defined(PSP) #define MUSIC_RESAMPLEMODE MODPLUG_RESAMPLE_LINEAR #define MUSIC_FLAGS 0 #else #define MUSIC_RESAMPLEMODE MODPLUG_RESAMPLE_FIR #define MUSIC_FLAGS MODPLUG_ENABLE_NOISE_REDUCTION | MODPLUG_ENABLE_REVERB | MODPLUG_ENABLE_MEGABASS | MODPLUG_ENABLE_SURROUND #endif ModPlugFile *musicFile; #elif defined(USE_XMP) # if defined(_3DS) || defined(PSP) #define MUSIC_INTERPOLATION XMP_INTERP_NEAREST # else #define MUSIC_INTERPOLATION XMP_INTERP_SPLINE #define MUSIC_EFFECTS XMP_DSP_ALL # endif xmp_context xmpC; #endif SDL_AudioSpec audioSpec; bool musicPaused = false; int musicVolume = MAX_VOLUME >> 1; // 50% int soundVolume = MAX_VOLUME >> 2; // 25% /** * Callback used to provide data to the audio subsystem. * * @param userdata N/A * @param stream Output stream * @param len Length of data to be placed in the output stream */ void audioCallback (void * userdata, unsigned char * stream, int len) { (void)userdata; int count; if (!musicPaused) { // Read the next portion of music into the audio stream #if defined(USE_MODPLUG) if (musicFile) { int bytes_read = ModPlug_Read(musicFile, stream, len); // poor mans loop (so modplug needs no patching) if (bytes_read < len) { ModPlug_Seek(musicFile, 0); ModPlug_Read(musicFile, stream + bytes_read, len - bytes_read); } } #elif defined(USE_XMP) if (xmp_get_player(xmpC, XMP_PLAYER_STATE) == XMP_STATE_PLAYING) xmp_play_buffer(xmpC, stream, len, 0); #endif } for (count = 0; count < 32; count++) { if (sounds[count].data && (sounds[count].position >= 0)) { // Add the next portion of the sound clip to the audio stream if (len < sounds[count].length - sounds[count].position) { // Play as much of the clip as possible SDL_MixAudio(stream, sounds[count].data + sounds[count].position, len, soundVolume * SDL_MIX_MAXVOLUME / MAX_VOLUME); sounds[count].position += len; } else { // Play the remainder of the clip SDL_MixAudio(stream, sounds[count].data + sounds[count].position, sounds[count].length - sounds[count].position, soundVolume * SDL_MIX_MAXVOLUME / MAX_VOLUME); sounds[count].position = -1; } } } return; } /** * Initialise audio. */ void openAudio () { SDL_AudioSpec asDesired; #if defined(USE_MODPLUG) musicFile = NULL; #elif defined(USE_XMP) xmpC = xmp_create_context(); #endif // Set up SDL audio asDesired.freq = SOUND_FREQ; asDesired.format = AUDIO_S16; asDesired.channels = 2; #if defined(GP2X) || defined(PSP) || defined(_3DS) asDesired.samples = 512; #else asDesired.samples = 2048; #endif asDesired.callback = audioCallback; asDesired.userdata = NULL; if (SDL_OpenAudio(&asDesired, &audioSpec) < 0) logError("Unable to open audio", SDL_GetError()); // Load sounds if (loadSounds("SOUNDS.000") != E_NONE) sounds = NULL; // Start audio for sfx to work SDL_PauseAudio(0); return; } /** * Stop audio. */ void closeAudio () { int count; stopMusic(); #ifdef USE_XMP xmp_free_context(xmpC); #endif SDL_CloseAudio(); if (rawSounds) { for (count = 0; count < nRawSounds; count++) { delete[] rawSounds[count].data; delete[] rawSounds[count].name; } delete[] rawSounds; } if (sounds) { freeSounds(); delete[] sounds; } return; } /** * Play music from the specified file. * * @param fileName Name of a file containing music data. */ void playMusic (const char * fileName) { File *file; unsigned char *psmData; int size; bool loadOk = false; #ifdef USE_MODPLUG ModPlug_Settings settings; #endif // Stop any existing music playing stopMusic(); // Load the music file try { file = new File(fileName, false); } catch (int e) { return; } // Find the size of the file size = file->getSize(); // Read the entire file into memory file->seek(0, true); psmData = file->loadBlock(size); delete file; #ifdef USE_MODPLUG // Set up libmodplug settings.mFlags = MUSIC_FLAGS; settings.mChannels = audioSpec.channels; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_S8)) settings.mBits = 8; else settings.mBits = 16; settings.mFrequency = audioSpec.freq; settings.mResamplingMode = MUSIC_RESAMPLEMODE; settings.mReverbDepth = 25; settings.mReverbDelay = 40; settings.mBassAmount = 50; settings.mBassRange = 10; settings.mSurroundDepth = 50; settings.mSurroundDelay = 40; settings.mLoopCount = -1; ModPlug_SetSettings(&settings); // Load the file into libmodplug musicFile = ModPlug_Load(psmData, size); loadOk = (musicFile != NULL); #elif defined(USE_XMP) // Load the file into libxmp loadOk = (xmp_load_module_from_memory(xmpC, psmData, size) == 0); #endif delete[] psmData; if (!loadOk) { logError("Could not play music file", fileName); return; } #ifdef USE_XMP int playerFlags = 0; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_S8)) playerFlags = playerFlags & XMP_FORMAT_8BIT; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_U16) || (audioSpec.format == AUDIO_U16MSB) || (audioSpec.format == AUDIO_U16LSB)) playerFlags = playerFlags & XMP_FORMAT_UNSIGNED; if (audioSpec.channels == 1) playerFlags = playerFlags & XMP_FORMAT_MONO; xmp_start_player(xmpC, audioSpec.freq, playerFlags); xmp_set_player(xmpC, XMP_PLAYER_INTERP, MUSIC_INTERPOLATION); # ifdef MUSIC_EFFECTS xmp_set_player(xmpC, XMP_PLAYER_DSP, MUSIC_EFFECTS); # endif #endif // Re-apply volume setting setMusicVolume(musicVolume); // Start the audio playing SDL_PauseAudio(0); musicPaused = false; return; } /** * Pauses and Unpauses the current music. * * @param pause set to true to pause */ void pauseMusic (bool pause) { musicPaused = pause; } /** * Stop the current music. */ void stopMusic () { // Stop the music playing SDL_PauseAudio(~0); #if defined(USE_MODPLUG) if (musicFile) { ModPlug_Unload(musicFile); musicFile = NULL; } #elif defined(USE_XMP) int state = xmp_get_player(xmpC, XMP_PLAYER_STATE); if (state == XMP_STATE_LOADED || state == XMP_STATE_PLAYING) { xmp_end_player(xmpC); xmp_release_module(xmpC); } #endif SDL_PauseAudio(0); return; } /** * Gets the current music volume * * @return music volume (0-100) */ int getMusicVolume () { return musicVolume; } /** * Sets the music volume * * @param volume new volume (0-100) */ void setMusicVolume (int volume) { musicVolume = volume; if (volume < 1) musicVolume = 0; if (volume > MAX_VOLUME) musicVolume = MAX_VOLUME; // do not access music player settings when not playing #if defined(USE_MODPLUG) if (musicFile) ModPlug_SetMasterVolume(musicFile, musicVolume * 5.12); #elif defined(USE_XMP) if (xmpC && xmp_get_player(xmpC, XMP_PLAYER_STATE) == XMP_STATE_PLAYING) xmp_set_player(xmpC, XMP_PLAYER_VOLUME, musicVolume); #endif } /** * Load raw sound clips from the specified file. * * @param fileName Name of a file containing sound clips */ int loadSounds (const char *fileName) { File *file; int count, offset, headerOffset; try { file = new File(fileName, false); } catch (int e) { return e; } sounds = new Sound[32]; for (count = 0; count < 32; count++) { sounds[count].data = NULL; } // Locate the header data file->seek(file->getSize() - 4, true); headerOffset = file->loadInt(); // Calculate number of sounds nRawSounds = (file->getSize() - headerOffset) / 18; // Load sound clips rawSounds = new RawSound[nRawSounds]; for (count = 0; count < nRawSounds; count++) { file->seek(headerOffset + (count * 18), true); // Read the name of the clip rawSounds[count].name = (char *)(file->loadBlock(12)); // Read the offset of the clip offset = file->loadInt(); // Read the length of the clip rawSounds[count].length = file->loadShort(); // Read the clip file->seek(offset, true); rawSounds[count].data = file->loadBlock(rawSounds[count].length); } delete file; resampleSounds(); return E_NONE; } /** * Resample sound clip data. */ void resampleSound (int index, const char* name, int rate) { int count, rsFactor, sample; if (sounds[index].data) { delete[] sounds[index].data; sounds[index].data = NULL; } // Search for matching sound for (count = 0; count < nRawSounds; count++) { if (!strcmp(name, rawSounds[count].name)) { // Calculate the resampling factor if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_S8)) rsFactor = (F2 * audioSpec.freq) / rate; else rsFactor = (F4 * audioSpec.freq) / rate; sounds[index].length = MUL(rawSounds[count].length, rsFactor); // Allocate the buffer for the resampled clip sounds[index].data = new unsigned char[sounds[index].length]; // Resample the clip for (sample = 0; sample < sounds[index].length; sample++) sounds[index].data[sample] = rawSounds[count].data[DIV(sample, rsFactor)]; sounds[index].position = -1; return; } } } /** * Resample all sound clips to matching indices. */ void resampleSounds () { int count; for (count = 0; (count < 32) && (count < nRawSounds); count++) { resampleSound(count, rawSounds[count].name, 11025); } return; } /** * Delete resampled sound clip data. */ void freeSounds () { int count; if (sounds) { for (count = 0; count < 32; count++) { if (sounds[count].data) delete[] sounds[count].data; } } return; } /** * Set the sound clip to be played. * * @param index Number of the sound to play plus one (0 to play no sound) */ void playSound (char index) { if (sounds && (index > 0) && (index <= 32)) sounds[index - 1].position = 0; return; } /** * Gets the current sound effect volume * * @return sound volume (0-100) */ int getSoundVolume () { return soundVolume; } /** * Sets the sound effect volume * * @param volume new volume (0-100) */ void setSoundVolume (int volume) { soundVolume = volume; if (volume < 1) soundVolume = 0; if (volume > MAX_VOLUME) soundVolume = MAX_VOLUME; } openjazz-20190106/src/io/sound.h000066400000000000000000000041551341440264100163210ustar00rootroot00000000000000 /** * * @file sound.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 2nd June 2009: Created sound.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _SOUND_H #define _SOUND_H #include "OpenJazz.h" // Constants // Sound effects #define S_INVULN 1 #define S_MACHGUN 2 #define S_BOOM 3 #define S_OW 4 #define S_YUM 5 #define S_FIRE 6 #define S_UPLOOP 7 #define S_1UP 8 #define S_PHOTON 9 #define S_WAIT 10 #define S_ORB 11 #define S_JUMPA 12 #define S_GODLIKE 13 #define S_YEAHOO 14 #define S_BIRDY 15 #define S_FLAMER 16 #define S_ELECTR 17 #define S_SPRING 18 #define S_ROCKET 19 #define S_STOP 20 #define S_BLOCK 21 #define MAX_VOLUME 100 // Datatype /// Raw sound effect data typedef struct { unsigned char *data; char *name; int length; } RawSound; /// Resampled sound effect data typedef struct { unsigned char *data; int length; int position; } Sound; // Variables EXTERN RawSound *rawSounds; EXTERN int nRawSounds; EXTERN Sound *sounds; #if defined(WIZ) || defined(GP2X) EXTERN int volume; EXTERN int volume_direction; #endif // Functions EXTERN void openAudio (); EXTERN void closeAudio (); EXTERN void playMusic (const char *fileName); EXTERN void pauseMusic (bool pause); EXTERN void stopMusic (); EXTERN int getMusicVolume (); EXTERN void setMusicVolume (int volume); EXTERN int loadSounds (const char *fileName); EXTERN void resampleSound (int index, const char* name, int rate); EXTERN void resampleSounds (); EXTERN void freeSounds (); EXTERN void playSound (char index); EXTERN int getSoundVolume (); EXTERN void setSoundVolume (int volume); #endif openjazz-20190106/src/jj1bonuslevel/000077500000000000000000000000001341440264100171675ustar00rootroot00000000000000openjazz-20190106/src/jj1bonuslevel/jj1bonuslevel.cpp000066400000000000000000000334311341440264100224620ustar00rootroot00000000000000 /** * * @file jj1bonuslevel.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created bonus.c * - 3rd February 2009: Renamed bonus.c to bonus.cpp * - 1st August 2012: Renamed bonus.cpp to jj1bonuslevel.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading, running and freeing of bonus levels. * */ #include "jj1bonuslevelplayer/jj1bonuslevelplayer.h" #include "jj1bonuslevel.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/paletteeffects.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" #include /** * Load sprites. * * @return Error code */ int JJ1BonusLevel::loadSprites () { File *file; unsigned char* pixels; int pos, maskLength, pixelsLength; int width, height; int count; try { file = new File("BONUS.000", false); } catch (int e) { return e; } file->seek(2, true); sprites = file->loadShort(256); spriteSet = new Sprite[sprites]; for (count = 0; count < sprites; count++) { // Load dimensions width = file->loadShort(SW); height = file->loadShort(SH); pixelsLength = file->loadShort(); maskLength = file->loadShort(); // Sprites can be either masked or not masked. if (pixelsLength != 0xFFFF) { // Masked width <<= 2; pos = file->tell() + (pixelsLength << 2) + maskLength; // Read scrambled, masked pixel data pixels = file->loadPixels(width * height, 0); spriteSet[count].setPixels(pixels, width, height, 0); delete[] pixels; file->seek(pos, true); } else if (width) { // Not masked // Read pixel data pixels = file->loadBlock(width * height); spriteSet[count].setPixels(pixels, width, height, 0); delete[] pixels; } else { // Zero-length sprite // Create blank sprite spriteSet[count].clearPixels(); } } delete file; return E_NONE; } /** * Load the tileset. * * @param fileName Name of the file containing the tileset * * @return Error code */ int JJ1BonusLevel::loadTiles (char *fileName) { File *file; unsigned char *pixels; unsigned char *sorted; int count, x, y; try { file = new File(fileName, false); } catch (int e) { return e; } // Load background pixels = file->loadRLE(832 * 20); sorted = new unsigned char[512 * 20]; for (count = 0; count < 20; count++) memcpy(sorted + (count * 512), pixels + (count * 832), 512); background = createSurface(sorted, 512, 20); delete[] sorted; delete[] pixels; // Load palette file->loadPalette(palette); // Load tile graphics pixels = file->loadRLE(1024 * 60); tileSet = createSurface(pixels, 32, 32 * 60); // Create mask for (count = 0; count < 60; count++) { memset(mask[count], 0, 64); for (y = 0; y < 32; y++) { for (x = 0; x < 32; x++) { if ((pixels[(count << 10) + (y << 5) + x] & 240) == 192) mask[count][((y << 1) & 56) + ((x >> 2) & 7)] = 1; } } } delete[] pixels; delete file; return E_NONE; } /** * Create a JJ1 bonus level. * * @param owner The current game * @param fileName Name of the file containing the level data. * @param multi Whether or not the level will be multi-player */ JJ1BonusLevel::JJ1BonusLevel (Game* owner, char * fileName, bool multi) : Level(owner) { Anim* pAnims[BPANIMS]; File *file; unsigned char *buffer; char *string, *fileString; int count, x, y; try { font = new Font(true); } catch (int e) { throw e; } try { file = new File(fileName, false); } catch (int e) { delete font; throw e; } // Load sprites count = loadSprites(); if (count < 0) { delete file; delete font; throw count; } // Load tileset file->seek(90, true); string = file->loadString(); fileString = createFileName(string, 0); x = loadTiles(fileString); delete[] string; delete[] fileString; if (x != E_NONE) throw x; // Load music file->seek(121, true); fileString = file->loadString(); playMusic(fileString); delete[] fileString; // Load animations file->seek(134, true); buffer = file->loadBlock(BANIMS << 6); // Create animation set based on that data for (count = 0; count < BANIMS; count++) { animSet[count].setData(buffer[(count << 6) + 6], buffer[count << 6], buffer[(count << 6) + 1], buffer[(count << 6) + 3], buffer[(count << 6) + 4], buffer[(count << 6) + 2], buffer[(count << 6) + 5]); for (y = 0; y < buffer[(count << 6) + 6]; y++) { // Get frame x = buffer[(count << 6) + 7 + y]; if (x > sprites) x = sprites; // Assign sprite and vertical offset animSet[count].setFrame(y, true); animSet[count].setFrameData(spriteSet + x, buffer[(count << 6) + 26 + y], buffer[(count << 6) + 45 + y]); } } delete[] buffer; // Load tiles file->seek(2694, true); buffer = file->loadRLE(BLW * BLH); for (y = 0; y < BLH; y++) { for (x = 0; x < BLW; x++) { grid[y][x].tile = buffer[x + (y * BLW)]; if (grid[y][x].tile > 59) grid[y][x].tile = 59; } } delete[] buffer; file->skipRLE(); // Mysterious block // Load events buffer = file->loadRLE(BLW * BLH); for (y = 0; y < BLW; y++) { for (x = 0; x < BLH; x++) { grid[y][x].event = buffer[x + (y * BLW)]; } } delete[] buffer; file->seek(178, false); // Set the tick at which the level will end endTime = file->loadShort() * 1000; // Number of gems to collect items = file->loadShort(); // The players' coordinates x = file->loadShort(); y = file->loadShort(); // Generate player's animation set references for (count = 0; count < BPANIMS; count++) pAnims[count] = animSet + count; createLevelPlayers(LT_JJ1BONUS, pAnims, NULL, false, x, y); delete file; // Palette animations // Spinny whirly thing paletteEffects = new RotatePaletteEffect(112, 16, F32, NULL); // Track sides paletteEffects = new RotatePaletteEffect(192, 16, F32, paletteEffects); // Bouncy things paletteEffects = new RotatePaletteEffect(240, 16, F32, paletteEffects); // Adjust panelBigFont to use bonus level palette panelBigFont->mapPalette(0, 32, 15, -16); multiplayer = multi; return; } /** * Delete the JJ1 bonus level. */ JJ1BonusLevel::~JJ1BonusLevel () { // Restore panelBigFont palette panelBigFont->restorePalette(); SDL_FreeSurface(tileSet); delete[] spriteSet; delete font; return; } /** * Determine whether or not the given point is in the event area of its tile. * * @param x X-coordinate * @param y Y-coordinate * * @return True if in the event area */ bool JJ1BonusLevel::isEvent (fixed x, fixed y) { return ((x & 32767) > F12) && ((x & 32767) < F20) && ((y & 32767) > F12) && ((y & 32767) < F20); } /** * Determine whether or not the given point is solid. * * @param x X-coordinate * @param y Y-coordinate * * @return Solidity */ bool JJ1BonusLevel::checkMask (fixed x, fixed y) { JJ1BonusLevelGridElement *ge; ge = grid[FTOT(y) & 255] + (FTOT(x) & 255); // Hand if ((ge->event == 3) && isEvent(x, y)) return true; // Check the mask in the tile in question return mask[ge->tile][((y >> 9) & 56) + ((x >> 12) & 7)]; } /** * Interpret data received from client/server * * @param buffer Received data */ void JJ1BonusLevel::receive (unsigned char* buffer) { switch (buffer[1]) { case MT_L_PROP: if (buffer[2] == 2) { if (stage == LS_NORMAL) endTime += buffer[3] * 1000; } break; case MT_L_GRID: if (buffer[4] == 0) grid[buffer[3]][buffer[2]].tile = buffer[5]; else if (buffer[4] == 2) grid[buffer[3]][buffer[2]].event = buffer[5]; break; case MT_L_STAGE: stage = LevelStage(buffer[2]); break; } return; } /** * Level iteration. * * @return Error code */ int JJ1BonusLevel::step () { JJ1BonusLevelPlayer* bonusPlayer; fixed playerX, playerY; int gridX, gridY; int count; // Check if time has run out if (ticks > endTime) return LOST; // Apply controls to local player for (count = 0; count < PCONTROLS; count++) localPlayer->setControl(count, controls.getState(count)); // Process players for (count = 0; count < nPlayers; count++) { bonusPlayer = players[count].getJJ1BonusLevelPlayer(); playerX = bonusPlayer->getX(); playerY = bonusPlayer->getY(); bonusPlayer->step(ticks, 16, this); if ((bonusPlayer->getZ() < FH) && isEvent(playerX, playerY)) { gridX = FTOT(playerX) & 255; gridY = FTOT(playerY) & 255; switch (grid[gridY][gridX].event) { case 1: // Extra time addTimer(60); grid[gridY][gridX].event = 0; break; case 2: // Gem bonusPlayer->addGem(); grid[gridY][gridX].event = 0; if (bonusPlayer->getGems() >= items) { players[count].addLife(); return WON; } break; case 4: // Exit return LOST; default: // Do nothing break; } } } direction = localPlayer->getJJ1BonusLevelPlayer()->getDirection(); return E_NONE; } /** * Draw the level. */ void JJ1BonusLevel::draw () { JJ1BonusLevelPlayer *bonusPlayer; unsigned char* row; Sprite* sprite; SDL_Rect dst; fixed playerX, playerY, playerSin, playerCos; fixed distance, fwdX, fwdY, nX, sideX, sideY; int levelX, levelY; int x, y; // Draw the background for (x = -(direction & 1023); x < canvasW; x += background->w) { dst.x = x; dst.y = (canvasH >> 1) - 4; SDL_BlitSurface(background, NULL, canvas, &dst); } x = 171; for (y = (canvasH >> 1) - 5; (y >= 0) && (x > 128); y--) drawRect(0, y, canvasW, 1, x--); if (y > 0) drawRect(0, 0, canvasW, y + 1, 128); bonusPlayer = localPlayer->getJJ1BonusLevelPlayer(); // Draw the ground playerX = bonusPlayer->getX(); playerY = bonusPlayer->getY(); playerSin = fSin(direction); playerCos = fCos(direction); if (SDL_MUSTLOCK(canvas)) SDL_LockSurface(canvas); for (y = 1; y <= (canvasH >> 1) - 15; y++) { distance = DIV(ITOF(800), ITOF(92) - (ITOF(y * 84) / ((canvasH >> 1) - 16))); sideX = MUL(distance, playerCos); sideY = MUL(distance, playerSin); fwdX = playerX + MUL(distance - F16, playerSin) - (sideX >> 1); fwdY = playerY - MUL(distance - F16, playerCos) - (sideY >> 1); row = ((unsigned char *)(canvas->pixels)) + (canvas->pitch * (canvasH - y)); for (x = 0; x < canvasW; x++) { nX = ITOF(x) / canvasW; levelX = FTOI(fwdX + MUL(nX, sideX)); levelY = FTOI(fwdY + MUL(nX, sideY)); row[x] = ((unsigned char *)(tileSet->pixels)) [(grid[ITOT(levelY) & 255][ITOT(levelX) & 255].tile << 10) + ((levelY & 31) * tileSet->pitch) + (levelX & 31)]; } } if (SDL_MUSTLOCK(canvas)) SDL_UnlockSurface(canvas); // Draw nearby events for (y = -6; y < 6; y++) { fixed sY = TTOF(((direction - FQ) & 512)? y: -y) + F16 - (playerY & 32767); for (x = -6; x < 6; x++) { fixed sX = TTOF((direction & 512)? x: -x) + F16 - (playerX & 32767); fixed divisor = F16 + MUL(sX, playerSin) - MUL(sY, playerCos); if (FTOI(divisor) > 8) { switch (grid[((((direction - FQ) & 512)? y: -y) + FTOT(playerY)) & 255][(((direction & 512)? x: -x) + FTOT(playerX)) & 255].event) { case 0: // No event sprite = NULL; break; case 1: // Extra time sprite = spriteSet + 46; break; case 2: // Gem sprite = spriteSet + 47; break; case 3: // Hand sprite = spriteSet + 48; break; case 4: // Exit sprite = spriteSet + 49; break; case 5: // Bounce sprite = spriteSet + 50; break; default: sprite = spriteSet + 14; break; } if (sprite) { nX = DIV(MUL(sX, playerCos) + MUL(sY, playerSin), divisor); dst.x = FTOI(nX * canvasW) + (canvasW >> 1); dst.y = canvasH >> 1; sprite->drawScaled(dst.x, dst.y, DIV(F64 * canvasW / SW, divisor)); } } } } // Show the player bonusPlayer->draw(ticks); // Show gem count font->showString("*", 0, 0); font->showNumber(bonusPlayer->getGems() / 10, 50, 0); font->showNumber(bonusPlayer->getGems() % 10, 68, 0); font->showString("/", 65, 0); font->showNumber(items, 124, 0); // Show time remaining if (endTime > ticks) x = (endTime - ticks) / 1000; else x = 0; font->showNumber(x / 60, 250, 0); font->showString(":", 247, 0); font->showNumber((x / 10) % 6, 274, 0); font->showNumber(x % 10, 291, 0); return; } /** * Play the level. * * @return Error code */ int JJ1BonusLevel::play () { bool pmenu, pmessage; int option; unsigned int returnTime; int ret; tickOffset = globalTicks; ticks = T_STEP; steps = 0; pmessage = pmenu = false; option = 0; returnTime = 0; video.setPalette(palette); while (true) { ret = loop(pmenu, option, pmessage); if (ret < 0) return ret; // Check if level has been won if (returnTime && (ticks > returnTime)) { if (localPlayer->getJJ1BonusLevelPlayer()->getGems() >= items) { if (playScene("BONUS.0SC") == E_QUIT) return E_QUIT; return WON; } return LOST; } // Process frame-by-frame activity while ((getTimeChange() >= T_STEP) && (stage == LS_NORMAL)) { ret = step(); steps++; if (ret < 0) return ret; else if (ret) { stage = LS_END; paletteEffects = new WhiteOutPaletteEffect(T_BONUS_END, paletteEffects); returnTime = ticks + T_BONUS_END; } } // Draw the graphics if ((ticks < returnTime) && !paused) direction += (ticks - prevTicks) * T_BONUS_END / (returnTime - ticks); draw(); // If paused, draw "PAUSE" if (pmessage && !pmenu) font->showString("pause", (canvasW >> 1) - 44, 32); // Draw statistics, menu etc. drawOverlay(0, pmenu, option, 0, 31, 16); } return E_NONE; } openjazz-20190106/src/jj1bonuslevel/jj1bonuslevel.h000066400000000000000000000036341341440264100221310ustar00rootroot00000000000000 /** * * @file jj1bonuslevel.h * * Part of the OpenJazz project * * @par History: * - 3rd February 2009: Created bonus.h * - 1st August 2012: Renamed bonus.h to jj1bonuslevel.h * * @par Licence: * Copyright (c) 2009-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _BONUS_H #define _BONUS_H #include "io/gfx/anim.h" #include "level/level.h" // Constants // General #define BLW 256 /* Bonus level width */ #define BLH 256 /* Bonus level height */ #define BANIMS 32 #define T_BONUS_END 2000 // Datatype /// JJ1 bonus level grid element typedef struct { unsigned char tile; ///< Indexes the tile set unsigned char event; ///< Event type } JJ1BonusLevelGridElement; // Classes class Font; /// JJ1 bonus level class JJ1BonusLevel : public Level { private: SDL_Surface* tileSet; ///< Tile images SDL_Surface* background; ///< Background image Font* font; ///< On-screen message font Sprite* spriteSet; ///< Sprite images Anim animSet[BANIMS]; ///< Animations JJ1BonusLevelGridElement grid[BLH][BLW]; ///< Level grid char mask[60][64]; ///< Tile masks (at most 60 tiles, all with 8 * 8 masks) fixed direction; ///< Player's direction int loadSprites (); int loadTiles (char* fileName); bool isEvent (fixed x, fixed y); int step (); void draw (); public: JJ1BonusLevel (Game* owner, char* fileName, bool multi); ~JJ1BonusLevel (); bool checkMask (fixed x, fixed y); void receive (unsigned char* buffer); int play (); }; #endif openjazz-20190106/src/jj1bonuslevel/jj1bonuslevelplayer/000077500000000000000000000000001341440264100231675ustar00rootroot00000000000000openjazz-20190106/src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.cpp000066400000000000000000000163071341440264100277020ustar00rootroot00000000000000 /** * * @file jj1bonuslevelplayer.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 18th July 2009: Created playerframe.cpp from parts of player.cpp * - 24th June 2010: Created bonusplayer.cpp from parts of player.cpp and * playerframe.cpp * - 1st August 2012: Renamed bonusplayer.cpp to jj1bonuslevelplayer.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with players in bonus levels. * */ #include "../jj1bonuslevel.h" #include "jj1bonuslevelplayer.h" #include "game/game.h" #include "io/controls.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "util.h" #include /** * Create a JJ1 bonus level player. * * @param parent The game player corresponding to this level player. * @param newAnims Animations * @param startX Starting position x-coordinate * @param startY Starting position y-coordinate * @param flockSize The number of birds accompanying the player */ JJ1BonusLevelPlayer::JJ1BonusLevelPlayer (Player* parent, Anim **newAnims, unsigned char startX, unsigned char startY, int flockSize) { int count; player = parent; memcpy(anims, newAnims, BPANIMS * sizeof(Anim*)); birds = flockSize; reset(startX, startY); // Create the player's palette for (count = 0; count < 256; count++) palette[count].r = palette[count].g = palette[count].b = count; /// @todo Custom colours return; } /** * Delete the JJ1 bonus level player. */ JJ1BonusLevelPlayer::~JJ1BonusLevelPlayer () { return; } /** * Reset the player's position, energy etc. * * @param startX New x-coordinate * @param startY New y-coordinate */ void JJ1BonusLevelPlayer::reset (int startX, int startY) { x = TTOF(startX) + F16; y = TTOF(startY) + F16; z = 0; dx = 0; dy = 0; dz = 0; direction = FQ; dr = 0; da = 0; gems = 0; animType = PA_WALK; return; } /** * Add to the player's gem tally. */ void JJ1BonusLevelPlayer::addGem () { gems++; return; } /** * Determine the direction the player is facing. * * @return The player's direction */ fixed JJ1BonusLevelPlayer::getDirection () { return direction; } /** * Determine the number of gems the player has collected. * * @return Number of gems collected */ int JJ1BonusLevelPlayer::getGems () { return gems; } /** * Determine the player's Z-coordinate (altitude). * * @return Player's Z-coordinate */ fixed JJ1BonusLevelPlayer::getZ () { return z; } /** * Determine how many birds are accompanying the player. * * @return The number of birds accompanying the player */ int JJ1BonusLevelPlayer::countBirds () { return birds; } /** * Player iteration. * * @param ticks Time * @param msps Ticks per step * @param bonus Bonus level */ void JJ1BonusLevelPlayer::step (unsigned int ticks, int msps, JJ1BonusLevel* bonus) { (void)ticks; fixed cdx, cdy; // Bonus stages use polar coordinates for movement (but not position) if (animType == PA_CRASH) { if (dr < 0) dr += PRA_REBOUND * msps; else { dr = 0; animType = PA_OTHER; } } else { if (player->getControl(C_FIRE)) { running = true; dr = PRS_RUN; } if (player->getControl(C_UP)) { // Walk/run forwards if (dr < 0) dr += PRA_REVERSE * msps; else if (dr < PRS_WALK) dr += PRA_WALK * msps; animType = PA_WALK; } else if (player->getControl(C_DOWN)) { // Walk/run back running = false; if (dr > 0) dr -= PRA_REVERSE * msps; else if (dr > PRS_REVERSE) dr -= PRA_WALK * msps; animType = PA_WALK; } else { // Slow down if (!running && (dr > 0)) { if (dr < PRA_STOP * msps) dr = 0; else dr -= PRA_STOP * msps; } if (dr < 0) { if (dr > -PRA_STOP * msps) dr = 0; else dr += PRA_STOP * msps; } if (dr == 0) running = false; animType = PA_OTHER; } if (player->getControl(C_LEFT)) { if (da > -PAS_TURN) da -= PAA_TURN * msps; animType = PA_LEFT; } else if (player->getControl(C_RIGHT)) { if (da < PAS_TURN) da += PAA_TURN * msps; animType = PA_RIGHT; } else { // Slow down rotation if (da > 0) { if (da < PAA_STOP * msps) da = 0; else da -= PAA_STOP * msps; } if (da < 0) { if (da > -PAA_STOP * msps) da = 0; else da += PAA_STOP * msps; } } if ((z == 0) && player->getControl(C_JUMP)) { // Jump dz = PZS_JUMP; if (dr < PRS_JUMP) dr = PRS_JUMP; } if (dz > PZS_FALL) dz += PZA_GRAVITY * msps; if (z > 0) animType = PA_JUMP; } // Apply trajectory direction += (da * msps) >> 10; cdx = (MUL(fSin(direction), dr) * msps) >> 10; cdy = (MUL(-fCos(direction), dr) * msps) >> 10; if (!bonus->checkMask(x + cdx, y)) x += cdx; if (!bonus->checkMask(x, y + cdy)) y += cdy; z += (dz * msps) >> 10; if (z > F1) z = F1; if (z < 0) z = 0; // React to running collision if (running && bonus->checkMask(x + cdx, y + cdy)) { running = false; dr = PRS_CRASH; da = 0; animType = PA_CRASH; } return; } /** * Draw the player. * * @param ticks Time */ void JJ1BonusLevelPlayer::draw (unsigned int ticks) { Anim* anim; anim = anims[animType]; anim->setFrame(ticks / 75, true); if (canvasW <= SW) anim->draw(ITOF((canvasW - anim->getWidth()) >> 1), ITOF(canvasH - anim->getHeight() - 16 - FTOI(z * 80))); else anim->drawScaled(ITOF(canvasW >> 1), ITOF(canvasH - ((((anim->getHeight() >> 1) + 16 + FTOI(z * 80)) * canvasW) / SW)), ITOF(canvasW) / SW); return; } /** * Fill a buffer with player data. * * @param buffer The buffer */ void JJ1BonusLevelPlayer::send (unsigned char *buffer) { // Copy data to be sent to clients/server buffer[9] = birds; buffer[23] = 0; buffer[25] = 0; buffer[26] = 0; buffer[27] = direction >> 2; buffer[29] = 0; buffer[30] = 0; buffer[31] = 0; buffer[32] = 0; buffer[33] = z >> 24; buffer[34] = (z >> 16) & 255; buffer[35] = (z >> 8) & 255; buffer[36] = z & 255; buffer[37] = x >> 24; buffer[38] = (x >> 16) & 255; buffer[39] = (x >> 8) & 255; buffer[40] = x & 255; buffer[41] = y >> 24; buffer[42] = (y >> 16) & 255; buffer[43] = (y >> 8) & 255; buffer[44] = y & 255; return; } /** * Adjust player data based on the contents of a given buffer. * * @param buffer The buffer */ void JJ1BonusLevelPlayer::receive (unsigned char *buffer) { // Interpret data received from client/server switch (buffer[1]) { case MT_P_TEMP: birds = buffer[9]; direction = buffer[27] << 2; z = (buffer[33] << 24) + (buffer[34] << 16) + (buffer[35] << 8) + buffer[36]; x = (buffer[37] << 24) + (buffer[38] << 16) + (buffer[39] << 8) + buffer[40]; y = (buffer[41] << 24) + (buffer[42] << 16) + (buffer[43] << 8) + buffer[44]; break; } return; } openjazz-20190106/src/jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.h000066400000000000000000000052371341440264100273470ustar00rootroot00000000000000 /** * * @file jj1bonuslevelplayer.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 24th June 2010: Created bonusplayer.h from parts of player.h * - 1st August 2012: Renamed bonusplayer.h to jj1bonuslevelplayer.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _BONUSPLAYER_H #define _BONUSPLAYER_H #include "level/levelplayer.h" #include "player/player.h" #include "OpenJazz.h" // Constants // Bonus level animations #define PA_WALK 0 #define PA_LEFT 1 #define PA_RIGHT 2 #define PA_USER 3 #define PA_JUMP 4 #define PA_CRASH 5 #define PA_OTHER 6 #define BPANIMS 7 // Player speeds #define PRS_CRASH -ITOF(60) #define PRS_REVERSE -ITOF(30) #define PRS_JUMP ITOF(40) #define PRS_WALK ITOF(40) #define PRS_RUN ITOF(80) #define PAS_TURN 384 #define PZS_FALL -ITOF(2) #define PZS_JUMP ITOF(3) // Player accelerations #define PRA_REBOUND 150 #define PRA_REVERSE 450 #define PRA_STOP 200 #define PRA_WALK 100 #define PAA_STOP 6 #define PAA_TURN 1 #define PZA_GRAVITY -6 // Classes class Anim; class JJ1BonusLevel; /// JJ1 bonus level player class JJ1BonusLevelPlayer : public LevelPlayer { private: Anim* anims[BPANIMS]; ///< Animations int birds; ///< Number of birds (not present in bonus levels) fixed z; ///< Z-coordinate (altitude) fixed direction; ///< Direction fixed dr; ///< Forward speed fixed da; ///< Angular speed fixed dz; ///< Vertical speed bool running; ///< Rolling/running unsigned char animType; ///< Current animation int gems; ///< Number of gems collected public: JJ1BonusLevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, int flockSize); ~JJ1BonusLevelPlayer (); void reset (int startX, int startY); void addGem (); int countBirds (); fixed getDirection (); int getGems (); fixed getZ (); void send (unsigned char* buffer); void receive (unsigned char* buffer); void step (unsigned int ticks, int msps, JJ1BonusLevel* bonus); void draw (unsigned int ticks); }; #endif openjazz-20190106/src/jj1level/000077500000000000000000000000001341440264100161205ustar00rootroot00000000000000openjazz-20190106/src/jj1level/jj1bullet.cpp000066400000000000000000000113521341440264100205220ustar00rootroot00000000000000 /** * * @file jj1bullet.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 11th February 2009: Created bullet.cpp from parts of events.cpp * - 1st August 2012: Renamed bullet.cpp to jj1bullet.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "jj1bullet.h" #include "jj1event/jj1event.h" #include "jj1level.h" #include "jj1levelplayer/jj1bird.h" #include "jj1levelplayer/jj1levelplayer.h" #include "game/game.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include /** * Generic bullet constructor. * * @param nextBullet The next bullet * @param sourcePlayer The player that fired the bullet (if any) * @param startX The starting x-coordinate of the bullet * @param startY The starting y-coordinate of the bullet * @param bullet Type * @param newDirection The direction of the bullet * @param ticks Time */ JJ1Bullet::JJ1Bullet (JJ1Bullet* nextBullet, JJ1LevelPlayer* sourcePlayer, fixed startX, fixed startY, signed char* bullet, int newDirection, unsigned int ticks) { next = nextBullet; source = sourcePlayer; set = bullet; direction = newDirection; x = startX; y = startY; dx = set[B_XSPEED + direction] << 18; dy = set[B_YSPEED + direction] << 16; if (source) { if ((newDirection & 1) == 0) { if (dx > 0) dx = -dx; } else { if (dx < 0) dx = -dx; } if (set[B_BEHAVIOUR] == 4) dx += source->getXSpeed(); } sprite = level->getSprite(((unsigned char *)set)[B_SPRITE + direction]); time = ticks + T_BULLET; return; } /** * Delete all bullets. */ JJ1Bullet::~JJ1Bullet () { if (next) delete next; return; } /** * Delete this bullet. * * @return The next bullet */ JJ1Bullet* JJ1Bullet::remove () { JJ1Bullet* oldNext; oldNext = next; next = NULL; delete this; return oldNext; } /** * Get the player responsible for this bullet. * * @return The player (NULL if fired by an event) */ JJ1LevelPlayer* JJ1Bullet::getSource () { return source; } /** * Bullet iteration. * * @param ticks Time * * @return Remaining bullet */ JJ1Bullet* JJ1Bullet::step (unsigned int ticks) { JJ1Event* event; int count; // Process the next bullet if (next) next = next->step(ticks); if (level->getStage() != LS_END) { // If the time has expired, destroy the bullet if (ticks > time) return remove(); // Check if a player has been hit for (count = 0; count < nPlayers; count++) { if (players[count].getJJ1LevelPlayer()->overlap(x, y, ITOF(sprite->getWidth()), ITOF(sprite->getHeight()))) { // If the hit was successful, destroy the bullet if (players[count].getJJ1LevelPlayer()->hit(source? source->player: NULL, ticks)) return remove(); } } if (source) { // Check if an event has been hit event = level->getEvents(); while (event) { // Check if the event has been hit if (event->overlap(x, y, ITOF(sprite->getWidth()), ITOF(sprite->getHeight()))) { // If the event is hittable, hit it and destroy the bullet if (event->hit(source, 1, ticks)) return remove(); } event = event->getNext(); } } } // If the scenery has been hit and this is not a bouncer, destroy the bullet if (level->checkMaskUp(x, y) && (set[B_BEHAVIOUR] != 4)) { playSound(set[B_FINISHSOUND]); return remove(); } // Calculate trajectory if (set[B_BEHAVIOUR] == 4) { if (level->checkMaskDown(x, y - F1)) { // Bounce the bullet away from a vertical surface if (dx < 0) direction |= 1; else direction &= ~1; dx = -dx; dy = 0; } if (level->checkMaskDown(x, y + (dy >> 6) - F1)) { // Bounce the bullet against a horizontal surface if (dy < 0) dy = 0; else dy = -dy - (abs(dx - (set[B_XSPEED + direction] << 18)) >> 1); } else { // Respond to gravity dy += F32 * set[B_GRAVITY]; } } else { dy += F32 * set[B_GRAVITY]; if (source && (abs(source->getXSpeed() + dx) > abs(dx))) { x += source->getXSpeed() >> 6; } } // Apply trajectory x += dx >> 6; y += dy >> 6; // Do not destroy the bullet return this; } /** * Draw the bullet. * * @param change Time since last iteration */ void JJ1Bullet::draw (int change) { if (next) next->draw(change); // Show the bullet sprite->draw(FTOI(getDrawX(change)), FTOI(getDrawY(change)), false); return; } openjazz-20190106/src/jj1level/jj1bullet.h000066400000000000000000000037651341440264100202000ustar00rootroot00000000000000 /** * * @file jj1bullet.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 4th February 2009: Created events.h from parts of level.h * - 11th February 2009: Created bullet.h from parts of events.h * - 1st August 2012: Renamed bullet.h to jj1bullet.h * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _BULLET_H #define _BULLET_H #include "level/movable.h" #include "OpenJazz.h" // Constants // Indexes for elements of the bullet set #define B_SPRITE 0 #define B_XSPEED 4 #define B_YSPEED 8 #define B_GRAVITY 12 #define B_FINISHANIM 16 #define B_FINISHSOUND 17 #define B_BEHAVIOUR 18 #define B_BEHAVIOR 18 #define B_STARTSOUND 19 // Survival time #define T_BULLET 1000 #define T_TNT 300 // Classes class JJ1Bird; class JJ1Event; class JJ1LevelPlayer; class Sprite; /// JJ1Bullet class JJ1Bullet : public Movable { private: JJ1Bullet* next; ///< The next bullet JJ1LevelPlayer* source; ///< Source player. If NULL, was fired by an event Sprite* sprite; ///< Sprite signed char* set; ///< Bullet type properties int direction; ///< 0: Left, 1: Right, 2: L (lower), 3: R (lower) unsigned int time; ///< Time at which the bullet will self-destruct JJ1Bullet* remove (); public: JJ1Bullet (JJ1Bullet* nextBullet, JJ1LevelPlayer* sourcePlayer, fixed startX, fixed startY, signed char *bullet, int newDirection, unsigned int ticks); ~JJ1Bullet (); JJ1LevelPlayer* getSource (); JJ1Bullet* step (unsigned int ticks); void draw (int change); }; #endif openjazz-20190106/src/jj1level/jj1demolevel.cpp000066400000000000000000000072201341440264100212060ustar00rootroot00000000000000 /** * * @file jj1demolevel.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed level.c to level.cpp and levelload.c to * levelload.cpp * - 18th July 2009: Created demolevel.cpp from parts of level.cpp and * levelload.cpp * - 1st August 2012: Renamed demolevel.cpp to jj1demolevel.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading and playing of demo levels. * */ #include "jj1level.h" #include "jj1levelplayer/jj1levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "loop.h" #include "util.h" /** * Create a JJ1 demo level. * * @param owner The current game * @param fileName Name of the file containing the macro data. */ JJ1DemoLevel::JJ1DemoLevel (Game* owner, const char* fileName) : JJ1Level(owner) { File* file; char* levelFile; int lNum, wNum, ret; multiplayer = false; try { file = new File(fileName, false); } catch (int e) { throw e; } // Check this is a normal level if (file->loadShort() == 0) throw E_DEMOTYPE; // Level file to load lNum = file->loadShort(9); wNum = file->loadShort(999); levelFile = createFileName("LEVEL", lNum, wNum); // Difficulty file->loadShort(); macro = file->loadBlock(1024); // Load level data ret = load(levelFile, false); delete[] levelFile; if (ret < 0) throw ret; return; } /** * Delete the JJ1 demo level. */ JJ1DemoLevel::~JJ1DemoLevel () { delete[] macro; return; } /** * Play the demo. * * @return Error code */ int JJ1DemoLevel::play () { unsigned char macroPoint; int ret; tickOffset = globalTicks; ticks = 17; steps = 0; video.setPalette(palette); while (true) { // Do general processing if (::loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE) || controls.release(C_ENTER)) return E_NONE; if (controls.release(C_STATS)) stats ^= S_SCREEN; timeCalcs(); // Use macro macroPoint = macro[(ticks / 76) & 1023]; if (macroPoint & 128) return E_NONE; if (macroPoint & 1) { localPlayer->setControl(C_LEFT, false); localPlayer->setControl(C_RIGHT, false); localPlayer->setControl(C_UP, !(macroPoint & 4)); } else { localPlayer->setControl(C_LEFT, !(macroPoint & 2)); localPlayer->setControl(C_RIGHT, macroPoint & 2); localPlayer->setControl(C_UP, false); } localPlayer->setControl(C_DOWN, macroPoint & 8); localPlayer->setControl(C_FIRE, macroPoint & 16); localPlayer->setControl(C_CHANGE, macroPoint & 32); localPlayer->setControl(C_JUMP, macroPoint & 64); localPlayer->setControl(C_SWIM, macroPoint & 64); // Check if level has been won if (getStage() == LS_END) return WON; // Process frame-by-frame activity // Process step while (getTimeChange() >= T_STEP) { ret = step(); steps++; if (ret < 0) return ret; } // Handle player reactions if (localPlayer->getJJ1LevelPlayer()->reacted(ticks) == PR_KILLED) return LOST; // Draw the graphics draw(); drawOverlay(LEVEL_BLACK, false, 0, 0, 0, 0); font->showString("demo", (canvasW >> 1) - 36, 32); } return E_NONE; } openjazz-20190106/src/jj1level/jj1event/000077500000000000000000000000001341440264100176465ustar00rootroot00000000000000openjazz-20190106/src/jj1level/jj1event/jj1bridge.cpp000066400000000000000000000112431341440264100222140ustar00rootroot00000000000000 /** * * @file jj1bridge.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 19th July 2009: Created eventframe.cpp from parts of events.cpp * - 19th July 2009: Renamed events.cpp to event.cpp * - 2nd March 2010: Created bridge.cpp from parts of event.cpp and eventframe.cpp * - 1st August 2012: Renamed bridge.cpp to jj1bridge.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the functions of bridge events. * */ #include "../jj1level.h" #include "../jj1levelplayer/jj1levelplayer.h" #include "jj1event.h" /** * Create bridge. * * @param gX X-coordinate * @param gY Y-coordinate */ JJ1Bridge::JJ1Bridge (unsigned char gX, unsigned char gY) : JJ1Event(gX, gY) { y = TTOF(gY) + ITOF(set->multiB); setAnimType(E_LEFTANIM); // Bridges should ignore the default yOffsets noAnimOffset = true; // leftDipX and rightDipX used to store leftmost and rightmost player on bridge // Start with minimum values leftDipX = set->multiA * set->pieceSize * F4; rightDipX = 0; return; } /** * Bridge iteration. * * @param ticks Time * * @return Remaining event */ JJ1Event* JJ1Bridge::step (unsigned int ticks) { JJ1LevelPlayer* levelPlayer; int count; fixed bridgeLength, playerDipX, playerDipY; set = prepareStep(ticks); if (!set) return remove(false); bridgeLength = set->multiA * set->pieceSize * F4; // Gradually stop the bridge sagging if (leftDipX < bridgeLength) leftDipX += 5120; if (leftDipX > bridgeLength) leftDipX = bridgeLength; if (rightDipX > 0) rightDipX -= 5120; if (rightDipX < 0) rightDipX = 0; for (count = 0; count < nPlayers; count++) { levelPlayer = players[count].getJJ1LevelPlayer(); playerDipX = levelPlayer->getX() + PXO_MID - x; if (playerDipX < bridgeLength >> 1) playerDipY = playerDipX >> 3; else playerDipY = (bridgeLength - playerDipX) >> 3; if (levelPlayer->overlap(x, y - F8 + playerDipY - F4, bridgeLength, F8) && !level->checkMaskDown(x + playerDipX, y - F8 + playerDipY - F32)) { // Player is on the bridge if (playerDipX < leftDipX) leftDipX = playerDipX; if (playerDipX > rightDipX) rightDipX = playerDipX; levelPlayer->setPlatform(gridX, gridY, 0, y - F8 - F1 + playerDipY); } else levelPlayer->clearEvent(gridX, gridY); } return this; } /** * Draw bridge. * * @param ticks Time * @param change Time since last iteration */ void JJ1Bridge::draw (unsigned int ticks, int change) { unsigned char frame; int count; fixed bridgeLength, anchorY, leftDipY, rightDipY; if (next) next->draw(ticks, change); // If the event has been removed from the grid, do not show it if (!set) return; // Check if the event has anything to draw if ((animType == E_NOANIM) || ((set->anims[animType] & 0x7F) == 0)) return; frame = ticks / (set->animSpeed << 5); setAnimFrame(frame + gridX + gridY, true); // Draw the bridge bridgeLength = set->multiA * set->pieceSize * F4; anchorY = getDrawY(change) - F10 - anim->getOffset(); if (rightDipX >= leftDipX) { leftDipY = (leftDipX <= (bridgeLength >> 1)) ? leftDipX >> 3: (bridgeLength - leftDipX) >> 3; rightDipY = (rightDipX <= (bridgeLength >> 1)) ? rightDipX >> 3: (bridgeLength - rightDipX) >> 3; for (count = 0; count < bridgeLength; count += F4 * set->pieceSize) { if (count < leftDipX) anim->draw(getDrawX(change) + count, anchorY + (count * leftDipY / leftDipX)); else if (count < rightDipX) anim->draw(getDrawX(change) + count, anchorY + leftDipY + ((count - leftDipX) * (rightDipY - leftDipY) / (rightDipX - leftDipX))); else anim->draw(getDrawX(change) + count, anchorY + ((bridgeLength - count) * rightDipY / (bridgeLength - rightDipX))); } } else { // No players on the bridge, de-sagging in progress // Midpoint leftDipY = (leftDipX + rightDipX) >> 1; // Dip rightDipY = (rightDipX < bridgeLength - leftDipX) ? rightDipX >> 3: (bridgeLength - leftDipX) >> 3; for (count = 0; count < bridgeLength; count += F4 * set->pieceSize) { if (count < leftDipY) anim->draw(getDrawX(change) + count, anchorY + (count * rightDipY / leftDipY)); else anim->draw(getDrawX(change) + count, anchorY + ((bridgeLength - count) * rightDipY / (bridgeLength - leftDipY))); } } return; } openjazz-20190106/src/jj1level/jj1event/jj1event.cpp000066400000000000000000000160301341440264100221000ustar00rootroot00000000000000 /** * * @file jj1event.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 11th February 2009: Created bullet.cpp from parts of events.cpp * - 1st March 2009: Created bird.cpp from parts of events.cpp * - 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp * - 19th July 2009: Created eventframe.cpp from parts of events.cpp * - 19th July 2009: Renamed events.cpp to event.cpp * - 2nd March 2010: Created guardians.cpp from parts of event.cpp and * eventframe.cpp * - 2nd March 2010: Created bridge.cpp from parts of event.cpp and eventframe.cpp * - 5th February 2011: Moved parts of eventframe.cpp to event.cpp * - 1st August 2012: Renamed event.cpp to jj1event.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with events in ordinary levels. * */ #include "../jj1level.h" #include "jj1event.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" /** * Create event * * @param gX X-coordinate * @param gY Y-coordinate */ JJ1Event::JJ1Event (unsigned char gX, unsigned char gY) { set = level->getEvent(gX, gY); x = TTOF(gX); y = TTOF(gY + 1); dx = 0; dy = 0; next = level->getEvents(); gridX = gX; gridY = gY; flashTime = 0; animType = E_NOANIM; anim = NULL; noAnimOffset = false; drawnX = x; drawnY = y; width = F32; height = F32; return; } /** * Delete all events */ JJ1Event::~JJ1Event () { if (next) delete next; return; } /** * Delete this event * * @param permanently Whether or not to delete the event from the level * * @return The next event */ JJ1Event* JJ1Event::remove (bool permanently) { JJ1Event *oldNext; if (permanently) level->clearEvent(gridX, gridY); oldNext = next; next = NULL; delete this; return oldNext; } /** * Get the next event * * @return The next event */ JJ1Event * JJ1Event::getNext () { return next; } /** * Initiate the destruction of the event * * @param ticks Time */ void JJ1Event::destroy (unsigned int ticks) { setAnimType(E_LFINISHANIM | (animType & 1)); level->setEventTime(gridX, gridY, ticks); playSound(set->sound); return; } /** * Deal with bullet collisions * * @param source Source of the hit(s) * @param hits Number of hits to inflict * @param ticks Current time * * @return Whether or not the hit was successful */ bool JJ1Event::hit (JJ1LevelPlayer *source, int hits, unsigned int ticks) { int hitsRemaining; // Check if event has already been destroyed if (((animType & ~1) == E_LFINISHANIM) || (ticks < flashTime)) return false; hitsRemaining = level->hitEvent(gridX, gridY, hits, source, ticks); // If the event cannot be hit, do not register hit if (hitsRemaining < 0) return false; // Check if the hit has destroyed the event if (hitsRemaining == 0) destroy(ticks); // The event has been hit, so it should flash flashTime = ticks + T_FLASH; // Register hit return true; } /** * Determine whether or not the event is an enemy * * @return Whether or not the event is an enemy */ bool JJ1Event::isEnemy () { return set->strength && (set->modifier == 0); } /** * Determine whether or not the event is from the given position * * @return Whether or not the event is from the given position */ bool JJ1Event::isFrom (unsigned char gX, unsigned char gY) { return (gX == gridX) && (gY == gridY); } /** * Calculate the width and height of the event */ void JJ1Event::calcDimensions () { if (animType == E_NOANIM) { width = F32; height = F32; } else { width = ITOF(anim->getWidth()); height = ITOF(anim->getHeight()); // Blank sprites for e.g. invisible springs if ((width == F1) && (height == F1)) { width = F32; height = F32; } } return; } /** * Determine whether or not the event is overlapping the given area * * @param areaX The x-coordinate of the left of the area * @param areaY The y-coordinate of the top of the area * @param areaWidth The width of the area * @param areaHeight The height of the area * * @return Whether or not there is an overlap */ bool JJ1Event::overlap (fixed areaX, fixed areaY, fixed areaWidth, fixed areaHeight) { return (drawnX + width >= areaX) && (drawnX < areaX + areaWidth) && (drawnY + height >= areaY) && (drawnY < areaY + areaHeight); } /** * Sets the animation type and updates the current animation and dimensions * * @param type The new animation type */ void JJ1Event::setAnimType(unsigned char type) { if (type == animType) return; animType = type; if (animType == E_NOANIM) anim = NULL; // If there is no shooting animation, use the normal animation instead else if (((animType & ~1) == E_LSHOOTANIM) && (set->anims[animType] == 0)) anim = level->getAnim(set->anims[animType & 1] & 0x7F); else anim = level->getAnim(set->anims[animType] & 0x7F); calcDimensions(); return; } /** * Sets the animation frame and updates the current dimensions */ void JJ1Event::setAnimFrame (int frame, bool looping) { if (!anim) return; anim->setFrame(frame, looping); calcDimensions(); return; } /** * Functionality required by all event types on each iteration * * @param ticks Time * * @return Animation */ JJ1EventType* JJ1Event::prepareStep (unsigned int ticks) { // Process the next event if (next) next = next->step(ticks); // If the event has been removed from the grid, destroy it if (!set) return NULL; // If the event and its origin are off-screen, the event is not in the // process of self-destruction, remove it if (((animType & ~1) != E_LFINISHANIM) && ((x < viewX - F192) || (x > viewX + ITOF(canvasW) + F192) || (y < viewY - F160) || (y > viewY + ITOF(canvasH) + F160)) && ((gridX < FTOT(viewX) - 1) || (gridX > ITOT(FTOI(viewX) + canvasW) + 1) || (gridY < FTOT(viewY) - 1) || (gridY > ITOT(FTOI(viewY) + canvasH) + 1))) return NULL; return set; } /** * Draw the event's energy bar * * @param ticks Time */ void JJ1Event::drawEnergy (unsigned int ticks) { Anim* miscAnim; int hits; if (!set || set->modifier != 8) { if (next) next->drawEnergy(ticks); return; } else if (set->strength) { // Draw boss energy bar hits = level->getEventHits(gridX, gridY) * 100 / set->strength; // Devan head miscAnim = level->getMiscAnim(MA_DEVHEAD); miscAnim->setFrame(0, true); if (ticks < flashTime) miscAnim->flashPalette(0); miscAnim->draw(ITOF(canvasW - 44), ITOF(hits + 48)); if (ticks < flashTime) miscAnim->restorePalette(); // Bar drawRect(canvasW - 40, hits + 40, 12, 100 - hits, (ticks < flashTime)? 0: 32); } return; } openjazz-20190106/src/jj1level/jj1event/jj1event.h000066400000000000000000000066151341440264100215550ustar00rootroot00000000000000 /** * * @file jj1event.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 4th February 2009: Created events.h from parts of level.h * - 11th February 2009: Created bullet.h from parts of events.h * - 1st March 2009: Created bird.h from parts of events.h * - 19th July 2009: Renamed events.h to event.h * - 2nd March 2010: Created guardians.h from parts of event.h * - 1st August 2012: Renamed event.h to jj1event.h * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _EVENT_H #define _EVENT_H #include "../jj1level.h" #include "io/gfx/anim.h" #include "level/movable.h" #include "OpenJazz.h" // Constants // Animations #define E_LEFTANIM 0 #define E_RIGHTANIM 1 #define E_LFINISHANIM 2 #define E_RFINISHANIM 3 #define E_LSHOOTANIM 4 #define E_RSHOOTANIM 5 #define E_NOANIM 6 // Delays #define T_FLASH 100 // Speed factors #define ES_SLOW ITOF(80) #define ES_FAST ITOF(240) // Classes class Anim; class JJ1LevelPlayer; /// JJ1 level event class JJ1Event : public Movable { private: void calcDimensions (); protected: JJ1Event* next; ///< Next event JJ1EventType* set; ///< Type Anim* anim; ///< Current animation fixed drawnX, drawnY; ///< Current drawing co-ordinates fixed width, height; ///< Current dimensions unsigned char gridX, gridY; ///< Grid position of the event unsigned char animType; ///< Animation type (E_LEFTANIM, etc.) unsigned int flashTime; ///< Time flash will end bool noAnimOffset; JJ1Event (unsigned char gX, unsigned char gY); JJ1Event* remove (bool permanently); void destroy (unsigned int ticks); void setAnimType (unsigned char type); void setAnimFrame (int frame, bool looping); JJ1EventType* prepareStep (unsigned int ticks); public: virtual ~JJ1Event (); JJ1Event* getNext (); bool hit (JJ1LevelPlayer *source, int hits, unsigned int ticks); bool isEnemy (); bool isFrom (unsigned char gX, unsigned char gY); bool overlap (fixed areaX, fixed areaY, fixed areaWidth, fixed areaHeight); virtual JJ1Event* step (unsigned int ticks) = 0; virtual void draw (unsigned int ticks, int change) = 0; void drawEnergy (unsigned int ticks); }; /// Standard JJ1 level event class JJ1StandardEvent : public JJ1Event { private: fixed node; ///< Current event path node bool onlyLAnimOffset; bool onlyRAnimOffset; void move (unsigned int ticks); public: JJ1StandardEvent (JJ1EventType* event, unsigned char gX, unsigned char gY, fixed startX, fixed startY); JJ1Event* step (unsigned int ticks); void draw (unsigned int ticks, int change); }; /// JJ1 level bridge class JJ1Bridge : public JJ1Event { private: fixed leftDipX; fixed rightDipX; public: JJ1Bridge (unsigned char gX, unsigned char gY); JJ1Event* step (unsigned int ticks); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj1level/jj1event/jj1guardians.cpp000066400000000000000000000174641341440264100227500ustar00rootroot00000000000000 /** * * @file jj1guardians.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 19th July 2009: Created eventframe.cpp from parts of events.cpp * - 19th July 2009: Renamed events.cpp to event.cpp * - 2nd March 2010: Created guardians.cpp from parts of event.cpp and eventframe.cpp * - 1st August 2012: Renamed guardians.cpp to jj1guardians.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the functions of guardian events. * */ #include "../jj1bullet.h" #include "../jj1level.h" #include "jj1guardians.h" #include "io/gfx/video.h" #include "util.h" #include /** * Create guardian. * * @param gX X-coordinate * @param gY Y-coordinate */ Guardian::Guardian(unsigned char gX, unsigned char gY) : JJ1Event(gX, gY) { setAnimType(E_LEFTANIM); stage = 0; return; } /** * Create episode B guardian. * * @param gX X-coordinate * @param gY Y-coordinate */ DeckGuardian::DeckGuardian (unsigned char gX, unsigned char gY) : Guardian(gX, gY) { return; } /** * Episode B guardian iteration. * * @param ticks Time * * @return Remaining event */ JJ1Event* DeckGuardian::step (unsigned int ticks) { int count; set = prepareStep(ticks); if (!set) return remove(false); count = level->getEventHits(gridX, gridY); if (count < 8) stage = 0; else if (count < 16) stage = 1; else if (count < 24) stage = 2; else stage = 3; // If the event has been destroyed, play its finishing animation and set its // reaction time if (set->strength && (level->getEventHits(gridX, gridY) >= set->strength) && ((animType & ~1) != E_LFINISHANIM)) { destroy(ticks); } // If the reaction time has expired if (level->getEventTime(gridX, gridY) && (ticks > level->getEventTime(gridX, gridY))) { if ((animType & ~1) != E_LFINISHANIM) { level->setEventTime(gridX, gridY, 0); } } return this; } /** * Draw episode B guardian. * * @param ticks Time * @param change Time since last iteration */ void DeckGuardian::draw (unsigned int ticks, int change) { Anim* unitAnim; if (next) next->draw(ticks, change); // If the event has been removed from the grid, do not show it if (!set) return; // Draw the boss if (stage < 3) { // Draw unit unitAnim = level->getAnim(29 + stage); if (stage == 0) { width = F8; drawnX = x - F64; } else if (stage == 1) { width = F8; drawnX = x + F32 - F8; } else if (stage == 2) { width = F64 + F32; drawnX = x - F64; } drawnY = y + F32; height = F32; if (ticks < flashTime) unitAnim->flashPalette(0); if (stage == 0) unitAnim->draw(getDrawX(change) - F64, getDrawY(change) + F32); else if (stage == 1) unitAnim->draw(getDrawX(change) + F32 - F8 - F4, getDrawY(change) + F32); else unitAnim->draw(getDrawX(change) + F8 - F64, getDrawY(change) + F32); if (ticks < flashTime) unitAnim->restorePalette(); } return; } /** * Create episode 1 guardian. * * @param gX X-coordinate * @param gY Y-coordinate */ MedGuardian::MedGuardian(unsigned char gX, unsigned char gY) : Guardian(gX, gY) { direction = 1; shoot = false; return; } /** * Episode 1 guardian iteration. * * @param ticks Time * * @return Remaining event */ JJ1Event* MedGuardian::step(unsigned int ticks) { fixed sin = fSin(ticks / 2); fixed cos = fCos(ticks / 2); set = prepareStep(ticks); if (!set) return remove(false); if (level->getEventHits(gridX, gridY) >= set->strength / 2) stage = 1; if (level->getEventHits(gridX, gridY) >= set->strength) stage = 2; // Stage 0: Move in an eight shape and fire the occasional shot if (stage == 0) { if (direction == 1) { // Lower right part of the eight setAnimType(E_LEFTANIM); dx = TTOF(gridX) + (sin * 96) - x + ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos > 0) direction = 2; } if (direction == 2) { // Upper left part of the eight setAnimType(E_LEFTANIM); dx = TTOF(gridX) - (sin * 96) - x - ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos < 0) direction = 3; } if (direction == 3) { // Lower left part of the eight setAnimType(E_RIGHTANIM); dx = TTOF(gridX) - (sin * 96) - x - ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos > 0) direction = 4; } if (direction == 4) { // Upper right part of the eight setAnimType(E_RIGHTANIM); dx = TTOF(gridX) + (sin * 96) - x + ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos < 0) direction = 1; } // Decide if there should be a shot if ((ticks % (set->bulletPeriod * 25) > (unsigned int)(set->bulletPeriod * 25) - 300)) { level->setEventTime(gridX, gridY, ticks + 300); shoot = true; } // Shoot if there is a shot if (level->getEventTime(gridX, gridY) && (ticks > level->getEventTime(gridX, gridY)) && shoot) { if (set->bullet < 32) level->createBullet(NULL, gridX, gridY, x + anim->getAccessoryShootX(), y + anim->getAccessoryShootY(), set->bullet, (animType != E_LEFTANIM), ticks); shoot = false; } } // Stage 1: Hop back and forth destroying the bottom row of tiles if (stage == 1) { fixed startPos = TTOF(gridY) + ITOF(40); if (direction < 5) { // Move up or down towards the starting position for hopping direction = (y > startPos) ? 5 : 6; } // Move up to the correct height if (direction == 5) { if (y > startPos) { dx = 0; dy = -ITOF(2); } else direction = 7; } // Move down to the correct height if (direction == 6) { if (y < startPos) { dx = 0; dy = ITOF(2); } else direction = 7; } // Cosinus should be near zero before we start hopping. if (direction == 7) { dx = 0; dy = 0; if (cos > -100 && cos < 100) direction = 8; } // Start hopping if (direction == 8) { if (level->checkMaskUp(x, y) || level->checkMaskUp(x + width, y)) setAnimType((animType == E_LEFTANIM) ? E_RIGHTANIM : E_LEFTANIM); dy = startPos - abs(cos * 96) - y; dx = abs(cos * 6); if (animType == E_LEFTANIM) dx *= -1; if (cos < 0 && level->checkMaskDown(x + ITOF(anim->getWidth() / 2), y + TTOF(1))) direction = 9; } // Destroy the block underneath if (direction == 9) { // Shake a bit dx = (FTOI(x) % 2) ? ITOF(1) : -ITOF(1); dy = 0; // Remove the tile if (cos > 0 && cos < 100) { level->setTile( FTOT(x + ITOF((anim->getWidth() / 2))), FTOT(y) + 1, set->magnitude); direction = 8; } } } // Stage 2: End of behavior if (stage == 2) { dx = 0; dy = ITOF(4); } x += dx; y += dy; dx = dx << 6; dy = dy << 6; return this; } /** * Draw episode 1 guardian. * * @param ticks Time * @param change Time since last iteration */ void MedGuardian::draw(unsigned int ticks, int change) { Anim *stageAnim; unsigned char frame; if (next) next->draw(ticks, change); fixed xChange = getDrawX(change); fixed yChange = getDrawY(change); frame = ticks / (set->animSpeed << 5); if (stage == 0) stageAnim = anim; else stageAnim = level->getAnim(set->anims[E_LFINISHANIM | (animType & 1)] & 0x7F); stageAnim->setFrame(frame + gridX + gridY, true); if (ticks < flashTime) stageAnim->flashPalette(0); drawnX = x + anim->getXOffset(); drawnY = y + anim->getYOffset() + stageAnim->getOffset(); stageAnim->draw(xChange, yChange); if (ticks < flashTime) stageAnim->restorePalette(); return; } openjazz-20190106/src/jj1level/jj1event/jj1guardians.h000066400000000000000000000032321341440264100224010ustar00rootroot00000000000000 /** * * @file jj1guardians.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 4th February 2009: Created events.h from parts of level.h * - 19th July 2009: Renamed events.h to event.h * - 2nd March 2010: Created guardians.h from parts of event.h * - 1st August 2012: Renamed guardians.h to jj1guardians.h * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _GUARDIANS_H #define _GUARDIANS_H #include "jj1event.h" // Class /// Guardian event base class class Guardian : public JJ1Event { protected: int stage; Guardian (unsigned char gX, unsigned char gY); }; /// Episode B guardian class DeckGuardian : public Guardian { public: DeckGuardian (unsigned char gX, unsigned char gY); bool overlap (fixed left, fixed top, fixed width, fixed height); JJ1Event* step (unsigned int ticks); void draw (unsigned int ticks, int change); }; /// Episode 1 guardian class MedGuardian : public Guardian { private: unsigned char direction; bool shoot; public: MedGuardian (unsigned char gX, unsigned char gY); //bool overlap (fixed left, fixed top, fixed width, fixed height); JJ1Event* step (unsigned int ticks); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj1level/jj1event/jj1standardevent.cpp000066400000000000000000000516761341440264100236400ustar00rootroot00000000000000 /** * * @file jj1standardevent.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 19th July 2009: Created eventframe.cpp from parts of events.cpp * - 2nd March 2010: Created guardians.cpp from parts of event.cpp and eventframe.cpp * - 2nd March 2010: Created bridge.cpp from parts of event.cpp and eventframe.cpp * - 5th February 2011: Moved parts of eventframe.cpp to event.cpp * - 5th February 2011: Renamed eventframe.cpp to standardevent.cpp * - 1st August 2012: Renamed standardevent.cpp to jj1standardevent.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the once-per-frame functions of ordinary events. * */ #include "../jj1bullet.h" #include "../jj1level.h" #include "../jj1levelplayer/jj1levelplayer.h" #include "jj1event.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" #include /** * Create standard event. * * @param event The event type * @param gX The grid X-coordinate of the origin of the event * @param gY The grid Y-coordinate of the origin of the event * @param startX The initial X-coordinate of the event * @param startY The initial Y-coordinate of the event */ JJ1StandardEvent::JJ1StandardEvent (JJ1EventType* event, unsigned char gX, unsigned char gY, fixed startX, fixed startY) : JJ1Event(gX, gY) { set = event; x = startX; y = startY; node = 0; onlyLAnimOffset = false; onlyRAnimOffset = false; switch (set->movement) { case 2: // Walk from side to side case 4: // Walk from side to side and down hills setAnimType(E_LEFTANIM); onlyLAnimOffset = true; break; case 6: // Use the path from the level file case 7: // Flying snake behavior setAnimType(E_LEFTANIM); noAnimOffset = true; break; case 21: // Destructible block case 25: // Float up / Belt case 37: // Sucker tubes case 38: // Sucker tubes case 40: // Monochrome case 42: // Reflection case 45: // Semitransparency case 57: // Bubbles animType = E_LEFTANIM; setAnimType(E_NOANIM); break; case 26: // Flip animation setAnimType(E_RIGHTANIM); onlyRAnimOffset = true; break; default: setAnimType(E_LEFTANIM); break; } return; } /** * Move standard event. * * @param ticks Time */ void JJ1StandardEvent::move (unsigned int ticks) { JJ1LevelPlayer* levelPlayer; int length; fixed angle; if ((animType & ~1) == E_LSHOOTANIM) { dx = 0; dy = 0; return; } levelPlayer = localPlayer->getJJ1LevelPlayer(); // Handle movement switch (set->movement) { case 1: // Sink down dy = ES_FAST; break; case 2: // Walk from side to side if (animType == E_LEFTANIM) dx = -ES_FAST; else if (animType == E_RIGHTANIM) dx = ES_FAST; else dx = 0; break; case 3: // Seek jazz if (levelPlayer->getX() + PXO_R < x) dx = -ES_FAST; else if (levelPlayer->getX() + PXO_L > x + width) dx = ES_FAST; else dx = 0; break; case 4: // Walk from side to side and down hills if (!level->checkMaskDown(x + (width >> 1), y)) { // Fall downwards dx = 0; dy = ES_FAST; } else { // Walk from side to side if (animType == E_LEFTANIM) dx = -ES_FAST; else if (animType == E_RIGHTANIM) dx = ES_FAST; dy = 0; } break; case 5: /// @todo Find out what behaviour 5 is break; case 6: case 7: node = (node + FH) % ITOF(level->path[set->multiA].length); // Use the path from the level file dx = TTOF(gridX) + ITOF(level->path[set->multiA].x[FTOI(node)]) - x; dy = TTOF(gridY) + ITOF(level->path[set->multiA].y[FTOI(node)]) - y; x += dx; y += dy; dx = dx << 6; dy = dy << 6; return; case 8: /// @todo Bird-esque following break; case 9: /// @todo Find out what behaviour 9 is break; case 10: /// @todo Find out what behaviour 10 is break; case 11: // Sink to ground if (!level->checkMaskDown(x + (width >> 1), y)) dy = ES_FAST; else dy = 0; break; case 12: // Move back and forth horizontally if (animType == E_LEFTANIM) dx = -ES_SLOW; else if (animType == E_RIGHTANIM) dx = ES_SLOW; else dx = 0; break; case 13: // Move up and down if (animType == E_LEFTANIM) dy = -ES_SLOW; else if (animType == E_RIGHTANIM) dy = ES_SLOW; else dy = 0; break; case 14: /// @todo Move back and forth rapidly break; case 15: /// @todo Rise or lower to meet jazz break; case 16: // Move across level to the left or right if (set->magnitude == 0) dx = -ES_SLOW; else dx = set->magnitude * ES_SLOW; break; case 17: /// @todo Find out what behaviour 17 is break; case 18: /// @todo Find out what behaviour 18 is break; case 19: /// @todo Find out what behaviour 19 is break; case 20: /// @todo Find out what behaviour 20 is break; case 21: // Destructible block if (level->getEventHits(gridX, gridY) >= set->strength) level->setTile(gridX, gridY, set->multiA); break; case 22: /// @todo Fall down in random spot and repeat break; case 23: /// @todo Find out what behaviour 23 is break; case 24: /// @todo Crawl along ground and go downstairs break; case 26: /// @todo Find out what behaviour 26 is break; case 27: /// @todo Face jazz break; case 29: // Rotate length = set->pieceSize * set->pieces; angle = (set->angle << 2) + (set->magnitude * ticks / 13); dx = TTOF(gridX) + (fSin(angle) * length) - x; dy = TTOF(gridY) + ((fCos(angle) + F1) * length) - y; x += dx; y += dy; dx = dx << 6; dy = dy << 6; return; case 30: // Swing length = set->pieceSize * set->pieces; angle = (set->angle << 2) + (set->magnitude * ticks / 13); dx = TTOF(gridX) + (fSin(angle) * length) - x; dy = TTOF(gridY) + ((abs(fCos(angle)) + F1) * length) - y; x += dx; y += dy; dx = dx << 6; dy = dy << 6; return; case 31: // Move horizontally if (animType == E_LEFTANIM) dx = -ES_FAST; else dx = ES_FAST; break; case 32: // Move horizontally if (animType == E_LEFTANIM) dx = -ES_FAST; else dx = ES_FAST; break; case 33: // Sparks-esque following if (levelPlayer->getFacing() && (x + width < levelPlayer->getX())) { dx = ES_FAST; if (y + height < levelPlayer->getY() + PYO_TOP) dy = ES_SLOW; else if (y > levelPlayer->getY()) dy = -ES_SLOW; else dy = 0; } else if (!levelPlayer->getFacing() && (x > levelPlayer->getX() + F32)) { dx = -ES_FAST; if (y + height < levelPlayer->getY() + PYO_TOP) dy = ES_SLOW; else if (y > levelPlayer->getY()) dy = -ES_SLOW; else dy = 0; } else { dx = 0; dy = 0; } break; case 34: // Launching event if (ticks > level->getEventTime(gridX, gridY)) { if (animType == E_LEFTANIM) dy = -(F16 + y - (TTOF(gridY) - (set->multiA * F12))) * 10; else dy = (F16 + y - (TTOF(gridY) - (set->multiA * F12))) * 10; } else { dy = TTOF(gridY) + F16 - y; y += dy; dy = dy << 6; return; } break; case 35: // Non-floating Sparks-esque following if (levelPlayer->getFacing() && (x + width < levelPlayer->getX() + PXO_L - F4)) { if (level->checkMaskDown(x + width, y + F4) && !level->checkMaskDown(x + width + F4, y - (height >> 1))) dx = ES_FAST; else dx = 0; } else if (!levelPlayer->getFacing() && (x > levelPlayer->getX() + PXO_R + F4)) { if (level->checkMaskDown(x, y + F4) && !level->checkMaskDown(x - F4, y - (height >> 1))) dx = -ES_FAST; else dx = 0; } else dx = 0; break; case 36: // Walk from side to side and down hills, staying on-screen if (!level->checkMaskDown(x + (width >> 1), y)) { // Fall downwards dx = 0; dy = ES_FAST; } else { // Walk from side to side, staying on-screen if (animType == E_LEFTANIM) dx = -ES_FAST; else if (animType == E_RIGHTANIM) dx = ES_FAST; else dx = 0; dy = 0; } break; case 39: /// @todo Collapsing floor break; case 40: /// @todo Find out what behaviour 40 is break; case 41: /// @todo Switch left & right anim periodically break; case 42: /// @todo Find out what behaviour 42 is break; case 43: /// @todo Find out what behaviour 43 is break; case 44: /// @todo Leap to greet Jazz very quickly break; case 45: /// @todo Find out what behaviour 45 is break; case 46: /// @todo "Final" boss break; case 53: // Dreempipes turtles if (y > level->getWaterLevel()) { if (animType == E_LEFTANIM) dx = -ES_SLOW; else if (animType == E_RIGHTANIM) dx = ES_SLOW; else dx = 0; } else dx = 0; break; default: // Do nothing for the following: // 0: Static // 25: Float up / Belt // 37/38: Repel /// @todo Remaining event behaviours break; } dx /= set->speed; dy /= set->speed; x += dx >> 6; y += dy >> 6; return; } /** * Event iteration. * * @param ticks Time * * @return Remaining event */ JJ1Event* JJ1StandardEvent::step (unsigned int ticks) { JJ1LevelPlayer* levelPlayer; int count; unsigned int eventTime; int hits; set = prepareStep(ticks); hits = level->getEventHits(gridX, gridY); // If the event is off-screen, remove it (permanently if it's been deflected by a shield) if (!set) return remove(hits == 255); // If the event has been deflected by a shield, move it if (hits == 255) { dy = 200 * F1; x += dx >> 6; y += dy >> 6; return this; } // Get the time of the event's next action eventTime = level->getEventTime(gridX, gridY); // If the event's finish animation has expired, remove it if (eventTime && ((animType & ~1) == E_LFINISHANIM)) { if (anim == NULL) return remove(true); if (((int)(ticks - eventTime) / (int)(set->animSpeed << 3)) > anim->getLength()) return remove(true); } // Get the player levelPlayer = localPlayer->getJJ1LevelPlayer(); // Move move(ticks); // Choose animation and direction if ((animType & ~1) == E_LEFTANIM) { switch (set->movement) { case 2: // Walk from side to side if (animType == E_LEFTANIM) { if (!level->checkMaskDown(x, y + F4) || level->checkMaskDown(x - F4, y - (height >> 1))) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (!level->checkMaskDown(x + width, y + F4) || level->checkMaskDown(x + width + F4, y - (height >> 1))) setAnimType(E_LEFTANIM); } break; case 3: // Seek jazz if (levelPlayer->getX() + PXO_R < x) setAnimType(E_LEFTANIM); else if (levelPlayer->getX() + PXO_L > x + width) setAnimType(E_RIGHTANIM); break; case 4: // Walk from side to side and down hills if (level->checkMaskDown(x + (width >> 1), y)) { // Walk from side to side if (animType == E_LEFTANIM) { if (level->checkMaskDown(x - F4, y - (height >> 1) - F12)) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + width + F4, y - (height >> 1) - F12)) setAnimType(E_LEFTANIM); } } break; case 6: // Use the path from the level file // Check movement direction if ((FTOI(node) < 3) || (level->path[set->multiA].x[FTOI(node)] <= level->path[set->multiA].x[FTOI(node) - 3])) setAnimType(E_LEFTANIM); else setAnimType(E_RIGHTANIM); break; case 7: // Move back and forth horizontally with tail if (animType == E_LEFTANIM) { if (x < TTOF(gridX)) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (x > TTOF(gridX) + F100) setAnimType(E_LEFTANIM); } break; case 12: // Move back and forth horizontally if (animType == E_LEFTANIM) { if (level->checkMaskDown(x - F4, y - (height >> 1))) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + width + F4, y - (height >> 1))) setAnimType(E_LEFTANIM); } break; case 13: // Move up and down if (animType == E_LEFTANIM) { if (level->checkMaskDown(x + (width >> 1), y - height - F4)) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + (width >> 1), y + F4)) setAnimType(E_LEFTANIM); } break; case 26: // Flip animation if (levelPlayer->overlap(x, y - height, width, height)) setAnimType(E_LEFTANIM); else setAnimType(E_RIGHTANIM); break; case 31: // Moving platform if (animType == E_LEFTANIM) { if (level->checkMaskDown(x, y - (height >> 1))) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + width, y - (height >> 1))) setAnimType(E_LEFTANIM); } break; case 32: // Moving platform if (x < TTOF(gridX) - (set->pieceSize << 14)) setAnimType(E_RIGHTANIM); else if (x > TTOF(gridX + set->pieceSize)) setAnimType(E_LEFTANIM); break; case 33: // Sparks-esque following if (levelPlayer->getFacing() && (x + width < levelPlayer->getX())) { setAnimType(E_RIGHTANIM); } else if (!levelPlayer->getFacing() && (x > levelPlayer->getX() + F32)) { setAnimType(E_LEFTANIM); } break; case 34: // Launching event if (ticks > eventTime) { if (y <= F16 + TTOF(gridY) - (set->multiA * F12)) setAnimType(E_RIGHTANIM); else if (y >= F16 + TTOF(gridY)) { setAnimType(E_LEFTANIM); level->setEventTime(gridX, gridY, ticks + (set->multiB * 50)); } } else setAnimType(E_LEFTANIM); break; case 36: // Walk from side to side and down hills, staying on-screen if (level->checkMaskDown(x + (width >> 1), y)) { // Walk from side to side, staying on-screen if (animType == E_LEFTANIM) { if (level->checkMaskDown(x - F4, y - (height >> 1)) || (x - F4 < viewX)) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + width + F4, y - (height >> 1)) || (x + width + F4 > viewX + ITOF(canvasW))) setAnimType(E_LEFTANIM); } } break; case 53: // Dreempipes turtles if (y > level->getWaterLevel()) { if (animType == E_LEFTANIM) { if (level->checkMaskDown(x - F4, y - (height >> 1))) setAnimType(E_RIGHTANIM); } else if (animType == E_RIGHTANIM) { if (level->checkMaskDown(x + width + F4, y - (height >> 1))) setAnimType(E_LEFTANIM); } else setAnimType(E_LEFTANIM); } break; default: if (levelPlayer->getX() + PXO_MID < x + (width >> 1)) setAnimType(E_LEFTANIM); else setAnimType(E_RIGHTANIM); break; } } // If the event is in its finish stage, nothing else needs to be done if ((animType & ~1) == E_LFINISHANIM) return this; // If the event has been destroyed, play its finishing animation and set its // reaction time if (set->strength && (hits >= set->strength)) { destroy(ticks); } if (set->bulletPeriod) { count = level->getAnim(set->anims[E_LSHOOTANIM | (animType & 1)])->getLength() * set->animSpeed << 5; if ((ticks % (set->bulletPeriod * 32) > (unsigned int)(set->bulletPeriod * 32) - count) && ((animType & ~1) == E_LEFTANIM)) { // Enter firing mode if (animType == E_LEFTANIM) setAnimType(E_LSHOOTANIM); else setAnimType(E_RSHOOTANIM); level->setEventTime(gridX, gridY, ticks + count); } } // If the reaction time has expired if (eventTime && (ticks > eventTime)) { if ((animType & ~1) == E_LSHOOTANIM) { if (set->bullet < 32) level->createBullet( NULL, gridX, gridY, drawnX + anim->getShootX(), drawnY + anim->getShootY(), set->bullet, (animType & 1)? true: false, ticks); setAnimType(E_LEFTANIM | (animType & 1)); } else { level->setEventTime(gridX, gridY, 0); } } if (level->getStage() == LS_END) return this; // Handle contact with player for (count = 0; count < nPlayers; count++) { levelPlayer = players[count].getJJ1LevelPlayer(); // Check if the player is touching the event if (set->modifier == 6) { if (width && height && levelPlayer->overlap(drawnX, drawnY - F4, width - F8, F8) && (levelPlayer->getY() <= F4 + (PYS_FALL >> 6) + drawnY) && !level->checkMaskDown(levelPlayer->getX() + PXO_MID, PYO_TOP + drawnY)) { // Player is on a platform levelPlayer->setPlatform(gridX, gridY, (dx >> 6), drawnY); } else levelPlayer->clearEvent(gridX, gridY); } else { // Check if the player is touching the event if (width && height && levelPlayer->overlap(drawnX + F2, drawnY + F2, width - F4, height - F4)) { // If the player picks up the event, destroy it if (levelPlayer->touchEvent(set, gridX, gridY, ticks)) { if (level->getEventHits(gridX, gridY) == 255) { if (levelPlayer->getX() + PXO_MID > x + (width >> 1)) dx = -400 * F1; else dx = 400 * F1; dy = 200 * F1; } else { destroy(ticks); } } } } } return this; } /** * Draw standard event. * * @param ticks Time * @param change Time since last iteration */ void JJ1StandardEvent::draw (unsigned int ticks, int change) { Anim* miscAnim; if (next) next->draw(ticks, change); // Uncomment the following to see the raw location /*drawRect(FTOI(getDrawX(change)), FTOI(getDrawY(change) - height), FTOI(width), FTOI(height), 88);*/ // If the event has been removed from the grid, do not show it if (!set) return; // Check if the event has anything to draw if (animType == E_NOANIM) { drawnX = x; drawnY = y - F32; width = F32; height = F32; return; } if ((animType & ~1) == E_LFINISHANIM) { setAnimFrame((ticks - level->getEventTime(gridX, gridY)) / (set->animSpeed << 3), false); } else if ((animType & ~1) == E_LSHOOTANIM) { setAnimFrame((ticks + (anim->getLength() * set->animSpeed << 5) - level->getEventTime(gridX, gridY)) / (set->animSpeed << 5), false); } else { setAnimFrame((ticks / (set->animSpeed << 5)) + gridX + gridY, true); } // Calculate new positions fixed changeX = getDrawX(change); fixed changeY = getDrawY(change); // Draw the event // Check if an explosive effect should be drawn if (((animType & ~1) == E_LFINISHANIM) && (set->anims[animType] & 0x80)) { // In case of an explosion // Determine position in a half circle path fixed xOffset = fCos((ticks - level->getEventTime(gridX, gridY)) >> 1) * 48 - ITOF(16); fixed yOffset = fSin((ticks - level->getEventTime(gridX, gridY)) >> 1) * 48; int val = gridX + gridY; // Draw the animation in six different positions anim->draw(changeX - yOffset, changeY - xOffset); anim->draw(changeX + yOffset, changeY - xOffset); anim->draw(changeX + ITOF(val % 32) - yOffset, changeY - ITOF(val % 8) - xOffset); anim->draw(changeX - ITOF(val % 16) + yOffset, changeY - ITOF(val % 16) - xOffset); anim->draw(changeX + ITOF(val % 24) - yOffset, changeY + ITOF(val % 12) - xOffset); anim->draw(changeX - ITOF(val % 48) + yOffset, changeY + ITOF(val % 24) - xOffset); } else { // In case an event can be drawn normally fixed offset; if ((ticks < flashTime) && ((ticks >> 4) & 3)) anim->flashPalette(0); // Determine the corect vertical offset // Most animations need a default offset of 1 tile (32 pixels) if ((anim->getWidth() == 1) && (anim->getHeight() == 1)) { offset = -F32; } else if (noAnimOffset) { offset = 0; } else { if (onlyLAnimOffset && (animType == E_RIGHTANIM)) { offset = level->getAnim(set->anims[E_LEFTANIM] & 0x7F)->getOffset(); } else if (onlyRAnimOffset && (animType == E_LEFTANIM)) { offset = level->getAnim(set->anims[E_RIGHTANIM] & 0x7F)->getOffset(); } else { offset = anim->getOffset(); } if (offset == 0) offset = -ITOF(TTOI(1) - 1); } drawnX = x + anim->getXOffset() + F1; drawnY = y + anim->getYOffset() + offset + F1; // Uncomment the following line to see the draw area //drawRect(FTOI(changeX - x + drawnX), FTOI(changeY - y + drawnY), FTOI(width), FTOI(height), 88); anim->draw(changeX + F1, changeY + offset + F1 - anim->getOffset()); if ((ticks < flashTime) && ((ticks >> 4) & 3)) anim->restorePalette(); } // If the event has been destroyed, draw an explosion if (set->strength && ((animType & ~1) == E_LFINISHANIM)) { miscAnim = level->getMiscAnim(MA_EXPLOSION1); miscAnim->setFrame((ticks - level->getEventTime(gridX, gridY)) >> 3, false); miscAnim->draw(changeX, changeY); } return; } openjazz-20190106/src/jj1level/jj1level.cpp000066400000000000000000000422451341440264100203470ustar00rootroot00000000000000 /** * * @file jj1level.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 18th July 2009: Created demolevel.cpp from parts of level.cpp and * levelload.cpp * - 19th July 2009: Created levelframe.cpp from parts of level.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 30th March 2010: Created baselevel.cpp from parts of level.cpp and * levelframe.cpp * - 29th June 2010: Created jj2level.cpp from parts of level.cpp * - 1st August 2012: Renamed level.cpp to jj1level.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creating, playing and freeing of levels. * */ #include "jj1bullet.h" #include "jj1event/jj1event.h" #include "jj1level.h" #include "jj1levelplayer/jj1levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/paletteeffects.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" #include /** * Base constructor for JJ1DemoLevel sub-class. * * @param owner The current game */ JJ1Level::JJ1Level (Game* owner) : Level(owner) { // Do nothing return; } /** * Create a JJ1 level. * * @param owner The current game * @param fileName Name of the file containing the level data. * @param checkpoint Whether or not the player(s) will start at a checkpoint * @param multi Whether or not the level will be multi-player */ JJ1Level::JJ1Level (Game* owner, char* fileName, bool checkpoint, bool multi) : Level (owner) { int ret; // Load level data ret = load(fileName, checkpoint); if (ret < 0) throw ret; multiplayer = multi; return; } /** * Delete HUD graphical data. */ void JJ1Level::deletePanel () { SDL_FreeSurface(panel); SDL_FreeSurface(panelAmmo[0]); SDL_FreeSurface(panelAmmo[1]); SDL_FreeSurface(panelAmmo[2]); SDL_FreeSurface(panelAmmo[3]); SDL_FreeSurface(panelAmmo[4]); SDL_FreeSurface(panelAmmo[5]); return; } /** * Delete the JJ1 level. */ JJ1Level::~JJ1Level () { int count; // Free events if (events) delete events; // Free bullets if (bullets) delete bullets; for (count = 0; count < PATHS; count++) { delete[] path[count].x; delete[] path[count].y; } delete[] sceneFile; delete[] musicFile; delete[] spriteSet; SDL_FreeSurface(tileSet); deletePanel(); delete font; resampleSounds(); return; } /** * Determine whether or not the given point is solid when travelling upwards. * * @param x X-coordinate * @param y Y-coordinate * * @return Solidity */ bool JJ1Level::checkMaskUp (fixed x, fixed y) { GridElement *ge; // Anything off the edge of the map is solid if ((x < 0) || (y < 0) || (x > TTOF(LW)) || (y > TTOF(LH))) return true; ge = grid[FTOT(y)] + FTOT(x); // JJ1Event 122 is one-way if (ge->event == 122) return false; // Check the mask in the tile in question return mask[ge->tile][((y >> 9) & 56) + ((x >> 12) & 7)]; } /** * Determine whether or not the given point is solid when travelling downwards. * * @param x X-coordinate * @param y Y-coordinate * * @return Solidity */ bool JJ1Level::checkMaskDown (fixed x, fixed y) { // Anything off the edge of the map is solid if ((x < 0) || (y < 0) || (x > TTOF(LW)) || (y > TTOF(LH))) return true; // Check the mask in the tile in question return mask[grid[FTOT(y)][FTOT(x)].tile][((y >> 9) & 56) + ((x >> 12) & 7)]; } /** * Determine whether or not the given point should cause damage to the player. * * @param x X-coordinate * @param y Y-coordinate * * @return Painful solidity */ bool JJ1Level::checkSpikes (fixed x, fixed y) { GridElement *ge; // Anything off the edge of the map is not spikes // Ignore the bottom, as it is deadly anyway if ((x < 0) || (y < 0) || (x > TTOF(LW))) return false; ge = grid[FTOT(y)] + FTOT(x); // JJ1Event 126 is spikes if (ge->event != 126) return false; // Check the mask in the tile in question return mask[ge->tile][((y >> 9) & 56) + ((x >> 12) & 7)]; } /** * Determine the level's world number. * * @return World number */ int JJ1Level::getWorld() { return worldNum; } /** * Set which level will come next. * * @param nextLevel Next level's number * @param nextWorld Next level's world number */ void JJ1Level::setNext (int nextLevel, int nextWorld) { unsigned char buffer[MTL_L_PROP]; nextLevelNum = nextLevel; nextWorldNum = nextWorld; if (multiplayer) { buffer[0] = MTL_L_PROP; buffer[1] = MT_L_PROP; buffer[2] = 0; // set next level buffer[3] = nextLevel; buffer[4] = nextWorld; game->send(buffer); } return; } /** * Set the tile at the given location. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param tile The new tile */ void JJ1Level::setTile (unsigned char gridX, unsigned char gridY, unsigned char tile) { unsigned char buffer[MTL_L_GRID]; grid[gridY][gridX].tile = tile; if (multiplayer) { buffer[0] = MTL_L_GRID; buffer[1] = MT_L_GRID; buffer[2] = gridX; buffer[3] = gridY; buffer[4] = 0; // tile variable buffer[5] = tile; game->send(buffer); } return; } /** * Get the active events. * * @return The first active event */ JJ1Event* JJ1Level::getEvents () { return events; } /** * Get the event data for the event from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * * @return JJ1Event data */ JJ1EventType* JJ1Level::getEvent (unsigned char gridX, unsigned char gridY) { int event = grid[gridY][gridX].event; if (event) return eventSet + event; return NULL; } /** * Get the hits incurred by the event from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * * @return Number of hits */ unsigned char JJ1Level::getEventHits (unsigned char gridX, unsigned char gridY) { return grid[gridY][gridX].hits; } /** * Get the set time for the event from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * * @return Time */ unsigned int JJ1Level::getEventTime (unsigned char gridX, unsigned char gridY) { return grid[gridY][gridX].time; } /** * Remove the event from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile */ void JJ1Level::clearEvent (unsigned char gridX, unsigned char gridY) { unsigned char buffer[MTL_L_GRID]; // Ignore if the event has been un-destroyed if (!grid[gridY][gridX].hits && eventSet[grid[gridY][gridX].event].strength) return; grid[gridY][gridX].event = 0; if (multiplayer) { buffer[0] = MTL_L_GRID; buffer[1] = MT_L_GRID; buffer[2] = gridX; buffer[3] = gridY; buffer[4] = 2; // event variable buffer[5] = 0; game->send(buffer); } return; } /** * Register hit(s) on the event for the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param hits The number of hits to attempt to inflict on the event * @param source The player that inflicted the hit(s) * @param time Time * * @return The remaining number of hits until the event is destroyed */ int JJ1Level::hitEvent (unsigned char gridX, unsigned char gridY, int hits, JJ1LevelPlayer* source, unsigned int time) { GridElement* ge; unsigned char buffer[MTL_L_GRID]; int hitsToKill; ge = grid[gridY] + gridX; hitsToKill = eventSet[ge->event].strength; // If the event cannot be hit, return negative if (!hitsToKill || (ge->hits == 255)) return -1; // If the event has already been destroyed, do nothing if (ge->hits >= hitsToKill) return 0; // Check if the event has been killed if (ge->hits + hits >= hitsToKill) { // Notify the player that shot the bullet // If this returns false, ignore the hit if (!source->takeEvent(eventSet + ge->event, gridX, gridY, ticks)) { return hitsToKill - ge->hits; } ge->hits = (hits == 255)? 255: hitsToKill; ge->time = time; } else { ge->hits += hits; } if (multiplayer) { buffer[0] = MTL_L_GRID; buffer[1] = MT_L_GRID; buffer[2] = gridX; buffer[3] = gridY; buffer[4] = 3; // hits variable buffer[5] = ge->hits; game->send(buffer); } return hitsToKill - ge->hits; } /** * Set the time of the event from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param time Time */ void JJ1Level::setEventTime (unsigned char gridX, unsigned char gridY, unsigned int time) { grid[gridY][gridX].time = time; return; } /** * Get a sprite. * * @param sprite Sprite number * * @return Sprite */ Sprite* JJ1Level::getSprite (unsigned char sprite) { return spriteSet + sprite; } /** * Get an animation. * * @param anim Animation number * * @return Animation */ Anim* JJ1Level::getAnim (unsigned char anim) { return animSet + anim; } /** * Get a "miscellaneous" animation. * * @param anim Animation number * * @return Animation */ Anim* JJ1Level::getMiscAnim (unsigned char anim) { return animSet + miscAnims[anim]; } /** * Get a player animation. * * @param anim Animation number * * @return Animation */ Anim* JJ1Level::getPlayerAnim (unsigned char anim) { return animSet + playerAnims[anim]; } /** * Set the water level. * * @param gridY New water level y-coordinate */ void JJ1Level::setWaterLevel (unsigned char gridY) { unsigned char buffer[MTL_L_PROP]; waterLevelTarget = TTOF(gridY) + F2; if (multiplayer) { buffer[0] = MTL_L_PROP; buffer[1] = MT_L_PROP; buffer[2] = 1; // set water level buffer[3] = gridY; buffer[4] = 0; // Doesn't really matter game->send(buffer); } return; } /** * Determine the water level. * * @return The y-coordinate of the water level */ fixed JJ1Level::getWaterLevel () { return waterLevel; } /** * Create new bullet(s) (or event(s), if applicable) * * @param sourcePlayer The player that fired the bullet (if any) * @param gridX The grid X-coordinate of the origin of the event that fired the bullet (if any) * @param gridY The grid Y-coordinate of the origin of the event that fired the bullet (if any) * @param startX The initial X-coordinate of the bullet * @param startY The initial Y-coordinate of the bullet * @param bullet Type * @param facing The direction of the bullet * @param time Time */ void JJ1Level::createBullet (JJ1LevelPlayer* sourcePlayer, unsigned char gridX, unsigned char gridY, fixed startX, fixed startY, unsigned char bullet, bool facing, unsigned int time) { signed char* set; int direction; set = bulletSet[bullet]; direction = facing? 1: 0; if (set[B_GRAVITY | direction] == 4) { events = new JJ1StandardEvent(eventSet + set[B_SPRITE | direction], gridX, gridY, startX, startY + F32); } else if (set[B_SPRITE | direction] != 0) { // Create new bullet level->bullets = new JJ1Bullet(level->bullets, sourcePlayer, startX, startY, set, direction, time); if (set[B_XSPEED | direction | 2] != 0) { // Create the other bullet level->bullets = new JJ1Bullet(level->bullets, sourcePlayer, startX, startY, set, direction | 2, time); } playSound(set[B_STARTSOUND]); } return; } /** * Start a flash palette effect. * * @param red Red component of flash colour * @param green Green component of flash colour * @param blue Blue component of flash colour * @param duration Duration of the flash effect */ void JJ1Level::flash (unsigned char red, unsigned char green, unsigned char blue, int duration) { paletteEffects = new FlashPaletteEffect(red, green, blue, duration, paletteEffects); return; } /** * Play the bonus level. * * @return Error code */ int JJ1Level::playBonus () { char *bonusFile; int ret; if (!localPlayer->getJJ1LevelPlayer()->hasGem()) return E_NONE; delete paletteEffects; paletteEffects = NULL; bonusFile = createFileName("BONUSMAP", 0); // If the gem has been collected, play the bonus level ret = game->playLevel(bonusFile); delete[] bonusFile; return ret; } /** * Interpret data received from client/server * * @param buffer Received data */ void JJ1Level::receive (unsigned char* buffer) { switch (buffer[1]) { case MT_L_PROP: if (buffer[2] == 0) { nextLevelNum = buffer[3]; nextWorldNum = buffer[4]; } else if (buffer[2] == 1) { waterLevelTarget = TTOF(buffer[3]); } else if (buffer[2] == 2) { if (stage == LS_NORMAL) endTime += buffer[3] * 1000; } break; case MT_L_GRID: if (buffer[4] == 0) grid[buffer[3]][buffer[2]].tile = buffer[5]; else if (buffer[4] == 2) grid[buffer[3]][buffer[2]].event = buffer[5]; else if (buffer[4] == 3) grid[buffer[3]][buffer[2]].hits = buffer[5]; break; case MT_L_STAGE: stage = LevelStage(buffer[2]); break; } return; } /** * Play the level. * * @return Error code */ int JJ1Level::play () { JJ1LevelPlayer* levelPlayer; char *string; bool pmessage, pmenu; int option; unsigned int returnTime; int perfect; int timeBonus; int count, ret; levelPlayer = localPlayer->getJJ1LevelPlayer(); tickOffset = globalTicks; ticks = T_STEP; steps = 0; pmessage = pmenu = false; option = 0; returnTime = 0; timeBonus = -1; perfect = 0; video.setPalette(palette); playMusic(musicFile); while (true) { ret = loop(pmenu, option, pmessage); if (ret < 0) return ret; // Check if level has been won if (game && returnTime && (ticks > returnTime)) { if (!multiplayer) { // If the gem has been collected, play the bonus level ret = playBonus(); if (ret < 0) return ret; } if (nextLevelNum == 99) { if (playScene(sceneFile) == E_QUIT) return E_QUIT; ret = game->setLevel(NULL); } else { string = createFileName("LEVEL", nextLevelNum, nextWorldNum); ret = game->setLevel(string); delete[] string; } if (ret < 0) return ret; return WON; } // Process frame-by-frame activity while (getTimeChange() >= T_STEP) { bool playerWasAlive = (localPlayer->getJJ1LevelPlayer()->getEnergy() != 0); // Apply controls to local player for (count = 0; count < PCONTROLS; count++) localPlayer->setControl(count, controls.getState(count)); ret = step(); steps++; if (ret) return ret; if (!multiplayer && playerWasAlive && (localPlayer->getJJ1LevelPlayer()->getEnergy() == 0)) flash(0, 0, 0, T_END << 1); } // Draw the graphics draw(); // If paused, draw "PAUSE" if (pmessage && !pmenu) font->showString("pause", (canvasW >> 1) - 44, 32); // If paused, silence music pauseMusic(pmessage && !pmenu); if (stage == LS_END) { // The level is over, so draw play statistics & bonuses // Apply time bonus if (timeBonus) { count = (ticks - prevTicks) / 100; if (!count) count = 1; if (timeBonus == -1) { if (ticks < endTime) timeBonus = ((endTime - ticks) / 60000) * 100; else timeBonus = 0; if ((levelPlayer->getEnemies() == enemies) && (levelPlayer->getItems() == items)) perfect = 100; } else if (timeBonus - count >= 0) { localPlayer->addScore(count * 10); timeBonus -= count; } else { localPlayer->addScore(timeBonus * 10); timeBonus = 0; } if (timeBonus == 0) { returnTime = ticks + T_END; paletteEffects = new WhiteOutPaletteEffect(T_END, paletteEffects); playSound(11); } } // Display statistics & bonuses font->showString("time", (canvasW >> 1) - 152, (canvasH >> 1) - 60); font->showNumber(timeBonus, (canvasW >> 1) + 124, (canvasH >> 1) - 60); font->showString("enemies", (canvasW >> 1) - 152, (canvasH >> 1) - 40); if (enemies) font->showNumber((levelPlayer->getEnemies() * 100) / enemies, (canvasW >> 1) + 124, (canvasH >> 1) - 40); else font->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 40); font->showString("%", (canvasW >> 1) + 124, (canvasH >> 1) - 40); font->showString("items", (canvasW >> 1) - 152, (canvasH >> 1) - 20); if (items) font->showNumber((levelPlayer->getItems() * 100) / items, (canvasW >> 1) + 124, (canvasH >> 1) - 20); else font->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 20); font->showString("%", (canvasW >> 1) + 124, (canvasH >> 1) - 20); font->showString("perfect", (canvasW >> 1) - 152, canvasH >> 1); font->showNumber(perfect, (canvasW >> 1) + 124, canvasH >> 1); font->showString("score", (canvasW >> 1) - 152, (canvasH >> 1) + 40); font->showNumber(localPlayer->getScore(), (canvasW >> 1) + 124, (canvasH >> 1) + 40); } // Draw statistics, menu etc. drawOverlay(LEVEL_BLACK, pmenu, option, 15, 47, -16); } return E_NONE; } openjazz-20190106/src/jj1level/jj1level.h000066400000000000000000000216521341440264100200130ustar00rootroot00000000000000 /** * * @file jj1level.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 4th February 2009: Created events.h from parts of level.h * - 19th March 2009: Created sprite.h from parts of level.h * - 30th March 2010: Created baselevel.h from parts of level.h * - 29th June 2010: Created jj2level.h from parts of level.h * - 1st August 2012: Renamed level.h to jj1level.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ /* "Tile" is a flexible term. Here it is used to refer specifically to the individual elements of the tile set. "Tiles" in the context of level units are referred to as grid elements. */ #ifndef _LEVEL_H #define _LEVEL_H #include "level/level.h" #include "io/gfx/anim.h" #include "OpenJazz.h" // Constants // General #define LW 256 /* Level width */ #define LH 64 /* Level height */ #define EVENTS 127 #define ELENGTH 32 /* Length of events, in bytes */ #define BULLETS 32 #define BLENGTH 20 /* Length of bullets, in bytes */ #define ANIMS 128 #define PATHS 16 #define TKEY 127 /* Tileset colour key */ // Player animations #define PA_LWALK 0 #define PA_RWALK 1 #define PA_LJUMP 2 #define PA_RJUMP 3 #define PA_LSPIN 4 #define PA_RSPIN 5 #define PA_LSHOOT 6 #define PA_RSHOOT 7 #define PA_LCROUCH 8 #define PA_RCROUCH 9 #define PA_LFALL 10 #define PA_RFALL 11 #define PA_LHURT 12 #define PA_RHURT 13 #define PA_LLEAN 14 #define PA_RLEAN 15 #define PA_LBOARD 16 #define PA_RBOARD 17 #define PA_LSTAND 18 #define PA_RSTAND 19 #define PA_LBORED 20 #define PA_RBORED 21 #define PA_LEDGE 22 #define PA_REDGE 23 #define PA_LOOKUP 24 #define PA_LOOKDOWN 25 #define PA_LSWIM 26 #define PA_RSWIM 27 #define PA_LRUN 28 #define PA_RRUN 29 #define PA_LDIE 30 #define PA_RDIE 31 #define PA_LSUCK 32 #define PA_RSUCK 33 #define PA_LSTOP 34 /* SUCK and STOP refer almost always to the same animation */ #define PA_RSTOP 35 #define PA_RSPRING 36 #define PA_LSPRING 37 /* Surely these are the wrong way round? */ #define JJ1PANIMS 38 /* Number of player animations. May be higher. */ // Miscellaneous animations #define MA_SPARKLE 0 #define MA_DEVHEAD 1 #define MA_EXPLOSION1 2 #define MA_EXPLOSION2 3 #define MA_4SHIELD 4 #define MA_LBOARD 5 #define MA_RBOARD 6 #define MA_LBIRD 7 #define MA_RBIRD 8 #define MA_ICY 9 #define MA_1SHIELD 10 #define JJ1MANIMS 11 // Black palette index #define LEVEL_BLACK 31 // Fade delays #define T_START 500 #define T_END 1000 // Datatypes /// JJ1 level grid element typedef struct { unsigned char tile; ///< Indexes the tile set unsigned char bg; ///< 0 = Effect background, 1 = Black background unsigned char event; ///< Indexes the event set unsigned char hits; ///< Number of times the event has been shot int time; ///< Point at which the event will do something, e.g. terminate } GridElement; /// JJ1 level event type typedef struct { unsigned char anims[6]; ///< Indices of animations signed char difficulty; ///< The minimum difficulty level at which the event is used signed char reflection; ///< Whether or not to show a reflection signed char movement; ///< Movement type signed char magnitude; ///< Usage depends on event type signed char strength; ///< Number of hits required to destroy the event signed char modifier; ///< Modifier unsigned char points; ///< Points obtained by getting/destroying the event unsigned char bullet; ///< Type of bullet the event fires unsigned char bulletPeriod; ///< The time between successive bullet shots unsigned char speed; ///< The speed at which the event moves unsigned char animSpeed; ///< The speed of the event's animation unsigned char sound; ///< The sound played on the appropriate trigger signed char multiA; ///< Usage depends on event type signed char multiB; ///< Usage depends on event type signed char pieceSize; ///< Size of pieces in bridges, swinging balls chains, etc. signed char pieces; ///< Number of pieces in bridges, swinging ball chains, etc. signed char angle; ///< Initial angle of swinging balls, etc. } JJ1EventType; /// Pre-defined JJ1 event movement path typedef struct { short int* x; ///< X-coordinates for each node short int* y; ///< Y-coordinates for each node unsigned char length; ///< Number of nodes } JJ1EventPath; // Classes class Font; class JJ1Bullet; class JJ1Event; class JJ1LevelPlayer; /// JJ1 level class JJ1Level : public Level { private: SDL_Surface* tileSet; ///< Tile images SDL_Surface* panel; ///< HUD background image SDL_Surface* panelAmmo[6]; ///< HUD ammo type images JJ1Event* events; ///< Active events JJ1Bullet* bullets; ///< Active bullets char* musicFile; ///< Music file name char* sceneFile; ///< File name of cutscene to play when level has been completed Sprite* spriteSet; ///< Sprites Anim animSet[ANIMS]; ///< Animations char miscAnims[JJ1MANIMS]; ///< Further animations char playerAnims[JJ1PANIMS]; ///< Default player animations signed char bulletSet[BULLETS][BLENGTH]; ///< Bullet types JJ1EventType eventSet[EVENTS]; ///< Event types char mask[240][64]; ///< Tile masks. At most 240 tiles, all with 8 * 8 masks GridElement grid[LH][LW]; ///< Level grid. All levels are the same size SDL_Color skyPalette[256]; ///< Full palette for sky background bool sky; ///< Whether or not to use sky background unsigned char skyOrb; ///< The tile to use as the background sun/moon/etc. int levelNum; ///< Number of current level int worldNum; ///< Number of current world int nextLevelNum; ///< Number of next level int nextWorldNum; ///< Number of next world int enemies; ///< Number of enemies to kill fixed waterLevel; ///< Height of water fixed waterLevelTarget; ///< Future height of water fixed waterLevelSpeed; ///< Rate of water level change fixed energyBar; ///< HUD energy bar fullness int ammoType; ///< HUD ammo type fixed ammoOffset; ///< HUD ammo offset void deletePanel (); int loadPanel (); void loadSprite (File* file, Sprite* sprite); int loadSprites (char* fileName); int loadTiles (char* fileName); int playBonus (); protected: Font* font; ///< On-screen message font JJ1Level (Game* owner); int load (char* fileName, bool checkpoint); int step (); void draw (); public: JJ1EventPath path[PATHS]; ///< Pre-defined event movement paths JJ1Level (Game* owner, char* fileName, bool checkpoint, bool multi); virtual ~JJ1Level (); bool checkMaskUp (fixed x, fixed y); bool checkMaskDown (fixed x, fixed y); bool checkSpikes (fixed x, fixed y); int getWorld (); void setNext (int nextLevel, int nextWorld); void setTile (unsigned char gridX, unsigned char gridY, unsigned char tile); JJ1Event* getEvents (); JJ1EventType* getEvent (unsigned char gridX, unsigned char gridY); unsigned char getEventHits (unsigned char gridX, unsigned char gridY); unsigned int getEventTime (unsigned char gridX, unsigned char gridY); void clearEvent (unsigned char gridX, unsigned char gridY); int hitEvent (unsigned char gridX, unsigned char gridY, int hits, JJ1LevelPlayer* source, unsigned int time); void setEventTime (unsigned char gridX, unsigned char gridY, unsigned int time); Sprite* getSprite (unsigned char sprite); Anim* getAnim (unsigned char anim); Anim* getMiscAnim (unsigned char anim); Anim* getPlayerAnim (unsigned char anim); void createBullet (JJ1LevelPlayer* sourcePlayer, unsigned char gridX, unsigned char gridY, fixed startX, fixed startY, unsigned char bullet, bool facing, unsigned int time); void setWaterLevel (unsigned char gridY); fixed getWaterLevel (); void flash (unsigned char red, unsigned char green, unsigned char blue, int duration); void receive (unsigned char* buffer); virtual int play (); }; /// JJ1 level played as a demo class JJ1DemoLevel : public JJ1Level { private: unsigned char* macro; ///< Sequence of player control codes public: JJ1DemoLevel (Game* owner, const char* fileName); ~JJ1DemoLevel (); int play (); }; // Variables EXTERN JJ1Level* level; ///< JJ1 level #endif openjazz-20190106/src/jj1level/jj1levelframe.cpp000066400000000000000000000251611341440264100213600ustar00rootroot00000000000000 /** * * @file jj1levelframe.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Created levelframe.cpp from parts of level.cpp * - 30th March 2010: Created baselevel.cpp from parts of level.cpp and * levelframe.cpp * - 29th June 2010: Created jj2levelframe.cpp from parts of levelframe.cpp * - 1st August 2012: Renamed levelframe.cpp to jj1levelframe.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the once-per-frame functions for levels. * */ #include "jj1bullet.h" #include "jj1event/jj1event.h" #include "jj1event/jj1guardians.h" #include "jj1level.h" #include "jj1levelplayer/jj1levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "util.h" /** * Level iteration. * * @return Error code */ int JJ1Level::step () { JJ1Event *event; int viewH; int x, y; // Can we see below the panel? if (canvasW > SW) viewH = canvasH; else viewH = canvasH - 33; // Search for active events for (y = FTOT(viewY) - 5; y < ITOT(FTOI(viewY) + viewH) + 5; y++) { for (x = FTOT(viewX) - 5; x < ITOT(FTOI(viewX) + canvasW) + 5; x++) { if ((x >= 0) && (y >= 0) && (x < LW) && (y < LH) && grid[y][x].event && (grid[y][x].event < 121) && (eventSet[grid[y][x].event].difficulty <= game->getDifficulty())) { event = events; while (event) { // If the event has been found, stop searching if (event->isFrom(x, y)) break; event = event->getNext(); } // If the event wasn't found, create it if (!event) { switch (getEvent(x, y)->movement) { case 28: events = new JJ1Bridge(x, y); break; case 41: events = new MedGuardian(x, y); break; case 60: events = new DeckGuardian(x, y); break; default: events = new JJ1StandardEvent(eventSet + grid[y][x].event, x, y, TTOF(x), TTOF(y + 1)); break; } } } } } // Process bullets if (bullets) bullets = bullets->step(ticks); // Determine the players' trajectories for (x = 0; x < nPlayers; x++) players[x].getJJ1LevelPlayer()->control(ticks); // Process active events if (events) events = events->step(ticks); // Apply as much of those trajectories as possible, without going into the // scenery for (x = 0; x < nPlayers; x++) players[x].getJJ1LevelPlayer()->move(ticks); // Check if time has run out if (ticks > endTime) { if (multiplayer) { game->getMode()->outOfTime(); } else { if ((game->getDifficulty() >= 2) && (stage == LS_NORMAL)) localPlayer->getJJ1LevelPlayer()->kill(NULL, endTime); } } // Handle change in ammo selection x = localPlayer->getAmmoType() + 1; if (x != ammoType) { // Change the ammo type display on the panel ammoType = x; ammoOffset = ITOF(26); } if (ammoOffset > 0) { // Descending ammoOffset -= F1; // Avoid an offset of 0, which prevents changes if (ammoOffset == 0) ammoOffset = -1; } // Handle change in water level if (waterLevel < waterLevelTarget) waterLevelSpeed += 3200; else waterLevelSpeed -= 3200; if (waterLevelSpeed > 80000) waterLevelSpeed = 80000; if (waterLevelSpeed < -80000) waterLevelSpeed = -80000; waterLevel += waterLevelSpeed >> 6; // Handle player reactions for (x = 0; x < nPlayers; x++) { if (players[x].getJJ1LevelPlayer()->reacted(ticks) == PR_KILLED) { players[x].clearAmmo(); if (!multiplayer) return LOST; game->resetPlayer(players + x); } } return E_NONE; } /** * Draw the level. */ void JJ1Level::draw () { GridElement *ge; SDL_Rect src, dst; int viewH; int vX, vY; int x, y, bgScale; unsigned int change; // Calculate change since last step change = getTimeChange(); // Calculate viewport if (game && (stage == LS_END)) game->view(paused? 0: ((ticks - prevTicks) * 160)); else localPlayer->getJJ1LevelPlayer()->view(ticks, paused? 0: (ticks - prevTicks), change); // Can we see below the panel? if (canvasW > SW) viewH = canvasH; else viewH = canvasH - 33; // Ensure the new viewport is within the level if (FTOI(viewX) + canvasW >= TTOI(LW)) viewX = ITOF(TTOI(LW) - canvasW); if (viewX < 0) viewX = 0; if (FTOI(viewY) + viewH >= TTOI(LH)) viewY = ITOF(TTOI(LH) - viewH); if (viewY < 0) viewY = 0; // Use the viewport dst.x = 0; dst.y = 0; vX = FTOI(viewX); vY = FTOI(viewY); dst.w = canvasW; dst.h = viewH; SDL_SetClipRect(canvas, &dst); // Set tile drawing dimensions src.w = TTOI(1); src.h = TTOI(1); src.x = 0; // If there is a sky, draw it if (sky) { // Background scale if (canvasW > 320) bgScale = ((canvasH - 1) / 100) + 1; else bgScale = ((canvasH - 34) / 100) + 1; for (y = 0; y < viewH; y += bgScale) drawRect(0, y, canvasW, bgScale, 156 + (y / bgScale)); // Show sun / moon / etc. if (skyOrb) { dst.x = ((canvasW * 4) / 5) - (vX & 3); dst.y = ((canvasH - 33) * 3) / 25; src.y = TTOI(skyOrb + (vX & 3)); SDL_BlitSurface(tileSet, &src, canvas, &dst); } } else { // If there is no sky, draw a blank background // This is only very occasionally actually visible video.clearScreen(127); } // Show background tiles for (y = 0; y <= ITOT(viewH - 1) + 1; y++) { for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) { if ((x + ITOT(vX) >= 256) || (y + ITOT(vY) >= 64)) { drawRect(TTOI(x) - (vX & 31), TTOI(y) - (vY & 31), 32, 32, LEVEL_BLACK); continue; } // Get the grid element from the given coordinates ge = grid[y + ITOT(vY)] + x + ITOT(vX); // If this tile uses a black background, draw it if (ge->bg) drawRect(TTOI(x) - (vX & 31), TTOI(y) - (vY & 31), 32, 32, LEVEL_BLACK); // If this is not a foreground tile, draw it if ((ge->event != 124) && (ge->event != 125) && (eventSet[ge->event].movement != 37) && (eventSet[ge->event].movement != 38)) { dst.x = TTOI(x) - (vX & 31); dst.y = TTOI(y) - (vY & 31); src.y = TTOI(ge->tile); SDL_BlitSurface(tileSet, &src, canvas, &dst); } } } // Show active events if (events) events->draw(ticks, change); // Show the players for (x = 0; x < nPlayers; x++) players[x].getJJ1LevelPlayer()->draw(ticks, change); // Show bullets if (bullets) bullets->draw(change); // Show foreground tiles for (y = 0; y <= ITOT(viewH - 1) + 1; y++) { for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) { if ((x + ITOT(vX) >= 256) || (y + ITOT(vY) >= 64)) continue; // Get the grid element from the given coordinates ge = grid[y + ITOT(vY)] + x + ITOT(vX); // If this is an "animated" foreground tile, draw it if (ge->event == 123) { dst.x = TTOI(x) - (vX & 31); dst.y = TTOI(y) - (vY & 31); if (ticks & 64) src.y = TTOI(eventSet[ge->event].multiB); else src.y = TTOI(eventSet[ge->event].multiA); SDL_BlitSurface(tileSet, &src, canvas, &dst); } // If this is a foreground tile, draw it if ((ge->event == 124) || (ge->event == 125) || (eventSet[ge->event].movement == 37) || (eventSet[ge->event].movement == 38)) { dst.x = TTOI(x) - (vX & 31); dst.y = TTOI(y) - (vY & 31); src.y = TTOI(ge->tile); SDL_BlitSurface(tileSet, &src, canvas, &dst); } } } // Temporary lines showing the water level drawRect(0, FTOI(waterLevel - viewY), canvasW, 2, 24); drawRect(0, FTOI(waterLevel - viewY) + 3, canvasW, 1, 24); drawRect(0, FTOI(waterLevel - viewY) + 6, canvasW, 1, 24); drawRect(0, FTOI(waterLevel - viewY) + 10, canvasW, 1, 24); // Show active guardian's energy bar if (events) events->drawEnergy(ticks); // If this is a competitive game, draw the score if (multiplayer) game->getMode()->drawScore(font); // Show panel SDL_SetClipRect(canvas, NULL); if (ammoOffset != 0) { if (ammoOffset < 0) { // Finished descending ammoOffset = 0; } src.x = 0; src.y = FTOI(ammoOffset); src.w = 64; src.h = 26 - src.y; dst.x = 248; dst.y = 3; SDL_BlitSurface(panelAmmo[ammoType], &src, panel, &dst); } dst.x = 0; dst.y = canvasH - 33; SDL_BlitSurface(panel, NULL, canvas, &dst); drawRect(0, canvasH - 1, SW, 1, LEVEL_BLACK); // Show panel data // Show score panelSmallFont->showNumber(localPlayer->getScore(), 84, canvasH - 27); // Show time remaining if (endTime > ticks) x = endTime - ticks; else x = 0; y = x / (60 * 1000); panelSmallFont->showNumber(y, 116, canvasH - 27); x -= (y * 60 * 1000); y = x / 1000; panelSmallFont->showNumber(y, 136, canvasH - 27); x -= (y * 1000); y = x / 100; panelSmallFont->showNumber(y, 148, canvasH - 27); // Show lives panelSmallFont->showNumber(localPlayer->getLives(), 124, canvasH - 13); // Show planet number if (worldNum <= 41) // Main game levels panelSmallFont->showNumber((worldNum % 3) + 1, 184, canvasH - 13); else if ((worldNum >= 50) && (worldNum <= 52)) // Christmas levels panelSmallFont->showNumber(worldNum - 49, 184, canvasH - 13); else panelSmallFont->showNumber(worldNum, 184, canvasH - 13); // Show level number panelSmallFont->showNumber(levelNum + 1, 196, canvasH - 13); // Show ammo if (localPlayer->getAmmoType() == -1) { panelSmallFont->showString(":", 225, canvasH - 13); panelSmallFont->showString(";", 233, canvasH - 13); } else { x = localPlayer->getAmmo(); // Trailing 0s if (x < 100) { panelSmallFont->showNumber(0, 229, canvasH - 13); if (x < 10) panelSmallFont->showNumber(0, 237, canvasH - 13); } panelSmallFont->showNumber(x > 999? 999: x, 245, canvasH - 13); } // Draw the health bar dst.x = 20; x = localPlayer->getJJ1LevelPlayer()->getEnergy(); y = (ticks - prevTicks) * 40; if (FTOI(energyBar) < (x << 4)) { if ((x << 14) - energyBar < y) energyBar = x << 14; else energyBar += y; } else if (FTOI(energyBar) > (x << 4)) { if (energyBar - (x << 14) < y) energyBar = x << 14; else energyBar -= y; } if (energyBar > F1) { dst.w = FTOI(energyBar) - 1; // Choose energy bar colour if (x == 4) x = 24; else if (x == 3) x = 17; else if (x == 2) x = 80; else if (x <= 1) x = 32 + (((ticks / 75) * 4) & 15); // Draw energy bar drawRect(dst.x, canvasH - 13, dst.w, 7, x); dst.x += dst.w; dst.w = 64 - dst.w; } else dst.w = 64; // Fill in remaining energy bar space with black drawRect(dst.x, canvasH - 13, dst.w, 7, LEVEL_BLACK); return; } openjazz-20190106/src/jj1level/jj1levelload.cpp000066400000000000000000000477451341440264100212210ustar00rootroot00000000000000 /** * * @file jj1levelload.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed levelload.c to levelload.cpp * - 18th July 2009: Created demolevel.cpp from parts of level.cpp and * levelload.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 28th June 2010: Created levelloadjj2.cpp from parts of levelload.cpp * - 1st August 2012: Renamed levelload.cpp to jj1levelload.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading of level data. * */ #include "jj1bullet.h" #include "jj1event/jj1event.h" #include "jj1level.h" #include "jj1levelplayer/jj1levelplayer.h" #include "game/game.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" #include #define SKEY 254 /* Sprite colour key */ /** * Load the HUD graphical data. * * @return Error code */ int JJ1Level::loadPanel () { File* file; unsigned char* pixels; unsigned char* sorted; int type, x, y; try { file = new File("PANEL.000", false); } catch (int e) { return e; } pixels = file->loadRLE(46272); delete file; // Create the panel background panel = createSurface(pixels, SW, 32); // De-scramble the panel's ammo graphics sorted = new unsigned char[64 * 26]; for (type = 0; type < 6; type++) { for (y = 0; y < 26; y++) { for (x = 0; x < 64; x++) sorted[(y * 64) + x] = pixels[(type * 64 * 32) + (y * 64) + (x >> 2) + ((x & 3) << 4) + (55 * 320)]; } panelAmmo[type] = createSurface(sorted, 64, 26); } delete[] sorted; delete[] pixels; return E_NONE; } /** * Load a sprite. * * @param file File from which to load the sprite data * @param sprite Sprite that will receive the loaded data */ void JJ1Level::loadSprite (File* file, Sprite* sprite) { unsigned char* pixels; int pos, maskOffset; int width, height; // Load dimensions width = file->loadShort() << 2; height = file->loadShort(); file->seek(2, false); maskOffset = file->loadShort(); pos = file->loadShort() << 2; // Sprites can be either masked or not masked. if (maskOffset) { // Masked height++; // Skip to mask file->seek(maskOffset, false); // Find the end of the data pos += file->tell() + ((width >> 2) * height); // Read scrambled, masked pixel data pixels = file->loadPixels(width * height, SKEY); sprite->setPixels(pixels, width, height, SKEY); delete[] pixels; file->seek(pos, true); } else if (width) { // Not masked // Read scrambled pixel data pixels = file->loadPixels(width * height); sprite->setPixels(pixels, width, height, SKEY); delete[] pixels; } return; } /** * Load sprites. * * @param fileName Name of the file containing the level-specific sprites * * @return Error code */ int JJ1Level::loadSprites (char * fileName) { File* mainFile = NULL; File* specFile = NULL; unsigned char* buffer; int count; bool loaded; // Open fileName try { specFile = new File(fileName, false); } catch (int e) { return e; } // This function loads all the sprites, not just those in fileName try { mainFile = new File("MAINCHAR.000", false); } catch (int e) { delete specFile; return e; } sprites = specFile->loadShort(256); // Include space in the sprite set for the blank sprite at the end spriteSet = new Sprite[sprites + 1]; // Read offsets buffer = specFile->loadBlock(sprites * 2); for (count = 0; count < sprites; count++) spriteSet[count].setOffset(buffer[count] << 2, buffer[sprites + count]); delete[] buffer; // Skip to where the sprites start in mainchar.000 mainFile->seek(2, true); // Loop through all the sprites to be loaded for (count = 0; count < sprites; count++) { loaded = false; if (mainFile->loadChar() == 0xFF) { // Go to the next sprite/file indicator mainFile->seek(1, false); } else { // Return to the start of the sprite mainFile->seek(-1, false); // Load the individual sprite data loadSprite(mainFile, spriteSet + count); loaded = true; } if (specFile->loadChar() == 0xFF) { // Go to the next sprite/file indicator specFile->seek(1, false); } else { // Return to the start of the sprite specFile->seek(-1, false); // Load the individual sprite data loadSprite(specFile, spriteSet + count); loaded = true; } /* If both fileName and mainchar.000 have file indicators, create a blank sprite */ if (!loaded) spriteSet[count].clearPixels(); // Check if the next sprite exists // If not, create blank sprites for the remainder if (specFile->tell() >= specFile->getSize()) { for (count++; count < sprites; count++) { spriteSet[count].clearPixels(); } } } delete mainFile; delete specFile; // Include a blank sprite at the end spriteSet[sprites].clearPixels(); return E_NONE; } /** * Load the tileset. * * @param fileName Name of the file containing the tileset * * @return The number of tiles loaded */ int JJ1Level::loadTiles (char* fileName) { File* file; unsigned char* buffer; int rle, pos, index, count, fileSize; int tiles; try { file = new File(fileName, false); } catch (int e) { return e; } // Load the palette file->loadPalette(palette); // Load the background palette file->loadPalette(skyPalette); // Skip the second, identical, background palette file->skipRLE(); // Load the tile pixel indices tiles = 240; // Never more than 240 tiles buffer = new unsigned char[tiles << 10]; file->seek(4, false); pos = 0; fileSize = file->getSize(); // Read the RLE pixels // file::loadRLE() cannot be used, for reasons that will become clear while ((pos < (tiles << 10)) && (file->tell() < fileSize)) { rle = file->loadChar(); if (rle & 128) { index = file->loadChar(); for (count = 0; count < (rle & 127); count++) buffer[pos++] = index; } else if (rle) { for (count = 0; count < rle; count++) buffer[pos++] = file->loadChar(); } else { // This happens at the end of each tile // 0 pixels means 1 pixel, apparently buffer[pos++] = file->loadChar(); file->seek(2, false); /* I assume this is the length of the next tile block */ if (pos == (60 << 10)) file->seek(2, false); if (pos == (120 << 10)) file->seek(2, false); if (pos == (180 << 10)) file->seek(2, false); } } delete file; // Work out how many tiles were actually loaded // Should be a multiple of 60 tiles = pos >> 10; tileSet = createSurface(buffer, TTOI(1), TTOI(tiles)); SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, TKEY); delete[] buffer; return tiles; } /** * Load the level. * * @param fileName Name of the file containing the level data * @param checkpoint Whether or not the player(s) will start at a checkpoint * * @return Error code */ int JJ1Level::load (char* fileName, bool checkpoint) { Anim* pAnims[JJ1PANIMS]; unsigned short int soundRates[32]; File* file; unsigned char* buffer; const char* ext; char* string = NULL; int tiles; int count, x, y, type; unsigned char startX, startY; // Load font try { font = new Font(false); } catch (int e) { return e; } // Load panel count = loadPanel(); if (count < 0) { delete font; return count; } // Show loading screen // Open planet.### file if (!strcmp(fileName, LEVEL_FILE)) { // Using the downloaded level file string = createString("DOWNLOADED"); } else { // Load the planet's name from the planet.### file string = createFileName("PLANET", fileName + strlen(fileName) - 3); try { file = new File(string, false); } catch (int e) { file = NULL; } delete[] string; if (file) { file->seek(2, true); string = file->loadString(); delete file; } else { string = createString("CUSTOM"); } } switch (fileName[5]) { case '0': ext = " LEVEL ONE"; break; case '1': ext = " LEVEL TWO"; break; case '2': string[0] = 0; ext = "SECRET LEVEL"; break; default: ext = " LEVEL"; break; } video.setPalette(menuPalette); video.clearScreen(0); x = (canvasW >> 1) - ((strlen(string) + strlen(ext)) << 2); x = fontmn2->showString("LOADING ", x - 60, (canvasH >> 1) - 16); x = fontmn2->showString(string, x, (canvasH >> 1) - 16); fontmn2->showString(ext, x, (canvasH >> 1) - 16); delete[] string; if (::loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; // Open level file try { file = new File(fileName, false); } catch (int e) { deletePanel(); delete font; return e; } // Load the blocks.### extension // Skip past all level data file->seek(39, true); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->skipRLE(); file->seek(598, false); file->skipRLE(); file->seek(4, false); file->skipRLE(); file->skipRLE(); file->seek(25, false); file->skipRLE(); file->seek(3, false); // Load the level number levelNum = file->loadChar() ^ 210; // Load the world number worldNum = file->loadChar() ^ 4; // Load tile set from appropriate blocks.### // Load tile set extension file->seek(8, false); ext = file->loadString(); // Create tile set file name if (!strcmp(ext, "999")) string = createFileName("BLOCKS", worldNum); else string = createFileName("BLOCKS", ext); delete[] ext; tiles = loadTiles(string); delete[] string; if (tiles < 0) { delete file; deletePanel(); delete font; return tiles; } // Load sprite set from corresponding Sprites.### string = createFileName("SPRITES", worldNum); count = loadSprites(string); delete[] string; if (count < 0) { SDL_FreeSurface(tileSet); delete file; deletePanel(); delete font; return count; } // Skip to tile and event reference data file->seek(39, true); // Load tile and event references buffer = file->loadRLE(LW * LH * 2); // Create grid from data for (x = 0; x < LW; x++) { for (y = 0; y < LH; y++) { grid[y][x].tile = buffer[(y + (x * LH)) << 1]; grid[y][x].bg = buffer[((y + (x * LH)) << 1) + 1] >> 7; grid[y][x].event = buffer[((y + (x * LH)) << 1) + 1] & 127; grid[y][x].hits = 0; grid[y][x].time = 0; } } delete[] buffer; // Ignore tile transparency settings (FIXME: needed for sun tiles at least) file->skipRLE(); // Load mask data buffer = file->loadRLE(tiles * 8); // Unpack bits for (count = 0; count < tiles; count++) { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) mask[count][(y << 3) + x] = (buffer[(count << 3) + y] >> x) & 1; } } delete[] buffer; /* Uncomment the code below if you want to see the mask instead of the tile graphics during gameplay */ /*if (SDL_MUSTLOCK(tileSet)) SDL_LockSurface(tileSet); for (count = 0; count < tiles; count++) { for (y = 0; y < 32; y++) { for (x = 0; x < 32; x++) { if (mask[count][((y >> 2) << 3) + (x >> 2)] == 1) ((char *)(tileSet->pixels)) [(count * 1024) + (y * 32) + x] = 88; } } } if (SDL_MUSTLOCK(tileSet)) SDL_UnlockSurface(tileSet);*/ // Load special event path buffer = file->loadRLE(PATHS << 9); for (type = 0; type < PATHS; type++) { path[type].length = buffer[type << 9] + (buffer[(type << 9) + 1] << 8); if (path[type].length < 1) path[type].length = 1; path[type].x = new short int[path[type].length]; path[type].y = new short int[path[type].length]; for (count = 0; count < path[type].length; count++) { path[type].x[count] = ((signed char *)buffer)[(type << 9) + (count << 1) + 3] << 2; path[type].y[count] = ((signed char *)buffer)[(type << 9) + (count << 1) + 2]; } } delete[] buffer; // Load event set buffer = file->loadRLE(EVENTS * ELENGTH); // Fill event set with data for (count = 0; count < EVENTS; count++) { eventSet[count].difficulty = buffer[count * ELENGTH]; eventSet[count].reflection = buffer[(count * ELENGTH) + 2]; eventSet[count].movement = buffer[(count * ELENGTH) + 4]; eventSet[count].anims[E_LEFTANIM] = buffer[(count * ELENGTH) + 5]; eventSet[count].anims[E_RIGHTANIM] = buffer[(count * ELENGTH) + 6]; eventSet[count].magnitude = buffer[(count * ELENGTH) + 8]; eventSet[count].strength = buffer[(count * ELENGTH) + 9]; eventSet[count].modifier = buffer[(count * ELENGTH) + 10]; eventSet[count].points = buffer[(count * ELENGTH) + 11]; eventSet[count].bullet = buffer[(count * ELENGTH) + 12]; eventSet[count].bulletPeriod = buffer[(count * ELENGTH) + 13]; eventSet[count].speed = buffer[(count * ELENGTH) + 15] + 1; eventSet[count].animSpeed = buffer[(count * ELENGTH) + 17] + 1; eventSet[count].sound = buffer[(count * ELENGTH) + 21]; eventSet[count].multiA = buffer[(count * ELENGTH) + 22]; eventSet[count].multiB = buffer[(count * ELENGTH) + 23]; eventSet[count].pieceSize = buffer[(count * ELENGTH) + 24]; eventSet[count].pieces = buffer[(count * ELENGTH) + 25]; eventSet[count].angle = buffer[(count * ELENGTH) + 26]; eventSet[count].anims[E_LFINISHANIM] = buffer[(count * ELENGTH) + 28]; eventSet[count].anims[E_RFINISHANIM] = buffer[(count * ELENGTH) + 29]; eventSet[count].anims[E_LSHOOTANIM] = buffer[(count * ELENGTH) + 30]; eventSet[count].anims[E_RSHOOTANIM] = buffer[(count * ELENGTH) + 31]; } // Process grid enemies = items = 0; for (x = 0; x < LW; x++) { for (y = 0; y < LH; y++) { type = grid[y][x].event; if (type) { // If the event hurts and can be killed, it is an enemy // Anything else that scores is an item if ((eventSet[type].modifier == 0) && eventSet[type].strength) enemies++; else if (eventSet[type].points) items++; } } } delete[] buffer; // Skip (usually empty) event names file->skipRLE(); // Load animation set buffer = file->loadRLE(ANIMS << 6); // Create animation set based on that data for (count = 0; count < ANIMS; count++) { animSet[count].setData(buffer[(count << 6) + 6], buffer[count << 6], buffer[(count << 6) + 1], buffer[(count << 6) + 3], buffer[(count << 6) + 4], buffer[(count << 6) + 2], buffer[(count << 6) + 5]); for (y = 0; y < buffer[(count << 6) + 6]; y++) { // Get frame x = buffer[(count << 6) + 7 + y]; if (x > sprites) x = sprites; // Assign sprite and vertical offset animSet[count].setFrame(y, true); animSet[count].setFrameData(spriteSet + x, buffer[(count << 6) + 26 + y], buffer[(count << 6) + 45 + y]); } } delete[] buffer; // Skip (usually empty) animation names file->skipRLE(); // Skip level block names file->seek(153, false); // Load sound map for (count = 0; count < 32; count++) soundRates[count] = file->loadShort(); x = file->tell(); for (count = 0; count < 32; count++) { file->seek(x + (count * 9), true); string = file->loadString(); resampleSound(count, string, soundRates[count]); delete[] string; } file->seek(x + 288, true); // Music file musicFile = file->loadString(); // Skip (usually empty) level start cutscene file->seek(x + 314, true); // End of episode cutscene sceneFile = file->loadString(); // Skip blank bytes file->seek(x + 366, true); // The players' initial coordinates startX = file->loadShort(LW); startY = file->loadShort(LH) + 1; // Next level x = file->loadChar(); y = file->loadChar(); setNext(x, y); // Skip jump height (FIXME) and some unknown level file->seek(4, false); // Thanks to Doubble Dutch for the water level bytes waterLevelTarget = ITOF(file->loadShort() + 17); waterLevel = waterLevelTarget - F8; waterLevelSpeed = -80000; // Skip Jazz animation speed(FIXME) and an unknown value (end marker?) file->seek(3, false); // Thanks to Feline and the JCS94 team for the next bits: // Load player's animation set references (always left + right) buffer = file->loadRLE(JJ1PANIMS * 2); string = new char[MTL_P_ANIMS + JJ1PANIMS]; for (x = 0; x < JJ1PANIMS; x++) { playerAnims[x] = buffer[x << 1]; pAnims[x] = animSet + playerAnims[x]; string[MTL_P_ANIMS + x] = playerAnims[x]; } delete[] buffer; if (multiplayer) { string[0] = MTL_P_ANIMS + JJ1PANIMS; string[1] = MT_P_ANIMS; string[2] = 0; game->send((unsigned char *)string); } delete[] string; createLevelPlayers(LT_JJ1, pAnims, NULL, checkpoint, startX, startY); // Load miscellaneous animations miscAnims[MA_SPARKLE] = file->loadChar(); miscAnims[MA_DEVHEAD] = file->loadChar(); miscAnims[MA_EXPLOSION1] = file->loadChar(); miscAnims[MA_EXPLOSION2] = file->loadChar(); // Load bullet set buffer = file->loadRLE(BULLETS * BLENGTH); for (count = 0; count < BULLETS; count++) { memcpy(bulletSet[count], buffer + (count * BLENGTH), BLENGTH); } delete[] buffer; // Skip (usually empty) attack names file->skipRLE(); // Load level properties (magic) // First byte is the background palette effect type type = file->loadChar(); sky = false; switch (type) { case 2: sky = true; // Sky background effect paletteEffects = new SkyPaletteEffect(156, 100, FH, skyPalette, NULL); break; case 8: // Parallaxing background effect paletteEffects = new P2DPaletteEffect(128, 64, FE, NULL); break; case 9: // Diagonal stripes "parallaxing" background effect paletteEffects = new P1DPaletteEffect(128, 32, FH, NULL); break; case 11: // The deeper below water, the darker it gets paletteEffects = new WaterPaletteEffect(TTOF(32), NULL); break; default: // No effect paletteEffects = NULL; break; } // Palette animations // These are applied to every level without a conflicting background effect // As a result, there are a few levels with things animated that shouldn't // be // In Diamondus: The red/yellow palette animation paletteEffects = new RotatePaletteEffect(112, 4, F32, paletteEffects); // In Diamondus: The waterfall palette animation paletteEffects = new RotatePaletteEffect(116, 8, F16, paletteEffects); // The following were discoverd by Unknown/Violet paletteEffects = new RotatePaletteEffect(124, 3, F16, paletteEffects); if ((type != PE_1D) && (type != PE_2D)) paletteEffects = new RotatePaletteEffect(132, 8, F16, paletteEffects); if ((type != PE_SKY) && (type != PE_2D)) paletteEffects = new RotatePaletteEffect(160, 32, -F16, paletteEffects); if (type != PE_SKY) { paletteEffects = new RotatePaletteEffect(192, 32, -F32, paletteEffects); paletteEffects = new RotatePaletteEffect(224, 16, F16, paletteEffects); } // Level fade-in/white-in effect if (checkpoint) paletteEffects = new FadeInPaletteEffect(T_START, paletteEffects); else paletteEffects = new WhiteInPaletteEffect(T_START, paletteEffects); // Check if a sun/star/distant planet, etc. is visible skyOrb = file->loadChar(); // If so, find out which tile it uses or skip it if (skyOrb) skyOrb = file->loadChar(); else file->loadChar(); // Skip some sound effects and empty animations file->seek(14, false); // 4 shield gem miscAnims[MA_4SHIELD] = file->loadChar(); // Board miscAnims[MA_LBOARD] = file->loadChar(); miscAnims[MA_RBOARD] = file->loadChar(); // Bird miscAnims[MA_LBIRD] = file->loadChar(); miscAnims[MA_RBIRD] = file->loadChar(); // Skip unknown animation file->seek(1, false); // Shiver and slide: 2, only shiver: 1 miscAnims[MA_ICY] = file->loadChar(); // 1 shield gem miscAnims[MA_1SHIELD] = file->loadChar(); // And that's us done! delete file; // Set the tick at which the level will end endTime = (5 - game->getDifficulty()) * 2 * 60 * 1000; events = NULL; bullets = NULL; energyBar = 0; ammoType = 0; ammoOffset = -1; return E_NONE; } openjazz-20190106/src/jj1level/jj1levelplayer/000077500000000000000000000000001341440264100210515ustar00rootroot00000000000000openjazz-20190106/src/jj1level/jj1levelplayer/jj1bird.cpp000066400000000000000000000120741341440264100231060ustar00rootroot00000000000000 /** * * @file jj1bird.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp * - 1st March 2009: Created bird.cpp from parts of events.cpp * - 1st August 2012: Renamed bird.cpp to jj1bird.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "../jj1bullet.h" #include "../jj1event/jj1event.h" #include "../jj1level.h" #include "jj1bird.h" #include "jj1levelplayer.h" #include "io/gfx/video.h" /** * Create a bird for the specified player. * * @param birds The player's existing birds (NULL if none) * @param rescuer The player that freed the bird * @param gX The new bird's grid x-coordinate * @param gY The new bird's grid y-coordinate */ JJ1Bird::JJ1Bird (JJ1Bird* birds, JJ1LevelPlayer *rescuer, unsigned char gX, unsigned char gY) { next = birds; player = rescuer; x = TTOF(gX); y = TTOF(gY); dx = 0; dy = 0; fleeing = false; fireTime = 0; return; } /** * Delete all birds. */ JJ1Bird::~JJ1Bird () { if (next) delete next; return; } /** * Delete this bird. * * @return The next bird */ JJ1Bird* JJ1Bird::remove () { JJ1Bird* oldNext; oldNext = next; next = NULL; delete this; return oldNext; } /** * Get the player that freed the bird. * * @return The player */ JJ1LevelPlayer * JJ1Bird::getPlayer () { return player; } /** * Notify the bird that the player has been hit. */ void JJ1Bird::hit () { fleeing = true; return; } /** * Recursively count the number of birds. * * @return The number of birds ahead of this bird, plus one */ int JJ1Bird::getFlockSize () { if (next) return next->getFlockSize() + 1; return 1; } /** * Recursively set the number of birds. * * @param size The number of birds not already counted * * @return Remaining bird (NULL if none) */ JJ1Bird* JJ1Bird::setFlockSize (int size) { if (size <= 0) { delete this; return NULL; } if (size > 1) { if (!next) next = new JJ1Bird(NULL, player, FTOT(x), FTOT(y)); next = next->setFlockSize(size - 1); } return this; } /** * JJ1Bird iteration. * * @param ticks Time * * @return Remaining bird (NULL if none) */ JJ1Bird* JJ1Bird::step (unsigned int ticks) { Movable* leader; JJ1Event* event; bool target; // Process the next bird if (next) next = next->step(ticks); if (next) leader = next; else leader = player; if (fleeing) { // Trajectory for flying away dx = F80; dy = -F80; // If the bird has flown off-screen, remove it if (y < viewY - F160) return remove(); } else { // Trajectory for flying towards the leader if ((x < leader->getX() - F160) || (x > leader->getX() + F160)) { // Far away from the leader // Approach the leader at a speed proportional to the distance dx = leader->getX() - x; } else if (x < leader->getX()) { // To the left of the leader, so move right if (dx < F80) dx += 6400; } else { // To the right of the leader, so move left if (dx > -F80) dx -= 6400; } if (y > level->getWaterLevel() - F24) { // Always stay above water y = level->getWaterLevel() - F24; dy = 0; } else { if ((y < leader->getY() - F100) || (y > leader->getY() + F100)) { // Far away from the leader // Approach the leader at a speed proportional to the distance dy = (leader->getY() - F64) - y; } else if (y < leader->getY() - F64) { // Above the leader, so move downwards if (dy < F80) dy += 6400; } else { // Below the leader, so move upwards if (dy > -F80) dy -= 6400; } } if (ticks > fireTime) { // Check for nearby targets target = false; event = level->getEvents(); if (player->getFacing()) { while (event && !target) { target = event->isEnemy() && event->overlap(x, y, F160, F100); event = event->getNext(); } } else { while (event && !target) { target = event->isEnemy() && event->overlap(x - F160, y, F160, F100); event = event->getNext(); } } // If there is a target in the vicinity, generate bullets if (target) { level->createBullet(player, 0, 0, x + (player->getFacing()? PXO_R: PXO_L), y, 30, player->getFacing(), ticks); fireTime = ticks + T_BIRD_FIRE; } } } // Apply trajectory x += dx >> 6; y += dy >> 6; return this; } /** * Draw the bird. * * @param ticks Time * @param change Time since last step */ void JJ1Bird::draw (unsigned int ticks, int change) { Anim *anim; if (next) next->draw(ticks, change); anim = level->getMiscAnim((player->getFacing() || fleeing)? MA_RBIRD: MA_LBIRD); anim->setFrame(ticks / 80, true); anim->draw(getDrawX(change), getDrawY(change)); return; } openjazz-20190106/src/jj1level/jj1levelplayer/jj1bird.h000066400000000000000000000031071341440264100225500ustar00rootroot00000000000000 /** * * @file jj1bird.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 4th February 2009: Created events.h from parts of level.h * - 1st March 2009: Created bird.h from parts of events.h * - 1st August 2012: Renamed bird.h to jj1bird.h * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _BIRD_H #define _BIRD_H #include "level/movable.h" #include "OpenJazz.h" // Constants // Time interval #define T_BIRD_FIRE 500 // Classes class JJ1LevelPlayer; /// JJ1 bird companion class JJ1Bird : public Movable { private: JJ1Bird* next; JJ1LevelPlayer* player; ///< Player that rescued the bird bool fleeing; ///< Flying away, player having been shot unsigned int fireTime; ///< Next time the bird will fire JJ1Bird* remove (); public: JJ1Bird (JJ1Bird* birds, JJ1LevelPlayer* player, unsigned char gX, unsigned char gY); ~JJ1Bird (); int getFlockSize (); JJ1LevelPlayer* getPlayer (); void hit (); JJ1Bird* setFlockSize (int size); JJ1Bird* step (unsigned int ticks); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj1level/jj1levelplayer/jj1levelplayer.cpp000066400000000000000000000375531341440264100245230ustar00rootroot00000000000000 /** * * @file jj1levelplayer.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 24th June 2010: Created levelplayer.cpp from parts of player.cpp * - 29th June 2010: Created jj2levelplayer.cpp from parts of levelplayer.cpp * - 1st August 2012: Renamed levelplayer.cpp to jj1levelplayer.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creation and destruction of players in levels, and their * interactions with other level objects. * */ #include "../jj1event/jj1event.h" #include "../jj1level.h" #include "jj1bird.h" #include "jj1levelplayer.h" #include "game/game.h" #include "io/sound.h" #include "setup.h" #include /** * Create a JJ1 level player. * * @param parent The game player corresponding to this level player. * @param newAnims Animations * @param startX Starting position x-coordinate * @param startY Starting position y-coordinate * @param flockSize The number of birds accompanying the player */ JJ1LevelPlayer::JJ1LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, int flockSize) { int offsets[15] = {PCO_GREY, PCO_SGREEN, PCO_BLUE, PCO_RED, PCO_LGREEN, PCO_LEVEL1, PCO_YELLOW, PCO_LEVEL2, PCO_ORANGE, PCO_LEVEL3, PCO_LEVEL4, PCO_SANIM, PCO_LANIM, PCO_LEVEL5, 256}; int count, start, length; player = parent; memcpy(anims, newAnims, JJ1PANIMS * sizeof(Anim *)); birds = NULL; for (count = 0; count < flockSize; count++) birds = new JJ1Bird(birds, this, startX, startY - 2); shield = 0; enemies = items = 0; gem = false; reset(startX, startY); // Create the player's palette for (count = 0; count < 256; count++) palette[count].r = palette[count].g = palette[count].b = count; // Fur colours start = offsets[player->cols[0]]; length = offsets[player->cols[0] + 1] - start; for (count = 0; count < 16; count++) palette[count + 48].r = palette[count + 48].g = palette[count + 48].b = (count * length / 16) + start; // Bandana colours start = offsets[player->cols[1]]; length = offsets[player->cols[1] + 1] - start; for (count = 0; count < 16; count++) palette[count + 32].r = palette[count + 32].g = palette[count + 32].b = (count * length / 16) + start; // Gun colours start = offsets[player->cols[2]]; length = offsets[player->cols[2] + 1] - start; for (count = 0; count < 9; count++) palette[count + 23].r = palette[count + 23].g = palette[count + 23].b = (count * length / 9) + start; // Wristband colours start = offsets[player->cols[3]]; length = offsets[player->cols[3] + 1] - start; for (count = 0; count < 8; count++) palette[count + 88].r = palette[count + 88].g = palette[count + 88].b = (count * length / 8) + start; return; } /** * Delete the JJ1 level player. */ JJ1LevelPlayer::~JJ1LevelPlayer () { if (birds) delete birds; return; } /** * Reset the player's position, energy etc. * * @param startX New x-coordinate * @param startY New y-coordinate */ void JJ1LevelPlayer::reset (int startX, int startY) { x = TTOF(startX); y = TTOF(startY); dx = 0; dy = 0; eventType = JJ1PE_NONE; energy = 4; flying = false; facing = true; udx = 0; animType = PA_RSTAND; reaction = PR_NONE; reactionTime = 0; jumpHeight = PYO_JUMP; targetY = TTOF(LH); fastFeetTime = 0; warpTime = 0; fireTime = 0; fireAnimTime = 0; return; } /** * Add to the player's item tally. */ void JJ1LevelPlayer::addItem () { items++; return; } /** * If the player is tied to the event from the given tile, untie it. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile */ void JJ1LevelPlayer::clearEvent (unsigned char gridX, unsigned char gridY) { // If the location matches, clear the event if ((gridX == eventX) && (gridY == eventY)) eventType = JJ1PE_NONE; return; } /** * Determine the player's current animation. * * @return The current animation */ Anim* JJ1LevelPlayer::getAnim () { return anims[animType]; } /** * Determine the number of enemies the player has killed. * * @return Number of enemies killed */ int JJ1LevelPlayer::getEnemies () { return enemies; } /** * Determine the player's current energy level. * * @return Energy level */ int JJ1LevelPlayer::getEnergy () { return energy; } /** * Determine the direction the player is facing. * * @return True if the player is facing right */ bool JJ1LevelPlayer::getFacing () { return facing; } /** * Get the horizontal speed of the player. * * @return The player's horizontal speed */ fixed JJ1LevelPlayer::getXSpeed () { return dx; } /** * Determine the number of items the player has collected. * * @return Number of items collected */ int JJ1LevelPlayer::getItems () { return items; } /** * Determine whether or not the player is being accompanied by a bird. * * @return Whether or not the player is being accompanied by a bird */ int JJ1LevelPlayer::countBirds () { if (birds) return birds->getFlockSize(); return 0; } /** * Determine whether or not the player has collected a gem. * * @return Whether or not the player has collected a gem */ bool JJ1LevelPlayer::hasGem () { return gem; } /** * Deal with bullet collisions. * * @param source Player that fired the bullet (NULL if an event) * @param ticks Time * * @return Whether or not the hit was successful */ bool JJ1LevelPlayer::hit (Player *source, unsigned int ticks) { // Invulnerable if reacting to e.g. having been hit if (reaction != PR_NONE) return false; // Hits from the same team have no effect if (source && (source->getTeam() == player->team)) return false; // Hits to the shield only affect the shield if (shield) { if (shield == 2) shield = 0; else shield--; reaction = PR_SHIELDED; reactionTime = ticks + PRT_SHIELDED; return true; } // Hits only cause damage in applicable game modes if (player->hit(source)) { // Hits don't cause damage with a bird, but do scare the bird away if (birds) birds->hit(); else energy--; } playSound(7); if (energy) { reaction = PR_HURT; reactionTime = ticks + PRT_HURT; if (dx < 0) dx = PXS_RUN; else dx = -PXS_RUN; dy = PYS_JUMP; } else { kill(source, ticks); } return true; } /** * Kill the player. * * @param source Player responsible for the kill (NULL if due to an event or time) * @param ticks time */ void JJ1LevelPlayer::kill (Player *source, unsigned int ticks) { if (reaction != PR_NONE) return; if (player->kill(source)) { energy = 0; player->lives--; reaction = PR_KILLED; reactionTime = ticks + PRT_KILLED; } return; } /** * Determine whether or not the player is overlapping the given area. * * @param left The x-coordinate of the left of the area * @param top The y-coordinate of the top of the area * @param width The width of the area * @param height The height of the area * * @return Whether or not there is an overlap */ bool JJ1LevelPlayer::overlap (fixed left, fixed top, fixed width, fixed height) { return (x + PXO_R >= left) && (x + PXO_L < left + width) && (y >= top) && (y + PYO_TOP < top + height); } /** * Handle the player's reaction. * * @param ticks Time * * @return The reaction the player has just finished */ JJ1PlayerReaction JJ1LevelPlayer::reacted (unsigned int ticks) { JJ1PlayerReaction oldReaction; if ((reaction != PR_NONE) && (reactionTime < ticks)) { oldReaction = reaction; reaction = PR_NONE; return oldReaction; } return PR_NONE; } /** * Tie the player to the platform from the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param shiftX Change in horizontal position * @param newY New vertical position */ void JJ1LevelPlayer::setPlatform (unsigned char gridX, unsigned char gridY, fixed shiftX, fixed newY) { eventType = JJ1PE_PLATFORM; eventX = gridX; eventY = gridY; if (((shiftX < 0) && !level->checkMaskUp(x + PXO_L + shiftX, y + PYO_MID)) || ((shiftX > 0) && !level->checkMaskUp(x + PXO_R + shiftX, y + PYO_MID))) { x += shiftX; } y = newY; return; } /** * Take the event from the given tile. * * @param event Event type * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param ticks Time * * @return Whether or not the event should be destroyed. */ bool JJ1LevelPlayer::takeEvent (JJ1EventType* event, unsigned char gridX, unsigned char gridY, unsigned int ticks) { switch (event->modifier) { case 41: // Bonus level if (energy) level->setNext(event->multiA, event->multiB); // The lack of a break statement is intentional case 8: // Boss case 27: // End of level if (!energy) return false; if (!player->endOfLevel(gridX, gridY)) return false; level->setStage(LS_END); break; case 0: // Enemy break; case 1: // Invincibility if (!energy) return false; reaction = PR_INVINCIBLE; reactionTime = ticks + PRT_INVINCIBLE; break; case 2: case 3: // Health if ((energy == 4) && setup.leaveUnneeded) return false; if (energy < 4) energy++; break; case 4: // Extra life player->addLife(); break; case 5: // High-jump feet jumpHeight += F16; break; case 7: // Used with destructible blocks break; case 9: // Sand timer level->addTimer(2 * 60); break; case 10: // Checkpoint player->setCheckpoint(gridX, gridY); break; case 11: // Item break; case 12: // Rapid fire player->fireSpeed++; fireTime = 0; break; case 15: // Ammo player->addAmmo(0, 15); break; case 16: // Ammo player->addAmmo(1, 15); break; case 17: // Ammo player->addAmmo(2, 15); break; case 18: // Ammo player->addAmmo(0, 2); break; case 19: // Ammo player->addAmmo(1, 2); break; case 20: // Ammo player->addAmmo(2, 2); break; case 26: // Fast feet box fastFeetTime = ticks + T_FASTFEET; break; case 30: // TNT player->addAmmo(4, 1); break; case 31: // Water level level->setWaterLevel(gridY + 1); break; case 33: // 1-hit shield if ((shield >= 1) && setup.leaveUnneeded) return false; else shield = 1; break; case 34: // Bird if (birds && !setup.manyBirds) return false; birds = new JJ1Bird(birds, this, gridX, gridY); break; case 35: // Airboard, etc. if (flying && setup.leaveUnneeded) return false; flying = true; break; case 36: // 4-hit shield if ((shield == 5) && setup.leaveUnneeded) return false; shield = 5; break; case 37: // Diamond if (gem && setup.leaveUnneeded) return false; gem = true; // Yellow flash level->flash(255, 255, 0, 320); break; case 39: // Ammo player->addAmmo(3, 15); break; case 40: // Ammo player->addAmmo(3, 2); break; default: return false; } player->addScore(event->points * 10); // Add to player's enemy/item tally // If the event hurts and can be killed, it is an enemy // Anything else that scores is an item if ((event->modifier == 0) && event->strength) enemies++; else if (event->points) items++; return true; } /** * Called when the player has touched the event from the given tile. * * @param event Event type * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param ticks Time * * @return Whether or not the event should be destroyed. */ bool JJ1LevelPlayer::touchEvent (JJ1EventType* event, unsigned char gridX, unsigned char gridY, unsigned int ticks) { if ((event->movement == 37) || (event->movement == 38)) { // Repel if (event->multiB) { if (event->multiA > 0) { udx = (event->magnitude < 0 ? -ITOF(240): ITOF(240)); eventType = JJ1PE_REPELUP; targetY = TTOF(gridY) - ITOF(event->multiA * 3); } else { eventType = JJ1PE_REPELDOWN; } eventX = gridX; eventY = gridY; dy = event->multiA * -F24; } else { eventType = JJ1PE_REPELH; eventX = gridX; eventY = gridY; } } switch (event->modifier) { case 0: // Hurt case 8: // Boss if ((event->movement < 37) || (event->movement > 44)) { if (reaction != PR_SHIELDED) hit(NULL, ticks); if (reaction == PR_SHIELDED) { level->hitEvent(gridX, gridY, 255, this, ticks); return true; } } break; case 7: // Used with destructible blocks, but should not destroy on contact break; case 13: // Warp if (!warpTime) { warpX = event->multiA; warpY = event->multiB; warpTime = ticks + T_WARP; // White flash level->flash(255, 255, 255, T_WARP); } break; case 28: // Belt if (event->magnitude < 0) { if (!level->checkMaskDown(x + PXO_L + (event->magnitude * 64), y + PYO_MID)) x += event->magnitude * 64; } else { if (!level->checkMaskDown(x + PXO_R + (event->magnitude * 64), y + PYO_MID)) x += event->magnitude * 64; } break; case 29: // Upwards spring eventType = JJ1PE_SPRING; eventX = gridX; eventY = gridY; targetY = TTOF(gridY) + (event->magnitude * ITOF(21)); playSound(event->sound); break; case 31: // Water level level->setWaterLevel(gridY + 1); break; case 32: // Float up / sideways if (event->multiB) { eventType = JJ1PE_FLOAT; eventX = gridX; eventY = gridY; targetY = TTOF(gridY) - (event->multiA * ITOF(17)); } else { eventType = JJ1PE_FLOATH; eventX = gridX; eventY = gridY; } break; case 38: // Airboard, etc. off flying = false; break; default: if (!event->strength) return takeEvent(event, gridX, gridY, ticks); break; } return false; } /** * Fill a buffer with player data. * * @param buffer The buffer */ void JJ1LevelPlayer::send (unsigned char *buffer) { // Copy data to be sent to clients/server buffer[9] = countBirds(); buffer[23] = energy; buffer[25] = shield; buffer[26] = flying; buffer[27] = getFacing(); buffer[29] = jumpHeight >> 24; buffer[30] = (jumpHeight >> 16) & 255; buffer[31] = (jumpHeight >> 8) & 255; buffer[32] = jumpHeight & 255; buffer[33] = targetY >> 24; buffer[34] = (targetY >> 16) & 255; buffer[35] = (targetY >> 8) & 255; buffer[36] = targetY & 255; buffer[37] = x >> 24; buffer[38] = (x >> 16) & 255; buffer[39] = (x >> 8) & 255; buffer[40] = x & 255; buffer[41] = y >> 24; buffer[42] = (y >> 16) & 255; buffer[43] = (y >> 8) & 255; buffer[44] = y & 255; return; } /** * Adjust player data based on the contents of a given buffer. * * @param buffer The buffer */ void JJ1LevelPlayer::receive (unsigned char *buffer) { int count; // Interpret data received from client/server switch (buffer[1]) { case MT_P_ANIMS: for (count = 0; count < JJ1PANIMS; count++) anims[count] = level->getAnim(buffer[MTL_P_ANIMS + count]); break; case MT_P_TEMP: if ((buffer[9] > 0) && (birds == NULL)) { birds = new JJ1Bird(birds, this, FTOT(x), FTOT(y) - 2); } if (birds) { birds = birds->setFlockSize(buffer[9]); } energy = buffer[23]; shield = buffer[25]; flying = buffer[26]; facing = buffer[27]; jumpHeight = (buffer[29] << 24) + (buffer[30] << 16) + (buffer[31] << 8) + buffer[32]; targetY = (buffer[33] << 24) + (buffer[34] << 16) + (buffer[35] << 8) + buffer[36]; x = (buffer[37] << 24) + (buffer[38] << 16) + (buffer[39] << 8) + buffer[40]; y = (buffer[41] << 24) + (buffer[42] << 16) + (buffer[43] << 8) + buffer[44]; break; } return; } openjazz-20190106/src/jj1level/jj1levelplayer/jj1levelplayer.h000066400000000000000000000143751341440264100241650ustar00rootroot00000000000000 /** * * @file jj1levelplayer.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 24th June 2010: Created levelplayer.h from parts of player.h * - 29th June 2010: Created jj2levelplayer.h from parts of levelplayer.h * - 1st August 2012: Renamed levelplayer.h to jj1levelplayer.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ /* "Tile" is a flexible term. Here it is used to refer specifically to the individual elements of the tile set. "Tiles" in the context of level units are referred to as grid elements. */ #ifndef _JJ1LEVELPLAYER_H #define _JJ1LEVELPLAYER_H #include "../jj1level.h" #include "level/levelplayer.h" #include "player/player.h" #include "OpenJazz.h" // Constants // Colour offsets #define PCO_GREY 0 #define PCO_SGREEN 16 #define PCO_BLUE 23 #define PCO_RED 32 #define PCO_LGREEN 48 #define PCO_LEVEL1 64 #define PCO_YELLOW 75 #define PCO_LEVEL2 80 #define PCO_ORANGE 88 #define PCO_LEVEL3 96 #define PCO_LEVEL4 104 #define PCO_SANIM 112 #define PCO_LANIM 116 #define PCO_LEVEL5 124 // Player reaction times #define PRT_HURT 1000 #define PRT_HURTANIM 200 #define PRT_KILLED 2000 #define PRT_INVINCIBLE 10000 #define PRT_SHIELDED 100 // Other time periods #define T_FASTFEET 25000 #define T_WARP 1000 #define T_FIRING 150 // Player offsets #define PXO_MID F16 #define PXO_L (PXO_MID - F12) #define PXO_ML (PXO_MID - F8) #define PXO_MR (PXO_MID + F8) #define PXO_R (PXO_MID + F12) #define PYO_TOP (-F20) #define PYO_MID (-F10) #define PYO_JUMP ITOF(84) // Player speeds #define PXS_WALK ITOF(150) #define PXS_RUN ITOF(325) #define PYS_FALL ITOF(350) #define PYS_SINK ITOF(150) #define PYS_JUMP -ITOF(350) // Player accelerations #define PXA_REVERSE ITOF(28) #define PXA_STOP ITOF(16) #define PXA_WALK ITOF(16) #define PXA_RUN ITOF(16) #define PYA_GRAVITY ITOF(36) #define PYA_SINK ITOF(16) // Enums /// JJ1 player event types enum JJ1PlayerEvent { JJ1PE_NONE, ///< No event JJ1PE_SPRING, ///< Spring JJ1PE_FLOAT, ///< Float up JJ1PE_FLOATH, ///< Float horizontally JJ1PE_REPELH, ///< Repel horizontally only JJ1PE_REPELUP, ///< Repel upwards JJ1PE_REPELDOWN, ///< Repel downwards JJ1PE_PLATFORM ///< Moving platform }; /// JJ1 player reaction type enum JJ1PlayerReaction { PR_NONE, ///< Not reacting PR_HURT, ///< Hurt PR_KILLED, ///< Killed PR_INVINCIBLE, ///< Invincibility PR_SHIELDED ///< Hit to shield }; // Classes class Anim; class JJ1Bird; /// JJ1 level player class JJ1LevelPlayer : public LevelPlayer { private: JJ1Bird* birds; ///< Bird companion(s) Anim* anims[JJ1PANIMS]; ///< Animations int energy; ///< 0 = dead, 4 = maximum int shield; ///< 0 = none, 1 = yellow, 2 = 1 orange, 3 = 2 orange, 4 = 3 orange, 5 = 4 orange bool flying; ///< false = normal, true = boarding/bird/etc. bool facing; ///< false = left, true = right fixed udx; ///< Unobstructed horizontal speed unsigned char animType; ///< Current animation unsigned char eventX; ///< X-coordinate (in tiles) of an event (spring, platform, bridge) unsigned char eventY; ///< Y-coordinate (in tiles) of an event (spring, platform, bridge) JJ1PlayerEvent eventType; ///< Event type int lookTime; ///< Negative if looking up, positive if looking down, 0 if neither JJ1PlayerReaction reaction; ///< Reaction type unsigned int reactionTime; ///< Time the reaction will end unsigned int fireTime; ///< The next time the player can fire unsigned int fireAnimTime; ///< Time the firing animation will end fixed jumpHeight; ///< The height the player can reach when jumping fixed targetY; ///< Having been propelled, the y-coordinate the player could reach unsigned int fastFeetTime; ///< Time fast feet will expire unsigned char warpX; ///< X-coordinate (in tiles) player will warp to unsigned char warpY; ///< Y-coordinate (in tiles) player will warp to unsigned int warpTime; ///< Time the warp will happen int enemies; ///< Number of enemies killed int items; ///< Number of items collected bool gem; ///< Bonus level gem collected bool checkMaskDown (fixed yOffset); bool checkMaskUp (fixed yOffset); void ground (); public: JJ1LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, int flockSize); ~JJ1LevelPlayer (); void reset (int startX, int startY); void addItem (); void clearEvent (unsigned char gridX, unsigned char gridY); int countBirds (); Anim* getAnim (); int getEnemies (); int getEnergy (); bool getFacing (); int getXSpeed (); int getItems (); bool hasGem (); bool hit (Player* source, unsigned int ticks); void kill (Player* source, unsigned int ticks); bool overlap (fixed left, fixed top, fixed width, fixed height); JJ1PlayerReaction reacted (unsigned int ticks); void setPlatform (unsigned char gridX, unsigned char gridY, fixed shiftX, fixed newY); bool takeEvent (JJ1EventType* set, unsigned char gridX, unsigned char gridY, unsigned int ticks); bool touchEvent (JJ1EventType* set, unsigned char gridX, unsigned char gridY, unsigned int ticks); void send (unsigned char* buffer); void receive (unsigned char* buffer); void control (unsigned int ticks); void move (unsigned int ticks); void view (unsigned int ticks, int mspf, int change); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj1level/jj1levelplayer/jj1levelplayerframe.cpp000066400000000000000000000462761341440264100255400ustar00rootroot00000000000000 /** * * @file jj1levelplayerframe.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 18th July 2009: Created playerframe.cpp from parts of player.cpp * - 24th June 2010: Renamed playerframe.cpp to levelplayerframe.cpp * - 29th June 2010: Created jj2levelplayerframe.cpp from parts of * levelplayerframe.cpp * - 1st August 2012: Renamed levelplayerframe.cpp to jj1levelplayerframe.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the once-per-frame functions of players in levels. * */ #include "../jj1bullet.h" #include "../jj1event/jj1event.h" #include "../jj1level.h" #include "jj1bird.h" #include "jj1levelplayer.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" /** * Determine whether or not the area below the player is solid when travelling * downwards. * * @param yOffset Vertical offset of the mask values to check * * @return Solidity */ bool JJ1LevelPlayer::checkMaskDown (fixed yOffset) { return level->checkMaskDown(x + PXO_ML + F1, y + yOffset) || level->checkMaskDown(x + PXO_MID, y + yOffset) || level->checkMaskDown(x + PXO_MR - F1, y + yOffset); } /** * Determine whether or not the area above the player is solid when travelling * upwards. * * @param yOffset Vertical offset of the mask values to check * * @return Solidity */ bool JJ1LevelPlayer::checkMaskUp (fixed yOffset) { return level->checkMaskUp(x + PXO_ML + F1, y + yOffset) || level->checkMaskUp(x + PXO_MID, y + yOffset) || level->checkMaskUp(x + PXO_MR - F1, y + yOffset); } /** * Move the player to the ground's surface. */ void JJ1LevelPlayer::ground () { // If on an uphill slope, push the player upwards if (checkMaskUp(0) && !checkMaskUp(-F4)) y -= F4; // If on a downhill slope, push the player downwards if (!checkMaskUp(F4) && checkMaskUp(F8)) y += F4; return; } /** * Respond to controls, unless the player has been killed. * * @param ticks Time */ void JJ1LevelPlayer::control (unsigned int ticks) { fixed speed; bool platform; // If the player has been killed, drop but otherwise do not move if (!energy) { dx = 0; udx = 0; if (flying) dy = 0; else { if (dy < 0) dy += PYA_GRAVITY; else dy = PYS_FALL; } return; } if ((eventType == JJ1PE_FLOATH) || (eventType == JJ1PE_REPELH)) { speed = level->getEvent(eventX, eventY)->magnitude * ((eventType == JJ1PE_FLOATH)? F10: F40); if (speed < -PXS_WALK || speed > PXS_WALK) { udx = speed; } else if ((speed < 0) && player->pcontrols[C_RIGHT]) { // Walk right, against the flow if (udx < speed) udx += PXA_REVERSE; else if (udx < speed + PXS_WALK) udx += PXA_WALK; if (udx > speed + PXS_WALK) udx = speed + PXS_WALK; facing = true; } else if ((speed > 0) && player->pcontrols[C_LEFT]) { // Walk left, against the flow if (udx > 0) udx -= PXA_REVERSE; else if (udx > speed - PXS_WALK) udx -= PXA_WALK; if (udx < speed - PXS_WALK) udx = speed - PXS_WALK; facing = false; } else { udx = speed; } eventType = JJ1PE_NONE; } else if (player->pcontrols[C_RIGHT]) { // Walk/run right if (udx < 0) udx = dx; if (udx < 0) udx += PXA_REVERSE; else if (udx < PXS_WALK) udx += PXA_WALK; else if (udx < PXS_RUN) udx += PXA_RUN; if (udx > PXS_RUN) udx = PXS_RUN; facing = true; } else if (player->pcontrols[C_LEFT]) { // Walk/run left if (udx > 0) udx = dx; if (udx > 0) udx -= PXA_REVERSE; else if (udx > -PXS_WALK) udx -= PXA_WALK; else if (udx > -PXS_RUN) udx -= PXA_RUN; if (udx < -PXS_RUN) udx = -PXS_RUN; facing = false; } else { // Slow down if (udx > 0) { if (udx < PXA_STOP) udx = 0; else udx -= PXA_STOP; } else if (udx < 0) { if (udx > -PXA_STOP) udx = 0; else udx += PXA_STOP; } } // Check for platform event, bridge or level mask below player platform = (eventType == JJ1PE_PLATFORM) || checkMaskDown(F4) || ((dx > 0) && level->checkMaskDown(x + PXO_ML, y + F8)) || ((dx < 0) && level->checkMaskDown(x + PXO_MR, y + F8)); if (flying) { if (player->pcontrols[C_UP]) { // Fly upwards if (dy > 0) dy -= PXA_REVERSE; else if (dy > -PXS_WALK) dy -= PXA_WALK; else if (dy > -PXS_RUN) dy -= PXA_RUN; } else if (player->pcontrols[C_DOWN]) { // Fly downwards if (dy < 0) dy += PXA_REVERSE; else if (dy < PXS_WALK) dy += PXA_WALK; else if (dy < PXS_RUN) dy += PXA_RUN; } else { // Slow down if (dy > 0) { if (dy < PXA_STOP) dy = 0; else dy -= PXA_STOP; } else if (dy < 0) { if (dy > -PXA_STOP) dy = 0; else dy += PXA_STOP; } } if (eventType == JJ1PE_SPRING) dy = level->getEvent(eventX, eventY)->multiA * -F20; else if (eventType == JJ1PE_FLOAT) dy = PYS_JUMP; if (dy < -PXS_RUN) dy = -PXS_RUN; else if (dy > PXS_RUN) dy = PXS_RUN; } else if (y + PYO_MID > level->getWaterLevel() + F8) { if (player->pcontrols[C_SWIM]) { // Swim upwards if (dy > 0) dy -= PXA_REVERSE; else if (dy > -PXS_WALK) dy -= PXA_WALK; else if (dy > -PXS_RUN) dy -= PXA_RUN; // Prepare to jump upon leaving the water if (!level->checkMaskUp(x + PXO_MID, y - F36)) { targetY = y - jumpHeight; if (dx < 0) targetY += dx >> 4; else if (dx > 0) targetY -= dx >> 4; eventType = JJ1PE_NONE; } } else if (player->pcontrols[C_DOWN]) { // Swim downwards if (dy < 0) dy += PXA_REVERSE; else if (dy < PXS_WALK) dy += PXA_WALK; else if (dy < PXS_RUN) dy += PXA_RUN; } else { // Sink dy += PYA_SINK; if (dy > PYS_SINK) dy = PYS_SINK; } if (dy < -PXS_RUN) dy = -PXS_RUN; else if (dy > PXS_RUN) dy = PXS_RUN; } else { if (platform && player->pcontrols[C_JUMP] && !level->checkMaskUp(x + PXO_MID, y - F36)) { // Jump targetY = y - jumpHeight; // Increase jump height if walking/running if (dx < 0) targetY += dx >> 3; else if (dx > 0) targetY -= dx >> 3; eventType = JJ1PE_NONE; playSound(9); } else if (((eventType == JJ1PE_NONE) || (eventType == JJ1PE_PLATFORM)) && !player->pcontrols[C_JUMP]) { // Stop jumping targetY = TTOF(LH); } if ((eventType == JJ1PE_FLOAT) && player->pcontrols[C_DOWN]) { // Prevent floating dy = PYS_FALL; } else if (y >= targetY) { if ((eventType == JJ1PE_FLOAT) && (dy > PYS_JUMP)) { dy -= F16 + F8; } else { dy = (targetY - y - F64) * 4; } // Spring/float up speed limit if ((eventType == JJ1PE_SPRING) || (eventType == JJ1PE_REPELUP)) { speed = level->getEvent(eventX, eventY)->multiA * -F20; if (speed >= 0) speed = PYS_JUMP; if (dy < speed) dy = speed; } // Avoid jumping too fast, unless caused by an event if ((eventType == JJ1PE_NONE) && (dy < PYS_JUMP)) dy = PYS_JUMP; } else if (eventType != JJ1PE_PLATFORM) { // Fall under gravity if (dy < 0) dy += PYA_GRAVITY; else dy = PYS_FALL; } // Don't descend through platforms if ((dy > 0) && (eventType == JJ1PE_PLATFORM)) dy = 0; if (platform && !lookTime) { // If requested, look up or down if (player->pcontrols[C_UP]) lookTime = -ticks; else if (player->pcontrols[C_DOWN]) lookTime = ticks; } // Stop looking if there is no platform or the control has been released if (!platform || (!player->pcontrols[C_UP] && (lookTime < 0)) || (!player->pcontrols[C_DOWN] && (lookTime > 0))) lookTime = 0; } // If there is an obstacle above, stop rising if ((targetY < y) && checkMaskUp(PYO_TOP - F4)) { targetY = TTOF(LH); if (dy < 0) dy = 0; if (eventType != JJ1PE_PLATFORM) eventType = JJ1PE_NONE; } // Handle firing if (player->pcontrols[C_FIRE]) { if (ticks > fireTime) { if (player->ammoType == 4) { JJ1Event* event; // TNT event = level->getEvents(); while (event) { // If the event is within range, hit it if (event->overlap(x - F160, y - F100, 2 * F160, 2 * F100)) { event->hit(this, 2, ticks); } event = event->getNext(); } // Red flash level->flash(255, 0, 0, T_TNT); } else { // Horizontal bullet position is taken from the shooting animation animType = facing? PA_RSHOOT: PA_LSHOOT; level->createBullet(this, 0, 0, x + anims[animType]->getShootX(), y - ITOF(lookTime? 5: 10), player->getAmmoType() + 1, facing, ticks); } // Set when the next bullet can be fired and length of shoot animation if (player->fireSpeed) { fireTime = ticks + (1000 / player->fireSpeed); fireAnimTime = ticks + 1000; } else { fireTime = 0x7FFFFFFF; fireAnimTime = ticks + T_FIRING; } // Remove the bullet from the arsenal if (player->ammoType != -1) player->ammo[player->ammoType]--; /* If the current ammo type has been exhausted or TNT has been used, use the previous non-exhausted ammo type */ while (((player->ammoType > -1) && !player->ammo[player->ammoType]) || (player->ammoType == 4)) player->ammoType--; } } else fireTime = 0; // Check for a change in ammo if (player->pcontrols[C_CHANGE]) { if (player == localPlayer) controls.release(C_CHANGE); player->ammoType = ((player->ammoType + 2) % 6) - 1; // If there is no ammo of this type, go to the next type that has ammo while ((player->ammoType > -1) && !player->ammo[player->ammoType]) player->ammoType = ((player->ammoType + 2) % 6) - 1; } // Deal with the bird if (birds) birds = birds->step(ticks); return; } /** * Move the player. * * @param ticks Time */ void JJ1LevelPlayer::move (unsigned int ticks) { fixed pdx, pdy; bool grounded = false; int count; if (warpTime && (ticks > warpTime)) { x = TTOF(warpX); y = TTOF(warpY + 1); warpTime = 0; } // Apply as much of the trajectory as possible, without going into the // scenery if (fastFeetTime > ticks) { pdx = (udx * 3) >> 7; pdy = (dy * 3) >> 7; } else { pdx = udx >> 6; pdy = dy >> 6; } // First for the vertical component of the trajectory if (pdy < 0) { // Moving up count = (-pdy) >> 12; while (count > 0) { if (checkMaskUp(PYO_TOP - F4)) { y &= ~4095; dy = 0; break; } y -= F4; count--; } pdy = (-pdy) & 4095; if (checkMaskUp(PYO_TOP - pdy)) { y &= ~4095; dy = 0; } else y -= pdy; } else { if (pdy > 0) { // Moving down count = pdy >> 12; while (count > 0) { if (checkMaskDown(F4)) { y |= 4095; dy = 0; break; } y += F4; count--; } pdy &= 4095; if (checkMaskDown(pdy)) { y |= 4095; dy = 0; } else y += pdy; } if (!flying) { if (checkMaskDown(0)) { // In the ground, so move up if (y >= 4096) y = (y - 4096) | 4095; grounded = true; } else if (checkMaskDown(1)) { // On the ground grounded = true; } } } // Then for the horizontal component of the trajectory dx = udx; if (pdx < 0) { // Moving left count = (-pdx) >> 12; while (count > 0) { // If there is an obstacle, stop if (level->checkMaskUp(x + PXO_L - F4, y + PYO_MID)) { x &= ~4095; dx = 0; if (udx < -PXS_RUN) udx = -PXS_RUN; break; } x -= F4; count--; if (grounded) ground(); } pdx = (-pdx) & 4095; if (level->checkMaskUp(x + PXO_L - pdx, y + PYO_MID)) { x &= ~4095; dx = 0; if (udx < -PXS_RUN) udx = -PXS_RUN; } else x -= pdx; if (grounded) ground(); } else if (pdx > 0) { // Moving right count = pdx >> 12; while (count > 0) { // If there is an obstacle, stop if (level->checkMaskUp(x + PXO_R + F4, y + PYO_MID)) { x |= 4095; dx = 0; if (udx > PXS_RUN) udx = PXS_RUN; break; } x += F4; count--; if (grounded) ground(); } pdx &= 4095; if (level->checkMaskUp(x + PXO_R + pdx, y + PYO_MID)) { x |= 4095; dx = 0; if (udx > PXS_RUN) udx = PXS_RUN; } else x += pdx; if (grounded) ground(); } // If the target has been reached, stop rising if (y <= targetY) { targetY = TTOF(LH); if ((eventType != JJ1PE_PLATFORM) && (eventType != JJ1PE_FLOATH) && (eventType != JJ1PE_REPELH)) eventType = JJ1PE_NONE; } if (level->getStage() != LS_END) { // If the player has hit the bottom of the level, kill if (y + F4 > TTOF(LH)) kill(NULL, ticks); // Handle spikes if (level->checkSpikes(x + PXO_MID, y + PYO_TOP - F4) || level->checkSpikes(x + PXO_MID, y + F4) || level->checkSpikes(x + PXO_L - F4, y + PYO_MID) || level->checkSpikes(x + PXO_R + F4, y + PYO_MID)) hit(NULL, ticks); } // Choose animation if (!energy) animType = facing? PA_RDIE: PA_LDIE; else if ((reaction == PR_HURT) && (reactionTime - ticks > PRT_HURT - PRT_HURTANIM)) animType = facing? PA_RHURT: PA_LHURT; else if (y + PYO_MID > level->getWaterLevel() + F8) animType = facing? PA_RSWIM: PA_LSWIM; else if (flying) animType = facing? PA_RBOARD: PA_LBOARD; else if (dy < 0) { if (eventType == JJ1PE_SPRING) animType = facing? PA_RSPRING: PA_LSPRING; else animType = facing? PA_RJUMP: PA_LJUMP; } else if (checkMaskDown(F4) || (eventType == JJ1PE_PLATFORM)) { if (udx) { if (udx <= -PXS_RUN) animType = PA_LRUN; else if (udx >= PXS_RUN) animType = PA_RRUN; else if ((udx < 0) && facing) animType = PA_LSTOP; else if ((udx > 0) && !facing) animType = PA_RSTOP; else animType = facing? PA_RWALK: PA_LWALK; } else if ((player->pcontrols[C_FIRE]) && (ticks < fireAnimTime)) animType = facing? PA_RSHOOT: PA_LSHOOT; else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) animType = PA_LOOKUP; else if (lookTime > 0) { if ((int)ticks < 1000 + lookTime) animType = facing? PA_RCROUCH: PA_LCROUCH; else animType = PA_LOOKDOWN; } else if (!level->checkMaskDown(x + PXO_ML, y + F20) && !level->checkMaskDown(x + PXO_L, y + F2) && (eventType != JJ1PE_PLATFORM)) animType = facing? PA_RSTAND: PA_LEDGE; else if (!level->checkMaskDown(x + PXO_MR, y + F20) && !level->checkMaskDown(x + PXO_R, y + F2) && (eventType != JJ1PE_PLATFORM)) animType = facing? PA_REDGE: PA_LSTAND; else animType = facing? PA_RSTAND: PA_LSTAND; } else animType = facing? PA_RFALL: PA_LFALL; return; } /** * Calculate viewport. * * @param ticks Time * @param mspf Ticks per frame * @param change Time since last step */ void JJ1LevelPlayer::view (unsigned int ticks, int mspf, int change) { int oldViewX, oldViewY, speed; // Record old viewport position for applying lag oldViewX = viewX; oldViewY = viewY; // Find new position viewX = x + ((dx * change) >> 10) + F8 - (canvasW << 9); viewY = y + ((dy * change) >> 10) - F24 - ((canvasH - 33) << 9); if ((lookTime > 0) && ((int)ticks > 1000 + lookTime)) { // Look down if ((int)ticks < 2000 + lookTime) viewY += 64 * (ticks - (1000 + lookTime)); else viewY += F64; } else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) { // Look up if ((int)ticks < 2000 - lookTime) viewY -= 64 * (ticks - (1000 - lookTime)); else viewY -= F64; } // Apply lag proportional to player "speed" speed = ((dx >= 0? dx: -dx) + (dy >= 0? dy: -dy)) >> 14; if (speed && (mspf < speed)) { viewX = ((oldViewX * (speed - mspf)) + (viewX * mspf)) / speed; viewY = ((oldViewY * (speed - mspf)) + (viewY * mspf)) / speed; } return; } /** * Draw the player. * * @param ticks Time * @param change Time since last step */ void JJ1LevelPlayer::draw (unsigned int ticks, int change) { Anim *an; int frame; fixed drawX, drawY; fixed xOffset, yOffset; fixed angle; // The current frame for animations if (reaction == PR_KILLED) frame = (ticks + PRT_KILLED - reactionTime) / 75; else frame = ticks / 75; // Get position drawX = getDrawX(change); drawY = getDrawY(change); // Choose sprite an = anims[animType]; an->setFrame(frame, reaction != PR_KILLED); // Show the player // Flash red if hurt, otherwise use player colour if ((reaction == PR_HURT) && (!((ticks / 30) & 3))) an->flashPalette(36); else { an->setPalette(palette, 23, 41); an->setPalette(palette, 88, 8); } // Draw "motion blur" if (fastFeetTime > ticks) an->draw(drawX - (dx >> 6), drawY); // Draw player an->draw(drawX, drawY); // Remove red flash or player colour from sprite an->restorePalette(); // Uncomment the following to see the area of the player /*drawRect(FTOI(drawX + PXO_L), FTOI(drawY + PYO_TOP), FTOI(PXO_R - PXO_L), FTOI(-PYO_TOP), 89); drawRect(FTOI(drawX + PXO_ML), FTOI(drawY + PYO_TOP), FTOI(PXO_MR - PXO_ML), FTOI(-PYO_TOP), 88);*/ // Uncomment the following to show the tile containing the player's base //drawRect(FTOI(TTOF(FTOT(x + PXO_MID)) - viewX), FTOI(TTOF(FTOT(y)) - viewY), 32, 32, 48); // Uncomment the following to show the player's event tile // if (eventType != JJ1PE_NONE) drawRect(FTOI(TTOF(eventX) - viewX), FTOI(TTOF(eventY) - viewY), 32, 32, 89); if (flying) { an = level->getMiscAnim(facing? MA_RBOARD: MA_LBOARD); an->setFrame(ticks >> 4, true); an->draw(drawX, drawY + F10); } if (reaction == PR_INVINCIBLE) { // Show invincibility stars xOffset = fSin(ticks * 2) * 12; yOffset = fCos(ticks * 2) * 12; an = level->getMiscAnim(MA_SPARKLE); an->setFrame(frame, true); an->draw(drawX + PXO_MID + xOffset, drawY + PYO_MID + yOffset); an->setFrame(frame + 1, true); an->draw(drawX + PXO_MID - xOffset, drawY + PYO_MID - yOffset); an->setFrame(frame + 2, true); an->draw(drawX + PXO_MID + yOffset, drawY + PYO_MID + xOffset); an->setFrame(frame + 3, true); an->draw(drawX + PXO_MID - yOffset, drawY + PYO_MID - xOffset); } else if (shield > 1) { // Show the 4-hit shield an = level->getMiscAnim(MA_4SHIELD); if (shield == 4) { // triangle based for (int i = 0; i < 3; i++) { angle = -(i * 341 + ticks); xOffset = fSin(angle) * 20; yOffset = fCos(angle) * 20; an->draw(drawX + xOffset, drawY + PYO_TOP + yOffset); } } else { // rectangle based xOffset = fCos(ticks) * 20; yOffset = fSin(ticks) * 20; an->draw(drawX + xOffset, drawY + PYO_TOP + yOffset); if (shield > 2) an->draw(drawX - xOffset, drawY + PYO_TOP - yOffset); if (shield > 4) { an->draw(drawX + yOffset, drawY + PYO_TOP - xOffset); an->draw(drawX - yOffset, drawY + PYO_TOP + xOffset); } } } else if (shield) { // Show the 1-hit shield xOffset = fCos(ticks) * 20; yOffset = fSin(ticks) * 20; an = level->getMiscAnim(MA_1SHIELD); an->draw(drawX + xOffset, drawY + PYO_TOP + yOffset); an->draw(drawX - xOffset, drawY + PYO_TOP - yOffset); } // Show the bird if (birds) birds->draw(ticks, change); // Show the player's name if (nPlayers > 1) panelBigFont->showString(player->name, FTOI(drawX + PXO_MID) - (panelBigFont->getStringWidth(player->name) >> 1), FTOI(drawY - F32 - F16)); return; } openjazz-20190106/src/jj1planet/000077500000000000000000000000001341440264100162745ustar00rootroot00000000000000openjazz-20190106/src/jj1planet/jj1planet.cpp000066400000000000000000000057111341440264100206740ustar00rootroot00000000000000 /** * * @file jj1planet.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created planet.c * - 3rd February 2009: Renamed planet.c to planet.cpp * - 1st August 2012: Renamed planet.cpp to jj1planet.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading, displaying and freeing of the planet landing * sequence. * */ #include "jj1planet.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" #include /** * Create a JJ1 planet approach sequence. * * @param fileName Name of the file containing the planet data * @param previous The ID of the last planet approach sequence */ JJ1Planet::JJ1Planet (char * fileName, int previous) { File *file; unsigned char *pixels; int count; try { file = new File(fileName, false); } catch (int e) { throw e; } id = file->loadShort(); if (id == previous) { // Not approaching a planet if already there delete file; throw E_NONE; } // Load planet name name = file->loadString(); // Lower-case the name for (count = 0; name[count]; count++) { if ((name[count] >= 65) && (name[count] <= 90)) name[count] += 32; } // Load the palette file->loadPalette(palette, false); // Load the planet image pixels = file->loadBlock(64 * 55); sprite.setPixels(pixels, 64, 55, 0); delete[] pixels; delete file; return; } /** * Delete the JJ1 planet approach sequence. */ JJ1Planet::~JJ1Planet () { delete[] name; return; } /** * Get the ID of the planet approach squence. * * @return The ID */ int JJ1Planet::getId () { return id; } /** * Run the JJ1 planet approach sequence. * * @return Error code */ int JJ1Planet::play () { unsigned int tickOffset; tickOffset = globalTicks; stopMusic(); video.setPalette(palette); while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE) || controls.wasCursorReleased()) return E_NONE; SDL_Delay(T_MENU_FRAME); video.clearScreen(0); if (globalTicks - tickOffset < F2) sprite.drawScaled(canvasW >> 1, canvasH >> 1, globalTicks - tickOffset); else if (globalTicks - tickOffset < F4) sprite.drawScaled(canvasW >> 1, canvasH >> 1, F2); else if (globalTicks - tickOffset < F4 + FQ) sprite.drawScaled(canvasW >> 1, canvasH >> 1, (globalTicks - tickOffset - F4) * 32 + F2); else return E_NONE; fontmn1->showString("now approaching", (canvasW - 288) >> 1, 0); fontmn1->showString(name, (canvasW - fontmn1->getStringWidth(name)) >> 1, canvasH - 24); } return E_NONE; } openjazz-20190106/src/jj1planet/jj1planet.h000066400000000000000000000016741341440264100203450ustar00rootroot00000000000000 /** * * @file jj1planet.h * * Part of the OpenJazz project * * @par History: * - 3rd February 2009: Created planet.h * - 1st August 2012: Renamed planet.h to jj1planet.h * * @par Licence: * Copyright (c) 2009-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PLANET_H #define _PLANET_H #include "io/gfx/sprite.h" // Class /// Planet approach sequence class JJ1Planet { private: SDL_Color palette[256]; /// Palette Sprite sprite; /// Planet image char* name; /// Planet name int id; /// World number public: JJ1Planet (char * fileName, int previous); ~JJ1Planet (); int getId (); int play (); }; #endif openjazz-20190106/src/jj1scene/000077500000000000000000000000001341440264100161065ustar00rootroot00000000000000openjazz-20190106/src/jj1scene/jj1scene.cpp000066400000000000000000000273121341440264100203210ustar00rootroot00000000000000 /** * * @file jj1scene.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created scene.c * - 3rd February 2009: Created scene.h from parts of scene.c * - 3rd February 2009: Renamed scene.c to scene.cpp * - 27th March 2010: Created sceneload.cpp from parts of scene.cpp * - 1st August 2012: Renamed scene.cpp to jj1scene.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the displaying and freeing of the cutscenes. * */ #include "jj1scene.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/paletteeffects.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" #include /** * Create a JJ1 cutscne frame. * * @param newFrameType The type of the frame * @param newFrameData The frame's data buffer * @param newFrameSize The size of the frame's data buffer */ JJ1SceneFrame::JJ1SceneFrame(int newFrameType, unsigned char* newFrameData, int newFrameSize) { soundId = 0; frameData = newFrameData; frameType = newFrameType; frameSize = newFrameSize; prev = NULL; next = NULL; } /** * Delete the JJ1 cutscene frame. */ JJ1SceneFrame::~JJ1SceneFrame() { delete [] frameData; } /** * Add a frame to the JJ1 cutscene animation. * * @param frameType The type of the frame * @param frameData The frame's data buffer * @param frameSize The size of the frame's data buffer */ void JJ1SceneAnimation::addFrame(int frameType, unsigned char* frameData, int frameSize) { JJ1SceneFrame* frame = new JJ1SceneFrame(frameType, frameData, frameSize); if(sceneFrames == NULL) { sceneFrames = frame; } else { frame->prev = lastFrame; lastFrame->next = frame; } lastFrame = frame; frames++; } /** * Create a JJ1 cutscene animation. * * @param newNext The next animation */ JJ1SceneAnimation::JJ1SceneAnimation (JJ1SceneAnimation* newNext) { next = newNext; background = NULL; lastFrame = NULL; sceneFrames = NULL; frames = 0; reverseAnimation = 0; } /** * Delete the JJ1 cutscene animation. */ JJ1SceneAnimation::~JJ1SceneAnimation () { if (next) delete next; if(sceneFrames) { JJ1SceneFrame* frame = sceneFrames; JJ1SceneFrame* nextFrame = NULL; while(frame) { nextFrame = frame->next; delete frame; frame = NULL; frame = nextFrame; } } if (background) SDL_FreeSurface(background); } /** * Create a JJ1 cutscene image. * * @param newNext The next image */ JJ1SceneImage::JJ1SceneImage (JJ1SceneImage *newNext) { next = newNext; image = NULL; } /** * Delete the JJ1 cutscene image. */ JJ1SceneImage::~JJ1SceneImage () { if (next) delete next; if (image) SDL_FreeSurface(image); } /** * Create a JJ1 cutscene palette. * * @param newNext The next palette */ JJ1ScenePalette::JJ1ScenePalette (JJ1ScenePalette *newNext) { next = newNext; } /** * Delete the JJ1 cutscene palette. */ JJ1ScenePalette::~JJ1ScenePalette () { if (next) delete next; } /** * Create a JJ1 cutscene text object. */ JJ1SceneText::JJ1SceneText() { x = -1; y = -1; textRect.x = -1; textRect.y = -1; extraLineHeight = -1; text = NULL; shadowColour = 0; } /** * Delete the JJ1 cutscene text object. */ JJ1SceneText::~JJ1SceneText() { if (text) delete[] text; } /** * Create a JJ1 cutscene page. */ JJ1ScenePage::JJ1ScenePage() { pageTime = 0; nTexts = 0; backgrounds = 0; musicFile = NULL; paletteIndex = 0; askForYesNo = 0; stopMusic = 0; animIndex = -1; // no anim backgroundFade = 255; } /** * Delete the JJ1 cutscene page. */ JJ1ScenePage::~JJ1ScenePage() { if (musicFile) delete[] musicFile; } /** * Create a JJ1 cutscene. * * @param fileName Name of the file containing the cutscene data */ JJ1Scene::JJ1Scene (const char * fileName) { File *file; int loop; nFonts = 0; LOG("\nScene", fileName); try { file = new File(fileName, false); } catch (int e) { throw e; } images = NULL; palettes = NULL; animations = NULL; file->seek(0x13, true); // Skip Digital Dimensions header signed long int dataOffset = file->loadInt(); //get offset pointer to first data block scriptItems = file->loadShort(); // Get number of script items scriptStarts = new signed long int[scriptItems]; pages = new JJ1ScenePage[scriptItems]; LOG("Scene: Script items", scriptItems); for (loop = 0; loop < scriptItems; loop++) { scriptStarts[loop] = file->loadInt();// Load offset to script LOG("scriptStart", scriptStarts[loop]); } // Seek to datastart now file->seek(dataOffset, true); // Seek to data offsets dataItems = file->loadShort() + 1; // Get number of data items LOG("Scene: Data items", dataItems); dataOffsets = new signed long int[dataItems]; for (loop = 0; loop < dataItems; loop++) { dataOffsets[loop] = file->loadInt();// Load offset to script LOG("dataOffsets", dataOffsets[loop]); } loadData(file); loadScripts(file); delete[] scriptStarts; delete[] dataOffsets; delete file; return; } /** * Delete the JJ1 cutscene. */ JJ1Scene::~JJ1Scene () { delete[] pages; if (images) delete images; if (palettes) delete palettes; if (animations) delete animations; } /** * Play the JJ1 cutscene. * * @return Error code */ int JJ1Scene::play () { SDL_Rect dst; unsigned int sceneIndex = 0; JJ1SceneImage *image; JJ1SceneAnimation* animation = NULL; JJ1SceneFrame* currentFrame = NULL; PaletteEffect* paletteEffect = NULL; int frameDelay = 0; int prevFrame = 0; int continueToNextPage = 0; unsigned int pageTime = pages[sceneIndex].pageTime; unsigned int lastTicks = globalTicks; int newpage = true; SDL_Rect textRect = {0, 0, SW, SH}; video.clearScreen(0); while (true) { bool upOrLeft = false; bool downOrRight = false; int x, y; if (loop(NORMAL_LOOP, paletteEffect) == E_QUIT) { if (paletteEffect) delete paletteEffect; return E_QUIT; } controls.getCursor(x, y); x -= (canvasW - SW) >> 1; y -= (canvasH - SH) >> 1; downOrRight = controls.wasCursorReleased(); if (controls.release(C_ESCAPE) || (controls.release(C_NO) && pages[sceneIndex].askForYesNo) || (downOrRight && (x >= 0) && (x < 100) && (y >= SH - 12) && (y < SH))) { if (paletteEffect) delete paletteEffect; return E_NONE; } SDL_Delay(T_MENU_FRAME); if(pages[sceneIndex].askForYesNo) { downOrRight |= controls.release(C_ENTER) || controls.release(C_YES); } else { upOrLeft = (controls.release(C_UP) || controls.release(C_LEFT)); downOrRight |= (controls.release(C_RIGHT) || controls.release(C_DOWN) || controls.release(C_ENTER)); } if ((sceneIndex > 0 && upOrLeft) || downOrRight || continueToNextPage || ((globalTicks-lastTicks) >= pageTime * 1000 && pageTime != 256 && pageTime != 0)) { if(pages[sceneIndex].stopMusic) { stopMusic(); } if (upOrLeft) sceneIndex--; else sceneIndex++; if (sceneIndex == scriptItems) { if (paletteEffect) delete paletteEffect; return E_NONE; } lastTicks = globalTicks; // Get bg for this page newpage = true; pageTime = pages[sceneIndex].pageTime; continueToNextPage = 0; } if (newpage) { //if (paletteEffect) delete paletteEffect; //paletteEffect = new FadeOutPaletteEffect(250, NULL); textRect.x = 0; textRect.y = 0; textRect.w = SW; textRect.h = SH; JJ1ScenePalette *palette = palettes; while (palette && (palette->id != pages[sceneIndex].paletteIndex)) palette = palette->next; if (palette) { video.setPalette(palette->palette); // Fade in from black if (paletteEffect) delete paletteEffect; paletteEffect = new FadeInPaletteEffect(250, NULL); } if(pages[sceneIndex].musicFile) { playMusic(pages[sceneIndex].musicFile); } newpage = 0; } // First draw the backgrounds associated with this page if (pages[sceneIndex].backgrounds > 0) { for (int bg = 0; bg < pages[sceneIndex].backgrounds; bg++) { image = images; while (image && (image->id != pages[sceneIndex].bgIndex[bg])) image = image->next; if (image) { dst.x = pages[sceneIndex].bgX[bg] + ((canvasW - SW) >> 1); dst.y = pages[sceneIndex].bgY[bg] + ((canvasH - SH) >> 1); SDL_BlitSurface(image->image, NULL, canvas, &dst); } } } else if (pages[sceneIndex].animIndex != -1) { if (currentFrame == NULL) { animation = animations; while (animation && (animation->id != pages[sceneIndex].animIndex)) animation = animation->next; if (animation && animation->background) { dst.x = (canvasW - SW) >> 1; dst.y = (canvasH - SH) >> 1; frameDelay = 1000 / (pages[sceneIndex].animSpeed >> 8); SDL_BlitSurface(animation->background, NULL, canvas, &dst); currentFrame = animation->sceneFrames; SDL_Delay(frameDelay); } } else { // Upload pixel data to the surface if (SDL_MUSTLOCK(animation->background)) SDL_LockSurface(animation->background); switch (currentFrame->frameType) { case ESquareAniHeader: loadCompactedMem(currentFrame->frameSize, currentFrame->frameData, (unsigned char*)animation->background->pixels); break; case EFFAniHeader: loadFFMem(currentFrame->frameSize, currentFrame->frameData, (unsigned char*)animation->background->pixels); break; default: LOG("Scene::Play unknown type", currentFrame->frameType); break; } if (SDL_MUSTLOCK(animation->background)) SDL_UnlockSurface(animation->background); dst.x = (canvasW - SW) >> 1; dst.y = (canvasH - SH) >> 1; SDL_BlitSurface(animation->background, NULL, canvas, &dst); playSound(currentFrame->soundId); if (prevFrame) currentFrame = currentFrame->prev; else currentFrame = currentFrame->next; SDL_Delay(frameDelay); if (currentFrame == NULL && animation->reverseAnimation) { //prevFrame = 1 - prevFrame; /*if(prevFrame) currentFrame = lastFrame->prev; else currentFrame = lastFrame->next;*/ currentFrame = NULL;//animation->sceneFrames; } else if (currentFrame == NULL && !pageTime && !pages[sceneIndex].askForYesNo && pages[sceneIndex].nextPageAfterAnim) { continueToNextPage = 1; } } } else video.clearScreen(0); // Draw the texts associated with this page x = 0; y = 0; int extraLineHeight = 0; for (int count = 0; count < pages[sceneIndex].nTexts; count++) { JJ1SceneText *text = pages[sceneIndex].texts + count; Font *font = NULL; int xOffset, yOffset; for (int index = 0; index < nFonts; index++) { if (text->fontId == fonts[index].id) { font = fonts[index].font; continue; } } if (text->x != -1) { x = text->x; y = text->y; } if (text->textRect.x != -1) { textRect = text->textRect; x = 0; y = 0; } if (text->extraLineHeight != -1) { extraLineHeight = text->extraLineHeight; } xOffset = ((canvasW - SW) >> 1) + textRect.x + x; yOffset = ((canvasH - SH) >> 1) + textRect.y + y; switch (text->alignment) { case 0: // left break; case 1: // right xOffset += textRect.w - font->getSceneStringWidth(text->text); break; case 2: // center xOffset += (textRect.w - font->getSceneStringWidth(text->text)) >> 1; break; } // Drop shadow font->mapPalette(0, 256, 0, 1); font->showSceneString(text->text, xOffset + 1, yOffset + 1); font->restorePalette(); // Text itself font->showSceneString(text->text, xOffset, yOffset); y += extraLineHeight + font->getHeight() / 2; } } return E_NONE; } openjazz-20190106/src/jj1scene/jj1scene.h000066400000000000000000000116321341440264100177640ustar00rootroot00000000000000 /** * * @file jj1scene.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created scene.c * - 3rd February 2009: Created scene.h from parts of scene.c * - 1st August 2012: Renamed scene.h to jj1scene.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _SCENE_H #define _SCENE_H #include "io/file.h" // Enums /** * Cutscene file animation headers 11 1L /0/0 PB FF RN RB RC RL RR ][ PL AN _E MX ST SL */ enum ANIHeaders { E11AniHeader = 0x3131, ///< Background/start image E1LAniHeader = 0x4c31, EPBAniHeader = 0x4250, EFFAniHeader = 0x4646, ///< Floodfill? or full frame? ERNAniHeader = 0x4e52, ERBAniHeader = 0x4252, ERCAniHeader = 0x4352, ERLAniHeader = 0x4c52, ERRAniHeader = 0x5252, E_EHeader = 0x455F, ///< ANI End ESquareAniHeader = 0x5b5d, EMXAniHeader = 0x584d, ESTAniHeader = 0x5453, ///< Sound tag ESoundListAniHeader = 0x4C53, EPlayListAniHeader = 0x4C50 }; /// Cutscene script types - these are the known types enum { ESceneYesNo = 0x23, ESceneMusic = 0x2A, ESceneStopMusic = 0x2D, ESceneFadeType = 0x3F, ESceneTextBlock = 0x40, ESceneTextColour = 0x41, ESceneFontFun = 0x45, ESceneFontIndex = 0x46, ESceneTextPosition = 0x47, ESceneTextAlign = 0x4A, ESceneTextAlign2 = 0x4B, ESceneBackground = 0x4c, ESceneBreaker = 0x50, ESceneSomethingElse = 0x51, ESceneTextRect = 0x57, ESceneFontDefine = 0x58, ESceneTime = 0x5d, ESceneTextLine = 0x5e, ESceneTextVAdjust = 0x5f, ESceneAnimationPlayAndContinue = 0xA7, ESceneAnimation = 0xA6, ESceneBackgroundFade = 0xb1, ESceneTextSomething = 0xd9, ESceneTextShadow = 0xdb }; // Classes class Font; /// Cutscene page text class JJ1SceneText { public: unsigned char* text; int alignment; int fontId; int x; int y; SDL_Rect textRect; int extraLineHeight; int shadowColour; JJ1SceneText (); ~JJ1SceneText (); }; /// Cutscene page class JJ1ScenePage { public: int backgrounds; int bgIndex[30]; unsigned short int bgX[30]; unsigned short int bgY[30]; int animLoops; int animSpeed; int animIndex; int nextPageAfterAnim; /// Length of the scene in seconds, or if zero = anim complete, or 256 = user interaction int pageTime; JJ1SceneText texts[100]; int nTexts; char* musicFile; int paletteIndex; int askForYesNo; int stopMusic; int backgroundFade; JJ1ScenePage (); ~JJ1ScenePage (); }; /// Cutscene background image class JJ1SceneImage { public: JJ1SceneImage* next; SDL_Surface* image; int id; JJ1SceneImage (JJ1SceneImage* newNext); ~JJ1SceneImage (); }; /// Cutscene palette class JJ1ScenePalette { public: JJ1ScenePalette* next; SDL_Color palette[256]; int id; JJ1ScenePalette (JJ1ScenePalette* newNext); ~JJ1ScenePalette (); }; /// Cutscene font class JJ1SceneFont { public: Font *font; int id; }; /// Cutscene animation frame class JJ1SceneFrame { public: JJ1SceneFrame* next; JJ1SceneFrame* prev; unsigned char* frameData; int frameSize; unsigned int frameType; unsigned char soundId; JJ1SceneFrame (int frameType, unsigned char* frameData, int frameSize); ~JJ1SceneFrame (); }; /// Cutscene animation class JJ1SceneAnimation { public: JJ1SceneAnimation* next; JJ1SceneFrame* sceneFrames; JJ1SceneFrame* lastFrame; SDL_Surface* background; int id; int frames; int reverseAnimation; JJ1SceneAnimation (JJ1SceneAnimation* newNext); ~JJ1SceneAnimation (); void addFrame (int frameType, unsigned char* frameData, int frameSize); }; /// Cutscene class JJ1Scene { private: JJ1SceneAnimation* animations; JJ1SceneImage* images; JJ1ScenePalette* palettes; JJ1SceneFont fonts[5]; int nFonts; unsigned short int scriptItems; unsigned short int dataItems; signed long int* scriptStarts; signed long int* dataOffsets; /// Scripts all information needed to render script pages, text etc JJ1ScenePage* pages; void loadScripts (File* f); void loadData (File* f); void loadAni (File* f, int dataIndex); void loadCompactedMem (int size, unsigned char* frameData, unsigned char* pixdata); void loadFFMem (int size, unsigned char* frameData, unsigned char* pixdata); unsigned short int loadShortMem (unsigned char **data); public: JJ1Scene (const char* fileName); ~JJ1Scene (); int play (); }; #endif openjazz-20190106/src/jj1scene/jj1sceneload.cpp000066400000000000000000000440361341440264100211630ustar00rootroot00000000000000 /** * * @file jj1sceneload.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created scene.c * - 3rd February 2009: Created scene.h from parts of scene.c * - 3rd February 2009: Renamed scene.c to scene.cpp * - 27th March 2010: Created sceneload.cpp from parts of scene.cpp * - 1st August 2012: Renamed sceneload.cpp to jj1sceneload.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading of cutscene data. * */ #include "jj1scene.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" #include /** * Load a short from a buffer and advance the pointer past it. * * @param data Pointer to data in a buffer * * @return The loaded short */ unsigned short int JJ1Scene::loadShortMem (unsigned char** data) { unsigned short int val; val = **data; (*data)++; val += ((unsigned short)(**data)) << 8; (*data)++; return val; } /** * Decompress JJ1 cutscene graphical data. * * @param size The size of the compressed data * @param frameData The compressed data * @param pixels Buffer to contain the decompressed data */ void JJ1Scene::loadFFMem (int size, unsigned char* frameData, unsigned char* pixels) { unsigned char* nextPixel = pixels; unsigned char* nextData = frameData; int fillWidth = 0; unsigned char header; bool trans = true; /*FILE* out = fopen("c:\\output.dat", "wb"); fwrite(frameData, size, 1, out); fclose(out);*/ while ((nextData < frameData + size) && (nextPixel < pixels + (SW * SH))) { header = *nextData; nextData++; LOG("PL FF frame header", header); if ((header & 0x7F) == 0x7F) { fillWidth = loadShortMem(&nextData); if (trans) fillWidth += 255; LOG("PL FF 0x7f skip", fillWidth); } else if (header) { if(trans) { fillWidth = header; LOG("PL FF SKIP bytes", fillWidth); } else { fillWidth = header & 0x1F; switch (header & 0x60) { default: break; case 0x00: LOG("PL FF 0x00 Copy bytes", header); memcpy(nextPixel, nextData, fillWidth); nextData += fillWidth; break; case 0x20: LOG("PL FF 0x20 copy previous line op", fillWidth); if (nextPixel - 320 >= pixels) memcpy(nextPixel, nextPixel - 320, fillWidth); break; case 0x40: LOG("PL FF 0x40 fillWidth", fillWidth); memset(nextPixel, *nextData, fillWidth); nextData++; break; case 0x60: LOG("PL FF 0x60 header", header); fillWidth = header&0x3F; memset(nextPixel, *nextData, fillWidth); nextData++; break; } } } else { LOG("PL FF FAULTY END OF STREAM", size); return; } nextPixel += fillWidth; if (header & 0x80) trans = false; else trans = !trans; } LOG("PL FF pixels", nextPixel - pixels); } /* * $0x $... Next x + 1 bytes are 'literals'; each byte colors 1 column (Max val $3F) * $4x $yy Next x + 1 columns drawn in color yy (Max value $7E) * $7F $xxxx $yy Next xxxx columns colored with color yy * $8x Next x + 1 pixels are skipped, they're already the right color (Max val $FE) * $FF $xxxx Skip next xxxx pixels of picture, they're already the right color */ /** * Decompress JJ1 cutscene graphical data. * * @param size The size of the compressed data * @param frameData The compressed data * @param pixels Buffer to contain the decompressed data */ void JJ1Scene::loadCompactedMem (int size, unsigned char* frameData, unsigned char* pixels) { unsigned char* nextPixel = pixels; unsigned char* endpixdata = pixels + (SW * SH); unsigned char* fillstart = NULL; int fillWidth = 0; unsigned char header; while (size > 0) { header = *frameData; frameData++; if (header == 0x7F) { fillWidth = loadShortMem(&frameData); unsigned char fillColor = *frameData; frameData++; fillstart = nextPixel; while (fillstart + fillWidth <= endpixdata) { memset(fillstart, fillColor, fillWidth); fillstart += SW; } size -= 3; } else if (header == 0xFF) { fillWidth = loadShortMem(&frameData); size -= 2; } else if (header & 0x80) { fillWidth = (header - 0x80) + 1; } else if (header & 0x40) { unsigned char fillColor = *frameData; frameData++; fillWidth = (header - 0x40) + 1; fillstart = nextPixel; while (fillstart + fillWidth <= endpixdata) { memset(fillstart, fillColor, fillWidth); fillstart += SW; } size--; } else { fillWidth = (header & 0x3F) + 1; unsigned char color; for (int col = 0; col < fillWidth; col++) { color = *frameData; frameData++; if (color != 0xFF) { fillstart = nextPixel + col; while (fillstart < endpixdata) { *fillstart = color; fillstart += SW; } } size--; } } nextPixel += fillWidth; size--; } LOG("PL Compacts pixels", nextPixel - pixels); } /** * Load JJ1 cutscene animation. * * @param f File from which to load animation * @param dataIndex Index */ void JJ1Scene::loadAni (File *f, int dataIndex) { LOGRESULT("ParseAni DataLen", f->loadShort()); // should be 0x02 LOGRESULT("ParseAni Frames?", f->loadShort()); // unknown, number of frames? unsigned short int type = 0;// int loop; while (type != EPlayListAniHeader) { type = f->loadShort(); if (type == ESoundListAniHeader) { // SL /*unsigned short int offset =*/ f->loadShort(); unsigned char nSounds = f->loadChar(); for(loop = 0; loop < nSounds; loop++) { char* soundName = f->loadString(); LOG("Soundname ", soundName); resampleSound(loop, soundName, 11025); delete[] soundName; } } else if (type == EPlayListAniHeader) {// PL int nextPos = f->tell(); LOG("PL Read position", nextPos); f->loadShort(); // Length palettes = new JJ1ScenePalette(palettes); f->loadPalette(palettes->palette, false); palettes->id = dataIndex; unsigned short int value = 0; int items = 0; int validValue = true; LOG("PL Read position start", f->tell()); while (validValue) { value = f->loadShort(); LOG("PL Read block start tag", value); int size = f->loadShort(); LOG("PL Anim block size", size); nextPos = f->tell(); // next pos is intial position + size and four bytes header nextPos += size; switch (value) { case E_EHeader: // END MARKER validValue = false; break; case E11AniHeader: //11 // Skip back size header, this is read by the surface reader LOG("PL 11 Background Type", 0); f->seek(-2, false); animations->background = f->loadSurface(SW, SH); // Use the most recently loaded palette video.setPalette(palettes->palette); break; case E1LAniHeader: { LOG("PL 1L Background Type", 0); unsigned char* pixels; pixels = new unsigned char[SW* SH]; memset(pixels, 0, SW*SH); unsigned char* frameData; frameData = f->loadBlock(size); loadCompactedMem(size, frameData, pixels); delete[] frameData; animations->background = createSurface(pixels, SW, SH); delete[] pixels; // Use the most recently loaded palette video.setPalette(palettes->palette); } break; case EFFAniHeader: { unsigned char* blockData = f->loadBlock(size); animations->addFrame(EFFAniHeader, blockData, size); } break; case ERNAniHeader: case ERBAniHeader: case ERLAniHeader: case EMXAniHeader: break; case ERRAniHeader: // Reverse animation when end found animations->reverseAnimation = 1; break; case ERCAniHeader: { unsigned char* blockData = f->loadBlock(size); animations->addFrame(ERCAniHeader, blockData, size); }break; case ESquareAniHeader: // Full screen animation frame, that does n't clear the screen first. { unsigned char* blockData = f->loadBlock(size); animations->addFrame(ESquareAniHeader, blockData, size); } break; case ESTAniHeader: // Sound item { unsigned char soundIndex = f->loadChar(); animations->lastFrame->soundId = soundIndex; LOG("PL Audio tag with index", soundIndex); LOGRESULT("PL Audio tag play at ", f->loadChar()); LOGRESULT("PL Audio tag play offset ", f->loadChar()); } break; case 0: { int longvalue = f->loadInt(); while (longvalue == 0) { longvalue = f->loadInt(); nextPos += 4; } f->seek(-4, false); value = longvalue; } break; default: //LOG("PL Read Unknown type", value); validValue = false; break; } LOG("PL Read position after block should be", nextPos); f->seek(nextPos, true); if(validValue) items++; } LOG("PL Parsed through number of items skipping 0 items", items); LOG("PL Read position after parsing anim blocks", f->tell()); } } } /** * Load JJ1 cutscene data. * * @param f File from which to load the data */ void JJ1Scene::loadData (File *f) { int loop; for (loop = 0; loop < dataItems; loop++) { f->seek(dataOffsets[loop], true); // Seek to data start unsigned short int dataLen = f->loadShort(); // Get get the length of the datablock LOG("Data dataLen", dataLen); // AN if (dataLen == 0x4e41) { LOG("Data Type", "ANI"); animations = new JJ1SceneAnimation(animations); animations->id = loop; loadAni(f, loop); } else { unsigned char type = f->loadChar(); LOG("Data Type", type); switch (type) { case 3: case 4: // image case 5: case 6: { LOG("Data Type", "Image"); LOG("Data Type Image index", loop); unsigned short int width = f->loadShort(SW); // get width unsigned short int height; if (type == 3) height = f->loadChar(); // Get height else height = f->loadShort(SH); // Get height f->seek(-2, false); images = new JJ1SceneImage(images); images->image = f->loadSurface(width, height); images->id = loop; } break; default: LOG("Data Type", "Palette"); LOG("Data Type Palette index", loop); f->seek(-3, false); palettes = new JJ1ScenePalette(palettes); f->loadPalette(palettes->palette); palettes->id = loop; break; } } } } /** * Load JJ1 cutscene scripts. * * @param f File from which to load the scripts */ void JJ1Scene::loadScripts (File *f) { int loop; /*int bgIndex = 0;*/ int textAlignment = 0; int textFont = 0; int textShadow = -1; for(loop = 0; loop < scriptItems; loop++) { LOG("\nParse Script", loop); int textPosX = -1; int textPosY = -1; int extraheight = -1; SDL_Rect textRect = { 0,0,0,0 }; bool textRectValid = false; f->seek(scriptStarts[loop], true); // Seek to data start if (f->loadChar() == 0x50) { // Script tag LOGRESULT("Script id", f->loadShort()); int palette = f->loadShort(); LOG("Script default palette", palette); pages[loop].paletteIndex = palette; unsigned char type = 0; bool breakloop = false; int pos = f->tell(); while(!breakloop && pos < dataOffsets[0]) { type = f->loadChar(); switch(type) { case ESceneYesNo: { pages[loop].askForYesNo = 1; LOG("ESceneYesNo", 1); }break; case ESceneStopMusic: { pages[loop].stopMusic = 1; LOG("ESceneStopMusic", 1); }break; case ESceneAnimation: { pages[loop].animLoops = f->loadInt(); pages[loop].animSpeed = f->loadShort(); pages[loop].animIndex = f->loadShort(); LOG("ESceneAnimation loops", pages[loop].animLoops); LOG("ESceneAnimation speed", pages[loop].animSpeed); LOG("ESceneAnimation anim num", pages[loop].animIndex); } break; case ESceneAnimationPlayAndContinue: { pages[loop].nextPageAfterAnim = f->loadChar(); LOG("ESceneAnimationPlayAndContinue", pages[loop].nextPageAfterAnim); } break; case ESceneFadeType: { LOGRESULT("ESceneFadeType", f->loadChar()); } break; case ESceneBackground: pages[loop].bgX[pages[loop].backgrounds] = f->loadShort(); pages[loop].bgY[pages[loop].backgrounds] = f->loadShort(); pages[loop].bgIndex[pages[loop].backgrounds] = f->loadShort(); LOG("ESceneBackground: xpos", pages[loop].bgX[pages[loop].backgrounds]); LOG("ESceneBackground: ypos", pages[loop].bgY[pages[loop].backgrounds]); LOG("ESceneBackground: index", pages[loop].bgIndex[pages[loop].backgrounds]); pages[loop].backgrounds++; break; case ESceneMusic: // Music file name pages[loop].musicFile = f->loadString(); LOG("ESceneMusic", pages[loop].musicFile); break; case ESceneSomethingElse: { LOG("ESceneSomethingElse", 0); } break; case ESceneTextRect: // String textRect.x = f->loadShort(); textRect.y = f->loadShort(); textRect.w = f->loadShort() - textRect.x; textRect.h = f->loadShort() - textRect.y; textRectValid = true; LOG("Text rectangle xpos", textRect.x); LOG("Text rectangle ypos", textRect.y); LOG("Text rectangle w", textRect.w); LOG("Text rectangle h", textRect.h); break; case ESceneFontDefine: // Font defnition if (nFonts < 5) { fonts[nFonts].id = f->loadShort(); char *fontname = f->loadString(); LOG("ESceneFontDefine", fontname); LOG("ESceneFontDefine with id", fonts[nFonts].id); if (strcmp(fontname, "FONT2") == 0) fonts[nFonts].font = font2; else if (strcmp(fontname, "FONTBIG") == 0) fonts[nFonts].font = fontbig; else if (strcmp(fontname, "FONTTINY") == 0) fonts[nFonts].font = fontiny; else if (strcmp(fontname, "FONTMN1") == 0) fonts[nFonts].font = fontmn1; else if (strcmp(fontname, "FONTMN2") == 0) fonts[nFonts].font = fontmn2; else fonts[nFonts].font = font2; nFonts++; delete[] fontname; } break; case ESceneTextPosition: textPosX = f->loadShort(); textPosY = f->loadShort(); LOG("TextPosition x", textPosX); LOG("TextPosition y", textPosY); break; case ESceneTextColour: { LOGRESULT("ESceneTextColour", f->loadShort()); } break; case ESceneFontFun: { LOGRESULT("ESceneFontFun len", f->loadShort()); /*while (len) { unsigned char data = f->loadChar(); len--; }*/ } break; case ESceneFontIndex: textFont = f->loadShort(); LOG("ESceneFontIndex", textFont); break; case ESceneTextVAdjust: extraheight = f->loadShort(); LOG("ESceneTextVAdjust", extraheight); break; case ESceneBackgroundFade: { pages[loop].backgroundFade = f->loadShort(); LOG("ESceneBackgroundFade", pages[loop].backgroundFade); } break; case ESceneTextShadow: { char enableShadow = f->loadChar(); if(enableShadow) { textShadow = f->loadChar(); } else { f->loadChar(); // Skip this value since shadows are turned off textShadow = -1; // Turn off shadow , -1 means no shadow colour } LOG("ESceneTextShadow", textShadow); } break; case ESceneTextAlign: textAlignment = f->loadChar(); LOG("ESceneTextAlign", textAlignment); break; case ESceneTextAlign2: { LOGRESULT("ESceneTextAlign2 a", f->loadChar()); LOGRESULT("ESceneTextAlign2 b", f->loadShort()); } break; case ESceneTextSomething: { LOGRESULT("ESceneTextSomething a", f->loadChar()); LOGRESULT("ESceneTextSomething b", f->loadShort()); } break; case ESceneTextLine: case ESceneTextBlock: { unsigned char datalen = f->loadChar(); LOG("Text len", datalen); JJ1SceneText *text = pages[loop].texts + pages[loop].nTexts; if (datalen > 0) { text->text = f->loadBlock(datalen + 1); f->seek(-1, false); // Convert number placeholders for (int textPos = 1; textPos < datalen; textPos++) { if (text->text[textPos] == 0x8B) { if (loop >= 9) text->text[textPos - 1] = ((loop + 1) / 10) + 53; text->text[textPos] = ((loop + 1) % 10) + 53; } else if (text->text[textPos] == 0x8A) { if (scriptItems >= 10) text->text[textPos - 1] = (scriptItems / 10) + 53; text->text[textPos] = (scriptItems % 10) + 53; } } text->text[datalen] = 0; } else { text->text = new unsigned char[1]; text->text[0] = 0; } text->alignment = textAlignment; text->fontId = textFont; text->shadowColour = textShadow; if(textPosX != -1) { text->x = textPosX; text->y = textPosY; textPosX = -1; textPosY = -1; } if(textRectValid) { text->textRect = textRect; textRectValid = false; } if(extraheight != -1) { text->extraLineHeight = extraheight; extraheight = -1; } pages[loop].nTexts++; } break; case ESceneTime: pages[loop].pageTime = (f->loadShort()); LOG("Scene time", pages[loop].pageTime); pages[loop].pageTime&=255; break; case ESceneBreaker: case 0x3e: pos = f->tell(); LOG("Parse script end at position", pos); LOG("Parse script end with", type); breakloop = true; f->loadChar(); break; default: pos = f->tell(); LOG("Parse script end at position", pos); LOG("Parse script breaker", type); breakloop = true; break; } pos = f->tell(); } } } } openjazz-20190106/src/jj2level/000077500000000000000000000000001341440264100161215ustar00rootroot00000000000000openjazz-20190106/src/jj2level/jj2event/000077500000000000000000000000001341440264100176505ustar00rootroot00000000000000openjazz-20190106/src/jj2level/jj2event/jj2event.cpp000066400000000000000000000117421341440264100221100ustar00rootroot00000000000000 /** * * @file jj2event.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 29th June 2010: Created jj2level.cpp from parts of level.cpp * - 2nd July 2010: Created jj2event.cpp from parts of jj2level.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creating and freeing of JJ2 events. * */ #include "jj2event.h" #include "level/level.h" /** * Create event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param newProperties Event properties */ JJ2Event::JJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, int newProperties) { x = TTOF(gridX); y = TTOF(gridY); dx = 0; dy = 0; next = newNext; type = newType; properties = newProperties; endTime = 0; flipped = false; return; } /** * Delete all events */ JJ2Event::~JJ2Event () { if (next) delete next; return; } /** * Create pickup event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations * @param newProperties Event properties */ PickupJJ2Event::PickupJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties) : JJ2Event(newNext, gridX, gridY, newType, newProperties) { floating = true; animSet = TSF? 71: 67; return; } /** * Delete pickup event */ PickupJJ2Event::~PickupJJ2Event () { return; } /** * Create ammo pickup event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations */ AmmoJJ2Event::AmmoJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF) : PickupJJ2Event(newNext, gridX, gridY, newType, TSF, 0) { return; } /** * Delete ammo pickup event */ AmmoJJ2Event::~AmmoJJ2Event () { return; } /** * Create coin/gem pickup event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations */ CoinGemJJ2Event::CoinGemJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF) : PickupJJ2Event(newNext, gridX, gridY, newType, TSF, 0) { return; } /** * Delete coin/gem pickup event */ CoinGemJJ2Event::~CoinGemJJ2Event () { return; } /** * Create food pickup event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations */ FoodJJ2Event::FoodJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF) : PickupJJ2Event(newNext, gridX, gridY, newType, TSF, 0) { return; } /** * Delete food pickup event */ FoodJJ2Event::~FoodJJ2Event () { return; } /** * Create spring event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations * @param newProperties Event properties */ SpringJJ2Event::SpringJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties) : JJ2Event(newNext, gridX, gridY, newType, newProperties) { animSet = TSF? 96: 92; return; } /** * Delete spring event */ SpringJJ2Event::~SpringJJ2Event () { return; } /** * Create placeholder event * * @param newNext Next event * @param gridX X-coordinate * @param gridY Y-coordinate * @param newType Event type * @param TSF Whether or not the level uses TSF animations * @param newProperties Event properties */ OtherJJ2Event::OtherJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties) : JJ2Event(newNext, gridX, gridY, newType, newProperties) { animSet = TSF? 71: 67; return; } /** * Delete placeholder event */ OtherJJ2Event::~OtherJJ2Event () { return; } /** * Initiate the destruction of the event * * @param ticks Time */ void JJ2Event::destroy (unsigned int ticks) { endTime = ticks + 500; return; } /** * Get the event's type * * @return Event type */ unsigned char JJ2Event::getType () { return type; } /** * Delete this event * * @return The next event */ JJ2Event* JJ2Event::remove () { JJ2Event *oldNext; oldNext = next; next = NULL; delete this; return oldNext; } openjazz-20190106/src/jj2level/jj2event/jj2event.h000066400000000000000000000066261341440264100215620ustar00rootroot00000000000000 /** * * @file jj2event.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 29th June 2010: Created jj2level.h from parts of level.h * - 2nd July 2010: Created jj2event.h from parts of jj2level.h * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _JJ2EVENT_H #define _JJ2EVENT_H #include "level/movable.h" // Classes class Anim; /// JJ2 level "movable" event class JJ2Event : public Movable { private: JJ2Event* next; protected: unsigned char type; int properties; ///< Event-specific options unsigned int endTime; ///< Point at which the event will terminate bool flipped; ///< Whether or not the sprite image should be flipped JJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, int newProperties); void destroy (unsigned int ticks); bool prepareStep (unsigned int ticks, int msps); bool prepareDraw (unsigned int ticks, int change); JJ2Event* remove (); public: virtual ~JJ2Event (); unsigned char getType (); virtual JJ2Event* step (unsigned int ticks, int msps) = 0; virtual void draw (unsigned int ticks, int change) = 0; }; /// JJ2 level pickup event class PickupJJ2Event : public JJ2Event { private: bool floating; protected: unsigned char animSet; PickupJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties); virtual ~PickupJJ2Event (); JJ2Event* step (unsigned int ticks, int msps); }; /// JJ2 level ammo class AmmoJJ2Event : public PickupJJ2Event { public: AmmoJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF); ~AmmoJJ2Event (); void draw (unsigned int ticks, int change); }; /// JJ2 level gold/silver coin class CoinGemJJ2Event : public PickupJJ2Event { private: void mapPalette (Anim* anim, int start); public: CoinGemJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF); ~CoinGemJJ2Event (); void draw (unsigned int ticks, int change); }; /// JJ2 level food class FoodJJ2Event : public PickupJJ2Event { public: FoodJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF); ~FoodJJ2Event (); void draw (unsigned int ticks, int change); }; /// JJ2 level spring class SpringJJ2Event : public JJ2Event { private: unsigned char animSet; public: SpringJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties); ~SpringJJ2Event (); JJ2Event* step (unsigned int ticks, int msps); void draw (unsigned int ticks, int change); }; /// Unimplemented JJ2 level event class OtherJJ2Event : public JJ2Event { private: unsigned char animSet; public: OtherJJ2Event (JJ2Event* newNext, int gridX, int gridY, unsigned char newType, bool TSF, int newProperties); ~OtherJJ2Event (); JJ2Event* step (unsigned int ticks, int msps); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj2level/jj2event/jj2eventframe.cpp000066400000000000000000000252521341440264100231240ustar00rootroot00000000000000 /** * * @file jj2eventframe.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 29th June 2010: Created jj2level.cpp from parts of level.cpp * - 2nd July 2010: Created jj2eventframe.cpp from parts of jj2level.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the playing of JJ2 levels. * */ #include "jj2event.h" #include "../jj2level.h" #include "../jj2levelplayer/jj2levelplayer.h" #include "io/gfx/anim.h" #include "io/gfx/font.h" #include "io/gfx/video.h" /// Look-up table for ammo animations (in animSet 0) const unsigned char ammoAnims[] = { 29, // Ice 25, // Bouncer 34, // Seeker 49, // RF 57, // Toaster 59, // TNT 62, // Pellets 69 // Sparks }; /// Look-up table for food etc. animations (in animSet 67/71) const unsigned char pickupAnims[] = { 0, // 0 0, // 1 0, // 2 0, // 3 0, // 4 0, // 5 0, // 6 0, // 7 0, // 8 0, // 9 0, // 10 0, // 11 0, // 12 0, // 13 0, // 14 0, // 15 0, // 16 0, // 17 0, // 18 0, // 19 0, // 20 0, // 21 0, // 22 0, // 23 0, // 24 0, // 25 0, // 26 0, // 27 0, // 28 0, // 29 0, // 30 0, // 31 0, // 32 0, // 33 0, // 34 0, // 35 0, // 36 0, // 37 0, // 38 0, // 39 0, // 40 0, // 41 0, // 42 0, // 43 84, // Silver coin 37, // Gold coin 0, // 46 0, // 47 0, // 48 0, // 49 0, // 50 0, // 51 0, // 52 55, // Ice crate 54, // Bouncer crate 56, // Seeker crate 57, // RF crate 58, // Toaster crate 90, // Armed TNT 36, // Board 0, // 60 29, // Rapid fire (can also be 30) 0, // 62 35, // Red gem 35, // Green gem 35, // Blue gem 35, // Purple gem 34, // Large red gem 0, // 68 3, // Ammo barrel 0, // 70 0, // 71 82, // Energy 72, // Full energy 31, // Fire shield 10, // Bubble shield 51, // Plasma shield 0, // 77 0, // 78 33, // High jump 0, // 1-up 28, // exit signpost 0, // 82 14, // Checkpoint 0, // 84 0, // 85 0, // 86 0, // 87 0, // 88 87, // Extra time 42, // Freeze 0, // 91 0, // 92 0, // 93 0, // 94 52, // Trigger crate 0, // 96 0, // 97 0, // 98 0, // 99 0, // 100 0, // 101 0, // 102 0, // 103 0, // 104 0, // 105 0, // 106 0, // 107 0, // 108 0, // 109 0, // 110 0, // 111 0, // 112 0, // 113 0, // 114 0, // 115 0, // 116 0, // 117 0, // 118 0, // 119 0, // 120 0, // 121 0, // 122 0, // 123 0, // 124 0, // 125 0, // 126 0, // 127 0, // 128 0, // 129 0, // 130 60, // Blaster PU (can also be 83) 61, // Bouncer PU 62, // Ice PU 63, // Seeker PU 64, // RF PU 65, // Toaster PU 0, // 137 0, // 138 0, // 139 0, // 140 1, // Apple 2, // Banana 16, // Cherry 71, // Orange 74, // Pear 79, // Pretzel 81, // Strawberry 0, // 148 0, // 149 0, // 150 0, // 151 0, // 152 0, // 153 48, // Lemon 50, // Lime 89, // Thing 92, // Watermelon 73, // Peach 38, // Grapes 49, // Lettuce 26, // Aubergine 23, // Cucumber 75, // Jazzade 20, // Cola 53, // Milk 76, // Tart 12, // Cake 25, // Doughnut 24, // Cupcake 18, // Crisps 13, // Sweet 19, // Chocolate 43, // Ice cream 11, // Burger 77, // Pizza 32, // Chips 17, // Chicken drumstick 80, // Sandwich 88, // Taco 91, // Hot dog 39, // Ham 15, // Cheese 0, // 183 0, // 184 0, // 185 0, // 186 0, // 187 0, // 188 0, // 189 0, // 190 0, // 191 0, // 192 0, // 193 0, // 194 0, // 195 0, // 196 0, // 197 0, // 198 0, // 199 0, // 200 0, // 201 0, // 202 0, // 203 0, // 204 0, // 205 0, // 206 0, // 207 0, // 208 0, // 209 0, // 210 0, // 211 0, // 212 0, // 213 0, // 214 0, // 215 0, // 216 0, // 217 0, // 218 0, // 219 66, // Pellet PU 67, // Sparks PU }; /** * Functionality required by all event types on each iteration * * @param ticks Time * @param msps Ticks per step * * @return Whether or not the event should be deleted */ bool JJ2Event::prepareStep (unsigned int ticks, int msps) { JJ2LevelPlayer *levelPlayer; int count; // Process next event(s) if (next) next = next->step(ticks, msps); // If the reaction time has expired if (endTime && (ticks > endTime)) { return true; } if (endTime) return false; // Handle contact with player for (count = 0; count < nPlayers; count++) { levelPlayer = players[count].getJJ2LevelPlayer(); // Check if the player is touching the event if (levelPlayer->overlap(x, y, F32, F32)) { // If the player picks up the event, destroy it if (levelPlayer->touchEvent(this, ticks, msps)) destroy(ticks); } } return false; } /** * Functionality required by all event types on each draw * * @param ticks Time * @param change Time since last iteration * * @return Whether or not the event shouldn't be drawn */ bool JJ2Event::prepareDraw (unsigned int ticks, int change) { // Draw next event(s) if (next) next->draw(ticks, change); // Don't draw if too far off-screen if ((x < viewX - F64) || (y < viewY - F64) || (x > viewX + ITOF(canvasW) + F64) || (y > viewY + ITOF(canvasH) + F64)) return true; return false; } /** * Pickup event iteration. * * @param ticks Time * @param msps Ticks per step * * @return Remaining event */ JJ2Event* PickupJJ2Event::step (unsigned int ticks, int msps) { if (prepareStep(ticks, msps)) return remove(); if (!floating) { if (jj2Level->checkMaskDown(x, y + F4, false)) { dy += 1000 / msps; } else { dy = 0; } } else { /// @todo Check for bullet overlap // floating = false; } return this; } /** * Draw ammo pickup event. * * @param ticks Time * @param change Time since last iteration */ void AmmoJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); /// @todo Check if ammo is powered up if (!endTime) an = jj2Level->getAnim(0, ammoAnims[type - 33], flipped); else an = jj2Level->getAnim(animSet, 86, flipped); an->setFrame((int)ticks / 60, true); an->draw(drawX + F16, drawY + F16 + F32); return; } /** * Map gem animation's palette. * * @param anim Gem animation * @param start Index of first colour */ void CoinGemJJ2Event::mapPalette (Anim* anim, int start) { SDL_Color palette[256]; int count; for (count = 0; count < 112; count++) palette[count + 128].r = palette[count + 128].g = palette[count + 128].b = start + 6 - (count >> 4); for (; count < 128; count++) palette[count + 128].r = palette[count + 128].g = palette[count + 128].b = 255; anim->setPalette(palette, 128, 128); return; } /** * Draw coin/gem pickup event. * * @param ticks Time * @param change Time since last iteration */ void CoinGemJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); if (endTime) { an = jj2Level->getAnim(animSet, 86, flipped); an->setFrame((int)ticks / 60, true); an->draw(drawX + F16, drawY + F16 + F32); } if (type == 44) an = jj2Level->getAnim(animSet, 84, flipped); // Silver coin else if (type == 45) an = jj2Level->getAnim(animSet, 37, flipped); // Gold coin else an = jj2Level->getAnim(animSet, 35, flipped); // Gem an->setFrame((int)ticks / 60, true); switch (type) { case 63: // Red gem mapPalette(an, 48); break; case 64: // Green gem mapPalette(an, 80); break; case 65: // Blue gem mapPalette(an, 32); break; case 66: // Purple gem mapPalette(an, 88); break; } if (endTime) { drawX += (ticks + 500 - endTime) << 8; drawY += (ticks + 500 - endTime) << 10; } an->draw(drawX + F16, drawY + F16 + F32); return; } /** * Draw food pickup event. * * @param ticks Time * @param change Time since last iteration */ void FoodJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); // Use look-up table if (!endTime) an = jj2Level->getAnim(animSet, pickupAnims[type], flipped); else an = jj2Level->getAnim(animSet, 86, flipped); an->setFrame((int)ticks / 60, true); an->draw(drawX + F16, drawY + F16 + F32); return; } /** * Spring event iteration. * * @param ticks Time * @param msps Ticks per step * * @return Remaining event */ JJ2Event* SpringJJ2Event::step (unsigned int ticks, int msps) { if (prepareStep(ticks, msps)) return remove(); if (!jj2Level->checkMaskDown(x, y + F1, true)) y += F1; return this; } /** * Draw spring event. * * @param ticks Time * @param change Time since last iteration */ void SpringJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); switch (type) { case 60: // Frozen green spring an = jj2Level->getAnim(animSet, 5, flipped); break; case 62: // Spring crate an = jj2Level->getAnim(animSet, 0, flipped); break; case 85: // Red spring an = jj2Level->getAnim(animSet, 7, flipped); break; case 86: // Green spring an = jj2Level->getAnim(animSet, 5, flipped); break; case 87: // Blue spring an = jj2Level->getAnim(animSet, 0, flipped); break; default: return; } an->setFrame(0, true); an->draw(drawX + F16, drawY + F16); return; } /** * Placeholder event iteration. * * @param ticks Time * @param msps Ticks per step * * @return Remaining event */ JJ2Event* OtherJJ2Event::step (unsigned int ticks, int msps) { if (prepareStep(ticks, msps)) return remove(); return this; } /** * Draw placeholder event. * * @param ticks Time * @param change Time since last iteration */ void OtherJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); switch (type) { default: if ((type <= 221) && pickupAnims[type]) { an = jj2Level->getAnim(animSet, pickupAnims[type], flipped); an->setFrame((int)ticks / 60, true); an->draw(drawX + F16, drawY + F16 + F32); } else if (!endTime) { drawRect(FTOI(drawX) + 8, FTOI(drawY) + 8, 16, 16, type); } panelBigFont->showNumber(type, FTOI(drawX) + 24, FTOI(drawY) + 12); return; } an->draw(drawX + F16, drawY + F16); return; } openjazz-20190106/src/jj2level/jj2layer.cpp000066400000000000000000000114061341440264100203510ustar00rootroot00000000000000 /** * * @file jj2layer.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Created levelframe.cpp from parts of level.cpp * - 29th June 2010: Created jj2levelframe.cpp from parts of levelframe.cpp * - 30th June 2010: Created jj2layer.cpp from parts of jj2levelframe.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Handles JJ2 level layers. * */ #include "jj2level.h" #include "io/gfx/video.h" /** * Create a blank 1-by-1 layer. */ JJ2Layer::JJ2Layer () { width = height = 1; grid = new JJ2Tile *[1]; *grid = new JJ2Tile[1]; (*grid)->tile = 0; return; } /** * Create a blank layer. * * @param newWidth The width of the layer (in tiles) * @param newHeight The height of the layer (in tiles) * @param newXSpeed The relative horizontal speed of the layer * @param newYSpeed The relative vertical speed of the layer * @param flags Layer flags */ JJ2Layer::JJ2Layer (int flags, int newWidth, int newHeight, fixed newXSpeed, fixed newYSpeed) { int row; width = newWidth; height = newHeight; grid = new JJ2Tile *[height]; *grid = new JJ2Tile[width * height]; for (row = 0; row < height; row++) grid[row] = *grid + (row * width); tileX = flags & 1; tileY = flags & 2; limit = flags & 4; warp = flags & 8; xSpeed = newXSpeed; ySpeed = newYSpeed; return; } /** * Delete the layer. */ JJ2Layer::~JJ2Layer () { delete[] *grid; delete[] grid; return; } /** * Get flipped. We aim to offend! * * @param x The x-coordinate of the tile (in tiles) * @param y The y-coordinate of the tile (in tiles) * * @return Whether or not the tile is flipped horizontally */ bool JJ2Layer::getFlipped (int x, int y) { if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return false; return grid[y][x].flipped; } /** * Get the height of the layer. * * @return The height of the layer (in tiles) */ int JJ2Layer::getHeight () { return height; } /** * Get the tile for the given co-ordinates. * * @param x The x-coordinate of the tile (in tiles) * @param y The y-coordinate of the tile (in tiles) * * @return The number of the tile */ int JJ2Layer::getTile (int x, int y) { if ((x < 0) || (y < 0)) return 0; if ((x >= width) && !tileX) return 0; if ((y >= height) && !tileY) return 0; return grid[y % height][x % width].tile; } /** * Get the width of the layer. * * @return The width of the layer (in tiles) */ int JJ2Layer::getWidth () { return width; } /** * Set the frame of the tile at the given co-ordinates. * * @param x The x-coordinate of the tile (in tiles) * @param y The y-coordinate of the tile (in tiles) * @param frame The new frame */ void JJ2Layer::setFrame (int x, int y, unsigned char frame) { grid[y][x].frame = frame; return; } /** * Set the tile at the given co-ordinates. * * @param x The x-coordinate of the tile (in tiles) * @param y The y-coordinate of the tile (in tiles) * @param tile The number of the tile * @param TSF Whether or not this is a TSF tile * @param tiles The total number of tiles */ void JJ2Layer::setTile (int x, int y, unsigned short int tile, bool TSF, int tiles) { JJ2Tile* ge; ge = grid[y] + x; if (TSF) { ge->flipped = tile & 0x1000; ge->tile = tile & 0xFFF; } else { ge->flipped = tile & 0x400; ge->tile = tile & 0x3FF; } if (ge->tile > tiles) ge->tile = 0; ge->frame = 0; return; } /** * Draw the layer. * * @param tileSet The tile set to use for non-flipped tiles * @param flippedTileSet The tile set to use for flipped tiles */ void JJ2Layer::draw (SDL_Surface* tileSet, SDL_Surface* flippedTileSet) { SDL_Rect src, dst; int vX, vY; int x, y; // Set tile drawing dimensions src.w = TTOI(1); src.h = TTOI(1); src.x = 0; // Calculate the layer view vX = FTOI(FTOI(viewX) * xSpeed); vY = FTOI(FTOI(viewY) * ySpeed); if (limit) { if (!tileX) { if (vX + canvasW > TTOI(width)) vX = TTOI(width) - canvasW; } if (!tileY) { vY -= canvasH - SH; if (vY + canvasH > TTOI(height)) vY = TTOI(height) - canvasH; } } for (y = 0; y <= ITOT(canvasH - 1) + 1; y++) { for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) { dst.x = TTOI(x) - (vX & 31); dst.y = TTOI(y) - (vY & 31); src.y = TTOI(getTile(x + ITOT(vX), y + ITOT(vY))); if (src.y) SDL_BlitSurface(getFlipped(x + ITOT(vX), y + ITOT(vY))? flippedTileSet: tileSet, &src, canvas, &dst); } } return; } openjazz-20190106/src/jj2level/jj2level.cpp000066400000000000000000000232751341440264100203530ustar00rootroot00000000000000 /** * * @file jj2level.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 29th June 2010: Created jj2level.cpp from parts of level.cpp * - 2nd July 2010: Created jj2event.cpp from parts of jj2level.cpp * - 2nd July 2010: Created jj2eventframe.cpp from parts of jj2level.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creating, playing and freeing of JJ2 levels. * */ #include "jj2event/jj2event.h" #include "jj2level.h" #include "jj2levelplayer/jj2levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" #include /** * Create a JJ2 level. * * @param owner The current game * @param fileName Name of the file containing the level data. * @param checkpoint Whether or not the player(s) will start at a checkpoint * @param multi Whether or not the level will be multi-player */ JJ2Level::JJ2Level (Game* owner, char* fileName, bool checkpoint, bool multi) : Level(owner) { int ret; // Load level data ret = load(fileName, checkpoint); if (ret < 0) throw ret; multiplayer = multi; return; } /** * Delete the JJ2 level. */ JJ2Level::~JJ2Level () { int count; if (events) delete events; delete[] *mods; delete[] mods; for (count = 0; count < LAYERS; count++) delete layers[count]; delete[] flippedMask; delete[] mask; delete[] musicFile; delete[] nextLevel; for (count = 0; count < nAnimSets; count++) { if (animSets[count]) delete[] animSets[count]; } delete[] animSets; delete[] spriteSet; SDL_FreeSurface(flippedTileSet); SDL_FreeSurface(tileSet); delete font; // Restore panel font palette panelBigFont->restorePalette(); panelSmallFont->restorePalette(); return; } /** * Determine whether or not the given point is solid when travelling upwards. * * @param x X-coordinate * @param y Y-coordinate * * @return Solidity */ bool JJ2Level::checkMaskUp (fixed x, fixed y) { int tX, tY; tX = FTOT(x); tY = FTOT(y); // Anything off the edge of the map is solid if ((x < 0) || (y < 0) || (tX >= layer->getWidth()) || (tY >= layer->getHeight())) return true; // Event 1 is one-way // Event 3 is vine // Event 4 is hook if ((mods[tY][tX].type == 1) || (mods[tY][tX].type == 3) || (mods[tY][tX].type == 4)) return false; // Check the mask in the tile in question return (layer->getFlipped(tX, tY)? flippedMask: mask)[(layer->getTile(tX, tY) << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)]; } /** * Determine whether or not the given point is solid when travelling downwards. * * @param x X-coordinate * @param y Y-coordinate * @param drop Whether or not the player is dropping * * @return Solidity */ bool JJ2Level::checkMaskDown (fixed x, fixed y, bool drop) { int tX, tY; tX = FTOT(x); tY = FTOT(y); // Anything off the edge of the map is solid if ((x < 0) || (y < 0) || (tX >= layer->getWidth()) || (tY >= layer->getHeight())) return true; // Event 3 is vine // Event 4 is hook if (drop && ((mods[tY][tX].type == 3) || (mods[tY][tX].type == 4))) return false; // Check the mask in the tile in question return (layer->getFlipped(tX, tY)? flippedMask: mask)[(layer->getTile(tX, tY) << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)]; } /** * Set which level will come next. * * @param fileName Next level's file name */ void JJ2Level::setNext (char* fileName) { unsigned char buffer[MTL_L_PROP]; delete[] nextLevel; nextLevel = createString(fileName); if (multiplayer) { buffer[0] = MTL_L_PROP; buffer[1] = MT_L_PROP; buffer[2] = 0; // set next level buffer[3] = 0; buffer[4] = 0; game->send(buffer); } return; } /** * Set the frame of the animated tile at the given location. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * @param frame The new frame */ void JJ2Level::setFrame (int gridX, int gridY, unsigned char frame) { unsigned char buffer[MTL_L_GRID]; layer->setFrame(gridX, gridY, frame); if (multiplayer) { buffer[0] = MTL_L_GRID; buffer[1] = MT_L_GRID; buffer[2] = gridX & 0xFF; buffer[3] = gridY & 0xFF; buffer[4] = 0; // tile variable buffer[5] = frame; buffer[6] = (gridX >> 8) & 0xFF; buffer[7] = (gridY >> 8) & 0xFF; game->send(buffer); } return; } /** * Get the modifier event for the given tile. * * @param gridX X-coordinate of the tile * @param gridY Y-coordinate of the tile * * @return Modifier event */ JJ2Modifier* JJ2Level::getModifier (int gridX, int gridY) { return mods[gridY] + gridX; } /** * Get a sprite. * * @param sprite Sprite number * * @return Sprite */ Sprite* JJ2Level::getSprite (unsigned char sprite) { return spriteSet + sprite; } /** * Get an animation. * * @param set Animation set number * @param anim Animation number * @param flipped Whether or not the animation should be flipped horizontally * * @return Animation */ Anim* JJ2Level::getAnim (int set, int anim, bool flipped) { return (flipped? flippedAnimSets: animSets)[set] + anim; } /** * Get a player animation. * * @param character Character * @param anim Animation number * @param flipped Whether or not the animation should be flipped horizontally * * @return Animation */ Anim* JJ2Level::getPlayerAnim (int character, int anim, bool flipped) { int set; if (TSF) { if (character == 1) set = 61; else if (character == 2) set = 89; else set = 55; } else { if (character == 1) set = 85; else set = 54; } return getAnim(set, playerAnims[anim], flipped); } /** * Set the water level. * * @param gridY New water level y-coordinate * @param instant Whether or not the change is instant */ void JJ2Level::setWaterLevel (int gridY, bool instant) { unsigned char buffer[MTL_L_PROP]; waterLevelTarget = TTOF(gridY); if (instant) waterLevel = waterLevelTarget - F8; if (multiplayer) { buffer[0] = MTL_L_PROP; buffer[1] = MT_L_PROP; buffer[2] = 1; // set water level buffer[3] = gridY & 0xFF; buffer[4] = (gridY >> 8) & 0xFF; game->send(buffer); } return; } /** * Determine the water level. * * @return The y-coordinate of the water level */ fixed JJ2Level::getWaterLevel () { return waterLevel; } /** * Move a player to a warp target. * * @param player The player to move * @param id The warp target ID */ void JJ2Level::warp (JJ2LevelPlayer *player, int id) { int x, y; for (y = 0; y < layer->getHeight(); y++) { for (x = 0; x < layer->getWidth(); x++) { if ((mods[y][x].type == 240) && ((mods[y][x].properties & 255) == id)) { player->setPosition(TTOF(x), TTOF(y)); return; } } } } /** * Interpret data received from client/server * * @param buffer Received data */ void JJ2Level::receive (unsigned char* buffer) { switch (buffer[1]) { case MT_L_PROP: if (buffer[2] == 1) { waterLevelTarget = TTOF(buffer[3] + (buffer[4] << 8)); } else if (buffer[2] == 2) { if (stage == LS_NORMAL) endTime += buffer[3] * 1000; } break; case MT_L_GRID: if (buffer[4] == 0) layer->setFrame(buffer[2] + (buffer[6] << 8), buffer[3] + (buffer[7] << 8), buffer[5]); break; case MT_L_STAGE: stage = LevelStage(buffer[2]); break; } return; } /** * Play the level. * * @return Error code */ int JJ2Level::play () { JJ2LevelPlayer* jj2LevelPlayer; bool pmessage, pmenu; int option; unsigned int returnTime; int count, ret; jj2LevelPlayer = localPlayer->getJJ2LevelPlayer(); tickOffset = globalTicks; ticks = T_STEP; steps = 0; pmessage = pmenu = false; option = 0; returnTime = 0; video.setPalette(palette); playMusic(musicFile); while (true) { ret = loop(pmenu, option, pmessage); if (ret < 0) return ret; // Check if level has been won if (game && returnTime && (ticks > returnTime)) { ret = game->setLevel(nextLevel); if (ret < 0) return ret; return WON; } // Process frame-by-frame activity while (getTimeChange() >= T_STEP) { // Apply controls to local player for (count = 0; count < PCONTROLS; count++) localPlayer->setControl(count, controls.getState(count)); ret = step(); steps++; if (ret) return ret; } // Draw the graphics draw(); // If paused, draw "PAUSE" if (pmessage && !pmenu) font->showString("pause", (canvasW >> 1) - 44, 32); // If paused, silence music pauseMusic(pmessage && !pmenu); if (stage == LS_END) { // The level is over, so draw gem counts if (!returnTime) { returnTime = ticks + 3000; playSound(S_UPLOOP); } // Display statistics font->showString("red gems", (canvasW >> 1) - 152, (canvasH >> 1) - 60); font->showNumber(jj2LevelPlayer->getGems(0), (canvasW >> 1) + 124, (canvasH >> 1) - 60); font->showString("green gems", (canvasW >> 1) - 152, (canvasH >> 1) - 40); font->showNumber(jj2LevelPlayer->getGems(1), (canvasW >> 1) + 124, (canvasH >> 1) - 40); font->showString("blue gems", (canvasW >> 1) - 152, (canvasH >> 1) - 20); font->showNumber(jj2LevelPlayer->getGems(2), (canvasW >> 1) + 124, (canvasH >> 1) - 20); } // Draw statistics, menu etc. drawOverlay(JJ2_BLACK, pmenu, option, 71, 31, -8); } return E_NONE; } openjazz-20190106/src/jj2level/jj2level.h000066400000000000000000000161241341440264100200130ustar00rootroot00000000000000 /** * * @file jj2level.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 29th June 2010: Created jj2level.h from parts of level.h * - 2nd July 2010: Created jj2event.h from parts of jj2level.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ /* "Tile" is a flexible term. Here it is used to refer specifically to the individual elements of the tile set. "Tiles" in the context of level units are referred to as grid elements. */ #ifndef _JJ2LEVEL_H #define _JJ2LEVEL_H #include "level/level.h" #include "io/gfx/anim.h" #include "OpenJazz.h" // Constants // Number of layers #define LAYERS 8 // Player animations #define JJ2PA_BOARD 0 #define JJ2PA_BOARDSW 1 #define JJ2PA_STOMP 2 #define JJ2PA_DEAD 3 #define JJ2PA_DIE 4 #define JJ2PA_CROUCH1 5 #define JJ2PA_CROUCHED 6 #define JJ2PA_CROUCHSHOOT 7 #define JJ2PA_CROUCH2 8 #define JJ2PA_VINE 9 #define JJ2PA_EXIT1 10 #define JJ2PA_FALL 11 #define JJ2PA_STOMPING 12 #define JJ2PA_LAND 13 #define JJ2PA_STANDSHOOT 14 #define JJ2PA_STANDSHOOTUP 15 #define JJ2PA_WHIP1 16 #define JJ2PA_UNFROG 17 #define JJ2PA_HOOKWHIP 18 #define JJ2PA_HOOKDIAG 19 #define JJ2PA_HOOKSHOOTUP 20 #define JJ2PA_HOOK1 21 #define JJ2PA_HOOK2 22 #define JJ2PA_HOOKWHIPUP 23 #define JJ2PA_HOOKSHOOT 24 #define JJ2PA_HELI 25 #define JJ2PA_HELIWHIP 26 #define JJ2PA_HELISHOOT 27 #define JJ2PA_HPOLE 28 #define JJ2PA_HURT 29 #define JJ2PA_WAIT1 30 #define JJ2PA_WAIT2 31 #define JJ2PA_WAIT3 32 #define JJ2PA_WAIT4 33 #define JJ2PA_WAIT5 34 #define JJ2PA_FALLWHIP 35 #define JJ2PA_FALLSHOOT 36 #define JJ2PA_FLOAT1 37 #define JJ2PA_FLOAT2 38 #define JJ2PA_UP1 39 #define JJ2PA_EDGE 40 #define JJ2PA_CARRY 41 #define JJ2PA_UNLOAD 42 #define JJ2PA_LOAD 43 #define JJ2PA_LOOKUP 44 #define JJ2PA_WOOZYWALK 45 #define JJ2PA_PUSH 46 #define JJ2PA_WHIP2 47 #define JJ2PA_EXIT2 48 #define JJ2PA_SPEED1 49 #define JJ2PA_SPEED2 50 #define JJ2PA_FALLMOVE 51 #define JJ2PA_JUMP 52 #define JJ2PA_BALL 53 #define JJ2PA_WALKSHOOT 54 #define JJ2PA_RUN 55 #define JJ2PA_SPEEDRUN 56 #define JJ2PA_STOP1 57 #define JJ2PA_MYSTERY 58 #define JJ2PA_STOP2 59 #define JJ2PA_UP2 60 #define JJ2PA_STAND 61 #define JJ2PA_POWER 62 #define JJ2PA_POWEREND 63 #define JJ2PA_POWERSTART 64 #define JJ2PA_WOOZYSTAND 65 #define JJ2PA_SWIMDOWN 66 #define JJ2PA_SWIM 67 #define JJ2PA_SWIMDIAGDOWN 68 #define JJ2PA_SWIMDIAGUP 69 #define JJ2PA_SWIMUP 70 #define JJ2PA_VINESDIAG 71 #define JJ2PA_WARPOUT 72 #define JJ2PA_WARPFALLIN 73 #define JJ2PA_WARPFALL 74 #define JJ2PA_WARPFALLOUT 75 #define JJ2PA_WARPIN 76 #define JJ2PA_VPOLE 77 #define JJ2PANIMS 78 /* Number of player animations. */ // Black palette index #define JJ2_BLACK 0 // Datatypes /// JJ2 level tile typedef struct { unsigned short int tile; ///< Indexes the tile set unsigned char frame; ///< Current frame being used (for animated tiles) bool flipped; ///< Whether or not the tile image and mask are flipped } JJ2Tile; /// JJ2 level tile modifier event typedef struct { unsigned char type; int properties; } JJ2Modifier; // Classes class Font; ///< JJ2 level parallaxing layer class JJ2Layer { private: JJ2Tile** grid; ///< Layer tiles int width; ///< Width (in tiles) int height; ///< Height (in tiles) bool tileX; ///< Repeat horizontally bool tileY; ///< Repeat vertically bool limit; ///< Do not view beyond edges bool warp; ///< Warp effect fixed xSpeed; ///< Relative horizontal speed fixed ySpeed; ///< Relative vertical speed public: JJ2Layer (); JJ2Layer (int flags, int newWidth, int newHeight, fixed newXSpeed, fixed newYSpeed); ~JJ2Layer (); bool getFlipped (int x, int y); int getHeight (); int getTile (int x, int y); int getWidth (); void setFrame (int x, int y, unsigned char frame); void setTile (int x, int y, unsigned short int tile, bool TSF, int tiles); void draw (SDL_Surface* tileSet, SDL_Surface* flippedTileSet); }; class JJ2Event; class JJ2LevelPlayer; /// JJ2 level class JJ2Level : public Level { private: SDL_Surface* tileSet; ///< Tile images SDL_Surface* flippedTileSet; ///< Tile images (flipped) JJ2Event* events; ///< "Movable" events Font* font; ///< On-screen message font char* mask; ///< Tile masks char* flippedMask; ///< Tile masks (flipped) char* musicFile; ///< Music file name char* nextLevel; ///< Next level file name Sprite* spriteSet; ///< Sprite images Sprite* flippedSpriteSet; ///< Sprite images (flipped) Anim** animSets; ///< Animation sets Anim** flippedAnimSets; ///< Animation sets (flipped) char playerAnims[JJ2PANIMS]; ///< Player animations JJ2Layer* layers[LAYERS]; ///< All layers JJ2Layer* layer; ///< Layer 4 JJ2Modifier** mods; ///< Modifier events for each tile in layer 4 int nAnimSets; ///< Number of animation sets bool TSF; ///< 1.24 level fixed waterLevel; ///< Height of water fixed waterLevelTarget; ///< Future height of water fixed waterLevelSpeed; ///< Rate of water level change void createEvent (int x, int y, unsigned char* data); int load (char* fileName, bool checkpoint); void loadSprite (unsigned char* parameters, unsigned char* compressedPixels, Sprite* sprite, Sprite* flippedSprite); int loadSprites (); int loadTiles (char* fileName); int step (); void draw (); public: JJ2Level (Game* owner, char* fileName, bool checkpoint, bool multi); ~JJ2Level (); bool checkMaskDown (fixed x, fixed y, bool drop); bool checkMaskUp (fixed x, fixed y); Anim* getAnim (int set, int anim, bool flipped); Anim* getPlayerAnim (int character, int anim, bool flipped); JJ2Modifier* getModifier (int gridX, int gridY); Sprite* getSprite (unsigned char sprite); fixed getWaterLevel (); void setFrame (int gridX, int gridY, unsigned char frame); void setNext (char* fileName); void setWaterLevel (int gridY, bool instant); void warp (JJ2LevelPlayer *player, int id); void receive (unsigned char* buffer); int play (); }; // Variable EXTERN JJ2Level* jj2Level; //< JJ2 level #endif openjazz-20190106/src/jj2level/jj2levelframe.cpp000066400000000000000000000107571341440264100213670ustar00rootroot00000000000000 /** * * @file jj2levelframe.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Created levelframe.cpp from parts of level.cpp * - 29th June 2010: Created jj2levelframe.cpp from parts of levelframe.cpp * - 30th June 2010: Created jj2layer.cpp from parts of jj2levelframe.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the once-per-frame functions for levels. * */ #include "jj2event/jj2event.h" #include "jj2level.h" #include "jj2levelplayer/jj2levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "util.h" /** * JJ2 level iteration. * * @return Error code */ int JJ2Level::step () { int x; int msps; // Milliseconds per step msps = T_STEP; // Determine the players' trajectories for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->control(ticks, msps); // Process events if (events) events = events->step(ticks, msps); // Apply as much of those trajectories as possible, without going into the // scenery for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->move(ticks, msps); // Handle change in water level if (waterLevel < waterLevelTarget) waterLevelSpeed += 100 * msps; else waterLevelSpeed -= 100 * msps; if (waterLevelSpeed > 40000) waterLevelSpeed = 40000; if (waterLevelSpeed < -40000) waterLevelSpeed = -40000; waterLevel += (waterLevelSpeed * msps) >> 10; // Handle player reactions for (x = 0; x < nPlayers; x++) { if (players[x].getJJ2LevelPlayer()->reacted(ticks) == JJ2PR_KILLED) { if (!multiplayer) return LOST; game->resetPlayer(players + x); } } return E_NONE; } /** * Draw the JJ2 level. */ void JJ2Level::draw () { int width, height; int x, y; unsigned int change; width = layer->getWidth(); height = layer->getHeight(); // Calculate change since last step change = getTimeChange(); // Calculate viewport if (game && (stage == LS_END)) game->view(paused? 0: ((ticks - prevTicks) * 160)); else localPlayer->getJJ2LevelPlayer()->view(ticks, paused? 0: (ticks - prevTicks), change); // Ensure the new viewport is within the level if (FTOI(viewX) + canvasW >= TTOI(width)) viewX = ITOF(TTOI(width) - canvasW); if (viewX < 0) viewX = 0; if (FTOI(viewY) + canvasH >= TTOI(height)) viewY = ITOF(TTOI(height) - canvasH); if (viewY < 0) viewY = 0; // Show background layers for (x = 7; x >= 3; x--) layers[x]->draw(tileSet, flippedTileSet); // Show the events if (events) events->draw(ticks, change); // Show the players for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->draw(ticks, change); // Show foreground layers for (x = 2; x >= 0; x--) layers[x]->draw(tileSet, flippedTileSet); // Temporary lines showing the water level drawRect(0, FTOI(waterLevel - viewY), canvasW, 2, 72); drawRect(0, FTOI(waterLevel - viewY) + 3, canvasW, 1, 72); drawRect(0, FTOI(waterLevel - viewY) + 6, canvasW, 1, 72); drawRect(0, FTOI(waterLevel - viewY) + 10, canvasW, 1, 72); // Black-out areas outside the level (for high resolutions) if (TTOI(layers[3]->getWidth()) - FTOI(viewX) < canvasW) drawRect(TTOI(layers[3]->getWidth()) - FTOI(viewX), 0, canvasW, canvasH, JJ2_BLACK); if (TTOI(layers[3]->getHeight()) - FTOI(viewY) < canvasH) drawRect(0, TTOI(layers[3]->getHeight()) - FTOI(viewY), TTOI(layers[3]->getWidth()) - FTOI(viewX), canvasH, JJ2_BLACK); // Show "panel" data // Show score if (multiplayer) game->getMode()->drawScore(font); else panelSmallFont->showNumber(localPlayer->getScore(), 64, 8); // Draw hearts x = localPlayer->getJJ2LevelPlayer()->getEnergy(); for (y = 1; y <= x; y++) { drawRect(canvasW - (y * 12), 4, 8, 8, 48); } // Show lives panelSmallFont->showNumber(localPlayer->getLives(), 16, canvasH - 16); // Show ammo if (localPlayer->getAmmoType() == -1) { panelSmallFont->showString(":", canvasW - 24, canvasH - 16); panelSmallFont->showString(";", canvasW - 16, canvasH - 16); } else panelSmallFont->showNumber(localPlayer->getAmmo(), canvasW - 8, canvasH - 16); return; } openjazz-20190106/src/jj2level/jj2levelload.cpp000066400000000000000000000463551341440264100212170ustar00rootroot00000000000000 /** * * @file jj2levelload.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 22nd July 2008: Created levelload.c from parts of level.c * - 3rd February 2009: Renamed levelload.c to levelload.cpp * - 28th June 2010: Created levelloadjj2.cpp from parts of levelload.cpp * - 29th June 2010: Renamed levelloadjj2.cpp to jj2levelload.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the loading of JJ2 level data. * */ #include "jj2event/jj2event.h" #include "jj2level.h" #include "jj2levelplayer/jj2levelplayer.h" #include "game/game.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" #include #define SKEY 254 /* Sprite colour key */ /** * Load a sprite. * * @param parameters Sprite parameters * @param compressedPixels Compressed data from which to obtain the sprite data * @param sprite Sprite that will receive the loaded data * @param flippedSprite Sprite that will receive the flipped loaded data */ void JJ2Level::loadSprite (unsigned char* parameters, unsigned char* compressedPixels, Sprite* sprite, Sprite* flippedSprite) { unsigned char* pixels; int width, height; int srcPos, dstPos, rle; int x, y; // Load dimensions width = createShort(parameters); height = createShort(parameters + 2); if ((width == 0) || (height == 0)) { sprite->clearPixels(); return; } // Decompress pixels pixels = new unsigned char[width * height]; memset(pixels, 0, width * height); srcPos = createInt(parameters + 16); dstPos = 0; while (dstPos < width * height) { rle = compressedPixels[srcPos]; srcPos++; if (rle > 128) { rle &= 127; if (dstPos + rle < width * height) memcpy(pixels + dstPos, compressedPixels + srcPos, rle); srcPos += rle; dstPos += rle; } else if (rle == 128) { rle = dstPos % width; if (rle) dstPos = dstPos + width - rle; } else { dstPos += rle; } } // Set sprite data sprite->setOffset(createShort(parameters + 8), createShort(parameters + 10)); sprite->setPixels(pixels, width, height, 0); // Flip sprite for (y = 0; y < height; y++) { for (x = 0; x < (width >> 1); x++) { rle = pixels[(y * width) + x]; pixels[(y * width) + x] = pixels[(y * width) + (width - 1) - x]; pixels[(y * width) + (width - 1) - x] = rle; } } // Set flipped sprite data flippedSprite->setOffset(-createShort(parameters + 8) - width, createShort(parameters + 10)); flippedSprite->setPixels(pixels, width, height, 0); delete[] pixels; return; } /** * Load sprites. * * @return Error code */ int JJ2Level::loadSprites () { File* file; unsigned char* aBuffer; unsigned char* bBuffer; unsigned char* cBuffer; int* setOffsets; int aCLength, bCLength, cCLength; int aLength, bLength, cLength; int setAnims, nSprites, animSprites; int set, anim, sprite, setSprite; // Thanks to Neobeo for working out the .j2a format try { file = new File("anims.j2a", false); } catch (int e) { return e; } file->seek(24, true); nAnimSets = file->loadInt(); setOffsets = new int[nAnimSets]; for (set = 0; set < nAnimSets; set++) setOffsets[set] = file->loadInt(); // Count number of sprites nSprites = 0; for (set = 0; set < nAnimSets; set++) { file->seek(setOffsets[set] + 6, true); nSprites += file->loadShort(); } spriteSet = new Sprite[nSprites]; flippedSpriteSet = new Sprite[nSprites]; animSets = new Anim *[nAnimSets]; flippedAnimSets = new Anim *[nAnimSets]; // Load animations and sprites nSprites = 0; for (set = 0; set < nAnimSets; set++) { file->seek(setOffsets[set] + 4, true); setAnims = file->loadChar(); if (setAnims) { animSets[set] = new Anim[setAnims]; flippedAnimSets[set] = new Anim[setAnims]; } else { animSets[set] = NULL; flippedAnimSets[set] = NULL; } file->seek(7, false); aCLength = file->loadInt(); aLength = file->loadInt(); bCLength = file->loadInt(); bLength = file->loadInt(); cCLength = file->loadInt(); cLength = file->loadInt(); file->loadInt(); // Don't need this compressed block length file->loadInt(); // Don't need this block length aBuffer = file->loadLZ(aCLength, aLength); bBuffer = file->loadLZ(bCLength, bLength); cBuffer = file->loadLZ(cCLength, cLength); setSprite = 0; for (anim = 0; anim < setAnims; anim++) { animSprites = createShort(aBuffer + (anim * 8)); // Fonts are loaded separately if (animSprites == 224) animSprites = 1; animSets[set][anim].setData(animSprites, 0, 0, 0, 0, 0, 0); flippedAnimSets[set][anim].setData(animSprites, 0, 0, 0, 0, 0, 0); for (sprite = 0; sprite < animSprites; sprite++) { loadSprite(bBuffer + (setSprite * 24), cBuffer, spriteSet + nSprites, flippedSpriteSet + nSprites); animSets[set][anim].setFrame(sprite, false); animSets[set][anim].setFrameData(spriteSet + nSprites, 0, 0); flippedAnimSets[set][anim].setFrame(sprite, false); flippedAnimSets[set][anim].setFrameData(flippedSpriteSet + nSprites, 0, 0); setSprite++; nSprites++; } } delete[] cBuffer; delete[] bBuffer; delete[] aBuffer; } delete[] setOffsets; delete file; return E_NONE; } /** * Load the tileset. * * @param fileName Name of the file containing the tileset * * @return The number of tiles loaded and the maximum possible number of tiles */ int JJ2Level::loadTiles (char* fileName) { File* file; unsigned char* aBuffer; unsigned char* bBuffer; unsigned char* dBuffer; unsigned char* tileBuffer; int aCLength, bCLength, cCLength, dCLength; int aLength, bLength, dLength; int count, x, y; int maxTiles; int tiles; // Thanks to Neobeo for working out the most of the .j2t format try { file = new File(fileName, false); } catch (int e) { return e; } // Skip to version indicator file->seek(220, true); maxTiles = file->loadShort(); if (maxTiles == 0x201) maxTiles = 4096; else maxTiles = 1024; // Skip to compressed block lengths file->seek(8, false); aCLength = file->loadInt(); aLength = file->loadInt(); bCLength = file->loadInt(); bLength = file->loadInt(); cCLength = file->loadInt(); file->loadInt(); // Don't need this block length dCLength = file->loadInt(); dLength = file->loadInt(); aBuffer = file->loadLZ(aCLength, aLength); bBuffer = file->loadLZ(bCLength, bLength); file->seek(cCLength, false); // Don't need this block dBuffer = file->loadLZ(dCLength, dLength); delete file; // Load the palette for (count = 0; count < 256; count++) { palette[count].r = aBuffer[count << 2]; palette[count].g = aBuffer[(count << 2) + 1]; palette[count].b = aBuffer[(count << 2) + 2]; } // Load tiles tiles = createShort(aBuffer + 1024); tileBuffer = new unsigned char[tiles << 10]; for (count = 0; count < tiles; count++) { memcpy(tileBuffer + (count << 10), bBuffer + createInt(aBuffer + 1028 + (maxTiles << 1) + (count << 2)), 1024); } tileSet = createSurface(tileBuffer, TTOI(1), TTOI(tiles)); SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, 0); // Flip tiles for (count = 0; count < TTOI(tiles); count++) { for (x = 0; x < 16; x++) { y = tileBuffer[(count * 32) + x]; tileBuffer[(count * 32) + x] = tileBuffer[(count * 32) + 31 - x]; tileBuffer[(count * 32) + 31 - x] = y; } } flippedTileSet = createSurface(tileBuffer, TTOI(1), TTOI(tiles)); SDL_SetColorKey(flippedTileSet, SDL_SRCCOLORKEY, 0); delete[] tileBuffer; // Load mask mask = new char[tiles << 10]; // Unpack bits for (count = 0; count < tiles; count++) { for (y = 0; y < 32; y++) { for (x = 0; x < 32; x++) mask[(count << 10) + (y << 5) + x] = (dBuffer[createInt(aBuffer + 1028 + (maxTiles * 18) + (count << 2)) + (y << 2) + (x >> 3)] >> (x & 7)) & 1; } } flippedMask = new char[tiles << 10]; // Unpack bits for (count = 0; count < tiles; count++) { for (y = 0; y < 32; y++) { for (x = 0; x < 32; x++) flippedMask[(count << 10) + (y << 5) + x] = (dBuffer[createInt(aBuffer + 1028 + (maxTiles * 22) + (count << 2)) + (y << 2) + (x >> 3)] >> (x & 7)) & 1; } } delete[] dBuffer; delete[] bBuffer; delete[] aBuffer; /* Uncomment the code below if you want to see the mask instead of the tile graphics during gameplay */ /*if (SDL_MUSTLOCK(tileSet)) SDL_LockSurface(tileSet); if (SDL_MUSTLOCK(flippedTileSet)) SDL_LockSurface(flippedTileSet); for (count = 0; count < tiles; count++) { for (y = 0; y < 32; y++) { for (x = 0; x < 32; x++) { if (mask[(count << 10) + (y << 5) + x] == 1) ((char *)(tileSet->pixels))[(count << 10) + (y << 5) + x] = 43; if (flippedMask[(count << 10) + (y << 5) + x] == 1) ((char *)(flippedTileSet->pixels))[(count << 10) + (y << 5) + x] = 88; } } } if (SDL_MUSTLOCK(tileSet)) SDL_UnlockSurface(tileSet); if (SDL_MUSTLOCK(flippedTileSet)) SDL_UnlockSurface(flippedTileSet);*/ return tiles | (maxTiles << 16); } /** * Create an event. * * @param x X-coordinate of the new event * @param y Y-coordinate of the new event * @param data Event parameters */ void JJ2Level::createEvent (int x, int y, unsigned char* data) { unsigned char type; int properties; type = *data; properties = (data[1] >> 4) + (data[2] << 4) + (data[3] << 12); if ((type < 33) || ((type >= 206) && (type <= 208)) || (type == 230) || (type == 240) || (type == 245)) { mods[y][x].type = type; mods[y][x].properties = properties; return; } mods[y][x].type = 0; if (type <= 40) { events = new AmmoJJ2Event(events, x, y, type, TSF); } else if ((type >= 44) && (type <= 45)) { events = new CoinGemJJ2Event(events, x, y, type, TSF); } else if (type == 60) { events = new SpringJJ2Event(events, x, y, type, TSF, properties); } else if (type == 62) { events = new SpringJJ2Event(events, x, y, type, TSF, properties); } else if ((type >= 63) && (type <= 66)) { events = new CoinGemJJ2Event(events, x, y, type, TSF); } else if ((type >= 72) && (type <= 73)) { events = new FoodJJ2Event(events, x, y, type, TSF); } else if (type == 80) { events = new FoodJJ2Event(events, x, y, type, TSF); } else if ((type >= 85) && (type <= 87)) { events = new SpringJJ2Event(events, x, y, type, TSF, properties); } else if ((type >= 141) && (type <= 147)) { events = new FoodJJ2Event(events, x, y, type, TSF); } else if ((type >= 154) && (type <= 182)) { events = new FoodJJ2Event(events, x, y, type, TSF); } else { events = new OtherJJ2Event(events, x, y, type, TSF, properties); } return; } /** * Load the level. * * @param fileName Name of the file containing the level data * @param checkpoint Whether or not the player(s) will start at a checkpoint * * @return Error code */ int JJ2Level::load (char *fileName, bool checkpoint) { Anim* pAnims[JJ2PANIMS]; Anim* pFlippedAnims[JJ2PANIMS]; File *file; char *string; unsigned char* aBuffer; unsigned char* bBuffer; unsigned char* cBuffer; unsigned char* dBuffer; int aCLength, bCLength, cCLength, dCLength; int aLength, bLength, cLength, dLength; int tiles; int count, x, y, ret; unsigned char tileQuad[8]; short int* quadRefs; int flags, width, pitch, height; fixed xSpeed, ySpeed; unsigned char startX, startY; // Thanks to Neobeo for working out the most of the .j2l format try { font = new Font(false); } catch (int e) { throw e; } // Open JJ2 level file try { file = new File(fileName, false); } catch (int e) { delete font; return e; } // Load level name file->seek(188, true); string = (char *)file->loadBlock(32); // Show loading screen video.setPalette(menuPalette); video.clearScreen(0); x = (canvasW >> 1) - ((strlen(string) + 6) << 2); x = fontmn2->showString("LOADING ", x - 60, (canvasH >> 1) - 16); fontmn2->showString(string, x, (canvasH >> 1) - 16); delete[] string; if (::loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; // Skip to compressed block lengths file->seek(230, true); aCLength = file->loadInt(); aLength = file->loadInt(); bCLength = file->loadInt(); bLength = file->loadInt(); cCLength = file->loadInt(); cLength = file->loadInt(); dCLength = file->loadInt(); dLength = file->loadInt(); aBuffer = file->loadLZ(aCLength, aLength); bBuffer = file->loadLZ(bCLength, bLength); cBuffer = file->loadLZ(cCLength, cLength); dBuffer = file->loadLZ(dCLength, dLength); delete file; // Load tile set from given file ret = loadTiles((char *)aBuffer + 51); if (ret < 0) { delete[] dBuffer; delete[] cBuffer; delete[] bBuffer; delete[] aBuffer; delete font; return ret; } TSF = ret >> 28; tiles = ret & 0xFFFF; // Next level string = (char *)aBuffer + 115; if (fileExists(string)) nextLevel = createString(string); else nextLevel = createString(string, ".j2l"); // Music file string = (char *)aBuffer + 179; if (fileExists(string)) musicFile = createString(string); else musicFile = createString(string, ".j2b"); // Create layers quadRefs = (short int *)dBuffer; for (count = 0; count < LAYERS; count++) { flags = aBuffer[8403 + (count << 2)]; width = createInt(aBuffer + 8403 + 48 + (count << 2)); pitch = createInt(aBuffer + 8403 + 80 + (count << 2)); height = createInt(aBuffer + 8403 + 112 + (count << 2)); xSpeed = createInt(aBuffer + 8403 + 248 + (count << 2)) >> 6; ySpeed = createInt(aBuffer + 8403 + 280 + (count << 2)) >> 6; pitch = (pitch + 3) >> 2; if (aBuffer[8403 + 40 + count]) { layers[count] = new JJ2Layer(flags, width, height, xSpeed, ySpeed); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { if ((x & 3) == 0) memcpy(tileQuad, cBuffer + (quadRefs[x >> 2] << 3), 8); layers[count]->setTile(x, y, createShort(tileQuad + ((x & 3) << 1)), TSF, tiles); } quadRefs += pitch; } } else { // No tile data layers[count] = new JJ2Layer(); } } layer = layers[3]; width = layer->getWidth(); height = layer->getHeight(); // Load events startX = 1; startY = 1; mods = new JJ2Modifier *[height]; *mods = new JJ2Modifier[width * height]; events = NULL; for (y = 0; y < height; y++) { mods[y] = *mods + (y * width); for (x = 0; x < width; x++) { // Create event or assign modifier createEvent(x, y, bBuffer + (((y * width) + x) << 2)); if (mods[y][x].type == 29) { // Jazz start pos startX = x; startY = y; } } } delete[] dBuffer; delete[] cBuffer; delete[] bBuffer; delete[] aBuffer; // Load anims from anims.j2a ret = loadSprites(); if (ret < 0) { delete file; if (events) delete events; delete[] *mods; delete[] mods; for (x = 0; x < LAYERS; x++) delete layers[x]; delete[] flippedMask; delete[] mask; delete[] musicFile; delete[] nextLevel; SDL_FreeSurface(flippedTileSet); SDL_FreeSurface(tileSet); delete font; return ret; } // Set initial water level waterLevelTarget = TTOF(layer->getHeight() + 1); waterLevel = waterLevelTarget - F8; waterLevelSpeed = 0; // Generate player's animation set references if (multiplayer) { string = new char[MTL_P_ANIMS + 1]; string[0] = MTL_P_ANIMS + 1; string[1] = MT_P_ANIMS; string[2] = 0; string[3] = 0; game->send((unsigned char *)string); delete[] string; } // Set the players' initial values if (TSF) { for (count = 0; count < JJ2PANIMS; count++) { playerAnims[count] = count; pAnims[count] = animSets[55] + count; pFlippedAnims[count] = flippedAnimSets[55] + count; } } else { playerAnims[JJ2PA_BOARD] = 1; playerAnims[JJ2PA_BOARDSW] = 2; playerAnims[JJ2PA_STOMP] = 3; playerAnims[JJ2PA_DEAD] = 4; playerAnims[JJ2PA_DIE] = 5; playerAnims[JJ2PA_CROUCH1] = 6; playerAnims[JJ2PA_CROUCHED] = 7; playerAnims[JJ2PA_CROUCHSHOOT] = 8; playerAnims[JJ2PA_CROUCH2] = 9; playerAnims[JJ2PA_VINE] = 11; playerAnims[JJ2PA_EXIT1] = 12; playerAnims[JJ2PA_FALL] = 13; playerAnims[JJ2PA_STOMPING] = 14; playerAnims[JJ2PA_LAND] = 15; playerAnims[JJ2PA_STANDSHOOT] = 16; playerAnims[JJ2PA_STANDSHOOTUP] = 17; playerAnims[JJ2PA_WHIP1] = 18; playerAnims[JJ2PA_UNFROG] = 19; playerAnims[JJ2PA_HOOKWHIP] = 21; playerAnims[JJ2PA_HOOKDIAG] = 22; playerAnims[JJ2PA_HOOKSHOOTUP] = 23; playerAnims[JJ2PA_HOOK1] = 24; playerAnims[JJ2PA_HOOK2] = 25; playerAnims[JJ2PA_HOOKWHIPUP] = 26; playerAnims[JJ2PA_HOOKSHOOT] = 27; playerAnims[JJ2PA_HELI] = 28; playerAnims[JJ2PA_HELIWHIP] = 29; playerAnims[JJ2PA_HELISHOOT] = 30; playerAnims[JJ2PA_HPOLE] = 31; playerAnims[JJ2PA_HURT] = 32; playerAnims[JJ2PA_WAIT1] = 33; playerAnims[JJ2PA_WAIT2] = 34; playerAnims[JJ2PA_WAIT3] = 35; playerAnims[JJ2PA_WAIT4] = 36; playerAnims[JJ2PA_WAIT5] = 37; playerAnims[JJ2PA_FALLWHIP] = 38; playerAnims[JJ2PA_FALLSHOOT] = 39; playerAnims[JJ2PA_FLOAT1] = 40; playerAnims[JJ2PA_FLOAT2] = 41; playerAnims[JJ2PA_UP1] = 42; playerAnims[JJ2PA_EDGE] = 43; playerAnims[JJ2PA_CARRY] = 44; playerAnims[JJ2PA_UNLOAD] = 45; playerAnims[JJ2PA_LOAD] = 46; playerAnims[JJ2PA_LOOKUP] = 47; playerAnims[JJ2PA_WOOZYWALK] = 55; playerAnims[JJ2PA_PUSH] = 56; playerAnims[JJ2PA_WHIP2] = 57; playerAnims[JJ2PA_EXIT2] = 58; playerAnims[JJ2PA_SPEED1] = 59; playerAnims[JJ2PA_SPEED2] = 60; playerAnims[JJ2PA_FALLMOVE] = 61; playerAnims[JJ2PA_JUMP] = 63; playerAnims[JJ2PA_BALL] = 67; playerAnims[JJ2PA_WALKSHOOT] = 68; playerAnims[JJ2PA_RUN] = 70; playerAnims[JJ2PA_SPEEDRUN] = 71; playerAnims[JJ2PA_STOP1] = 72; playerAnims[JJ2PA_MYSTERY] = 73; playerAnims[JJ2PA_STOP2] = 74; playerAnims[JJ2PA_UP2] = 75; playerAnims[JJ2PA_STAND] = 76; playerAnims[JJ2PA_POWER] = 77; playerAnims[JJ2PA_POWEREND] = 78; playerAnims[JJ2PA_POWERSTART] = 79; playerAnims[JJ2PA_WOOZYSTAND] = 80; playerAnims[JJ2PA_SWIMDOWN] = 81; playerAnims[JJ2PA_SWIM] = 82; playerAnims[JJ2PA_SWIMDIAGDOWN] = 83; playerAnims[JJ2PA_SWIMDIAGUP] = 84; playerAnims[JJ2PA_SWIMUP] = 85; playerAnims[JJ2PA_VINESDIAG] = 86; playerAnims[JJ2PA_WARPOUT] = 87; playerAnims[JJ2PA_WARPFALLIN] = 88; playerAnims[JJ2PA_WARPFALL] = 89; playerAnims[JJ2PA_WARPFALLOUT] = 90; playerAnims[JJ2PA_WARPIN] = 91; playerAnims[JJ2PA_VPOLE] = 92; for (count = 0; count < JJ2PANIMS; count++) { pAnims[count] = animSets[54] + playerAnims[count]; pFlippedAnims[count] = flippedAnimSets[54] + playerAnims[count]; } } createLevelPlayers(LT_JJ2, pAnims, pFlippedAnims, checkpoint, startX, startY); // And that's us done! // Set the tick at which the level will end, though this is not used endTime = (5 - game->getDifficulty()) * 2 * 60 * 1000; // Adjust panel fonts to use bonus level palette panelBigFont->mapPalette(0, 32, 64, 8); panelSmallFont->mapPalette(75, 5, 64, 8); return E_NONE; } openjazz-20190106/src/jj2level/jj2levelplayer/000077500000000000000000000000001341440264100210535ustar00rootroot00000000000000openjazz-20190106/src/jj2level/jj2levelplayer/jj2levelplayer.cpp000066400000000000000000000311551341440264100245160ustar00rootroot00000000000000 /** * * @file jj2levelplayer.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 24th June 2010: Created levelplayer.cpp from parts of player.cpp * - 29th June 2010: Created jj2levelplayer.cpp from parts of levelplayer.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creation and destruction of players in levels, and their * interactions with other level objects. * */ #include "../jj2event/jj2event.h" #include "../jj2level.h" #include "jj2levelplayer.h" #include "game/game.h" #include "game/gamemode.h" #include "io/sound.h" #include /** * Create a JJ2 level player. * * @param parent The game player corresponding to this level player. * @param newAnims Animations * @param newFlippedAnims Flipped animations * @param startX Starting position x-coordinate * @param startY Starting position y-coordinate * @param flockSize The number of birds accompanying the player */ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, Anim** newAnims, Anim** newFlippedAnims, unsigned char startX, unsigned char startY, int flockSize) { int offsets[14] = {JJ2PCO_GREY, JJ2PCO_SGREEN, JJ2PCO_BLUE, JJ2PCO_RED, JJ2PCO_LGREEN, JJ2PCO_LEVEL1, JJ2PCO_YELLOW, JJ2PCO_LEVEL2, JJ2PCO_ORANGE, JJ2PCO_LEVEL3, JJ2PCO_LEVEL4, JJ2PCO_SANIM, JJ2PCO_LANIM, JJ2PCO_LEVEL5}; int lengths[14] = {JJ2PCL_GREY, JJ2PCL_SGREEN, JJ2PCL_BLUE, JJ2PCL_RED, JJ2PCL_LGREEN, JJ2PCL_LEVEL1, JJ2PCL_YELLOW, JJ2PCL_LEVEL2, JJ2PCL_ORANGE, JJ2PCL_LEVEL3, JJ2PCL_LEVEL4, JJ2PCL_SANIM, JJ2PCL_LANIM, JJ2PCL_LEVEL5}; int count, start, length; player = parent; memcpy(anims, newAnims, JJ2PANIMS * sizeof(Anim *)); memcpy(flippedAnims, newFlippedAnims, JJ2PANIMS * sizeof(Anim *)); birds = flockSize; shield = JJ2S_NONE; reset(startX, startY); // Create the player's palette for (count = 0; count < 256; count++) palette[count].r = palette[count].g = palette[count].b = count; // Fur colours start = offsets[player->cols[0]]; length = lengths[player->cols[0]]; for (count = 0; count < 16; count++) palette[count + 16].r = palette[count + 16].g = palette[count + 16].b = (count * length / 8) + start; // Bandana colours start = offsets[player->cols[1]]; length = lengths[player->cols[1]]; for (count = 0; count < 16; count++) palette[count + 24].r = palette[count + 24].g = palette[count + 24].b = (count * length / 8) + start; // Gun colours start = offsets[player->cols[2]]; length = lengths[player->cols[2]]; for (count = 0; count < 9; count++) palette[count + 32].r = palette[count + 32].g = palette[count + 32].b = (count * length / 8) + start; // Wristband colours start = offsets[player->cols[3]]; length = lengths[player->cols[3]]; for (count = 0; count < 8; count++) palette[count + 40].r = palette[count + 40].g = palette[count + 40].b = (count * length / 8) + start; return; } /** * Delete the JJ2 level player. */ JJ2LevelPlayer::~JJ2LevelPlayer () { return; } /** * Reset the player's position, energy etc. * * @param startX New x-coordinate * @param startY New y-coordinate */ void JJ2LevelPlayer::reset (int startX, int startY) { mod = NULL; energy = 5; floating = false; facing = true; animType = JJ2PA_STAND; event = JJ2PE_NONE; reaction = JJ2PR_NONE; reactionTime = 0; jumpHeight = JJ2PYO_JUMP; throwY = TTOF(256); fastFeetTime = 0; stopTime = 0; dx = 0; dy = 0; x = TTOF(startX); y = TTOF(startY); gems[0] = gems[1] = gems[2] = gems[3] = 0; coins = 0; return; } /** * Add to the player's tally of gems of a certain colour. * * @param colour The colour of the gem */ void JJ2LevelPlayer::addGem (int colour) { gems[colour]++; return; } /** * Centre the player horizontally on the nearest tile. */ void JJ2LevelPlayer::centreX () { x = ((x + JJ2PXO_MID) & ~32767) + F16 - JJ2PXO_MID; return; } /** * Centre the player vertically on the nearest tile. */ void JJ2LevelPlayer::centreY () { y = ((y + JJ2PYO_MID) & ~32767) + F16 - JJ2PYO_MID; return; } /** * Determine the player's current animation. * * @return The current animation */ Anim* JJ2LevelPlayer::getAnim () { return (facing? anims: flippedAnims)[animType]; } /** * Determine the player's current energy level. * * @return Energy level */ int JJ2LevelPlayer::getEnergy () { return energy; } /** * Determine the direction the player is facing. * * @return True if the player is facing right */ bool JJ2LevelPlayer::getFacing () { return facing; } /** * Determine the number of gems, of a certain colour, the player has collected. * * @param colour The colour of the gems * * @return Number of gems collected */ int JJ2LevelPlayer::getGems (int colour) { return gems[colour]; } /** * Determine whether or not the player is being accompanied by a bird. * * @return Whether or not the player is being accompanied by a bird */ int JJ2LevelPlayer::countBirds () { return birds; } /** * Deal with bullet collisions. * * @param source Player that fired the bullet (NULL if an event) * @param ticks Time * * @return Whether or not the hit was successful */ bool JJ2LevelPlayer::hit (Player *source, unsigned int ticks) { // Invulnerable if reacting to e.g. having been hit if (reaction != JJ2PR_NONE) return false; // Hits from the same team have no effect if (source && (source->getTeam() == player->team)) return false; if (player->hit(source)) { energy--; //if (bird) bird->hit(); playSound(S_OW); } if (energy) { reaction = JJ2PR_HURT; reactionTime = ticks + JJ2PRT_HURT; if (dx < 0) dx = JJ2PXS_RUN; else dx = -JJ2PXS_RUN; dy = JJ2PYS_JUMP; } else { kill(source, ticks); } return true; } /** * Kill the player. * * @param source Player responsible for the kill (NULL if due to an event or time) * @param ticks time */ void JJ2LevelPlayer::kill (Player *source, unsigned int ticks) { if (reaction != JJ2PR_NONE) return; if (player->kill(source)) { energy = 0; player->lives--; reaction = JJ2PR_KILLED; reactionTime = ticks + JJ2PRT_KILLED; } return; } /** * Determine whether or not the player is overlapping the given area. * * @param left The x-coordinate of the left of the area * @param top The y-coordinate of the top of the area * @param width The width of the area * @param height The height of the area * * @return Whether or not there is an overlap */ bool JJ2LevelPlayer::overlap (fixed left, fixed top, fixed width, fixed height) { return (x + JJ2PXO_R >= left) && (x + JJ2PXO_L < left + width) && (y >= top) && (y + JJ2PYO_TOP < top + height); } /** * Handle the player's reaction. * * @param ticks Time * * @return The reaction the player has just finished */ JJ2PlayerReaction JJ2LevelPlayer::reacted (unsigned int ticks) { JJ2PlayerReaction oldReaction; if ((reaction != JJ2PR_NONE) && (reactionTime < ticks)) { oldReaction = reaction; reaction = JJ2PR_NONE; return oldReaction; } return JJ2PR_NONE; } /** * Set the player's position. * * @param newX New x-coordinate * @param newY New y-coordinate */ void JJ2LevelPlayer::setPosition (fixed newX, fixed newY) { x = newX; y = newY; return; } /** * Set the player's speed. * * @param newDx New x-speed * @param newDy New y-speed */ void JJ2LevelPlayer::setSpeed (fixed newDx, fixed newDy) { dx = newDx; if (newDy) dy = newDy; return; } /** * Called when the player has touched an event. * * @param touched The event that was touched * @param ticks Time * @param msps Ticks per step * * @return Whether or not the event should be destroyed. */ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps) { (void)msps; unsigned char type; bool fullPickup = false; type = touched->getType(); switch (type) { case 34: // Ammo player->addAmmo(2, 3); player->addScore(100); return true; case 36: // Ammo player->addAmmo(1, 3); player->addScore(100); return true; case 37: // Ammo player->addAmmo(0, 3); player->addScore(100); return true; case 38: // TNT player->addAmmo(3, 3); player->addScore(100); return true; case 44: coins++; player->addScore(500); return true; case 45: coins += 5; player->addScore(1000); return true; case 59: // Board floating = true; return true; case 60: // Frozen green spring throwY = y - TTOF(14); dx = 0; event = JJ2PE_SPRING; break; case 61: // Rapid fire player->fireSpeed++; return true; case 62: // Spring crate throwY = y - TTOF(18); dx = 0; event = JJ2PE_SPRING; break; case 63: // Red gem gems[0]++; player->addScore(100); return true; case 64: // Green gem gems[1]++; player->addScore(100); return true; case 65: // Blue gem gems[2]++; player->addScore(100); return true; case 66: // Purple gem gems[3]++; player->addScore(100); return true; case 72: // Carrot if ((energy < 5) || fullPickup) { if (energy < 5) energy++; player->addScore(200); return true; } break; case 73: // Full carrot if ((energy < 5) || fullPickup) { energy = 5; return true; } break; case 80: // 1-up player->addLife(); return true; case 83: // Checkpoint player->setCheckpoint(FTOT(x + JJ2PXO_MID), FTOT(y + JJ2PYO_MID)); break; case 85: // Red spring throwY = y - TTOF(8); dx = 0; event = JJ2PE_SPRING; break; case 86: // Green spring throwY = y - TTOF(14); dx = 0; event = JJ2PE_SPRING; break; case 87: // Blue spring throwY = y - TTOF(18); dx = 0; event = JJ2PE_SPRING; break; case 88: //Invincibility reaction = JJ2PR_INVINCIBLE; reactionTime = ticks + JJ2PRT_INVINCIBLE; return true; case 91: // Horizontal red spring if (true) throwX = x + TTOF(7); else throwX = x - TTOF(7); dy = 0; break; case 92: // Horizontal green spring if (true) throwX = x + TTOF(14); else throwX = x - TTOF(14); dy = 0; break; case 93: // Horizontal blue spring if (true) throwX = x + TTOF(18); else throwX = x - TTOF(18); dy = 0; break; case 96: // Helicarrot floating = true; return true; case 192: // Gem ring gems[0] += 8; return true; default: if (((type >= 141) && (type <= 147)) || ((type >= 154) && (type <= 182))) { // Food player->addScore(50); return true; } break; } return false; } /** * Fill a buffer with player data. * * @param buffer The buffer */ void JJ2LevelPlayer::send (unsigned char *buffer) { buffer[9] = birds; buffer[23] = energy; buffer[25] = shield; buffer[26] = floating; buffer[27] = getFacing(); buffer[29] = jumpHeight >> 24; buffer[30] = (jumpHeight >> 16) & 255; buffer[31] = (jumpHeight >> 8) & 255; buffer[32] = jumpHeight & 255; buffer[33] = throwY >> 24; buffer[34] = (throwY >> 16) & 255; buffer[35] = (throwY >> 8) & 255; buffer[36] = throwY & 255; buffer[37] = x >> 24; buffer[38] = (x >> 16) & 255; buffer[39] = (x >> 8) & 255; buffer[40] = x & 255; buffer[41] = y >> 24; buffer[42] = (y >> 16) & 255; buffer[43] = (y >> 8) & 255; buffer[44] = y & 255; return; } /** * Adjust player data based on the contents of a given buffer. * * @param buffer The buffer */ void JJ2LevelPlayer::receive (unsigned char *buffer) { int count; switch (buffer[1]) { case MT_P_ANIMS: for (count = 0; count < JJ2PANIMS; count++) { anims[count] = jj2Level->getPlayerAnim(buffer[3], count, false); flippedAnims[count] = jj2Level->getPlayerAnim(buffer[3], count, true); } break; case MT_P_TEMP: birds = buffer[9]; energy = buffer[23]; shield = (JJ2Shield)buffer[25]; floating = buffer[26]; facing = buffer[27]; jumpHeight = (buffer[29] << 24) + (buffer[30] << 16) + (buffer[31] << 8) + buffer[32]; throwY = (buffer[33] << 24) + (buffer[34] << 16) + (buffer[35] << 8) + buffer[36]; x = (buffer[37] << 24) + (buffer[38] << 16) + (buffer[39] << 8) + buffer[40]; y = (buffer[41] << 24) + (buffer[42] << 16) + (buffer[43] << 8) + buffer[44]; break; } return; } openjazz-20190106/src/jj2level/jj2levelplayer/jj2levelplayer.h000066400000000000000000000151201341440264100241550ustar00rootroot00000000000000 /** * * @file jj2levelplayer.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 24th June 2010: Created levelplayer.h from parts of player.h * - 29th June 2010: Created jj2levelplayer.h from parts of levelplayer.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ /* "Tile" is a flexible term. Here it is used to refer specifically to the individual elements of the tile set. "Tiles" in the context of level units are referred to as grid elements. */ #ifndef _JJ2LEVELPLAYER_H #define _JJ2LEVELPLAYER_H #include "../jj2level.h" #include "level/levelplayer.h" #include "player/player.h" #include "OpenJazz.h" // Constants // Colour offsets #define JJ2PCO_GREY 72 #define JJ2PCO_SGREEN 16 #define JJ2PCO_BLUE 35 #define JJ2PCO_RED 24 #define JJ2PCO_LGREEN 16 #define JJ2PCO_LEVEL1 96 #define JJ2PCO_YELLOW 59 #define JJ2PCO_LEVEL2 112 #define JJ2PCO_ORANGE 43 #define JJ2PCO_LEVEL3 128 #define JJ2PCO_LEVEL4 144 #define JJ2PCO_SANIM 160 #define JJ2PCO_LANIM 176 #define JJ2PCO_LEVEL5 208 // Colour lengths #define JJ2PCL_GREY 8 #define JJ2PCL_SGREEN 8 #define JJ2PCL_BLUE 5 #define JJ2PCL_RED 8 #define JJ2PCL_LGREEN 8 #define JJ2PCL_LEVEL1 16 #define JJ2PCL_YELLOW 5 #define JJ2PCL_LEVEL2 16 #define JJ2PCL_ORANGE 5 #define JJ2PCL_LEVEL3 16 #define JJ2PCL_LEVEL4 16 #define JJ2PCL_SANIM 16 #define JJ2PCL_LANIM 32 #define JJ2PCL_LEVEL5 16 // Player reaction times #define JJ2PRT_HURT 1000 #define JJ2PRT_HURTANIM 200 #define JJ2PRT_KILLED 2000 #define JJ2PRT_INVINCIBLE 10000 // Other time periods #define T_FASTFEET 25000 #define T_WARP 1000 // Player offsets #define JJ2PXO_MID F16 #define JJ2PXO_L (JJ2PXO_MID - F10) #define JJ2PXO_ML (JJ2PXO_MID - F4) #define JJ2PXO_MR (JJ2PXO_MID + F4) #define JJ2PXO_R (JJ2PXO_MID + F10) #define JJ2PYO_TOP (-F20) #define JJ2PYO_MID (-F10) #define JJ2PYO_JUMP ITOF(92) // Player speeds #define JJ2PXS_LIMIT ITOF(500) #define JJ2PYS_LIMIT ITOF(500) #define JJ2PXS_WALK ITOF(300) #define JJ2PXS_RUN ITOF(325) #define JJ2PXS_FFRUN ITOF(500) #define JJ2PYS_FALL ITOF(350) #define JJ2PYS_SINK ITOF(150) #define JJ2PYS_JUMP -ITOF(350) #define JJ2PXS_POLE ITOF(500) #define JJ2PYS_POLE ITOF(500) #define JJ2PYS_SPRING -ITOF(500) // Player accelerations #define JJ2PXA_REVERSE 900 #define JJ2PXA_STOP 1000 #define JJ2PXA_WALK 500 #define JJ2PXA_RUN 200 #define JJ2PXA_FFRUN 200 #define JJ2PYA_GRAVITY 2750 #define JJ2PYA_SINK 1000 // Enum /// JJ2 player event types enum JJ2PlayerEvent { JJ2PE_NONE, ///< No event JJ2PE_SPRING, ///< Spring JJ2PE_FLOAT, ///< Float up JJ2PE_PLATFORM ///< Moving platform }; /// JJ2 player reaction type enum JJ2PlayerReaction { JJ2PR_NONE, ///< Not reacting JJ2PR_HURT, ///< Hurt JJ2PR_KILLED, ///< Killed JJ2PR_INVINCIBLE ///< Invincibility }; /// JJ2 shield type enum JJ2Shield { JJ2S_NONE = 0, ///< No shield JJ2S_FLAME = 1, ///< Flame shield JJ2S_BUBBLE = 2, ///< Bubble shield JJ2S_PLASMA = 3, ///< Plasma shield JJ2S_LASER = 4 ///< Laser shield }; // Classes class Anim; class JJ2Event; /// JJ2 level player class JJ2LevelPlayer : public LevelPlayer { private: int birds; ///< Placeholder for eventual JJ2Bird objects Anim* anims[JJ2PANIMS]; ///< Animations Anim* flippedAnims[JJ2PANIMS]; ///< Animations (flipped) JJ2Modifier* mod; ///< Modifier currently affecting player int energy; ///< 0 = dead, 3 or 5 = maximum JJ2Shield shield; ///< Current shield int floating; ///< 0 = normal, 1 = helicopter ears, 2 = boarding bool facing; ///< false = left, true = right unsigned char animType; ///< Current animation JJ2PlayerEvent event; ///< Event type int lookTime; ///< Negative if looking up, positive if looking down, 0 if neither JJ2PlayerReaction reaction; ///< Reaction type unsigned int reactionTime; ///< Time reaction will end unsigned int fireTime; ///< The next time the player can fire fixed jumpHeight; ///< The height the player can reach when jumping fixed throwX; ///< Having been thrown, the x-coordinate the player can reach fixed throwY; ///< Having been thrown, the y-coordinate the player can reach unsigned int fastFeetTime; ///< Time fast feet will expire unsigned int stopTime; ///< Time a modifier will cease stopping the player int gems[4]; ///< Gems collected int coins; ///< Value of coins collected bool checkMaskDown (fixed yOffset, bool drop); bool checkMaskUp (fixed yOffset); void centreX (); void centreY (); void ground (); void modify (JJ2Modifier* nextMod, unsigned int ticks); public: JJ2LevelPlayer (Player* parent, Anim** newAnims, Anim** newFlippedAnims, unsigned char startX, unsigned char startY, int flockSize); ~JJ2LevelPlayer (); void reset (int startX, int startY); void addGem (int colour); int countBirds (); Anim* getAnim (); int getEnemies (); int getEnergy (); bool getFacing (); int getGems (int colour); bool hit (Player* source, unsigned int ticks); void kill (Player* source, unsigned int ticks); bool overlap (fixed left, fixed top, fixed width, fixed height); JJ2PlayerReaction reacted (unsigned int ticks); void setPosition (fixed newX, fixed newY); void setSpeed (fixed newDx, fixed newDy); bool touchEvent (JJ2Event* touched, unsigned int ticks, int msps); void send (unsigned char* buffer); void receive (unsigned char* buffer); void control (unsigned int ticks, int msps); void move (unsigned int ticks, int msps); void view (unsigned int ticks, int mspf, int change); void draw (unsigned int ticks, int change); }; #endif openjazz-20190106/src/jj2level/jj2levelplayer/jj2levelplayerframe.cpp000066400000000000000000000434411341440264100255320ustar00rootroot00000000000000 /** * * @file jj2levelplayerframe.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 18th July 2009: Created playerframe.cpp from parts of player.cpp * - 24th June 2010: Renamed playerframe.cpp to levelplayerframe.cpp * - 29th June 2010: Created jj2levelplayerframe.cpp from parts of * levelplayerframe.cpp * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides the once-per-frame functions of players in levels. * */ #include "../jj2event/jj2event.h" #include "../jj2level.h" #include "jj2levelplayer.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "util.h" /** * Determine whether or not the area below the player is solid when travelling * downwards. * * @param yOffset Vertical offset of the mask values to check * * @return Solidity */ bool JJ2LevelPlayer::checkMaskDown (fixed yOffset, bool drop) { return jj2Level->checkMaskDown(x + JJ2PXO_ML, y + yOffset, drop) || jj2Level->checkMaskDown(x + JJ2PXO_MID, y + yOffset, drop) || jj2Level->checkMaskDown(x + JJ2PXO_MR, y + yOffset, drop); } /** * Determine whether or not the area above the player is solid when travelling * upwards. * * @param yOffset Vertical offset of the mask values to check * * @return Solidity */ bool JJ2LevelPlayer::checkMaskUp (fixed yOffset) { return jj2Level->checkMaskUp(x + JJ2PXO_ML, y + yOffset) || jj2Level->checkMaskUp(x + JJ2PXO_MID, y + yOffset) || jj2Level->checkMaskUp(x + JJ2PXO_MR, y + yOffset); } /** * Move the player to the ground's surface. */ void JJ2LevelPlayer::ground () { // If on an uphill slope, push the player upwards if (checkMaskUp(0) && !checkMaskUp(-F1)) y -= F1; // If on a downhill slope, push the player downwards if (!checkMaskUp(F1) && checkMaskUp(F2)) y += F1; return; } /** * Respond to tile modifier events. * * @param nextMod The modifier event * @param ticks Time */ void JJ2LevelPlayer::modify (JJ2Modifier* nextMod, unsigned int ticks) { switch (nextMod->type) { case 2: // Spikes if (jj2Level->checkMaskDown(x + JJ2PXO_MID, y + F1, false)) hit(NULL, ticks); break; case 4: // Hook dx = 0; break; case 6: // H-pole if (!stopTime) { // Catch player if (nextMod != mod) { centreX(); centreY(); stopTime = ticks + 1000; } } else if (ticks > stopTime) { dx = (dx > 0) ? JJ2PXS_POLE: -JJ2PXS_POLE; stopTime = 0; } break; case 7: // V-pole if (!stopTime) { // Catch player if (nextMod != mod) { centreX(); centreY(); stopTime = ticks + 1000; } } else if (ticks > stopTime) { if (dy < 0) { throwY = y - TTOF(16); dy = -JJ2PYS_POLE; } else { dy = JJ2PYS_POLE; } stopTime = 0; } break; case 8: // Fly off floating = false; break; case 17: // End of level case 18: // End of level if (!energy) return; if (!player->endOfLevel(FTOT(x + JJ2PXO_MID), FTOT(y + JJ2PYO_MID))) return; jj2Level->setStage(LS_END); break; case 206: // Sucker tube dx = (nextMod->properties & 0x40) ? -((nextMod->properties << 15) & 0x1F8000): ((nextMod->properties << 15) & 0x1F8000); dy = (nextMod->properties & 0x2000) ? -((nextMod->properties << 8) & 0x1F8000): ((nextMod->properties << 8) & 0x1F8000); if (dx) centreY(); if (dy) centreX(); break; case 207: // Text break; case 208: // Water level jj2Level->setWaterLevel(nextMod->properties & 0xFF, nextMod->properties & 0x100); break; case 230: // Warp if (!stopTime) { // Catch player if (coins >= ((nextMod->properties >> 8) & 255)) stopTime = ticks + 1000; } else if (ticks > stopTime) { coins -= (nextMod->properties >> 8) & 255; jj2Level->warp(this, nextMod->properties & 255); stopTime = 0; } break; default: stopTime = 0; break; } mod = nextMod; return; } /** * Respond to controls, unless the player has been killed * * @param ticks Time * @param msps Ticks per step */ void JJ2LevelPlayer::control (unsigned int ticks, int msps) { JJ2Modifier* nextMod; bool drop, platform; // If the player has been killed, do not move if (!energy) { dx = 0; dy = 0; animType = JJ2PA_DIE; return; } // Get overlapping modifier nextMod = jj2Level->getModifier(FTOT(x + JJ2PXO_MID), FTOT(y + JJ2PYO_MID)); if (stopTime) { // Can't control player, so just apply modifier modify(nextMod, ticks); return; } if (player->pcontrols[C_RIGHT]) { // Walk/run right if (dx < 0) dx += JJ2PXA_REVERSE * msps; else if (dx < JJ2PXS_WALK) dx += JJ2PXA_WALK * msps; else if (dx < JJ2PXS_RUN) dx += JJ2PXA_RUN * msps; facing = true; } else if (player->pcontrols[C_LEFT]) { // Walk/run left if (dx > 0) dx -= JJ2PXA_REVERSE * msps; else if (dx > -JJ2PXS_WALK) dx -= JJ2PXA_WALK * msps; else if (dx > -JJ2PXS_RUN) dx -= JJ2PXA_RUN * msps; facing = false; } else if ((nextMod->type >> 1) != 3) { // Slow down if (dx > 0) { if (dx < JJ2PXA_STOP * msps) dx = 0; else dx -= JJ2PXA_STOP * msps; } if (dx < 0) { if (dx > -JJ2PXA_STOP * msps) dx = 0; else dx += JJ2PXA_STOP * msps; } } drop = player->pcontrols[C_DOWN]; // Check for platform event, bridge or level mask below player platform = (event == JJ2PE_PLATFORM) || checkMaskDown(1, drop) || ((dx > 0) && jj2Level->checkMaskDown(x + JJ2PXO_ML, y + F8, drop)) || ((dx < 0) && jj2Level->checkMaskDown(x + JJ2PXO_MR, y + F8, drop)); if (floating) { if (player->pcontrols[C_UP]) { // Fly upwards if (dy > 0) dy -= JJ2PXA_REVERSE * msps; else if (dy > -JJ2PXS_WALK) dy -= JJ2PXA_WALK * msps; else if (dy > -JJ2PXS_RUN) dy -= JJ2PXA_RUN * msps; } else if (player->pcontrols[C_DOWN]) { // Fly downwards if (dy < 0) dy += JJ2PXA_REVERSE * msps; else if (dy < JJ2PXS_WALK) dy += JJ2PXA_WALK * msps; else if (dy < JJ2PXS_RUN) dy += JJ2PXA_RUN * msps; } else if ((nextMod->type >> 1) != 3) { // Slow down if (dy > 0) { if (dy < JJ2PXA_STOP * msps) dy = 0; else dy -= JJ2PXA_STOP * msps; } if (dy < 0) { if (dy > -JJ2PXA_STOP * msps) dy = 0; else dy += JJ2PXA_STOP * msps; } } if (event == JJ2PE_SPRING) dy = JJ2PYS_SPRING; else if (event == JJ2PE_FLOAT) dy = JJ2PYS_JUMP; } else if (y + JJ2PYO_MID > jj2Level->getWaterLevel()) { if (player->pcontrols[C_SWIM]) { // Swim upwards if (dy > 0) dy -= JJ2PXA_REVERSE * msps; else if (dy > -JJ2PXS_WALK) dy -= JJ2PXA_WALK * msps; else if (dy > -JJ2PXS_RUN) dy -= JJ2PXA_RUN * msps; // Prepare to jump upon leaving the water if (!jj2Level->checkMaskUp(x + JJ2PXO_MID, y - F36)) { throwY = y - jumpHeight; if (dx < 0) throwY += dx >> 4; else if (dx > 0) throwY -= dx >> 4; event = JJ2PE_NONE; } } else if (player->pcontrols[C_DOWN]) { // Swim downwards if (dy < 0) dy += JJ2PXA_REVERSE * msps; else if (dy < JJ2PXS_WALK) dy += JJ2PXA_WALK * msps; else if (dy < JJ2PXS_RUN) dy += JJ2PXA_RUN * msps; } else { // Sink dy += JJ2PYA_SINK * msps; if (dy > JJ2PYS_SINK) dy = JJ2PYS_SINK; } } else { if (platform && player->pcontrols[C_JUMP] && !jj2Level->checkMaskUp(x + JJ2PXO_MID, y - F36)) { // Jump throwY = y - jumpHeight; // Increase jump height if walking/running if (dx < 0) throwY += dx >> 3; else if (dx > 0) throwY -= dx >> 3; event = JJ2PE_NONE; playSound(S_JUMPA); } // Stop jumping if (!player->pcontrols[C_JUMP] && (event != JJ2PE_SPRING) && (event != JJ2PE_FLOAT)) throwY = TTOF(256); if (y >= throwY) { // If jumping, rise dy = (throwY - y - F64) * 4; // Avoid jumping too fast, unless caused by an event if ((event == JJ2PE_NONE) && (dy < JJ2PYS_JUMP)) dy = JJ2PYS_JUMP; } else if (!platform) { // Fall under gravity dy += JJ2PYA_GRAVITY * msps; if (dy > JJ2PYS_FALL) dy = JJ2PYS_FALL; } // Don't descend through platforms if ((dy > 0) && (event == JJ2PE_PLATFORM)) dy = 0; if (platform && !lookTime) { // If requested, look up or down if (player->pcontrols[C_UP]) lookTime = -ticks; else if (player->pcontrols[C_DOWN]) lookTime = ticks; } // Stop looking if there is no platform or the control has been released if (!platform || (!player->pcontrols[C_UP] && (lookTime < 0)) || (!player->pcontrols[C_DOWN] && (lookTime > 0))) lookTime = 0; } // If there is an obstacle above and the player is not floating up, stop // rising if (jj2Level->checkMaskUp(x + JJ2PXO_MID, y + JJ2PYO_TOP - F1) && (throwY < y) && (event != JJ2PE_FLOAT)) { throwY = TTOF(256); if (dy < 0) dy = 0; if (event != JJ2PE_PLATFORM) event = JJ2PE_NONE; } // If jump completed, stop rising if (y <= throwY) { throwY = TTOF(256); if (event != JJ2PE_PLATFORM) event = JJ2PE_NONE; } // Apply modifier modify(nextMod, ticks); // Limit speed if (dx < -JJ2PXS_LIMIT) dx = -JJ2PXS_LIMIT; else if (dx > JJ2PXS_LIMIT) dx = JJ2PXS_LIMIT; if (dy < -JJ2PYS_LIMIT) dy = -JJ2PYS_LIMIT; else if (dy > JJ2PYS_LIMIT) dy = JJ2PYS_LIMIT; // Handle firing if (player->pcontrols[C_FIRE]) { if (ticks > fireTime) { // Make sure bullet position is taken from correct animation if (platform) animType = JJ2PA_STANDSHOOT; /// @todo Create new bullet when firing // Set when the next bullet can be fired if (player->fireSpeed) fireTime = ticks + (1000 / player->fireSpeed); else fireTime = 0x7FFFFFFF; // Remove the bullet from the arsenal if (player->ammoType != -1) player->ammo[player->ammoType]--; /* If the current ammo type has been exhausted, use the previous non-exhausted ammo type */ while ((player->ammoType > -1) && !player->ammo[player->ammoType]) player->ammoType--; } } else fireTime = 0; // Check for a change in ammo if (player->pcontrols[C_CHANGE]) { if (player == localPlayer) controls.release(C_CHANGE); player->ammoType = ((player->ammoType + 2) % 5) - 1; // If there is no ammo of this type, go to the next type that has ammo while ((player->ammoType > -1) && !player->ammo[player->ammoType]) player->ammoType = ((player->ammoType + 2) % 5) - 1; } // Deal with the bird //if (birds) birds = birds->step(ticks, msps); // Choose animation if ((reaction == JJ2PR_HURT) && (reactionTime - ticks > JJ2PRT_HURT - JJ2PRT_HURTANIM)) animType = JJ2PA_HURT; else if (y + JJ2PYO_MID > jj2Level->getWaterLevel()) animType = JJ2PA_SWIM; else if (floating) animType = JJ2PA_BOARD; else if (dy < 0) { if (event == JJ2PE_SPRING) animType = JJ2PA_FLOAT1; else animType = JJ2PA_JUMP; } else if (platform) { if (dx) { if (dx <= -JJ2PXS_RUN) animType = JJ2PA_RUN; else if (dx >= JJ2PXS_RUN) animType = JJ2PA_RUN; else if ((dx < 0) && facing) animType = JJ2PA_STOP1; else if ((dx > 0) && !facing) animType = JJ2PA_STOP1; else animType = JJ2PA_WALKSHOOT; } else if (!jj2Level->checkMaskDown(x + JJ2PXO_ML, y + F12, drop) && !jj2Level->checkMaskDown(x + JJ2PXO_L, y + F2, drop) && (event != JJ2PE_PLATFORM)) animType = JJ2PA_EDGE; else if (!jj2Level->checkMaskDown(x + JJ2PXO_MR, y + F12, drop) && !jj2Level->checkMaskDown(x + JJ2PXO_R, y + F2, drop) && (event != JJ2PE_PLATFORM)) animType = JJ2PA_EDGE; else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) animType = JJ2PA_LOOKUP; else if (lookTime > 0) { if ((int)ticks < 1000 + lookTime) animType = JJ2PA_CROUCHED; else animType = JJ2PA_CROUCH1; } else if (player->pcontrols[C_FIRE]) animType = JJ2PA_STANDSHOOT; else animType = JJ2PA_STAND; } else animType = JJ2PA_FALL; return; } /** * Move the player. * * @param ticks Time * @param msps Ticks per step */ void JJ2LevelPlayer::move (unsigned int ticks, int msps) { fixed pdx, pdy; bool grounded = false; int count; bool drop; if (stopTime) return; // Apply as much of the trajectory as possible, without going into the // scenery if (fastFeetTime > ticks) { pdx = (dx * msps * 3) >> 11; pdy = (dy * msps * 3) >> 11; } else { pdx = (dx * msps) >> 10; pdy = (dy * msps) >> 10; } // First for the vertical component of the trajectory drop = player->pcontrols[C_DOWN]; if (pdy < 0) { // Moving up count = (-pdy) >> 10; while (count > 0) { if (jj2Level->checkMaskUp(x + JJ2PXO_MID, y + JJ2PYO_TOP - F1)) { y &= ~1023; dy = 0; break; } y -= F1; count--; } pdy = (-pdy) & 1023; if (jj2Level->checkMaskUp(x + JJ2PXO_MID, y + JJ2PYO_TOP - pdy)) { y &= ~1023; dy = 0; } else y -= pdy; } else { if (pdy > 0) { // Moving down count = pdy >> 10; while (count > 0) { if (checkMaskDown(F1, drop)) { y |= 1023; dy = 0; break; } y += F1; count--; } pdy &= 1023; if (checkMaskDown(pdy, drop)) y |= 1023; else y += pdy; } if (checkMaskDown(0, drop)) { // In the ground, so move up if (y >= 1024) y = (y - 1024) | 1023; dy = 0; grounded = true; } else if (checkMaskDown(1, drop)) { // On the ground dy = 0; grounded = true; } } // Then for the horizontal component of the trajectory if (pdx < 0) { // Moving left count = (-pdx) >> 10; while (count > 0) { // If there is an obstacle, stop if (jj2Level->checkMaskUp(x + JJ2PXO_L - F1, y + JJ2PYO_MID)) { x &= ~1023; dx = 0; break; } x -= F1; count--; if (grounded) ground(); } pdx = (-pdx) & 1023; if (jj2Level->checkMaskUp(x + JJ2PXO_L - pdx, y + JJ2PYO_MID)) { x &= ~1023; dx = 0; } else x -= pdx; if (grounded) ground(); } else if (pdx > 0) { // Moving right count = pdx >> 10; while (count > 0) { // If there is an obstacle, stop if (jj2Level->checkMaskUp(x + JJ2PXO_R + F1, y + JJ2PYO_MID)) { x |= 1023; dx = 0; break; } x += F1; count--; if (grounded) ground(); } pdx &= 1023; if (jj2Level->checkMaskUp(x + JJ2PXO_R + pdx, y + JJ2PYO_MID)) { x |= 1023; dx = 0; } else x += pdx; if (grounded) ground(); } // If using a float up event and have hit a ceiling, ignore event if ((event == JJ2PE_FLOAT) && jj2Level->checkMaskUp(x + JJ2PXO_MID, y + JJ2PYO_TOP - F1)) { throwY = TTOF(256); event = JJ2PE_NONE; } if (jj2Level->getStage() == LS_END) return; return; } /** * Calculate viewport. * * @param ticks Time * @param mspf Ticks per frame * @param change Time since last step */ void JJ2LevelPlayer::view (unsigned int ticks, int mspf, int change) { int oldViewX, oldViewY, speed; // Record old viewport position for applying lag oldViewX = viewX; oldViewY = viewY; // Find new position viewX = x + ((dx * change) >> 10) + F8 - (canvasW << 9); viewY = y + ((dy * change) >> 10) - F24 - (canvasH << 9); if ((lookTime > 0) && ((int)ticks > 1000 + lookTime)) { // Look down if ((int)ticks < 2000 + lookTime) viewY += 64 * (ticks - (1000 + lookTime)); else viewY += F64; } else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) { // Look up if ((int)ticks < 2000 - lookTime) viewY -= 64 * (ticks - (1000 - lookTime)); else viewY -= F64; } // Apply lag proportional to player "speed" speed = ((dx >= 0? dx: -dx) + (dy >= 0? dy: -dy)) >> 14; if (speed && (mspf < speed)) { viewX = ((oldViewX * (speed - mspf)) + (viewX * mspf)) / speed; viewY = ((oldViewY * (speed - mspf)) + (viewY * mspf)) / speed; } return; } /** * Draw the player. * * @param ticks Time * @param change Time since last step */ void JJ2LevelPlayer::draw (unsigned int ticks, int change) { Anim *an; int frame; fixed drawX, drawY; // The current frame for animations if (reaction == JJ2PR_KILLED) frame = (ticks + JJ2PRT_KILLED - reactionTime) / 75; else frame = ticks / 75; // Get position drawX = getDrawX(stopTime? 0: change); drawY = getDrawY(stopTime? 0: change); // Choose sprite an = getAnim(); an->setFrame(frame, reaction != JJ2PR_KILLED); // Show the player // Use player colour an->setPalette(palette, 16, 32); // Flash on and off if hurt if ((reaction != JJ2PR_HURT) || ((ticks / 30) & 2)) { // Draw "motion blur" if (fastFeetTime > ticks) an->draw(drawX + F16 - (dx >> 6), drawY + F16); // Draw player an->draw(drawX + F16, drawY + F16); } // Uncomment the following to see the area of the player /*drawRect(FTOI(drawX + JJ2PXO_L - viewX), FTOI(drawY + JJ2PYO_TOP - viewY), FTOI(JJ2PXO_R - JJ2PXO_L), FTOI(-JJ2PYO_TOP), 89); drawRect(FTOI(drawX + JJ2PXO_ML - viewX), FTOI(drawY + JJ2PYO_TOP - viewY), FTOI(JJ2PXO_MR - JJ2PXO_ML), FTOI(-JJ2PYO_TOP), 88);*/ if (reaction == JJ2PR_INVINCIBLE) { /// @todo Show invincibility effect } switch (shield) { case JJ2S_NONE: // Do nothing break; case JJ2S_FLAME: /// @todo Show shield effect break; case JJ2S_BUBBLE: /// @todo Show shield effect break; case JJ2S_PLASMA: /// @todo Show shield effect break; case JJ2S_LASER: /// @todo Show shield effect break; } // Show the bird //if (birds) birds->draw(ticks, change); // Show the player's name if (nPlayers > 1) panelBigFont->showString(player->name, FTOI(drawX + JJ2PXO_MID) - (panelBigFont->getStringWidth(player->name) >> 1), FTOI(drawY - F32 - F16)); //panelBigFont->showNumber(mod->properties, FTOI(drawX) + 24, FTOI(drawY) + 12); return; } openjazz-20190106/src/level/000077500000000000000000000000001341440264100155135ustar00rootroot00000000000000openjazz-20190106/src/level/level.cpp000066400000000000000000000233611341440264100173330ustar00rootroot00000000000000 /** * * @file level.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 3rd February 2009: Renamed level.c to level.cpp * - 19th July 2009: Created levelframe.cpp from parts of level.cpp * - 19th July 2009: Added parts of levelload.cpp to level.cpp * - 30th March 2010: Created baselevel.cpp from parts of level.cpp and * levelframe.cpp * - 1st August 2012: Renamed baselevel.cpp to level.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with functionality common to ordinary levels and bonus levels. * */ #include "level.h" #include "game/game.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/sprite.h" #include "io/gfx/video.h" #include "io/sound.h" #include "player/player.h" #include "jj1scene/jj1scene.h" #include "loop.h" #include "setup.h" /** * Create a new base level */ Level::Level (Game* owner) { game = owner; menuOptions[0] = "continue game"; menuOptions[2] = "save game"; menuOptions[3] = "load game"; menuOptions[4] = "setup options"; menuOptions[5] = "quit game"; // Arbitrary initial value smoothfps = 50.0f; paletteEffects = NULL; paused = false; // Set the level stage stage = LS_NORMAL; stats = 0; return; } /** * Destroy base level */ Level::~Level () { stopMusic(); if (paletteEffects) delete paletteEffects; return; } /** * Set the players' initial values. * * @param levelType The type of level for which to create a level player * @param anims New level player animations * @param flippedAnims New level player flipped animations * @param checkpoint Whether or not a checkpoint is in use * @param x The level players' new grid x-coordinate * @param y The level players' new grid y-coordinate */ void Level::createLevelPlayers (LevelType levelType, Anim** anims, Anim** flippedAnims, bool checkpoint, unsigned char x, unsigned char y) { int count; if (!checkpoint) game->setCheckpoint(x, y); for (count = 0; count < nPlayers; count++) { players[count].createLevelPlayer(levelType, anims, flippedAnims, x, y); game->resetPlayer(players + count); } return; } /** * Play a cutscene. * * @param file File name of the cutscene to be played * * @return Error code */ int Level::playScene (const char* file) { JJ1Scene* scene; int ret; delete paletteEffects; paletteEffects = NULL; try { scene = new JJ1Scene(file); } catch (int e) { return e; } ret = scene->play(); delete scene; return ret; } /** * Perform timing calculations. */ void Level::timeCalcs () { // Calculate smoothed fps smoothfps = smoothfps + 1.0f - (smoothfps * ((float)(ticks - prevTicks)) / 1000.0f); /* This equation is a simplified version of (fps * c) + (smoothfps * (1 - c)) where c = (1 / fps) and fps = 1000 / (ticks - prevTicks) In other words, the response of smoothFPS to changes in FPS decreases as the framerate increases The following version is for c = (1 / smoothfps) */ // smoothfps = (fps / smoothfps) + smoothfps - 1; // Ignore outlandish values if (smoothfps > 9999.0f) smoothfps = 9999.0f; if (smoothfps < 1.0f) smoothfps = 1.0f; // Track number of ticks of gameplay since the level started if (paused) { tickOffset = globalTicks - ticks; } else if (globalTicks - tickOffset > ticks + 100) { prevTicks = ticks; ticks += 100; tickOffset = globalTicks - ticks; } else { prevTicks = ticks; ticks = globalTicks - tickOffset; } return; } /** * Calculate the amount of time since the last completed step. * * @return Time since last step */ int Level::getTimeChange () { return paused? 0: ticks - ((steps * (setup.slowMotion? 100: 50)) / 3); } /** * Display menu (if visible) and statistics. * * @param bg Palette index of the box(es) * @param menu Whether or not the level menu should be displayed * @param option Selected menu uption * @param textPalIndex The first palette index for unseleceted text * @param selectedTextPalIndex The first palette index for selected text * @param textPalSpan The number of palette indices for text */ void Level::drawOverlay (unsigned char bg, bool menu, int option, unsigned char textPalIndex, unsigned char selectedTextPalIndex, int textPalSpan) { const char* difficultyOptions[4] = {"easy", "medium", "hard", "turbo"}; int count, width; // Draw graphics statistics if (stats & S_SCREEN) { #ifdef SCALE if (video.getScaleFactor() > 1) drawRect(canvasW - 84, 11, 80, 37, bg); else #endif drawRect(canvasW - 84, 11, 80, 25, bg); panelBigFont->showNumber(video.getWidth(), canvasW - 52, 14); panelBigFont->showString("x", canvasW - 48, 14); panelBigFont->showNumber(video.getHeight(), canvasW - 12, 14); panelBigFont->showString("fps", canvasW - 76, 26); panelBigFont->showNumber((int)smoothfps, canvasW - 12, 26); #ifdef SCALE if (video.getScaleFactor() > 1) { panelBigFont->showNumber(canvasW, canvasW - 52, 38); panelBigFont->showString("x", canvasW - 48, 39); panelBigFont->showNumber(canvasH, canvasW - 12, 38); } #endif } // Draw player list if (stats & S_PLAYERS) { width = 39; for (count = 0; count < nPlayers; count++) if (panelBigFont->getStringWidth(players[count].getName()) > width) width = panelBigFont->getStringWidth(players[count].getName()); drawRect((canvasW >> 1) - 48, 11, width + 57, (nPlayers * 12) + 1, bg); for (count = 0; count < nPlayers; count++) { panelBigFont->showNumber(count + 1, (canvasW >> 1) - 24, 14 + (count * 12)); panelBigFont->showString(players[count].getName(), (canvasW >> 1) - 16, 14 + (count * 12)); panelBigFont->showNumber(players[count].teamScore, (canvasW >> 1) + width + 1, 14 + (count * 12)); } } if (menu) { // Draw the menu drawRect((canvasW >> 2) - 8, (canvasH >> 1) - 54, 144, 108, bg); menuOptions[1] = difficultyOptions[game->getDifficulty()]; for (count = 0; count < 6; count++) { if (count == option) fontmn2->mapPalette(240, 8, selectedTextPalIndex, textPalSpan); else fontmn2->mapPalette(240, 8, textPalIndex, textPalSpan); fontmn2->showString(menuOptions[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 46); } fontmn2->restorePalette(); } return; } /** * Process in-game menu selection. * * @param menu Whether or not the level menu should be displayed * @param option Chosen menu option * * @return Error code */ int Level::select (bool& menu, int option) { bool wasSlow; switch (option) { case 0: // Continue menu = false; case 1: // Change difficulty if (!multiplayer) game->setDifficulty((game->getDifficulty() + 1) & 3); break; case 2: // Save break; case 3: // Load break; case 4: // Setup if (!multiplayer) { wasSlow = setup.slowMotion; if (setupMenu.setupMain() == E_QUIT) return E_QUIT; if (wasSlow && !setup.slowMotion) steps <<= 1; else if (!wasSlow && setup.slowMotion) steps >>= 1; // Restore level palette video.setPalette(palette); } break; case 5: // Quit game return E_RETURN; } return E_NONE; } /** * Process iteration. * * @param menu Whether or not the level menu should be displayed * @param option Selected menu uption * @param message Whether or not the "paused" message is being displayed * * @return Error code */ int Level::loop (bool& menu, int& option, bool& message) { int ret, x, y; // Networking if (multiplayer) { ret = game->step(ticks); if (ret < 0) return ret; } // Main loop if (::loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) { menu = !menu; option = 0; } if (controls.release(C_PAUSE)) message = !message; if (controls.release(C_STATS)) { if (!multiplayer) stats ^= S_SCREEN; else stats = (stats + 1) & 3; } if (menu) { // Deal with menu controls if (controls.release(C_UP)) option = (option + 5) % 6; if (controls.release(C_DOWN)) option = (option + 1) % 6; if (controls.release(C_ENTER)) { ret = select(menu, option); if (ret < 0) return ret; } if (controls.getCursor(x, y)) { x -= canvasW >> 2; y -= (canvasH >> 1) - 46; if ((x >= 0) && (x < 128) && (y >= 0) && (y < 96)) { option = y >> 4; if (controls.wasCursorReleased()) { ret = select(menu, option); if (ret < 0) return ret; } } else if (controls.wasCursorReleased()) menu = false; } } #if !defined(ANDROID) else { if (controls.wasCursorReleased()) menu = true; } #endif if (!multiplayer) paused = message || menu; timeCalcs(); return E_NONE; } /** * Add extra time. * * @param seconds Number of seconds to add */ void Level::addTimer (int seconds) { unsigned char buffer[MTL_L_PROP]; if (stage != LS_NORMAL) return; endTime += seconds * 1000; if (endTime >= ticks + (10 * 60 * 1000)) endTime = ticks + (10 * 60 * 1000) - 1; if (multiplayer) { buffer[0] = MTL_L_PROP; buffer[1] = MT_L_PROP; buffer[2] = 2; // add timer buffer[3] = seconds; buffer[4] = 0; // not used game->send(buffer); } return; } /** * Set the level stage. * * @param newStage New level stage */ void Level::setStage (LevelStage newStage) { unsigned char buffer[MTL_L_STAGE]; if (stage == newStage) return; stage = newStage; if (multiplayer) { buffer[0] = MTL_L_STAGE; buffer[1] = MT_L_STAGE; buffer[2] = stage; game->send(buffer); } return; } /** * Determine the current level stage. * * @return The current level stage. */ LevelStage Level::getStage () { return stage; } openjazz-20190106/src/level/level.h000066400000000000000000000067351341440264100170060ustar00rootroot00000000000000 /** * * @file level.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created level.h from parts of OpenJazz.h * - 30th March 2010: Created baselevel.h from parts of level.h * - 1st August 2012: Renamed baselevel.h to level.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _BASELEVEL_H #define _BASELEVEL_H #include "menu/menu.h" // Macros // For converting between tile positions and int/fixed values #define FTOT(x) ((x) >> 15) ///< Fixed to Tile #define TTOF(x) ((x) << 15) ///< Tile to Fixed #define ITOT(x) ((x) >> 5) ///< Int to Tile #define TTOI(x) ((x) << 5) ///< Tile to Int // Constants // Return values #define WON 1 #define LOST 2 // Time interval #define T_STEP 16 // Enums /// Level type enum LevelType { LT_JJ1 = 0, ///< JJ1 level LT_JJ1BONUS = 1, ///< JJ1 bonus level LT_JJ2 = 2 ///< JJ2 level }; /// Which stats to display on-screen enum LevelStats { S_PLAYERS = 1, ///< Display player list S_SCREEN = 2 ///< Display video statisitics }; /// Level stage enum LevelStage { LS_NORMAL = 0, ///< Normal gameplay LS_SUDDENDEATH = 1, ///< Sudden death LS_END = 2 ///< Ending sequence }; // Classes class Anim; class File; class Game; class PaletteEffect; class Sprite; /// Base class for all level classes class Level { private: const char* menuOptions[6]; SetupMenu setupMenu; ///< Setup menu to run on the player's command int select (bool& menu, int option); protected: Game* game; PaletteEffect* paletteEffects; ///< Palette effects in use while playing the level SDL_Color palette[256]; ///< Palette in use while playing the level int sprites; ///< The number of sprite that have been loaded unsigned int tickOffset; ///< Level time offset from system time unsigned int steps; ///< Number of steps taken unsigned int prevTicks; ///< Time the last visual update started unsigned int ticks; ///< Current time unsigned int endTime; ///< Tick at which the level will end float smoothfps; ///< Smoothed FPS counter int items; ///< Number of items to be collected bool multiplayer; ///< Whether or not this is a multiplayer game bool paused; ///< Whether or not the level is paused LevelStage stage; ///< Level stage int stats; ///< Which statistics to display on-screen, see #LevelStats void createLevelPlayers (LevelType levelType, Anim** anims, Anim** flippedAnims, bool checkpoint, unsigned char x, unsigned char y); int playScene (const char* file); void timeCalcs (); int getTimeChange (); void drawOverlay (unsigned char bg, bool menu, int option, unsigned char textPalIndex, unsigned char selectedTextPalIndex, int textPalSpan); int loop (bool& menu, int& option, bool& message); public: Level (Game* owner); virtual ~Level (); void addTimer (int seconds); LevelStage getStage (); void setStage (LevelStage stage); virtual void receive (unsigned char* buffer) = 0; }; // Variables EXTERN fixed viewX, viewY; ///< Level viewing co-ordinates #endif openjazz-20190106/src/level/levelplayer.cpp000066400000000000000000000013551341440264100205470ustar00rootroot00000000000000 /** * * @file levelplayer.cpp * * Part of the OpenJazz project * * @par History: * - 5th August 2012: Created levelplayer.cpp * * @par Licence: * Copyright (c) 2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creation and destruction of players in levels, and their * interactions with other level objects. * */ #include "levelplayer.h" /** * Delete the level player. */ LevelPlayer::~LevelPlayer () { } openjazz-20190106/src/level/levelplayer.h000066400000000000000000000027421341440264100202150ustar00rootroot00000000000000 /** * * @file levelplayer.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 24th June 2010: Created bonusplayer.h and levelplayer.h from parts of * player.h * - 29th June 2010: Created jj2levelplayer.h from parts of levelplayer.h * - 1st August 2012: Renamed levelplayer.h to jj1levelplayer.h * - 5th August 2012: Created levelplayer.h from parts of jj1levelplayer.h, * jj1bonuslevelplayer.h and jj2levelplayer.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _LEVELPLAYER_H #define _LEVELPLAYER_H #include "io/gfx/video.h" #include "level/movable.h" // Classes class Player; /// Level player class LevelPlayer : public Movable { protected: SDL_Color palette[256]; ///< Palette (for custom colours) public: Player* player; ///< Corresponding game player virtual ~LevelPlayer (); virtual void reset (int startX, int startY) = 0; virtual int countBirds () = 0; virtual void send (unsigned char* buffer) = 0; virtual void receive (unsigned char* buffer) = 0; }; #endif openjazz-20190106/src/level/movable.cpp000066400000000000000000000026111341440264100176440ustar00rootroot00000000000000 /** * * @file movable.cpp * * Part of the OpenJazz project * * @par History: * - 15th January 2010: Created movable.cpp * * @par Licence: * Copyright (c) 2010-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Contains the base class for all movable objects. * */ #include "level.h" #include "movable.h" /** * Derive the x-coordinate of the Movable relative to the view coordinates for * the current time. * * @param change Time since last step * * @return The x-coordinate */ fixed Movable::getDrawX (int change) { return x + ((dx * change) >> 10) - viewX; } /** * Derive the y-coordinate of the Movable relative to the view coordinates for * the current time. * * @param change Time since last step * * @return The y-coordinate */ fixed Movable::getDrawY (int change) { return y + ((dy * change) >> 10) - viewY; } /** * Get the basic x-coordinate of the Movable. * * @return The x-coordinate */ fixed Movable::getX () { return x; } /** * Get the basic y-coordinate of the Movable. * * @return The y-coordinate */ fixed Movable::getY () { return y; } openjazz-20190106/src/level/movable.h000066400000000000000000000014701341440264100173130ustar00rootroot00000000000000 /** * * @file movable.h * * Part of the OpenJazz project * * @par History: * - 15th January 2010: Created movable.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _MOVABLE_H #define _MOVABLE_H #include "OpenJazz.h" // Class /// Base class for all movable objects (players, events, bullets, birds) class Movable { protected: fixed x, y, dx, dy; fixed getDrawX (int change); fixed getDrawY (int change); public: fixed getX (); fixed getY (); }; #endif openjazz-20190106/src/loop.h000066400000000000000000000022671341440264100155350ustar00rootroot00000000000000 /** * * @file loop.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 30th April 2010: Created loop.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _LOOP_H #define _LOOP_H #include "io/gfx/paletteeffects.h" // Constants // Return values #define JOYSTICKB 0x100 #define JOYSTICKANEG 0x200 #define JOYSTICKAPOS 0x300 // Variable EXTERN unsigned int globalTicks; // Enum /// Ways the loop function should handle input. enum LoopType { NORMAL_LOOP, ///< Normal behaviour TYPING_LOOP, ///< Return key presses SET_KEY_LOOP, ///< Return key presses without modifying control state SET_JOYSTICK_LOOP ///< Return joystick actions without modifying control state }; // Function in main.cpp EXTERN int loop (LoopType type, PaletteEffect* paletteEffects = NULL); #endif openjazz-20190106/src/main.cpp000066400000000000000000000252461341440264100160450ustar00rootroot00000000000000 /** * * @file main.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed main.c to main.cpp * - 4th February 2009: Created palette.cpp from parts of main.cpp and util.cpp * - 13th July 2009: Created controls.cpp from parts of main.cpp * - 21st July 2013: Created setup.cpp from parts of main.cpp and setupmenu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Contains the main function. * */ #define EXTERN #include "game/game.h" #include "io/controls.h" #include "io/file.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/network.h" #include "io/sound.h" #include "jj2level/jj2level.h" #include "jj1level/jj1level.h" #include "menu/menu.h" #include "player/player.h" #include "jj1scene/jj1scene.h" #include "loop.h" #include "setup.h" #include "util.h" #ifdef PSP #include #include #include #include #include #include #include #elif defined(_3DS) #include <3ds.h> #elif defined(__HAIKU__) #include #include #include #endif #include #if defined(WIZ) || defined(GP2X) #include "platforms/wiz.h" #endif #ifdef __SYMBIAN32__ extern char KOpenJazzPath[256]; extern float sinf (float); #else #include #endif #define PI 3.141592f /** * Initialises OpenJazz. * * Establishes the paths from which to read files, loads configuration, sets up * the game window and loads required data. * * @param argc Number of arguments, as passed to main function * @param argv Array of argument strings, as passed to main function */ void startUp (int argc, char *argv[]) { File* file; unsigned char* pixels = NULL; int count; int screenW = DEFAULT_SCREEN_WIDTH; int screenH = DEFAULT_SCREEN_HEIGHT; int scaleFactor = 1; #ifdef FULLSCREEN_ONLY bool fullscreen = true; #else bool fullscreen = false; #endif // Determine paths // Use hard-coded paths, if available #ifdef DATAPATH firstPath = new Path(NULL, createString(DATAPATH)); #else firstPath = NULL; #endif #ifdef __HAIKU__ dev_t volume = dev_for_path("/boot"); char buffer[10 + B_PATH_NAME_LENGTH + B_FILE_NAME_LENGTH]; status_t result; result = find_directory(B_SYSTEM_DATA_DIRECTORY, volume, false, buffer, sizeof(buffer)); strncat(buffer, "/openjazz/", sizeof(buffer)); firstPath = new Path(firstPath, createString(buffer)); result = find_directory(B_USER_NONPACKAGED_DATA_DIRECTORY, volume, false, buffer, sizeof(buffer)); strncat(buffer, "/openjazz/", sizeof(buffer)); firstPath = new Path(firstPath, createString(buffer)); #endif #ifdef __SYMBIAN32__ #ifdef UIQ3 firstPath = new Path(firstPath, createString("c:\\shared\\openjazz\\")); #else firstPath = new Path(firstPath, createString("c:\\data\\openjazz\\")); #endif firstPath = new Path(firstPath, createString(KOpenJazzPath)); #endif // Use any provided paths, appending a directory separator as necessary for (count = 1; count < argc; count++) { // If it isn't an option, it should be a path if (argv[count][0] != '-') { #ifdef _WIN32 if (argv[count][strlen(argv[count]) - 1] != '\\') { firstPath = new Path(firstPath, createString(argv[count], "\\")); #else if (argv[count][strlen(argv[count]) - 1] != '/') { firstPath = new Path(firstPath, createString(argv[count], "/")); #endif } else { firstPath = new Path(firstPath, createString(argv[count])); } } } // Use the path of the program count = strlen(argv[0]) - 1; // Search for directory separator #ifdef _WIN32 while ((argv[0][count] != '\\') && (count >= 0)) count--; #else while ((argv[0][count] != '/') && (count >= 0)) count--; #endif // If a directory was found, copy it to the path if (count > 0) { firstPath = new Path(firstPath, new char[count + 2]); memcpy(firstPath->path, argv[0], count + 1); firstPath->path[count + 1] = 0; } // Use the user's home directory, if available #ifdef HOMEDIR #ifdef _WIN32 firstPath = new Path(firstPath, createString(getenv("HOME"), "\\")); #else firstPath = new Path(firstPath, createString(getenv("HOME"), "/.")); #endif #endif // Use the current working directory firstPath = new Path(firstPath, createString("")); // Default settings // Sound settings #if defined(WIZ) || defined(GP2X) volume = 40; #endif // Create the network address netAddress = createString(NET_ADDRESS); // Load settings from config file setup.load(&screenW, &screenH, &fullscreen, &scaleFactor); // Get command-line override for (count = 1; count < argc; count++) { // If there's a hyphen, it should be an option if (argv[count][0] == '-') { #ifndef FULLSCREEN_ONLY if (argv[count][1] == 'f') fullscreen = true; #endif if (argv[count][1] == 'm') { setMusicVolume(0); setSoundVolume(0); } } } // Create the game's window canvas = NULL; if (!video.init(screenW, screenH, fullscreen)) { delete firstPath; throw E_VIDEO; } #ifdef SCALE video.setScaleFactor(scaleFactor); #endif if (SDL_NumJoysticks() > 0) SDL_JoystickOpen(0); // Set up audio openAudio(); // Load fonts // Open the panel, which contains two fonts try { file = new File("PANEL.000", false); } catch (int e) { closeAudio(); delete firstPath; log("Unable to find game data files. When launching OpenJazz, pass the location"); log("of the original game data, eg:"); log(" OpenJazz ~/jazz1"); #ifdef __HAIKU__ char alertBuffer[100+B_PATH_NAME_LENGTH+B_FILE_NAME_LENGTH]; strcpy(alertBuffer, "Unable to find game data files!\n" "Put the data into the folder:\n"); strncat(alertBuffer, buffer, sizeof(alertBuffer)); BAlert* alert = new BAlert("OpenJazz", alertBuffer, "Exit", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); alert->Go(); #endif throw e; } pixels = file->loadRLE(46272); delete file; panelBigFont = NULL; panelSmallFont = NULL; font2 = NULL; fontbig = NULL; fontiny = NULL; fontmn1 = NULL; try { panelBigFont = new Font(pixels + (40 * 320), true); panelSmallFont = new Font(pixels + (48 * 320), false); font2 = new Font("FONT2.0FN"); fontbig = new Font("FONTBIG.0FN"); fontiny = new Font("FONTINY.0FN"); fontmn1 = new Font("FONTMN1.0FN"); fontmn2 = new Font("FONTMN2.0FN"); } catch (int e) { if (panelBigFont) delete panelBigFont; if (panelSmallFont) delete panelSmallFont; if (font2) delete font2; if (fontbig) delete fontbig; if (fontiny) delete fontiny; if (fontmn1) delete fontmn1; delete[] pixels; closeAudio(); delete firstPath; throw e; } delete[] pixels; // Establish arbitrary timing globalTicks = SDL_GetTicks() - 20; // Fill trigonometric function look-up tables for (count = 0; count < 1024; count++) sinLut[count] = fixed(sinf(2 * PI * float(count) / 1024.0f) * 1024.0f); // Initiate networking net = new Network(); level = NULL; jj2Level = NULL; } /** * De-initialises OpenJazz. * * Frees data, writes configuration, and shuts down SDL. */ void shutDown () { delete net; delete panelBigFont; delete panelSmallFont; delete font2; delete fontbig; delete fontiny; delete fontmn1; delete fontmn2; #ifdef SCALE if (video.getScaleFactor() > 1) SDL_FreeSurface(canvas); #endif closeAudio(); // Save settings to config file setup.save(); delete firstPath; } /** * Run the cutscenes and the main menu. * * @return Error code */ int play () { MainMenu *mainMenu = NULL; JJ1Scene *scene = NULL; // Load and play the startup cutscene try { scene = new JJ1Scene("STARTUP.0SC"); } catch (int e) { return e; } if (scene->play() == E_QUIT) { delete scene; return E_NONE; } delete scene; // Load and run the menu try { mainMenu = new MainMenu(); } catch (int e) { return e; } if (mainMenu->main() == E_QUIT) { delete mainMenu; return E_NONE; } delete mainMenu; // Load and play the ending cutscene try { scene = new JJ1Scene("END.0SC"); } catch (int e) { return e; } scene->play(); delete scene; return E_NONE; } /** * Process iteration. * * Called once per game iteration. Updates timing, video, and input * * @param type Type of loop. Normal, typing, or input configuration * @param paletteEffects Palette effects to apply to video output * * @return Error code */ int loop (LoopType type, PaletteEffect* paletteEffects) { SDL_Event event; int prevTicks, ret; // Update tick count prevTicks = globalTicks; globalTicks = SDL_GetTicks(); if (globalTicks - prevTicks < 4) { // Limit framerate SDL_Delay(4 + prevTicks - globalTicks); globalTicks = SDL_GetTicks(); } // Show what has been drawn video.flip(globalTicks - prevTicks, paletteEffects); // Process system events while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) return E_QUIT; ret = controls.update(&event, type); if (ret != E_NONE) return ret; video.update(&event); #if defined(WIZ) || defined(GP2X) if ((event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP)) { if (event.jbutton.button == GP2X_BUTTON_VOLUP ) { if( event.type == SDL_JOYBUTTONDOWN ) volume_direction = VOLUME_UP; else volume_direction = VOLUME_NOCHG; } if (event.jbutton.button == GP2X_BUTTON_VOLDOWN ) { if( event.type == SDL_JOYBUTTONDOWN ) volume_direction = VOLUME_DOWN; else volume_direction = VOLUME_NOCHG; } } #endif } controls.loop(); #if defined(WIZ) || defined(GP2X) WIZ_AdjustVolume( volume_direction ); #endif return E_NONE; } #ifdef PSP PSP_MODULE_INFO("OpenJazz", PSP_MODULE_USER, 0, 1); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); PSP_HEAP_SIZE_KB(-2048); #endif /** * Main. * * Initialises SDL and launches game. */ int main(int argc, char *argv[]) { int ret; #ifdef PSP pspDebugScreenInit(); atexit(sceKernelExitGame); sceIoChdir("ms0:/PSP/GAME/OpenJazz"); #endif // Initialise SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0) { logError("Could not start SDL", SDL_GetError()); return -1; } // Load configuration and establish a window try { startUp(argc, argv); } catch (int e) { SDL_Quit(); return -1; } // Play the opening cutscene, run the main menu, etc. ret = play(); // Save configuration and shut down shutDown(); SDL_Quit(); return ret; } openjazz-20190106/src/menu/000077500000000000000000000000001341440264100153505ustar00rootroot00000000000000openjazz-20190106/src/menu/gamemenu.cpp000066400000000000000000000311131341440264100176510ustar00rootroot00000000000000 /** * * @file gamemenu.cpp * * Part of the OpenJazz project * * @par History: * - 23rd of August 2005: Created menu.c * - 3rd of February 2009: Renamed menu.c to menu.cpp * - 18th July 2009: Created menugame.cpp from parts of menu.cpp * - 26th July 2009: Renamed menugame.cpp to gamemenu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the running of the menus used to create a new game. * */ #include "menu.h" #include "game/game.h" #include "game/gamemode.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" /** * Create the game menu. * * @param file File containing menu graphics */ GameMenu::GameMenu (File *file) { unsigned char pixel; int count, col; // Load the difficulty graphics file->loadPalette(menuPalette); difficultyScreen = file->loadSurface(SW, SH); SDL_SetColorKey(difficultyScreen, SDL_SRCCOLORKEY, 0); // Default difficulty setting difficulty = 1; // Load the episode pictures (max. 10 episodes + bonus level) // Load their palette file->loadPalette(palette); // Generate a greyscale mapping for (count = 0; count < 256; count++) { col = ((palette[count].r >> 1) + (palette[count].g << 1) + (palette[count].b >> 1)) >> 3; if (col > 79) col = 79; greyPalette[count].r = greyPalette[count].g = greyPalette[count].b = col; } episodes = 11; for (count = 0; count < 11; count++) { episodeScreens[count] = file->loadSurface(134, 110); if (file->tell() >= file->getSize()) { episodes = ++count; for (; count < 11; count++) { pixel = 0; episodeScreens[count] = createSurface(&pixel, 1, 1); } } } return; } /** * Delete the game menu. */ GameMenu::~GameMenu () { int count; for (count = 0; count < 11; count++) SDL_FreeSurface(episodeScreens[count]); SDL_FreeSurface(difficultyScreen); return; } /** * Create and play a new game. * * @param mode Game mode * @param firstLevel First level's file name * * @return Error code */ int GameMenu::playNewGame (GameModeType mode, char* firstLevel) { Game* game; int ret; playSound(S_ORB); if (mode == M_SINGLE) { try { game = new LocalGame(firstLevel, difficulty); } catch (int e) { if (message("COULD NOT START GAME") == E_QUIT) return E_QUIT; return e; } } else { try { game = new ServerGame(mode, firstLevel, difficulty); } catch (int e) { if (message("COULD NOT CREATE SERVER") == E_QUIT) return E_QUIT; return e; } } // Play the level(s) ret = game->play(); delete game; if (ret != E_QUIT) playMusic("menusng.psm"); switch (ret) { case E_QUIT: return E_QUIT; case E_FILE: return message("FILE NOT FOUND"); } return E_NONE; } /** * Run the new game difficulty menu. * * @param mode Game mode * @param firstLevel First level's file name * * @return Error code */ int GameMenu::newGameDifficulty (GameModeType mode, char* firstLevel) { const char *options[4] = {"easy", "medium", "hard", "turbo"}; SDL_Rect src, dst; int x, y, count; video.setPalette(menuPalette); while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_UP)) difficulty = (difficulty + 3) % 4; if (controls.release(C_DOWN)) difficulty = (difficulty + 1) % 4; if (controls.release(C_ENTER)) return playNewGame(mode, firstLevel); if (controls.getCursor(x, y)) { if ((x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; x -= canvasW >> 2; y -= (canvasH >> 1) - 32; if ((x >= 0) && (x < 256) && (y >= 0) && (y < 64)) { difficulty = y >> 4; if (controls.wasCursorReleased()) return playNewGame(mode, firstLevel); } } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); for (count = 0; count < 4; count++) { if (count == difficulty) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString(options[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 32); if (count == difficulty) fontmn2->restorePalette(); } src.x = (difficulty & 1) * 160; src.y = (difficulty & 2) * 50; src.w = 160; src.h = 100; dst.x = (canvasW >> 1) - 40; dst.y = (canvasH >> 1) - 50; SDL_BlitSurface(difficultyScreen, &src, canvas, &dst); showEscString(); } return E_NONE; } /** * Run the new game difficulty menu. * * @param mode Game mode * @param levelNum First level's number * @param levelNum First level's world number * * @return Error code */ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) { char* firstLevel; int ret; if (levelNum == -1) firstLevel = createFileName("BONUSMAP", worldNum); else firstLevel = createFileName("LEVEL", levelNum, worldNum); ret = newGameDifficulty(mode, firstLevel); delete[] firstLevel; return ret; } /** * Run the game loading menu. * * @return Error code */ int GameMenu::loadGame () { /// @todo Actual loading of saved games int option, worldNum, levelNum, x, y; worldNum = levelNum = option = 0; video.setPalette(menuPalette); while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_UP)) option ^= 1; if (controls.release(C_DOWN)) option ^= 1; if (controls.release(C_LEFT)) { if (option) levelNum = ((levelNum + 11) % 11) - 1; else worldNum = (worldNum + 999) % 1000; } if (controls.release(C_RIGHT)) { if (option) levelNum = ((levelNum + 2) % 11) - 1; else worldNum = (worldNum + 1) % 1000; } if (controls.release(C_ENTER)) { playSound(S_ORB); if (newGameDifficulty(M_SINGLE, levelNum, worldNum) == E_QUIT) return E_QUIT; video.setPalette(menuPalette); } if (controls.getCursor(x, y)) { if ((x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; if (y < (canvasH >> 1)) option = 0; else option = 1; } SDL_Delay(T_MENU_FRAME); video.clearScreen(15); if (option == 0) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString("choose world:", 32, canvasH / 3); fontmn2->showNumber(worldNum, 208, canvasH / 3); if (option == 0) fontmn2->restorePalette(); else fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString("choose level:", 32, (canvasH << 1) / 3); if (levelNum >= 0) fontmn2->showNumber(levelNum, 208, (canvasH << 1) / 3); else fontmn2->showString("bonus", 172, (canvasH << 1) / 3); if (option != 0) fontmn2->restorePalette(); showEscString(); } return E_NONE; } /** * Run the new game level selection menu. * * @param mode Game mode * * @return Error code */ int GameMenu::newGameLevel (GameModeType mode) { char* fileName; int ret; fileName = createString("level0.000"); ret = E_NONE; while (true) { ret = textInput("level file name:", fileName); if (ret < 0) break; ret = newGameDifficulty(mode, fileName); if (ret < 0) break; } delete[] fileName; return ret; } /** * Run the appropriate menu for the given episode selection. * * @param mode Game mode * @param episode Episode number * * @return Error code */ int GameMenu::selectEpisode (GameModeType mode, int episode) { int worldNum; playSound(S_ORB); if (episode < 10) { if (episode < 6) worldNum = episode * 3; else if ((episode >= 6) && (episode < 9)) worldNum = (episode + 4) * 3; else worldNum = 50; if (newGameDifficulty(mode, 0, worldNum) == E_QUIT) return E_QUIT; } else if (episode == 10) { if (newGameDifficulty(mode, -1, 0) == E_QUIT) return E_QUIT; } else { if (newGameLevel(mode) == E_QUIT) return E_QUIT; } video.setPalette(palette); return E_NONE; } /** * Run the new game episode menu. * * @param mode Game mode * * @return Error code */ int GameMenu::newGameEpisode (GameModeType mode) { const char *options[12] = {"episode 1", "episode 2", "episode 3", "episode 4", "episode 5", "episode 6", "episode a", "episode b", "episode c", "episode x", "bonus stage", "specific level"}; bool exists[12]; char *check; SDL_Rect dst; int episode, count, x, y; video.setPalette(palette); for (count = 0; count < 10; count++) { if (count < 6) x = count * 3; else if ((count >= 6) && (count < 9)) x = (count + 4) * 3; else x = 50; check = createFileName("LEVEL", 0, x); exists[count] = fileExists(check); delete[] check; if (exists[count]) video.restoreSurfacePalette(episodeScreens[count]); else SDL_SetPalette(episodeScreens[count], SDL_LOGPAL, greyPalette, 0, 256); } if (mode == M_SINGLE) { check = createFileName("BONUSMAP", 0); exists[10] = fileExists(check); delete[] check; } else exists[10] = false; exists[11] = true; episode = 0; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_UP)) episode = (episode + 11) % 12; if (controls.release(C_DOWN)) episode = (episode + 1) % 12; if (controls.release(C_ENTER) && exists[episode]) { count = selectEpisode(mode, episode); if (count < 0) return count; } if (controls.getCursor(x, y)) { if ((x >= canvasW - 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; x -= canvasW >> 3; y -= (canvasH >> 1) - 92; if ((x >= 0) && (x < 256) && (y >= 0) && (y < 192)) { episode = y >> 4; if (controls.wasCursorReleased() && exists[episode]) { count = selectEpisode(mode, episode); if (count < 0) return count; } } } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); dst.x = canvasW - 144; dst.y = (canvasH - 110) >> 1; if ((episode < episodes - 1) || (episode < 6)) { SDL_BlitSurface(episodeScreens[episode], NULL, canvas, &dst); } else if ((episode == 10) && (episodes > 6)) { SDL_BlitSurface(episodeScreens[episodes - 1], NULL, canvas, &dst); } for (count = 0; count < 12; count++) { if (count == episode) { fontmn2->mapPalette(240, 8, 79, -80); drawRect((canvasW >> 3) - 4, (canvasH >> 1) + (count << 4) - 94, 136, 15, 79); } else if (!exists[count]) fontmn2->mapPalette(240, 8, 94, -16); fontmn2->showString(options[count], canvasW >> 3, (canvasH >> 1) + (count << 4) - 92); if ((count == episode) || (!exists[count])) fontmn2->mapPalette(240, 8, 9, 80); } fontbig->showString(ESCAPE_STRING, canvasW - 100, canvasH - 12); } return E_NONE; } /** * Run the game joining menu. * * @return Error code */ int GameMenu::joinGame () { Game* game; int ret; ret = textInput("ip address:", netAddress); if (ret < 0) return ret; try { game = new ClientGame(netAddress); } catch (int e) { switch (e) { case E_N_SOCKET: if (message("SOCKET ERROR") == E_QUIT) return E_QUIT; break; case E_N_ADDRESS: if (message("INVALID ADDRESS") == E_QUIT) return E_QUIT; break; case E_N_CONNECT: if (message("COULD NOT CONNECT") == E_QUIT) return E_QUIT; break; case E_TIMEOUT: if (message("OPERATION TIMED OUT") == E_QUIT) return E_QUIT; break; case E_DATA: if (message("INCORRECT DATA\nRECEIVED") == E_QUIT) return E_QUIT; break; case E_VERSION: if (message("WRONG SERVER VERSION") == E_QUIT) return E_QUIT; break; case E_RETURN: case E_QUIT: break; default: if (message("COULD NOT COMPLETE CONNECTION") == E_QUIT) return E_QUIT; break; } return e; } // Play the level(s) ret = game->play(); delete game; if (ret != E_QUIT) playMusic("menusng.psm"); switch (ret) { case E_QUIT: return E_QUIT; case E_FILE: return message("FILE NOT FOUND"); case E_N_DISCONNECT: return message("DISCONNECTED"); } return E_NONE; } /** * Run the new game menu. * * @return Error code */ int GameMenu::newGame () { #if (defined USE_SOCKETS) || (defined USE_SDL_NET) const char *newGameOptions[6] = {"new single player game", "new co-op game", "new battle", "new team battle", "new race", "join game"}; int ret; int option; option = 0; while (true) { video.setPalette(menuPalette); ret = generic(newGameOptions, 6, option); if (ret == E_QUIT) return E_QUIT; if (ret < 0) return E_NONE; if (option == 5) { if (joinGame() == E_QUIT) return E_QUIT; } else { if (newGameEpisode(GameModeType(option)) == E_QUIT) return E_QUIT; } } return E_NONE; #else return newGameEpisode(M_SINGLE); #endif } openjazz-20190106/src/menu/mainmenu.cpp000066400000000000000000000151451341440264100176730ustar00rootroot00000000000000 /** * * @file mainmenu.cpp * * Part of the OpenJazz project * * @par History: * - 23rd of August 2005: Created menu.c * - 3rd of February 2009: Renamed menu.c to menu.cpp * - 19th July 2009: Created menumain.cpp from parts of menu.cpp * - 26th July 2009: Renamed menumain.cpp to mainmenu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the running of the main menu and its generic sub-menus. * */ #include "menu.h" #include "plasma.h" #include "game/game.h" #include "io/controls.h" #include "io/gfx/video.h" #include "io/sound.h" #include "jj1scene/jj1scene.h" #include "loop.h" #include "util.h" #include /** * Create the main menu. */ MainMenu::MainMenu () { File *file; time_t currentTime; // Load the OpenJazz logo try { file = new File("openjazz.000", false); } catch (int e) { throw e; } logo = file->loadSurface(64, 40); delete file; // Load the menu graphics try { file = new File("MENU.000", false); } catch (int e) { SDL_FreeSurface(logo); throw e; } // only available in Holiday Hare 94/95 if (file->getSize() > 200000) { time(¤tTime); // In December, load the Christmas menu graphics if (localtime(¤tTime)->tm_mon == 11) { file->skipRLE(); file->skipRLE(); file->skipRLE(); file->loadPalette(palette); background = file->loadSurface(SW, SH); highlight = file->loadSurface(SW, SH); } else { file->loadPalette(palette); background = file->loadSurface(SW, SH); highlight = file->loadSurface(SW, SH); file->skipRLE(); file->skipRLE(); file->skipRLE(); } } else { file->loadPalette(palette); background = file->loadSurface(SW, SH); highlight = file->loadSurface(SW, SH); } SDL_SetColorKey(background, SDL_SRCCOLORKEY, 0); SDL_SetColorKey(highlight, SDL_SRCCOLORKEY, 0); SDL_SetColorKey(logo, SDL_SRCCOLORKEY, 28); gameMenu = new GameMenu(file); delete file; return; } /** * Delete the main menu. */ MainMenu::~MainMenu () { SDL_FreeSurface(background); SDL_FreeSurface(highlight); SDL_FreeSurface(logo); delete gameMenu; return; } /** * Process a main menu selection. * * @param option Chosen menu option * * @return Error code */ int MainMenu::select (int option) { JJ1Scene *scene; SetupMenu setupMenu; playSound(S_ORB); switch (option) { case 0: // New game if (gameMenu->newGame() == E_QUIT) return E_QUIT; break; case 1: // Load game if (gameMenu->loadGame() == E_QUIT) return E_QUIT; break; case 2: // Instructions try { scene = new JJ1Scene("INSTRUCT.0SC"); } catch (int e) { if (message("COULD NOT LOAD INSTRUCTIONS") == E_QUIT) return E_QUIT; break; } if (scene->play() == E_QUIT) { delete scene; return E_QUIT; } delete scene; break; case 3: // Setup options if (setupMenu.setupMain() == E_QUIT) return E_QUIT; break; case 4: // Order info try { scene = new JJ1Scene("ORDER.0SC"); } catch (int e) { if (message("COULD NOT LOAD ORDER INFO") == E_QUIT) return E_QUIT; break; } if (scene->play() == E_QUIT) { delete scene; return E_QUIT; } delete scene; break; case 5: // Exit return E_RETURN; } // Restore the main menu palette video.setPalette(palette); return E_NONE; } /** * Run the main menu. * * @return Error code */ int MainMenu::main () { SDL_Rect options[6] = { {92, 35, 136, 22}, {92, 57, 140, 22}, {88, 83, 144, 22}, {86, 109, 150, 23}, {82, 137, 156, 26}, {78, 166, 166, 29}}; int macroType[4]; File* file; char* fileName; Plasma plasma; SDL_Rect dst; int option, macro, x, y, ret; unsigned int idleTime; option = 0; video.setPalette(palette); playMusic("menusng.psm"); // Demo timeout idleTime = globalTicks + T_DEMO; // Check for demo macros fileName = createString("MACRO.1"); for (macro = 0; macro < 4; macro++) { try { file = new File(fileName, false); macroType[macro] = file->loadChar(); delete file; } catch (int e) { macroType[macro] = -1; } fileName[6]++; } macro = 3; delete[] fileName; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) option = 5; if (controls.release(C_UP)) option = (option + 5) % 6; if (controls.release(C_DOWN)) option = (option + 1) % 6; if (controls.release(C_ENTER)) { ret = select(option); if (ret < 0) return ret; // New demo timeout idleTime = globalTicks + T_DEMO; } if (controls.getCursor(x, y)) { int count; x -= (canvasW - SW) >> 1; y -= (canvasH - SH) >> 1; for (count = 0; count < 6; count++) { if ((x >= options[count].x) && (x < options[count].x + options[count].w) && (y >= options[count].y) && (y < options[count].y + options[count].h)) { option = count; if (controls.wasCursorReleased()) { ret = select(option); if (ret < 0) return ret; } // New demo timeout idleTime = globalTicks + T_DEMO; break; } } } if (idleTime <= globalTicks) { Game* game = NULL; try { game = new LocalGame("", 0); } catch (int e) { // Do nothing } if (game) { // Load the macro x = macro; macro = (macro + 1) & 3; while ((macroType[macro] != 0xFF) && (macro != x)) macro = (macro + 1) & 3; if (macro != x) { fileName = createString("MACRO.1"); fileName[6] += macro; if (game->playLevel(fileName) == E_QUIT) { delete[] fileName; delete game; return E_QUIT; } delete[] fileName; } delete game; playMusic("menusng.psm"); // Restore the main menu palette video.setPalette(palette); } idleTime = globalTicks + T_DEMO; } SDL_Delay(T_MENU_FRAME); //as long as we're drawing plasma, we don't need to clear the screen. //video.clearScreen(28); plasma.draw(); dst.x = (canvasW >> 2) - 72; dst.y = canvasH - (canvasH >> 2); SDL_BlitSurface(logo, NULL, canvas, &dst); dst.x = (canvasW - SW) >> 1; dst.y = (canvasH - SH) >> 1; SDL_BlitSurface(background, NULL, canvas, &dst); dst.x = ((canvasW - SW) >> 1) + options[option].x; dst.y = ((canvasH - SH) >> 1) + options[option].y; SDL_BlitSurface(highlight, options + option, canvas, &dst); } return E_NONE; } openjazz-20190106/src/menu/menu.cpp000066400000000000000000000134561341440264100170310ustar00rootroot00000000000000 /** * * @file menu.cpp * * Part of the OpenJazz project * * @par History: * - 23rd of August 2005: Created menu.c * - 3rd of February 2009: Renamed menu.c to menu.cpp * - 9th March 2009: Created game.cpp from parts of menu.cpp and level.cpp * - 18th July 2009: Created menugame.cpp from parts of menu.cpp * - 18th July 2009: Created menuutil.cpp from parts of menu.cpp * - 18th July 2009: Created menusetup.cpp from parts of menu.cpp * - 19th July 2009: Created menumain.cpp from parts of menu.cpp * - 23rd June 2010: Merged menuutil.cpp into menu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Provides various generic menus. * */ #include "menu.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "loop.h" #include "util.h" #include /** * Show the "(esc) quits" string. */ void Menu::showEscString () { fontbig->showString(ESCAPE_STRING, 3, canvasH - 12); return; } /** * Display a message to the user. * * @param text The message to display * * @return Error code */ int Menu::message (const char* text) { video.setPalette(menuPalette); while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ENTER) || controls.release(C_ESCAPE) || controls.wasCursorReleased()) return E_NONE; SDL_Delay(T_MENU_FRAME); video.clearScreen(15); // Draw the message fontmn2->showString(text, canvasW >> 2, (canvasH >> 1) - 16); } return E_NONE; } /** * Let the user select from a menu of the given options. * * @param optionNames Array of option names * @param options The number of options (and size of the names array) * @param chosen Which option is selected * * @return Error code */ int Menu::generic (const char** optionNames, int options, int& chosen) { int x, y, count; if (chosen >= options) chosen = 0; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_RETURN; if (controls.release(C_UP)) chosen = (chosen + options - 1) % options; if (controls.release(C_DOWN)) chosen = (chosen + 1) % options; if (controls.release(C_ENTER)) { playSound(S_ORB); return E_NONE; } if (controls.getCursor(x, y)) { if ((x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_RETURN; x -= canvasW >> 2; y -= (canvasH >> 1) - (options << 3); if ((x >= 0) && (x < 256) && (y >= 0) && (y < (options << 4))) { chosen = y >> 4; if (controls.wasCursorReleased()) { playSound(S_ORB); return E_NONE; } } } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); for (count = 0; count < options; count++) { if (count == chosen) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString(optionNames[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - (options << 3)); if (count == chosen) fontmn2->restorePalette(); } showEscString(); } return E_NONE; } /** * Let the user edit a text string * * @param request Description of the text string * @param text The text string to be edited * * @return Error code */ int Menu::textInput (const char* request, char*& text) { char *input; int count, terminate, character, x, y; unsigned int cursor; video.setPalette(menuPalette); // Create input string input = createEditableString(text); cursor = strlen(input); while (true) { character = loop(TYPING_LOOP); if (character == E_QUIT) { delete[] input; return E_QUIT; } // Ensure there is space for another character if (cursor < STRING_LENGTH) { terminate = (input[cursor] == 0); // If the character is valid, add it to the input string if ((character == ' ') || (character == '.') || ((character >= '0') && (character <= '9')) || ((character >= 'a') && (character <= 'z'))) { input[cursor] = character; cursor++; if (terminate) input[cursor] = 0; } else if ((character >= 'A') && (character <= 'Z')) { input[cursor] = character | 32; cursor++; if (terminate) input[cursor] = 0; } } if ((character == SDLK_DELETE) && (cursor < strlen(input))) { for (count = cursor; count < STRING_LENGTH; count++) input[count] = input[count + 1]; } if ((character == SDLK_BACKSPACE) && (cursor > 0)) { for (count = cursor - 1; count < STRING_LENGTH; count++) input[count] = input[count + 1]; cursor--; } if (controls.release(C_ESCAPE) || (controls.getCursor(x, y) && (x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased())) { delete[] input; return E_RETURN; } SDL_Delay(T_MENU_FRAME); video.clearScreen(15); // Draw the prompt fontmn2->showString(request, canvasW >> 2, (canvasH >> 1) - 16); // Draw the section of the text before the cursor fontmn2->mapPalette(240, 8, 114, 16); terminate = input[cursor]; input[cursor] = 0; x = fontmn2->showString(input, (canvasW >> 2) + 8, canvasH >> 1); // Draw the cursor drawRect(x, (canvasH >> 1) + 10, 8, 2, 79); // Draw the section of text after the cursor input[cursor] = terminate; fontmn2->showString(input + cursor, x, canvasH >> 1); fontmn2->restorePalette(); showEscString(); if (controls.release(C_LEFT) && (cursor > 0)) cursor--; if (controls.release(C_RIGHT) && (cursor < strlen(input))) cursor++; if (controls.release(C_ENTER)) { playSound(S_ORB); // Replace the original string with the input string delete[] text; text = input; return E_NONE; } } delete[] input; return E_RETURN; } openjazz-20190106/src/menu/menu.h000066400000000000000000000053501341440264100164700ustar00rootroot00000000000000 /** * * @file menu.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 3rd February 2009: Created menu.h from parts of OpenJazz.h * - 21st July 2013: Created setup.h from parts of menu.h * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _MENU_H #define _MENU_H #include "game/gamemode.h" #include "io/file.h" #include "OpenJazz.h" // Constants #define ESCAPE_STRING "(esc) quits" // Demo timeout #define T_DEMO 20000 // Classes /// Menu base class, providing generic menu screens class Menu { protected: void showEscString (); int message (const char* text); int generic (const char** optionNames, int options, int& chosen); int textInput (const char* request, char*& text); }; /// New game menus class GameMenu : public Menu { private: SDL_Surface* episodeScreens[11]; ///< Episode images SDL_Surface* difficultyScreen; ///< 4 difficulty images SDL_Color palette[256]; ///< Episode selection palette SDL_Color greyPalette[256]; ///< Greyed-out episode selection palette int episodes; ///< Number of episodes unsigned char difficulty; ///< Difficulty setting (0 = easy, 1 = medium, 2 = hard, 3 = turbo (hard in JJ2 levels)) int playNewGame (GameModeType mode, char* firstLevel); int newGameDifficulty (GameModeType mode, char* firstLevel); int newGameDifficulty (GameModeType mode, int levelNum, int worldNum); int newGameLevel (GameModeType mode); int selectEpisode (GameModeType mode, int episode); int newGameEpisode (GameModeType mode); int joinGame (); public: GameMenu (File* file); ~GameMenu (); int newGame (); int loadGame (); }; /// Setup menus class SetupMenu : public Menu { private: int setupKeyboard (); int setupJoystick (); int setupResolution (); #ifdef SCALE int setupScaling (); #endif int setupSound (); public: int setupMain (); }; /// Main menu class MainMenu : public Menu { private: SDL_Surface* background; ///< Menu image SDL_Surface* highlight; ///< Menu image with highlighted text SDL_Surface* logo; ///< OJ logo image GameMenu* gameMenu; ///< New game menu SDL_Color palette[256]; ///< Menu palette int select (int option); public: MainMenu (); ~MainMenu (); int main (); }; // Variables EXTERN SDL_Color menuPalette[256]; /// Palette used by most menu screens #endif openjazz-20190106/src/menu/plasma.cpp000066400000000000000000000032671341440264100173410ustar00rootroot00000000000000 /** * * @file plasma.cpp * * Part of the OpenJazz project * * @par History: * - 23rd June 2010: Created plasma.cpp * * @par Licence: * Copyright (c) 2010 Alireza Nejati * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Cool plasma effects for the main menu. * */ #include "plasma.h" #include "level/level.h" #include "util.h" #include "io/gfx/video.h" #include #ifdef SCALE #include "io/gfx/scale2x/scalebit.h" #endif /** * Create the plasma. */ Plasma::Plasma(){ p0=0; p1=0; p2=0; p3=0; //fSin, fCos: pi = 512 // -1024 < out < 1024 } /** * Draw the plasma. * * @return Error code */ int Plasma::draw(){ int x,y; int t1,t2,t3,t4; int w,h,pitch; unsigned char *px; unsigned char colour; unsigned int colb; // draw plasma SDL_LockSurface(canvas); w = canvas->w; h = canvas->h; pitch = canvas->pitch; px = (unsigned char *)canvas->pixels; t1 = p0; t2 = p1; for(y=0;y>10) & 0xF; t3 += 3; t4 += 2; px[x] = colour; } // go to next row px += pitch; t1 += 2; t2 += 1; } p0 = p0 < 256 ? p0+1 : 1; p1 = p1 < 256 ? p1+2 : 2; p2 = p2 < 256 ? p2+3 : 3; p3 = p3 < 256 ? p3+4 : 4; SDL_UnlockSurface(canvas); return E_NONE; } openjazz-20190106/src/menu/plasma.h000066400000000000000000000012311341440264100167730ustar00rootroot00000000000000 /** * * @file plasma.h * * Part of the OpenJazz project * * @par History: * - 23rd June 2010: Created plasma.h * * @par Licence: * Copyright (c) 2010 Alireza Nejati * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PLASMA_H #define _PLASMA_H /// Main menu background plasma effect class Plasma { private: int p0,p1,p2,p3; public: Plasma (); int draw(); }; #endif openjazz-20190106/src/menu/setupmenu.cpp000066400000000000000000000365131341440264100201110ustar00rootroot00000000000000 /** * * @file setupmenu.cpp * * Part of the OpenJazz project * * @par History: * - 23rd of August 2005: Created menu.c * - 3rd of February 2009: Renamed menu.c to menu.cpp * - 18th July 2009: Created menusetup.cpp from parts of menu.cpp * - 26th July 2009: Renamed menusetup.cpp to setupmenu.cpp * - 21st July 2013: Created setup.cpp from parts of main.cpp and setupmenu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the running of setup menus. * */ #include "menu.h" #include "io/controls.h" #include "io/gfx/font.h" #include "io/gfx/video.h" #include "io/sound.h" #include "player/player.h" #include "loop.h" #include "setup.h" #include "util.h" /** * Run the keyboard setup menu. * * @return Error code */ int SetupMenu::setupKeyboard () { const char *options[PCONTROLS] = {"up", "down", "left", "right", "jump", "swim up", "fire", "weapon"}; int progress, character, x, y, count; progress = 0; while (true) { character = loop(SET_KEY_LOOP); if (character == E_QUIT) return E_QUIT; if (character == controls.getKey(C_ESCAPE)) return E_NONE; if (controls.getCursor(x, y) && (x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; if (character > 0) { // If this is a navigation controls (up, down, or enter), // make sure it's not the same as other navigation controls if (((progress != C_UP) && (progress != C_DOWN) && (progress != C_ENTER)) || (controls.getKey(progress) == character) || ((controls.getKey(C_UP) != character) && (controls.getKey(C_DOWN) != character) && (controls.getKey(C_ENTER) != character))) { controls.setKey(progress, character); progress++; if (progress == PCONTROLS) { // If all controls have been assigned, return playSound(S_ORB); return E_NONE; } } } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); for (count = 0; count < PCONTROLS; count++) { if (count < progress) fontmn2->showString("okay", (canvasW >> 2) + 176, (canvasH >> 1) + (count << 4) - 56); else if (count == progress) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString(options[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 56); if (count == progress) { fontmn2->showString("press key", (canvasW >> 2) + 112, (canvasH >> 1) + (count << 4) - 56); fontmn2->restorePalette(); } } showEscString(); } return E_NONE; } /** * Run the joystick setup menu. * * @return Error code */ int SetupMenu::setupJoystick () { const char *options[PCONTROLS] = {"up", "down", "left", "right", "jump", "swim up", "fire", "weapon"}; int progress, control, x, y, count; progress = 0; while (true) { control = loop(SET_JOYSTICK_LOOP); if (control == E_QUIT) return E_QUIT; switch (control & 0xF00) { case JOYSTICKB: // If this is a navigation controls (up, down, or enter), // make sure it's not the same as other navigation controls if (((progress != C_UP) && (progress != C_DOWN) && (progress != C_ENTER)) || (controls.getButton(progress) == (control & 0xFF)) || ((controls.getButton(C_UP) != (control & 0xFF)) && (controls.getButton(C_DOWN) != (control & 0xFF)) && (controls.getButton(C_ENTER) != (control & 0xFF)))) { controls.setButton(progress, control & 0xFF); progress++; if (progress == PCONTROLS) { // If all controls have been assigned, return playSound(S_ORB); return E_NONE; } } break; case JOYSTICKANEG: // If this is a navigation controls (up, down, or enter), // make sure it's not the same as other navigation controls if (((progress != C_UP) && (progress != C_DOWN) && (progress != C_ENTER)) || ((controls.getAxis(progress) == (control & 0xFF)) && !controls.getAxisDirection(progress)) || (((controls.getAxis(C_UP) != (control & 0xFF)) || controls.getAxisDirection(C_UP)) && ((controls.getAxis(C_DOWN) != (control & 0xFF)) || controls.getAxisDirection(C_DOWN)) && ((controls.getAxis(C_ENTER) != (control & 0xFF)) || controls.getAxisDirection(C_ENTER)))) { controls.setAxis(progress, control & 0xFF, false); progress++; if (progress == PCONTROLS) { // If all controls have been assigned, return playSound(S_ORB); return E_NONE; } } break; case JOYSTICKAPOS: // If this is a navigation controls (up, down, or enter), // make sure it's not the same as other navigation controls if (((progress != C_UP) && (progress != C_DOWN) && (progress != C_ENTER)) || ((controls.getAxis(progress) == (control & 0xFF)) && controls.getAxisDirection(progress)) || (((controls.getAxis(C_UP) != (control & 0xFF)) || !controls.getAxisDirection(C_UP)) && ((controls.getAxis(C_DOWN) != (control & 0xFF)) || !controls.getAxisDirection(C_DOWN)) && ((controls.getAxis(C_ENTER) != (control & 0xFF)) || !controls.getAxisDirection(C_ENTER)))) { controls.setAxis(progress, control & 0xFF, true); progress++; if (progress == PCONTROLS) { // If all controls have been assigned, return playSound(S_ORB); return E_NONE; } } break; } if (controls.release(C_ESCAPE)) return E_NONE; if ((controls.getCursor(x, y) && (x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased())) return E_NONE; SDL_Delay(T_MENU_FRAME); video.clearScreen(0); for (count = 0; count < PCONTROLS; count++) { if (count < progress) fontmn2->showString("okay", (canvasW >> 2) + 176, (canvasH >> 1) + (count << 4) - 56); else if (count == progress) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString(options[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 56); if (count == progress) { fontmn2->showString("press control", (canvasW >> 2) + 112, (canvasH >> 1) + (count << 4) - 56); fontmn2->restorePalette(); } } showEscString(); } return E_NONE; } /** * Run the resolution setup menu. * * @return Error code */ int SetupMenu::setupResolution () { int widthOptions[] = {SW, 352, 384, 400, 480, 512, 640, 720, 768, 800, 960, 1024, 1152, 1280, 1366, 1400, 1440, 1600, 1680, 1920, 2048, 2560, 3200, 3440, 3840, 4096, MAX_SCREEN_WIDTH}; int heightOptions[] = {SH, 240, 288, 300, 320, 384, 400, 480, 576, 600, 720, 768, 800, 864, 900, 960, 1024, 1050, 1080, 1152, 1200, 1440, 1536, 1600, 2048, 2160, MAX_SCREEN_HEIGHT}; int screenW, screenH, x, y, count; bool dimension; screenW = video.getWidth(); screenH = video.getHeight(); dimension = false; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_ENTER)) return E_NONE; if (controls.getCursor(x, y)) { if ((x >= 32) && (x < 132) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; dimension = (x >= (canvasW >> 2) + 44); } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); // Show screen corners drawRect(0, 0, 32, 32, 79); drawRect(canvasW - 32, 0, 32, 32, 79); drawRect(canvasW - 32, canvasH - 32, 32, 32, 79); drawRect(0, canvasH - 32, 32, 32, 79); // X fontmn2->showString("x", (canvasW >> 2) + 40, canvasH >> 1); if (!dimension) fontmn2->mapPalette(240, 8, 114, 16); // Width fontmn2->showNumber(screenW, (canvasW >> 2) + 32, canvasH >> 1); if (!dimension) fontmn2->restorePalette(); else fontmn2->mapPalette(240, 8, 114, 16); // Height fontmn2->showNumber(screenH, (canvasW >> 2) + 104, canvasH >> 1); if (dimension) fontmn2->restorePalette(); count = 0; if (controls.release(C_LEFT)) dimension = !dimension; if (controls.release(C_RIGHT)) dimension = !dimension; if (controls.release(C_UP)) { if ((!dimension) && (screenW < video.getMaxWidth())) { while (screenW >= widthOptions[count]) count++; screenW = widthOptions[count]; } if (dimension && (screenH < video.getMaxHeight())) { while (screenH >= heightOptions[count]) count++; screenH = heightOptions[count]; } } if (controls.release(C_DOWN)) { if ((!dimension) && (screenW > SW)) { count = 18; while (screenW <= widthOptions[count]) count--; screenW = widthOptions[count]; count = -1; } if (dimension && (screenH > SH)) { count = 22; while (screenH <= heightOptions[count]) count--; screenH = heightOptions[count]; count = -1; } } // Check for a resolution change if (count) { playSound(S_ORB); video.reset(screenW, screenH); } fontbig->showString(ESCAPE_STRING, 35, canvasH - 12); } return E_NONE; } #ifdef SCALE /** * Run the scaling setup menu. * * @return Error code */ int SetupMenu::setupScaling () { int scaleFactor, x, y; scaleFactor = video.getScaleFactor(); if ( scaleFactor < MIN_SCALE || scaleFactor > MAX_SCALE ) scaleFactor = 1; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_ENTER)) return E_NONE; if (controls.getCursor(x, y) && (x >= 32) && (x < 132) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; SDL_Delay(T_MENU_FRAME); video.clearScreen(0); // Show screen corners drawRect(0, 0, 32, 32, 79); drawRect(canvasW - 32, 0, 32, 32, 79); drawRect(canvasW - 32, canvasH - 32, 32, 32, 79); drawRect(0, canvasH - 32, 32, 32, 79); fontmn2->mapPalette(240, 8, 114, 16); // Scale fontmn2->showNumber(video.getScaleFactor(), (canvasW >> 2) + 32, canvasH >> 1); // X fontmn2->showString("x", (canvasW >> 2) + 40, canvasH >> 1); fontmn2->restorePalette(); if ((controls.release(C_DOWN) || controls.release(C_LEFT)) && (scaleFactor > MIN_SCALE)) scaleFactor--; if ((controls.release(C_UP) || controls.release(C_RIGHT)) && (scaleFactor < MAX_SCALE)) scaleFactor++; // Check for a scaling change if (scaleFactor != video.getScaleFactor()) { playSound(S_ORB); scaleFactor = video.setScaleFactor(scaleFactor); } fontbig->showString(ESCAPE_STRING, 35, canvasH - 12); } return E_NONE; } #endif /** * Run the audio setup menu. * * @return Error code */ int SetupMenu::setupSound () { int x, y; bool soundActive; soundActive = false; while (true) { if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_ENTER)) return E_NONE; if (controls.getCursor(x, y)) { if ((x < 100) && (y >= canvasH - 12) && controls.wasCursorReleased()) return E_NONE; x -= (canvasW >> 2) + 128; y -= canvasH >> 1; if ((x >= 0) && (x < (MAX_VOLUME >> 1)) && (y >= 0) && (y < 11)) setMusicVolume(x << 1); if ((x >= 0) && (x < (MAX_VOLUME >> 1)) && (y >= 16) && (y < 27)) setSoundVolume(x << 1); if (controls.wasCursorReleased()) playSound(S_ORB); } SDL_Delay(T_MENU_FRAME); video.clearScreen(0); // Music Volume if (!soundActive) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString("music volume", canvasW >> 2, canvasH >> 1); fontmn2->restorePalette(); drawRect((canvasW >> 2) + 128, canvasH >> 1, getMusicVolume() >> 1, 11, 175); // Sound Volume if (soundActive) fontmn2->mapPalette(240, 8, 114, 16); fontmn2->showString("effect volume", canvasW >> 2, (canvasH >> 1) + 16); fontmn2->restorePalette(); drawRect((canvasW >> 2) + 128, (canvasH >> 1) + 16, getSoundVolume() >> 1, 11, 175); if (controls.release(C_UP)) soundActive = !soundActive; if (controls.release(C_DOWN)) soundActive = !soundActive; if (controls.release(C_LEFT)) { if (soundActive) setSoundVolume(getSoundVolume() - 4); else setMusicVolume(getMusicVolume() - 4); playSound(S_ORB); } if (controls.release(C_RIGHT)) { if (soundActive) setSoundVolume(getSoundVolume() + 4); else setMusicVolume(getMusicVolume() + 4); playSound(S_ORB); } showEscString(); } return E_NONE; } /** * Run the setup menu. * * @return Error code */ int SetupMenu::setupMain () { const char* setupOptions[7] = {"character", "keyboard", "joystick", "resolution", "scaling", "sound", "gameplay"}; const char* setupCharacterOptions[5] = {"name", "fur", "bandana", "gun", "wristband"}; const char* setupCharacterColOptions[8] = {"white", "red", "orange", "yellow", "green", "blue", "animation 1", "animation 2"}; const unsigned char setupCharacterCols[8] = {PC_GREY, PC_RED, PC_ORANGE, PC_YELLOW, PC_LGREEN, PC_BLUE, PC_SANIM, PC_LANIM}; const char* setupModsOff[3] = {"slow motion off", "take extra items", "one-bird limit"}; const char* setupModsOn[3] = {"slow motion on", "leave extra items", "unlimited birds"}; const char* setupMods[3]; int ret; int option, suboption, subsuboption; option = 0; setupMods[0] = (setup.slowMotion? setupModsOn[0]: setupModsOff[0]); setupMods[1] = (setup.leaveUnneeded? setupModsOn[1]: setupModsOff[1]); setupMods[2] = (setup.manyBirds? setupModsOn[2]: setupModsOff[2]); video.setPalette(menuPalette); while (true) { ret = generic(setupOptions, 7, option); if (ret == E_RETURN) return E_NONE; if (ret < 0) return ret; switch (option) { case 0: suboption = 0; while (true) { ret = generic(setupCharacterOptions, 5, suboption); if (ret == E_QUIT) return E_QUIT; if (ret < 0) break; switch (suboption) { case 0: // Character name if (textInput("character name:", setup.characterName) == E_QUIT) return E_QUIT; break; default: // Character colour subsuboption = 0; ret = generic(setupCharacterColOptions, 8, subsuboption); if (ret == E_QUIT) return E_QUIT; if (ret == E_NONE) setup.characterCols[suboption - 1] = setupCharacterCols[subsuboption]; break; } } break; case 1: #if !defined(CAANOO) && !defined(WIZ) && !defined(GP2X) && !defined(PSP) if (setupKeyboard() == E_QUIT) return E_QUIT; #else if (message("FEATURE NOT AVAILABLE") == E_QUIT) return E_QUIT; #endif break; case 2: #if !defined(DINGOO) && !defined(PSP) if (setupJoystick() == E_QUIT) return E_QUIT; #else if (message("FEATURE NOT AVAILABLE") == E_QUIT) return E_QUIT; #endif break; case 3: #ifndef NO_RESIZE if (setupResolution() == E_QUIT) return E_QUIT; #else if (message("FEATURE NOT AVAILABLE") == E_QUIT) return E_QUIT; #endif break; case 4: #ifdef SCALE if (setupScaling() == E_QUIT) return E_QUIT; #else if (message("FEATURE NOT AVAILABLE") == E_QUIT) return E_QUIT; #endif break; case 5: if (setupSound() == E_QUIT) return E_QUIT; break; case 6: suboption = 0; while (true) { ret = generic(setupMods, 3, suboption); if (ret == E_QUIT) return E_QUIT; if (ret < 0) break; if (setupMods[suboption] == setupModsOff[suboption]) setupMods[suboption] = setupModsOn[suboption]; else setupMods[suboption] = setupModsOff[suboption]; setup.slowMotion = (setupMods[0] == setupModsOn[0]); setup.leaveUnneeded = (setupMods[1] == setupModsOn[1]); setup.manyBirds = (setupMods[2] == setupModsOn[2]); } break; } } return E_NONE; } openjazz-20190106/src/platforms/000077500000000000000000000000001341440264100164135ustar00rootroot00000000000000openjazz-20190106/src/platforms/symbian.cpp000066400000000000000000000060571341440264100205710ustar00rootroot00000000000000 /** * * @file symbian.cpp * * Part of the OpenJazz project * * @section Licence * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include char KOpenJazzPath[256]; FILE* mystdout = NULL; FILE *mystderr = NULL; /// Symbian app class COpenJazzApp: public CSDLApp { public: COpenJazzApp(); ~COpenJazzApp(); #ifdef UIQ3 /** * Returns the resource id to be used to declare the views supported by this UIQ3 app * @return TInt, resource id */ TInt ViewResourceId(); #endif /** * This has a default empty implementation. * Is called just before SDL_Main is called to allow init of system vars */ virtual void PreInitializeAppL(); TUid AppDllUid() const; }; CApaApplication* NewApplication() { // Return pointer to newly created CQMApp return new COpenJazzApp; } #include // E32Main() contains the program's start up code, the entry point for an EXE. GLDEF_C TInt E32Main() { return EikStart::RunApplication(NewApplication); } COpenJazzApp::COpenJazzApp() { } COpenJazzApp::~COpenJazzApp() { fflush(mystdout); fflush(mystderr); fflush(stdout); fflush(stderr); fclose(stdout); fclose(stderr); } #ifdef UIQ3 #include /** * Returns the resource id to be used to declare the views supported by this UIQ3 app * @return TInt, resource id */ TInt COpenJazzApp::ViewResourceId() { return R_SDL_VIEW_UI_CONFIGURATIONS; } #endif /** * This has a default empty implementation. * Is called just before SDL_Main is called to allow init of system vars */ void COpenJazzApp::PreInitializeAppL() { TFileName filename; TPtr8 ptr((unsigned char*) KOpenJazzPath, 0, 255); #ifdef UIQ3 mystdout = fopen("c:\\shared\\openjazz\\stdout.txt","w+"); mystderr = fopen("c:\\shared\\openjazz\\stderr.txt","w+"); #else mystdout = fopen("c:\\data\\openjazz\\stdout.txt","w+"); mystderr = fopen("c:\\data\\openjazz\\stderr.txt","w+"); #endif *stderr = *mystdout; *stdout = *mystderr; filename = _L("C:\\openjazz\\"); for(TInt i = 'D';i<'Z';i++) { filename[0] = i; if(BaflUtils::PathExists(CEikonEnv::Static()->FsSession(), filename)) { ptr.Copy(filename); ptr.ZeroTerminate(); return; } } #ifdef UIQ3 ptr.Copy(_L8("c:\\shared\\openjazz\\")); #else ptr.Copy(_L8("c:\\data\\openjazz\\")); #endif ptr.ZeroTerminate(); } /** * Responsible for returning the unique UID of this application * @return unique UID for this application in a TUid **/ TUid COpenJazzApp::AppDllUid() const { return TUid::Uid(0xA000A005); } float sinf(float value) { TReal ret; Math::Sin(ret, value); return ret; } ///////////////////////////////////////////////////////////////////////////////////////////////// openjazz-20190106/src/platforms/wiz.cpp000066400000000000000000000024141341440264100177310ustar00rootroot00000000000000 /** * * @file wiz.cpp * * Part of the OpenJazz project * * @par Licence: * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "wiz.h" #if defined(WIZ) || defined(GP2X) #include #include #include #include #include #include "io/sound.h" void WIZ_AdjustVolume( int direction ) { if( direction != VOLUME_NOCHG ) { if( volume <= 10 ) { if( direction == VOLUME_UP ) volume += VOLUME_CHANGE_RATE/2; if( direction == VOLUME_DOWN ) volume -= VOLUME_CHANGE_RATE/2; } else { if( direction == VOLUME_UP ) volume += VOLUME_CHANGE_RATE; if( direction == VOLUME_DOWN ) volume -= VOLUME_CHANGE_RATE; } if( volume < VOLUME_MIN ) volume = VOLUME_MIN; if( volume > VOLUME_MAX ) volume = VOLUME_MAX; printf( "Volume Change: %i\n", volume ); } unsigned long soundDev = open("/dev/mixer", O_RDWR); if(soundDev) { int vol = ((volume << 8) | volume); ioctl(soundDev, SOUND_MIXER_WRITE_PCM, &vol); close(soundDev); } } #endif openjazz-20190106/src/platforms/wiz.h000066400000000000000000000013371341440264100174010ustar00rootroot00000000000000 /** * * @file wiz.h * * Part of the OpenJazz project * * @par Licence: * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _WIZ_H #define _WIZ_H #if defined(WIZ) || defined(GP2X) #define GP2X_BUTTON_VOLUP (16) #define GP2X_BUTTON_VOLDOWN (17) #define VOLUME_MIN 0 #define VOLUME_MAX 100 #define VOLUME_CHANGE_RATE 2 #define VOLUME_NOCHG 0 #define VOLUME_DOWN 1 #define VOLUME_UP 2 void WIZ_AdjustVolume( int direction ); #endif #endif openjazz-20190106/src/player/000077500000000000000000000000001341440264100157005ustar00rootroot00000000000000openjazz-20190106/src/player/player.cpp000066400000000000000000000220501341440264100176770ustar00rootroot00000000000000 /** * * @file player.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created level.c * - 1st January 2006: Created events.c from parts of level.c * - 3rd February 2009: Renamed events.c to events.cpp and level.c to level.cpp, * created player.cpp * - 5th February 2009: Added parts of events.cpp and level.cpp to player.cpp * - 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp * - 18th July 2009: Created playerframe.cpp from parts of player.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the creation and destruction of players, and their interactions * with other objects. * */ #include "jj1bonuslevel/jj1bonuslevelplayer/jj1bonuslevelplayer.h" #include "jj1level/jj1levelplayer/jj1levelplayer.h" #include "jj2level/jj2levelplayer/jj2levelplayer.h" #include "level/levelplayer.h" #include "game/game.h" #include "io/controls.h" #include "util.h" #include /** * Create the player. */ Player::Player () { levelPlayer = NULL; name = NULL; return; } /** * Delete the player. */ Player::~Player () { deinit(); return; } /** * Initialise player data. * * Deinitialise any existing player data, assign properties and initial values. * * @param owner The current game * @param playerName Name (displayed in multiplayer games) * @param playerCols Colours (only used in multiplayer games) * @param newTeam Team (in multiplayer games) */ void Player::init (Game* owner, char *playerName, unsigned char *playerCols, unsigned char newTeam) { // Clear existing player deinit(); // Assign owner game = owner; // Assign name name = createString(playerName); // Assign initial values score = 0; lives = 3; ammoType = -1; ammo[0] = 0; ammo[1] = 0; ammo[2] = 0; ammo[3] = 0; ammo[4] = 0; fireSpeed = 0; flockSize = 0; team = newTeam; teamScore = 0; if (playerCols) { memcpy(cols, playerCols, PCOLOURS); } else { cols[0] = CHAR_FUR; cols[1] = CHAR_BAND; cols[2] = CHAR_GUN; cols[3] = CHAR_WBAND; } return; } /** * Deinitialise player data. */ void Player::deinit () { if (levelPlayer) delete levelPlayer; levelPlayer = NULL; if (name) delete[] name; name = NULL; return; } /** * Discard all the player's ammo. */ void Player::clearAmmo () { int type; for (type = 0; type < 5; type++) ammo[type] = 0; ammoType = -1; fireSpeed = 0; return; } /** * Reset the player's current level player. * * @param x The level player's new grid x-coordinate * @param y The level player's new grid y-coordinate */ void Player::reset (int x, int y) { levelPlayer->reset(x, y); return; } /** * Create a new level player for the player (and delete any existing one). * * @param levelType The type of level for which to create a level player * @param anims New level player animations * @param flippedAnims New level player flipped animations * @param x The level player's new grid x-coordinate * @param y The level player's new grid y-coordinate */ void Player::createLevelPlayer (LevelType levelType, Anim** anims, Anim** flippedAnims, unsigned char x, unsigned char y) { int count; if (levelPlayer) { flockSize = levelPlayer->countBirds(); delete levelPlayer; } switch (levelType) { case LT_JJ1: levelPlayer = new JJ1LevelPlayer(this, anims, x, y, flockSize); break; case LT_JJ1BONUS: levelPlayer = new JJ1BonusLevelPlayer(this, anims, x, y, flockSize); break; case LT_JJ2: levelPlayer = new JJ2LevelPlayer(this, anims, flippedAnims, x, y, flockSize); break; } for (count = 0; count < PCONTROLS; count++) pcontrols[count] = false; return; } /** * Get the player's level player. * * @return The level player */ LevelPlayer* Player::getLevelPlayer () { return levelPlayer; } /** * Get the player's colours. * * @return The player's colours */ unsigned char * Player::getCols () { return cols; } /** * Get the player's name. * * @return The player's name */ char * Player::getName () { return name; } /** * Get the player's JJ1 bonus level player. * * @return The JJ1 bonus level player */ JJ1BonusLevelPlayer* Player::getJJ1BonusLevelPlayer () { return dynamic_cast(levelPlayer); } /** * Get the player's JJ1 level player. * * @return The JJ1 level player */ JJ1LevelPlayer* Player::getJJ1LevelPlayer () { return dynamic_cast(levelPlayer); } /** * Get the player's JJ2 level player. * * @return The JJ2 level player */ JJ2LevelPlayer* Player::getJJ2LevelPlayer () { return dynamic_cast(levelPlayer); } /** * Set the state of the specified control. * * @param control Affected control * @param state New state */ void Player::setControl (int control, bool state) { pcontrols[control] = state; return; } /** * Get the state of the specified control. * * @param control The control * * @return State */ bool Player::getControl (int control) { return pcontrols[control]; } /** * Add to the player's total score. * * @param addedScore The amount to be added */ void Player::addScore (int addedScore) { score += addedScore; return; } /** * Get the player's score. */ int Player::getScore () { return score; } /** * Add an extra life to the player. */ void Player::addLife () { if (lives < 99) lives++; return; } /** * Get the number of extra lives. * * @return Number of extra lives */ int Player::getLives () { return lives; } /** * Add ammo to the player's arsenal. * * @param type Type of ammo * @param amount Amount of ammo to add */ void Player::addAmmo (int type, int amount) { if (!ammo[type]) ammoType = type; ammo[type] += amount; return; } /** * Get the current type of ammo. * * @return The type of ammo */ int Player::getAmmoType () { return ammoType; } /** * Get the total amount of ammo of the current type. * * @return The amount of ammo */ int Player::getAmmo () { return ammo[ammoType]; } /** * Get the player's team * * @return Team number */ unsigned char Player::getTeam () { return team; } /** * Deal with bullet collisions. * * @param source Player that fired the bullet (NULL if an event) * * @return Whether or not the hit was successful */ bool Player::hit (Player *source) { return game->getMode()->hit(source, this); } /** * Kill the player. * * @param source Player responsible for the kill (NULL if due to an event or time) * * @return Whether or not the kill was successful */ bool Player::kill (Player *source) { return game->getMode()->kill(game, source, this); } /** * Set the checkpoint * * @param gridX X-coordinate (in tiles) of the checkpoint * @param gridY Y-coordinate (in tiles) of the checkpoint */ void Player::setCheckpoint (int gridX, int gridY) { game->setCheckpoint(gridX, gridY); return; } /** * Outcome of level being completed * * @param gridX X-coordinate (in tiles) of finishing position * @param gridY Y-coordinate (in tiles) of finishing position * * @return Whether or not the level should end */ bool Player::endOfLevel (int gridX, int gridY) { return game->getMode()->endOfLevel(game, this, gridX, gridY); } /** * Copy data to be sent to clients/server */ void Player::send (unsigned char *buffer) { buffer[3] = pcontrols[C_UP]; buffer[4] = pcontrols[C_DOWN]; buffer[5] = pcontrols[C_LEFT]; buffer[6] = pcontrols[C_RIGHT]; buffer[7] = pcontrols[C_JUMP]; buffer[8] = pcontrols[C_FIRE]; buffer[10] = ammo[0] >> 8; buffer[11] = ammo[0] & 255; buffer[12] = ammo[1] >> 8; buffer[13] = ammo[1] & 255; buffer[14] = ammo[2] >> 8; buffer[15] = ammo[2] & 255; buffer[16] = ammo[3] >> 8; buffer[17] = ammo[3] & 255; buffer[18] = ammoType + 1; buffer[19] = score >> 24; buffer[20] = (score >> 16) & 255; buffer[21] = (score >> 8) & 255; buffer[22] = score & 255; buffer[24] = lives; buffer[28] = fireSpeed; buffer[45] = pcontrols[C_SWIM]; if (levelPlayer) levelPlayer->send(buffer); return; } /** * Interpret data received from client/server */ void Player::receive (unsigned char *buffer) { if (buffer[1] == MT_P_TEMP) { pcontrols[C_UP] = buffer[3]; pcontrols[C_DOWN] = buffer[4]; pcontrols[C_LEFT] = buffer[5]; pcontrols[C_RIGHT] = buffer[6]; pcontrols[C_JUMP] = buffer[7]; pcontrols[C_SWIM] = buffer[45]; pcontrols[C_FIRE] = buffer[8]; pcontrols[C_CHANGE] = false; flockSize = buffer[9]; ammo[0] = (buffer[10] << 8) + buffer[11]; ammo[1] = (buffer[12] << 8) + buffer[13]; ammo[2] = (buffer[14] << 8) + buffer[15]; ammo[3] = (buffer[16] << 8) + buffer[17]; ammoType = buffer[18] - 1; score = (buffer[19] << 24) + (buffer[20] << 16) + (buffer[21] << 8) + buffer[22]; lives = buffer[24]; fireSpeed = buffer[28]; } if (levelPlayer) levelPlayer->receive(buffer); return; } openjazz-20190106/src/player/player.h000066400000000000000000000077151341440264100173570ustar00rootroot00000000000000 /** * * @file player.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 31st January 2006: Created player.h from parts of OpenJazz.h * - 24th June 2010: Created levelplayer.h from parts of player.h * - 24th June 2010: Created bonusplayer.h from parts of player.h * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ /* "Tile" is a flexible term. Here it is used to refer specifically to the individual elements of the tile set. "Tiles" in the context of level units are referred to as grid elements. */ #ifndef _PLAYER_H #define _PLAYER_H #include "level/level.h" // Constants // Player defaults #define CHAR_NAME "jazz" #define CHAR_FUR 4 #define CHAR_BAND 3 #define CHAR_GUN 2 #define CHAR_WBAND 8 // General #define PCONTROLS 8 /* Number of player controls. */ // Number of configurable player colour ranges #define PCOLOURS 4 // Enums /// Player colours enum PlayerColour { PC_GREY = 0, PC_SGREEN = 1, PC_BLUE = 2, PC_RED = 3, PC_LGREEN = 4, PC_LEVEL1 = 5, PC_YELLOW = 6, PC_LEVEL2 = 7, PC_ORANGE = 8, PC_LEVEL3 = 9, PC_LEVEL4 = 10, PC_SANIM = 11, PC_LANIM = 12, PC_LEVEL5 = 13 }; // Classes class Anim; class JJ1LevelPlayer; class JJ1BonusLevelPlayer; class JJ2LevelPlayer; class LevelPlayer; /// Game player class Player { private: Game* game; LevelPlayer* levelPlayer; ///< Level player base class char* name; ///< Name bool pcontrols[PCONTROLS]; ///< Control status unsigned char cols[PCOLOURS]; ///< Character colours int ammo[5]; ///< Amount of ammo int ammoType; ///< Ammo type. -1 = blaster, 0 = toaster, 1 = missiles, 2 = bouncer, 3 = unknown, 4 = TNT int score; ///< Total score int lives; ///< Remaining lives int fireSpeed; ///< Rapid-fire rate int flockSize; ///< Number of accompanying birds unsigned char team; ///< Team ID void addAmmo (int type, int amount); public: int teamScore; ///< Team's total score Player (); ~Player (); void init (Game* owner, char* playerName, unsigned char* cols, unsigned char newTeam); void deinit (); void clearAmmo (); void reset (int x, int y); void createLevelPlayer (LevelType levelType, Anim** anims, Anim** flippedAnims, unsigned char x, unsigned char y); LevelPlayer* getLevelPlayer (); JJ1BonusLevelPlayer* getJJ1BonusLevelPlayer (); JJ1LevelPlayer* getJJ1LevelPlayer (); JJ2LevelPlayer* getJJ2LevelPlayer (); void addLife (); void addScore (int addedScore); bool endOfLevel (int gridX, int gridY); int getAmmoType (); int getAmmo (); unsigned char* getCols (); bool getControl (int control); int getLives (); char* getName (); int getScore (); unsigned char getTeam (); bool hit (Player* source); bool kill (Player* source); void setCheckpoint (int gridX, int gridY); void setControl (int control, bool state); void send (unsigned char* buffer); void receive (unsigned char* buffer); friend class JJ1LevelPlayer; friend class JJ2LevelPlayer; }; // Variables EXTERN Player* players; EXTERN Player* localPlayer; EXTERN int nPlayers; #endif openjazz-20190106/src/setup.cpp000066400000000000000000000120301341440264100162440ustar00rootroot00000000000000 /** * * @file setup.cpp * * Part of the OpenJazz project * * @par History: * - 23rd of August 2005: Created main.c and menu.c * - 3rd of February 2009: Renamed main.c to main.cpp and menu.c to menu.cpp * - 18th July 2009: Created menusetup.cpp from parts of menu.cpp * - 26th July 2009: Renamed menusetup.cpp to setupmenu.cpp * - 21st July 2013: Created setup.cpp from parts of main.cpp and setupmenu.cpp * * @par Licence: * Copyright (c) 2005-2017 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Deals with the running of setup menus. * */ #include "io/controls.h" #include "io/file.h" #include "io/gfx/video.h" #include "io/sound.h" #include "player/player.h" #include "setup.h" #include "util.h" #ifdef __SYMBIAN32__ #ifdef UIQ3 #define CONFIG_FILE "c:\\shared\\openjazz\\openjazz.cfg" #else #define CONFIG_FILE "c:\\data\\openjazz\\openjazz.cfg" #endif #else #define CONFIG_FILE "openjazz.cfg" #endif /** * Create default setup */ Setup::Setup () { // Create the player's name characterName = createEditableString(CHAR_NAME); // Assign the player's colour characterCols[0] = CHAR_FUR; characterCols[1] = CHAR_BAND; characterCols[2] = CHAR_GUN; characterCols[3] = CHAR_WBAND; return; } /** * Delete the setup data */ Setup::~Setup () { delete[] characterName; } /** * Load settings from config file. */ void Setup::load (int* videoW, int* videoH, bool* fullscreen, int* videoScale) { File* file; int count; // Open config file try { file = new File(CONFIG_FILE, false); } catch (int e) { log("Configuration file not found."); return; } // Check that the config file has the correct version if (file->loadChar() != 3) { log("Valid configuration file not found."); return; } // Read video settings *videoW = file->loadShort(MAX_SCREEN_WIDTH); *videoH = file->loadShort(MAX_SCREEN_HEIGHT); count = file->loadChar(); #ifndef FULLSCREEN_ONLY *fullscreen = count & 1; #endif #ifdef SCALE if (count >= 10) count = 2; *videoScale = count >> 1; #endif // Read controls for (count = 0; count < CONTROLS - 4; count++) controls.setKey(count, (SDLKey)(file->loadInt())); for (count = 0; count < CONTROLS; count++) controls.setButton(count, file->loadInt()); for (count = 0; count < CONTROLS; count++) { int a, d; a = file->loadInt(); d = file->loadInt(); controls.setAxis(count, a, d); } // Read the player's name for (count = 0; count < STRING_LENGTH; count++) setup.characterName[count] = file->loadChar(); setup.characterName[STRING_LENGTH] = 0; // Read the player's colours setup.characterCols[0] = file->loadChar(); setup.characterCols[1] = file->loadChar(); setup.characterCols[2] = file->loadChar(); setup.characterCols[3] = file->loadChar(); // Read the music and sound effect volume setMusicVolume(file->loadChar()); setSoundVolume(file->loadChar()); // Read gameplay options count = file->loadChar(); setup.slowMotion = ((count & 4) != 0); setup.manyBirds = ((count & 1) != 0); setup.leaveUnneeded = ((count & 2) != 0); delete file; return; } /** * Save settings to config file. */ void Setup::save () { File *file; int count; int videoScale; // Open config file try { file = new File(CONFIG_FILE, true); } catch (int e) { file = NULL; } // Check that the config file was opened if (!file) { logError("Could not write configuration file", "File could not be opened."); return; } // Write the version number file->storeChar(3); // Write video settings file->storeShort(video.getWidth()); file->storeShort(video.getHeight()); #ifdef SCALE videoScale = video.getScaleFactor(); #else videoScale = 1; #endif videoScale <<= 1; #ifndef FULLSCREEN_ONLY videoScale |= video.isFullscreen()? 1: 0; #endif file->storeChar(videoScale); // Write controls for (count = 0; count < CONTROLS - 4; count++) file->storeInt(controls.getKey(count)); for (count = 0; count < CONTROLS; count++) file->storeInt(controls.getButton(count)); for (count = 0; count < CONTROLS; count++) { file->storeInt(controls.getAxis(count)); file->storeInt(controls.getAxisDirection(count)); } // Write the player's name for (count = 0; count < STRING_LENGTH; count++) file->storeChar(setup.characterName[count]); // Write the player's colour file->storeChar(setup.characterCols[0]); file->storeChar(setup.characterCols[1]); file->storeChar(setup.characterCols[2]); file->storeChar(setup.characterCols[3]); // Write the music and sound effect volume file->storeChar(getMusicVolume()); file->storeChar(getSoundVolume()); // Write gameplay options count = 0; if (setup.slowMotion) count |= 4; if (setup.manyBirds) count |= 1; if (setup.leaveUnneeded) count |= 2; file->storeChar(count); delete file; return; } openjazz-20190106/src/setup.h000066400000000000000000000021021341440264100157100ustar00rootroot00000000000000 /** * * @file setup.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 3rd February 2009: Created menu.h from parts of OpenJazz.h * - 21st July 2013: Created setup.h from parts of menu.h * * @par Licence: * Copyright (c) 2005-2013 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _SETUP_H #define _SETUP_H #include "player/player.h" #include "OpenJazz.h" // Class /// Configuration class Setup { public: char* characterName; unsigned char characterCols[PCOLOURS]; bool slowMotion; bool leaveUnneeded; bool manyBirds; Setup (); ~Setup (); void load (int* videoW, int* videoH, bool* fullscreen, int* videoScale); void save (); }; // Variable EXTERN Setup setup; #endif openjazz-20190106/src/util.cpp000066400000000000000000000140071341440264100160670ustar00rootroot00000000000000 /** * * @file util.cpp * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created main.c * - 22nd July 2008: Created util.c from parts of main.c * - 3rd February 2009: Renamed util.c to util.cpp * - 3rd February 2009: Created file.cpp from parts of util.cpp * - 4th February 2009: Created palette.cpp from parts of main.cpp and util.cpp * - 13th July 2009: Created graphics.cpp from parts of util.cpp * * @par Licence: * Copyright (c) 2005-2012 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * @par Description: * Contains core utility functions. * */ #include "util.h" #include "io/file.h" #include /** * Check if a file exists. * * @param fileName The file to check * * @return Whether or not the file exists */ bool fileExists (const char * fileName) { File *file; #ifdef VERBOSE printf("Check: "); #endif try { file = new File(fileName, false); } catch (int e) { return false; } delete file; return true; } /** * Create a short based on the little-endian contents of the first two bytes in * the given memory location. * * @param data Pointer to the memory location * * @return The generated short */ unsigned short int createShort (unsigned char* data) { unsigned short int val; val = data[0] + (data[1] << 8); return val; } /** * Create an int based on the little-endian contents of the first two bytes in * the given memory location. * * @param data Pointer to the memory location * * @return The generated int */ int createInt (unsigned char* data) { unsigned int val; val = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24); return *((int *)&val); } /** * Create a new string from the contents of an existing string. * * @param string The existing string * * @return The new string */ char * createString (const char *string) { char *cloned; cloned = new char[strlen(string) + 1]; strcpy(cloned, string); return cloned; } /** * Create a new string from the concatenation of two existing strings. * * @param first The existing string to form the start of the new string * @param second The exisitng string to form the end of the new string * * @return The new string */ char * createString (const char *first, const char *second) { char *concatenated; concatenated = new char[strlen(first) + strlen(second) + 1]; strcpy(concatenated, first); strcat(concatenated, second); return concatenated; } /** * Create a new file name string with a 3-digit numerical extension. * * @param type The pre-dot file name * @param extension The number to constitute the extension * * @return The new file name string */ char * createFileName (const char *type, int extension) { char *fileName; int pos; pos = strlen(type); fileName = new char[pos + 5]; strcpy(fileName, type); fileName[pos++] = '.'; fileName[pos++] = '0' + ((extension / 100) % 10); fileName[pos++] = '0' + ((extension / 10) % 10); fileName[pos++] = '0' + (extension % 10); fileName[pos] = 0; return fileName; } /** * Create a new file name string with the given extension. * * @param type The pre-dot file name * @param extension The extension * * @return The new file name string */ char * createFileName (const char *type, const char *extension) { char *fileName; int pos; pos = strlen(type); fileName = new char[pos + strlen(extension) + 2]; strcpy(fileName, type); fileName[pos++] = '.'; strcpy(fileName + pos, extension); return fileName; } /** * Create a new file name string with a 1-digit numerical suffix and a 3-digit * numerical extension. * * @param type The pre-dot file name * @param level The number to constitute the suffix * @param extension The number to constitute the extension * * @return The new file name string */ char * createFileName (const char *type, int level, int extension) { char *fileName; int pos; pos = strlen(type); fileName = new char[pos + 6]; strcpy(fileName, type); fileName[pos++] = '0' + (level % 10); fileName[pos++] = '.'; fileName[pos++] = '0' + ((extension / 100) % 10); fileName[pos++] = '0' + ((extension / 10) % 10); fileName[pos++] = '0' + (extension % 10); fileName[pos] = 0; return fileName; } /** * Create a new variable-length string from the contents of an existing string. * * @param string The existing string * * @return The new string */ char * createEditableString (const char *string) { char *cloned; cloned = new char[STRING_LENGTH + 1]; strcpy(cloned, string); return cloned; } /** * Add a message to the log. * * @param message The log message */ void log (const char *message) { printf("%s\n", message); return; } /** * Add a message with a detail message to the log. * * @param message The log message * @param detail The detail message */ void log (const char *message, const char *detail) { printf("%s: %s\n", message, detail); return; } /** * Add a message with a detail number to the log. * * @param message The log message * @param number The detail number */ void log (const char *message, int number) { printf("%s: %d\n", message, number); return; } /** * Add a message with a detail message to the error log. * * @param message The log message * @param detail The detail message */ void logError (const char *message, const char *detail) { fprintf(stderr, "%s: %s\n", message, detail); return; } /** * Get the sine of the given angle * * @param angle The given angle (where 1024 represents a full circle) * * @return The sine of the angle */ fixed fSin (fixed angle) { return sinLut[angle & 1023]; } /** * Get the cosine of the given angle * * @param angle The given angle (where 1024 represetns a full circle) * * @return The cosine of the angle */ fixed fCos (fixed angle) { return sinLut[(angle + 256) & 1023]; } openjazz-20190106/src/util.h000066400000000000000000000041141341440264100155320ustar00rootroot00000000000000 /** * * @file util.h * * Part of the OpenJazz project * * @par History: * - 23rd August 2005: Created OpenJazz.h * - 30th April 2010: Created util.h from parts of OpenJazz.h * * @par Licence: * Copyright (c) 2005-2010 Alister Thomson * * OpenJazz is distributed under the terms of * the GNU General Public License, version 2.0 * * You 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 St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _UTIL_H #define _UTIL_H #include "OpenJazz.h" // Macros #ifdef VERBOSE #define LOG(message, detail) log(message, detail) #define LOGRESULT(message, expression) log(message, expression) #else #define LOG(message, detail) #define LOGRESULT(message, expression) expression #endif // Variable /// Trigonometric function look-up table EXTERN fixed sinLut[1024]; // Functions EXTERN bool fileExists (const char *fileName); EXTERN unsigned short int createShort (unsigned char* data); EXTERN int createInt (unsigned char* data); EXTERN char* createString (const char *string); EXTERN char* createString (const char *first, const char *second); EXTERN char* createFileName (const char *type, int extension); EXTERN char* createFileName (const char *type, const char *extension); EXTERN char* createFileName (const char *type, int level, int extension); EXTERN char* createEditableString (const char *string); EXTERN void log (const char *message); EXTERN void log (const char *message, const char *detail); EXTERN void log (const char *message, int number); EXTERN void logError (const char *message, const char *detail); EXTERN fixed fSin (fixed angle); EXTERN fixed fCos (fixed angle); #endif openjazz-20190106/symbian/000077500000000000000000000000001341440264100152575ustar00rootroot00000000000000openjazz-20190106/symbian/s60v3/000077500000000000000000000000001341440264100161405ustar00rootroot00000000000000openjazz-20190106/symbian/s60v3/BLD.INF000066400000000000000000000001221341440264100170720ustar00rootroot00000000000000PRJ_PLATFORMS GCCE WINSCW THUMB PRJ_MMPFILES gnumakefile icons.mk .\openjazz.mmp openjazz-20190106/symbian/s60v3/icons.mk000066400000000000000000000010101341440264100175740ustar00rootroot00000000000000ifeq (WINS,$(findstring WINS, $(PLATFORM))) ZDIR=$(EPOCROOT)epoc32\release\$(PLATFORM)\$(CFG)\Z else ZDIR=$(EPOCROOT)epoc32\data\z endif TARGETDIR=$(ZDIR)\RESOURCE\APPS ICONTARGETFILENAME=$(TARGETDIR)\openjazz.mif do_nothing : @rem do_nothing MAKMAKE : do_nothing BLD : do_nothing CLEAN : do_nothing LIB : do_nothing CLEANLIB : do_nothing RESOURCE : mifconv $(ICONTARGETFILENAME) \ /c32 openjazz.svg FREEZE : do_nothing SAVESPACE : do_nothing RELEASABLES : @echo $(ICONTARGETFILENAME) FINAL : do_nothing openjazz-20190106/symbian/s60v3/openjazz.mmp000066400000000000000000000047601341440264100205220ustar00rootroot00000000000000target openjazz.exe targetpath \sys\bin targettype exe SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\..\src sourcepath ..\..\src\platforms source symbian.cpp SOURCEPATH . START RESOURCE openjazz.rss HEADER TARGETPATH \Resource\Apps LANG SC END START RESOURCE openjazz_reg.rss TARGETPATH \private\10003a3f\apps END EPOCSTACKSIZE 80000 EPOCHEAPSIZE 8192000 32768000 UID 0x100039ce 0xA000A005 LIBRARY cone.lib eikcore.lib LIBRARY euser.lib apparc.lib fbscli.lib LIBRARY apgrfx.lib staticlibrary modpluglibpsm.lib staticlibrary esdl.lib sdl_mixer.lib sdl_net.lib zlib.lib LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library bafl.lib estlib.lib esock.lib insock.lib library avkon.lib MACRO S60V3 CAPABILITY NetworkServices LocalServices sourcepath ..\..\src userinclude ..\..\src source main.cpp util.cpp baselevel.cpp sourcepath ..\..\src\bonus userinclude ..\..\src\bonus source bonus.cpp sourcepath ..\..\src\scene userinclude ..\..\src\scene source scene.cpp sceneload.cpp sourcepath ..\..\src\game userinclude ..\..\src\game source clientgame.cpp game.cpp gamemode.cpp servergame.cpp sourcepath ..\..\src\planet userinclude ..\..\src\planet source planet.cpp sourcepath ..\..\src\io userinclude ..\..\src\io source controls.cpp file.cpp network.cpp sound.cpp sourcepath ..\..\src\io\gfx userinclude ..\..\src\io\gfx source anim.cpp font.cpp paletteeffects.cpp sprite.cpp video.cpp sourcepath ..\..\src\level userinclude ..\..\src\level source bullet.cpp demolevel.cpp level.cpp levelframe.cpp levelload.cpp movable.cpp sourcepath ..\..\src\level\event userinclude ..\..\src\level\event source event.cpp eventframe.cpp bridge.cpp guardians.cpp sourcepath ..\..\src\menu userinclude ..\..\src\menu source gamemenu.cpp mainmenu.cpp menu.cpp setupmenu.cpp plasma.cpp sourcepath ..\..\src\player userinclude ..\..\src\player source bird.cpp bonusplayer.cpp jj2levelplayer.cpp jj2levelplayerframe.cpp levelplayer.cpp levelplayerframe.cpp player.cpp userinclude ..\..\src\jj2level sourcepath ..\..\src\jj2level source jj2layer.cpp jj2level.cpp jj2levelframe.cpp jj2levelload.cpp userinclude ..\..\src\jj2level\jj2event sourcepath ..\..\src\jj2level\jj2event source jj2event.cpp jj2eventframe.cpp MACRO USE_SDL_NET MACRO USE_MODPLUG MACRO FULLSCREEN_ONLY OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char OPTION CW -char signed openjazz-20190106/symbian/s60v3/openjazz.pkg000066400000000000000000000020751341440264100205070ustar00rootroot00000000000000; ; Basic install file for openjazz ; ; Languages ; none - English only by default ; Installation header ; Only one component name as we only support English ; UID is the app's UID - &EN ; List of localised vendor names - one per language. At least one must be provided (English [EN]). ; List must correspond to list of languages specified elsewhere in the .pkg %{"SomeOne"} ; The non-localised, globally unique vendor name (mandatory) :"SomeOne" #{"OpenJazz"},(0xA000A005),0,2,1 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} ; Application file "\epoc32\release\gcce\urel\openjazz.exe"-"!:\sys\bin\openjazz.exe" "\epoc32\data\z\resource\apps\openjazz.rsc"-"!:\resource\apps\openjazz.rsc" "\epoc32\data\z\private\10003a3f\apps\openjazz_reg.rsc"-"!:\private\10003a3f\import\apps\openjazz_reg.rsc" "\epoc32\data\z\resource\apps\openjazz.mif"-"!:\resource\apps\openjazz.mif" "..\..\openjazz.000"-"c:\data\openjazz\openjazz.000" ""-"c:\data\openjazz\sdl.ini",FN ""-"c:\data\openjazz\openjazz.cfg",FN ; Required files ; None ; Component .sis files ; None openjazz-20190106/symbian/s60v3/openjazz.rss000066400000000000000000000015271341440264100205360ustar00rootroot00000000000000NAME OJZZ // Include definitions of resource STRUCTS used by this // resource script #include #include // Include the standard Eikon resource ids #include RESOURCE RSS_SIGNATURE { } RESOURCE TBUF16 { buf=""; } RESOURCE EIK_APP_INFO { } // This file localise the applications icons and caption RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info { caption_and_icon = { CAPTION_AND_ICON_INFO { // The caption text is defined in the rls file caption = "OpenJazz"; // Icons are used to represent applications in the // application launcher and application title bar. // The number_of_icons value identifies how many icons // that exist in the icon_file. number_of_icons = 1; // Using the application icons. icon_file = "\\Resource\\Apps\\OpenJazz.mif"; } }; } openjazz-20190106/symbian/s60v3/openjazz.svg000066400000000000000000003437431341440264100205370ustar00rootroot00000000000000 image/svg+xml openjazz-20190106/symbian/s60v3/openjazz_reg.rss000066400000000000000000000014261341440264100213710ustar00rootroot00000000000000// All registration files need to #include appinfo.rh. #include #include // All registration files must define UID2, which is always // KUidAppRegistrationResourceFile, and UID3, which is the application's UID. UID2 KUidAppRegistrationResourceFile UID3 0xA000A005 // application UID // Registration file need to containo an APP_REGISTRATION_INFO resource that // minimally needs to provide the name of the application binary (using the // app_file statement). RESOURCE APP_REGISTRATION_INFO { app_file = "openjazz"; // filename of application binary (minus extension) // Specify the location of the localisable icon/caption definition file localisable_resource_file = "\\Resource\\Apps\\openjazz"; localisable_resource_id = R_LOCALISABLE_APP_INFO; } openjazz-20190106/symbian/uiq3/000077500000000000000000000000001341440264100161405ustar00rootroot00000000000000openjazz-20190106/symbian/uiq3/BLD.INF000066400000000000000000000001071341440264100170750ustar00rootroot00000000000000PRJ_PLATFORMS WINS ARMI GCCE WINSCW THUMB PRJ_MMPFILES .\openjazz.mmp openjazz-20190106/symbian/uiq3/openjazz.mmp000066400000000000000000000060221341440264100205130ustar00rootroot00000000000000target openjazz.exe targetpath \sys\bin targettype exe SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\..\src sourcepath ..\..\src\platforms source symbian.cpp SOURCEPATH . START RESOURCE openjazz.rss HEADER TARGETPATH \Resource\Apps LANG SC END START RESOURCE openjazz_reg.rss TARGETPATH \private\10003a3f\apps END EPOCSTACKSIZE 80000 EPOCHEAPSIZE 8192000 32768000 sourcepath . START BITMAP OpenJazz.mbm HEADER TARGETPATH \Resource\Apps SOURCEPATH . // Source Color-depth Source-bitmap-list // c denotes whether the bitmap is a colour bitmap and the digits represent the // colour-depth of the bitmap and the bitmap mask respectively SOURCE c24 openjazz_s.bmp SOURCE 8 openjazz_sm.bmp SOURCE c24 openjazz_l.bmp SOURCE 8 openjazz_lm.bmp SOURCE c24 openjazz_xl.bmp SOURCE 8 openjazz_xlm.bmp END UID 0x100039ce 0xA000A005 LIBRARY cone.lib eikcore.lib LIBRARY euser.lib apparc.lib fbscli.lib LIBRARY apgrfx.lib staticlibrary modpluglibpsm.lib staticlibrary esdl.lib sdl_mixer.lib sdl_net.lib zlib.lib LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library bafl.lib estlib.lib esock.lib insock.lib library qikcore.lib MACRO UIQ3 CAPABILITY NetworkServices LocalServices sourcepath ..\..\src userinclude ..\..\src source main.cpp util.cpp baselevel.cpp sourcepath ..\..\src\bonus userinclude ..\..\src\bonus source bonus.cpp sourcepath ..\..\src\scene userinclude ..\..\src\scene source scene.cpp sceneload.cpp sourcepath ..\..\src\game userinclude ..\..\src\game source clientgame.cpp game.cpp gamemode.cpp servergame.cpp sourcepath ..\..\src\planet userinclude ..\..\src\planet source planet.cpp sourcepath ..\..\src\io userinclude ..\..\src\io source controls.cpp file.cpp network.cpp sound.cpp sourcepath ..\..\src\io\gfx userinclude ..\..\src\io\gfx source anim.cpp font.cpp paletteeffects.cpp sprite.cpp video.cpp sourcepath ..\..\src\level userinclude ..\..\src\level source bullet.cpp demolevel.cpp level.cpp levelframe.cpp levelload.cpp movable.cpp sourcepath ..\..\src\level\event userinclude ..\..\src\level\event source event.cpp eventframe.cpp bridge.cpp guardians.cpp sourcepath ..\..\src\menu userinclude ..\..\src\menu source gamemenu.cpp mainmenu.cpp menu.cpp setupmenu.cpp plasma.cpp sourcepath ..\..\src\player userinclude ..\..\src\player source bird.cpp bonusplayer.cpp jj2levelplayer.cpp jj2levelplayerframe.cpp levelplayer.cpp levelplayerframe.cpp player.cpp userinclude ..\..\src\jj2level sourcepath ..\..\src\jj2level source jj2layer.cpp jj2level.cpp jj2levelframe.cpp jj2levelload.cpp userinclude ..\..\src\jj2level\jj2event sourcepath ..\..\src\jj2level\jj2event source jj2event.cpp jj2eventframe.cpp MACRO USE_SDL_NET MACRO USE_MODPLUG MACRO FULLSCREEN_ONLY OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char OPTION CW -char signed openjazz-20190106/symbian/uiq3/openjazz.pkg000066400000000000000000000021761341440264100205110ustar00rootroot00000000000000; ; Basic install file for openjazz ; ; Languages ; none - English only by default ; Installation header ; Only one component name as we only support English ; UID is the app's UID - &EN ; List of localised vendor names - one per language. At least one must be provided (English [EN]). ; List must correspond to list of languages specified elsewhere in the .pkg %{"SomeOne"} ; The non-localised, globally unique vendor name (mandatory) :"SomeOne" #{"OpenJazz"},(0xA000A005),0,2,1 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID (0x101F6300), 3, 0, 0, {"UIQ30ProductID"} ; Application file "\epoc32\release\gcce\urel\openjazz.exe"-"!:\sys\bin\openjazz.exe" "\epoc32\data\z\resource\apps\openjazz.rsc"-"!:\resource\apps\openjazz.rsc" "\epoc32\data\z\private\10003a3f\apps\openjazz_reg.rsc"-"!:\private\10003a3f\import\apps\openjazz_reg.rsc" ;"\epoc32\data\z\resource\apps\openjazz.mbm"-"!:\resource\apps\openjazz.mbm" "..\..\openjazz.000"-"c:\shared\openjazz\openjazz.000" ""-"c:\shared\openjazz\sdl.ini",FN ""-"c:\shared\openjazz\openjazz.cfg",FN ; Required files ; None ; Component .sis files ; None openjazz-20190106/symbian/uiq3/openjazz.rss000066400000000000000000000016231341440264100205330ustar00rootroot00000000000000NAME OJZZ // Include definitions of resource STRUCTS used by this // resource script #include #include #include #include // Include the standard Eikon resource ids #include RESOURCE RSS_SIGNATURE { } RESOURCE TBUF16 { buf=""; } RESOURCE EIK_APP_INFO { } // This file localise the applications icons and caption RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info { caption_and_icon = { CAPTION_AND_ICON_INFO { // The caption text is defined in the rls file caption = "OpenJazz"; // Icons are used to represent applications in the // application launcher and application title bar. // The number_of_icons value identifies how many icons // that exist in the icon_file. number_of_icons = 3; // Using the application icons. icon_file = "\\Resource\\Apps\\OpenJazz.mbm"; } }; } #include openjazz-20190106/symbian/uiq3/openjazz_l.bmp000066400000000000000000000113661341440264100210220ustar00rootroot00000000000000BMі6(((Р @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5.!uЃ Х Х И•)];@@@@@BsЎЫЫЫЎlA@@@@@@@@@@@@@@?3= НїћќќќќќћыŒ7@@nвњќќќќќњвh@@@@@@@@@@@@=•їќќќќќќќќќќќп,Iђќќќќќќќќќё@@@@@@@@@@=Вћќќќќќќќќќќќќќђaљќќќќќќќќќќёm@@@@@@@@=Ÿћќќќќќќќќќќќќќќќ ьД>ќќќќќќќќќќќаF@@@@@@@'Nїќќќќќњх8ОCИ+а яќќќќќќ* Ы№ ќіВ„œыќќќќњz@@@@@@? Ыќќќќќ ьhфіјёб(I­њќќќќњ“ mќŠA@@e№ќќќќЛ@@@@@@+OљќќќќэЎDїјјјјјэ_‘ћќќќќ емE@@@@Рќќќќп@@@@@@–ќќќќќŒnїјјјјјјјщ3ЦќќќќїD-@@@@@Ѓќќќќт@@@@@@ Ыќќќќюш јјјјјјјјј‰lќќќќћ.[@@@@@Ёќќќќп@@@@@@кќќќќ,вѕјјјјјјјјјФ9ќќќќќ{@@@@@Ёќќќќп@@@@@@кќќќќ,вѕјјјјјјјјјУ3ќќќќќ{@@@@@Ёќќќќп@@@@@@Ыќќќќьыјјјјјјјјјjќќќќћ* ^@@@@@Ёќќќќп@@@@@@›ќќќќќ“Yјјјјјјјј№<Сќќќќї11@@@@@Ёќќќќп@@@@@@,RњќќќќъТ6јјјјјјёl‡њќќќќоB@@@@@Ёќќќќп@@@@@@=йќќќќќч›Tъ јјїи _šљќќќќћx@@@@@@Ёќќќќп@@@@@@@*Yјќќќќќј"зLГ]Ё@Нщќќќќќќи=@@@@@@Ёќќќќп@@@@@@@=Ўќќќќќќќќќќќќќќќќѓ*R@@@@@@@Ёќќќќп@@@@@@@@8Гќќќќќќќќќќќќќќє% u?@@@@@@@Ёќќќќп@@@@@@@@@;Єјќќќќќќќќќќќщ)c?@@@@@@@@Ёќќќќп@@@@@@@@@@@*K вњќќќќќќћ№š4 @@@@@@@@@@Ёќќќќп@@@@@@@@@@@@?.D‹ СллеБ w6@@@@@@@@@@@@‘ррррЦ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@openjazz-20190106/symbian/uiq3/openjazz_lm.bmp000066400000000000000000000113661341440264100211770ustar00rootroot00000000000000BMі6(((Р џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџopenjazz-20190106/symbian/uiq3/openjazz_reg.rss000066400000000000000000000014261341440264100213710ustar00rootroot00000000000000// All registration files need to #include appinfo.rh. #include #include // All registration files must define UID2, which is always // KUidAppRegistrationResourceFile, and UID3, which is the application's UID. UID2 KUidAppRegistrationResourceFile UID3 0xA000A005 // application UID // Registration file need to containo an APP_REGISTRATION_INFO resource that // minimally needs to provide the name of the application binary (using the // app_file statement). RESOURCE APP_REGISTRATION_INFO { app_file = "openjazz"; // filename of application binary (minus extension) // Specify the location of the localisable icon/caption definition file localisable_resource_file = "\\Resource\\Apps\\openjazz"; localisable_resource_id = R_LOCALISABLE_APP_INFO; } openjazz-20190106/symbian/uiq3/openjazz_s.bmp000066400000000000000000000020461341440264100210240ustar00rootroot00000000000000BM&6(№ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?*VА к иЏ,R?CŠвсвˆC@@;НќќќќќќВВќќќќќМC>ПќќќќќќќќEЏљќ№ћќќˆ'ZќќјvƒЬ*Ь,n‰љќќ­P—A|ќќеНќќxјјјїn‰ќќ.­H@@ђќюцќќкјјјјЯ)ќќн@@@ьќьцќќкјјјја'ќќо@@@ьќьПќќ~wјјјјv‚ќќБ@@@ьќь&dќќї}yккxјќќ*V@@@ьќь? ХќќќќќќќќН?@@@ьќь@; УќќќќќќП;@@@@ьќь@@?&dНццН'Z>@@@@@оьо@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@openjazz-20190106/symbian/uiq3/openjazz_sm.bmp000066400000000000000000000020461341440264100212010ustar00rootroot00000000000000BM&6(№  џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџopenjazz-20190106/symbian/uiq3/openjazz_xl.bmp000066400000000000000000000300661341440264100212100ustar00rootroot00000000000000BM606(@@0 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AB!W'}ЌЌЌ &| VB@@@@@@@@@@BgœЖЖЖЖœdB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B"XФєќќќќќќќќєМ0GA@@@@@BлќќќќќќќќЬB@@@@@@@@@@@@@@@@@@@@@@@@@@@@0GЬќќќќќќќќќќќќќќФ+ 2@@@]ЬќќќќќќќќќќќќЬL@@@@@@@@@@@@@@@@@@@@@@@@@?—ќќќќќќќќќќќќќќќќќє†Ctшќќќќќќќќќќќќќќш_@@@@@@@@@@@@@@@@@@@@@@@?ФќќќќќќќќќќќќќќќќќќќќЋт ќќќќќќќќќќќќќќќќшL@@@@@@@@@@@@@@@@@@@@@?ФќќќќќќќќќќќќќќќќќќќќќќDЋяќќќќќќќќќќќќќќќќЬB@@@@@@@@@@@@@@@@@@@A ќќќќќќќќќќќќќќќќќќќќќќќќu wќќќќќќќќќќќќќќќќќp@@@@@@@@@@@@@@@@@@@"PќќќќќќќќќќќќќќќќќќќќќќќќќєФ.ќќќќќлдяќќќќќќќќлB@@@@@@@@@@@@@@@@@DдќќќќќќќќќюOД„eІVІV…pOД ёќќќќќќќќќDГќќќйfB@NЎќќќќќќќќg@@@@@@@@@@@@@@@@@)`ќќќќќќќќќQЁтјјјјјјм3ТќќќќќќќќќНGќшL@@@@@ЎќќќќќќќЉ@@@@@@@@@@@@@@@@BдќќќќќќќќdѓјјјјјјјјъV›ќќќќќќќќA Оќš@@@@@@NќќќќќќќХ@@@@@@@@@@@@@@@@/>ќќќќќќќќ\žѓјјјјјјјјјјъ3ТќќќќќќќєОg@@@@@@@яќќќќќќт@@@@@@@@@@@@@@@@%sќќќќќќќштјјјјјјјјјјјјм ёќќќќќќќ!O@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@Ќќќќќќќќl‹јјјјјјјјјјјјјјOДќќќќќќќ'}@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@ЬќќќќќќќІYјјјјјјјјјјјјјј…hќќќќќќќЌ@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@ЬќќќќќќќЫ6јјјјјјјјјјјјјјИIќќќќќќќФ@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@ЬќќќќќќќЫ6јјјјјјјјјјјјјјЗ@ќќќќќќќФ@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@ЬќќќќќќќІVјјјјјјјјјјјјјј’bќќќќќќќЌ@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@ЌќќќќќќќttјјјјјјјјјјјјјјOДќќќќќќќ „@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@&|ќќќќќќќнъјјјјјјјјјјјјтюќќќќќќќ!W@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@/>ќќќќќќќќf’јјјјјјјјјјјѓQЁќќќќќќќќC@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@CмќќќќќќќќŽoјјјјјјјјјѓdќќќќќќќќФA@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@}ќќќќќќќќќf’ъјјјјјјт\žќќќќќќќќќ"X@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@?тќќќќќќќќќнl‹ІYЫ6Ы6ІYl‹шќќќќќќќќќЬB@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@$Zќќќќќќќќќќќќќќќќќќќќќќќќќќ0G@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@BМќќќќќќќќќќќќќќќќќќќќќќќќ—@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@0ЬќќќќќќќќќќќќќќќќќќќќќќФ?@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@@?ЬќќќќќќќќќќќќќќќќќќќќФ?@@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@@@0 Аќќќќќќќќќќќќќќќќќќ ?@@@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@@@@B$Zтќќќќќќќќќќќќќќд"PA@@@@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@@@@@@?}мќќќќќќќќќќд)`D@@@@@@@@@@@@@@@@дќќќќќќд@@@@@@@@@@@@@@@@@@@@@@@@@@C/>%sЌЬЬЬЬЌ%s/>B@@@@@@@@@@@@@@@@@@БддддддБ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@openjazz-20190106/symbian/uiq3/openjazz_xlm.bmp000066400000000000000000000041661341440264100213670ustar00rootroot00000000000000BMvv(@@  џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwpwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwppwwwwwwwwpwwpwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwopenjazz-20190106/unix/000077500000000000000000000000001341440264100146005ustar00rootroot00000000000000openjazz-20190106/unix/OpenJazz.6.pod000066400000000000000000000046721341440264100172210ustar00rootroot00000000000000=encoding utf8 =head1 NAME OpenJazz - Jack Jazzrabbit 1 game engine reimplementation =head1 SYNOPSIS B [options] > =head1 DESCRIPTION OpenJazz is a free, open-source version of the classic Jazz Jackrabbit PC platform games. To play, you will need original data files. =head1 OPTIONS =over 4 =item B<-f> Start in full-screen mode =item B<-m> Start with muted audio =back =head1 FILES =head2 F The engine configuration file. B Command line parameters will take precedence over values in the configuration file =head2 Game Data OpenJazz should be compatible with all released versions of Jazz Jackrabbit 1, this includes the Shareware Episodes, "Holiday Hare" and "Holiday Hare '95", the "Jazz Jackrabbit CD" with "The Lost Episodes" and the "Complete" edition. =head1 INGAME CONTROLS =head2 Fixed Controls =over 4 =item C to choose a menu option =item C to go back to the previous menu =item C to view in-game statistics (e.g. FPS) =item C

to pause the game =item C + C switches between full-screen and windowed mode =back =head2 Configurable Controls These are configurable via the "setup options" menu. Default settings: =over 4 =item C and C arrow keys to move left and right =item C to jump =item C to shoot =item C to change weapon =back =head2 Game Controllers Most game controllers and joysticks that SDL recognizes can be used. However, not all axes or buttons may be available. Needs manual settings. =head1 REPORTING BUGS Bugs can be reported at the L. =head1 SEE ALSO B - level editor by Newspaz, B - graphic editor by Doubble Dutch The L. =head1 AUTHORS =over 4 =item Alister Thomson (AlisterT) Engine, project lead =item Alireza Nejati Menu plasma effect =item newspaz Bug fixes, enemy improvements =item Carsten Teibes (carstene1ns) Maintenance, bug fixes, documentation =item Lars Persson (anotherguest) Movie playback fixes =item Scott Smith (Pickle) GP2X/WIZ, Canoo, Pandora ports =item PrzemysХ‚aw Buczkowski (przemub) Android, Haiku ports =item Matthieu Milan (usineur) PSVita port =item deniska PSP port =item tehpola Wii port =item pocketinsanity PocketPC port =item Ricerind Mac OS X port =item Slaanesh GP32 port =item GPF Dreamcast port =back openjazz-20190106/unix/OpenJazz.desktop000077500000000000000000000004051341440264100177350ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=OpenJazz Comment=Jazz Jackrabbitт„Ђ game engine reimplementation Icon=OpenJazz Exec=OpenJazz Categories=Game;ActionGame; Keywords=jazz;jackrabbit;green;rabbit;bunny;jump;run;gun;platform; Terminal=false StartupNotify=false openjazz-20190106/unix/OpenJazz.png000066400000000000000000000017561341440264100170570ustar00rootroot00000000000000‰PNG  IHDR00Wљ‡ЕIDATxкэйДфZ…с}­gлЖmлЖmлЖmлЖmлЖ•sRяЯєš8ЅTжwэ8еЊЋЎКъЊЋ’Вь*ZZійt`\Ь‚EАЦLmХУ˜аљБ,–iА,цD[–•Ÿ ;р&МƒёўСŸјoтZl‰Iђ‡0a4М€џ6pИНiV|JO`)…x‡bЂьALЏС"<ˆоИ•oЧFxVР+X­9Мš7@ŽФ_АќŠНа Ёќ6DN‚‡•ш_€vхА!ZА7Xќ…-  ќKтGX!,ƒЯ1GiLd<˜f…пJўТЭфv?AСЖgщП—Лq5ЙoЦN}и]‡nЅи щаљv,љ}R0Счђ2…<Д gzUЎ_А;їЪXІЬ=И хг‰ф—НKN?tўЋpЏcќнт2Д•`Vќ5ц} зОFN–nhs Oк5ёB№1&…P8РА(WЎ'зя‘Ѕ&ќLў­icЯ‰џАJYNыŸ.…Ып!'Ы>НOт^иПŒэИ1jЌ'‘яЗ5ѓXщVЙ =і\8ЇŒ=И/jЌ—f•љ—|цzVўЗc\…жІxefЙQЪ`оЇф!S€ђЁ/Ч“Ÿт§|њ]Й|kѓ!с”ЈБ\›ТѕЎЬu‡чl-—pяWЩeєО%хFќ-лeДп]љ‹ёхžNW*рд72з6рю*KbЄ_хЏ_#~ыџЌQ~КAЋЯzжnˆ`ƒŒ‡їaю@gъG‰~W“NUаљo|ˆБО•П`saKќЃФхкРuщŸMFвЏQэƒe№',Т…PІ‡Й~7Е~wх|HAжъŽљќšзЩ=1Тq?дgKы“ьEL 5їУbьeœЦЏ#)|zЙЫ6”ыwЂі;\о˜>ЭS(pжДn§=шзА>ІФфXСbќ‚yЁфš’}Ў l=пјч_с ќKpzЁJ_)џRmЁѓ‹ЮцЌНдџ­n;@‡[{ёms&:  šЖЪЯ/iжSЙъМ^pVЗclЊhlНŒU@й\x–‘Ч5˜@Ѕm-ž€O3v*оУ!˜њRу šуD8 пУRјЛcЄј•/ЏЙ{ Жhlюrз•dƒДa.‡ч№-ўФ?ј_р!ь)у{нХкы‹6ДзЧŠoЏл№Œ‚щА0–Тќ˜НVМъ8,“ІU]uеUW]џ ozУ­ђЛ­IENDЎB`‚openjazz-20190106/unix/OpenJazz.svg000066400000000000000000000015221341440264100170610ustar00rootroot00000000000000