diff --git a/.github/workflows/build-full.yml b/.github/workflows/build-full.yml index ebb3cb0c..f5505541 100644 --- a/.github/workflows/build-full.yml +++ b/.github/workflows/build-full.yml @@ -19,11 +19,16 @@ jobs: run: | sudo apt-get update sudo apt-get install -y \ - liballegro4-dev \ + liballegro5-dev \ + liballegro-acodec5-dev \ + liballegro-audio5-dev \ + liballegro-image5-dev \ + liballegro-physfs5-dev \ autoconf \ automake \ build-essential \ - clang + clang \ + pkg-config - name: Run autoconf run: autoconf @@ -94,11 +99,16 @@ jobs: run: | apt-get update apt-get install -y \ - liballegro4-dev \ + liballegro5-dev \ + liballegro-acodec5-dev \ + liballegro-audio5-dev \ + liballegro-image5-dev \ + liballegro-physfs5-dev \ autoconf \ automake \ build-essential \ - clang + clang \ + pkg-config - name: Run autoconf run: autoconf @@ -168,8 +178,7 @@ jobs: - name: Install dependencies run: | dnf install -y \ - allegro-devel \ - allegro-tools \ + allegro5-devel \ autoconf \ automake \ make \ @@ -247,7 +256,7 @@ jobs: run: | pacman -Syu --noconfirm pacman -S --noconfirm \ - allegro4 \ + allegro \ autoconf \ automake \ make \ @@ -312,268 +321,9 @@ jobs: - name: Clean run: make clean - build-freebsd: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Build on FreeBSD - uses: vmactions/freebsd-vm@v1 - with: - usesh: true - prepare: | - pkg install -y allegro autoconf automake gmake pkgconf - run: | - autoconf - ./configure --prefix=$HOME/lw5 - gmake - gmake install - gmake package_source - - # Check binary exists and is executable - if [ ! -x "$HOME/lw5/bin/liquidwar" ]; then - echo "ERROR: $HOME/lw5/bin/liquidwar is not executable" - exit 1 - fi - echo "SUCCESS: liquidwar binary is executable" - - # Check version starts with 5 - VERSION_OUTPUT=$($HOME/lw5/bin/liquidwar --version) - echo "Version output: $VERSION_OUTPUT" - - if echo "$VERSION_OUTPUT" | head -n1 | grep -q '^5'; then - echo "SUCCESS: Version starts with 5" - else - echo "ERROR: Version does not start with 5" - echo "Got: $VERSION_OUTPUT" - exit 1 - fi - - # Test liquidwar-mapgen binary - if [ -x "$HOME/lw5/bin/liquidwar-mapgen" ]; then - echo "liquidwar-mapgen is executable" - $HOME/lw5/bin/liquidwar-mapgen --version || true - else - echo "WARNING: liquidwar-mapgen not found or not executable" - fi - - build-windows: - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Setup MSYS2 with MinGW32 - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW32 - update: true - install: >- - mingw-w64-i686-toolchain - mingw-w64-i686-cmake - autoconf - automake - make - dos2unix - wget - unzip - - - name: Build and install Allegro 4.4 - run: | - # Download Allegro 4.4.3.1 source - wget https://github.com/liballeg/allegro5/releases/download/4.4.3.1/allegro-4.4.3.1.zip - unzip allegro-4.4.3.1.zip - cd allegro - - # List files to debug - ls -la - - # Build Allegro 4 for MinGW using cmake - mkdir build - cd build - cmake .. \ - -G "MSYS Makefiles" \ - -DCMAKE_INSTALL_PREFIX=/mingw32 \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -DWANT_DOCS=OFF \ - -DWANT_TESTS=OFF \ - -DWANT_EXAMPLES=OFF \ - -DWANT_TOOLS=ON - make -j2 - make install - - # Debug: Search for Allegro DLL files - echo "Searching Allegro DLL files in /mingw32:" - find /mingw32 -name "alleg*.dll" -ls 2>/dev/null || echo "No alleg*.dll in /mingw32" - - # Verify installation - echo "Checking for dat tool:" - ls -la /mingw32/bin/dat* || echo "dat not found in /mingw32/bin" - - cd ../.. - - - name: Build Liquid War with Makefile.mgw - run: | - # Ensure /mingw32/bin is in PATH for Allegro - export PATH="/mingw32/bin:$PATH" - - # Check if dat tool exists - echo "Checking for required tools:" - which dat || echo "WARNING: dat not found" - ls -la /mingw32/bin/dat* || ( echo "dat not in /mingw32/bin" && exit 1) - - # Debug: Check what Allegro libraries are available - echo "Libraries in /mingw32/lib:" - ls -la /mingw32/lib/liballeg* || ( echo "No Allegro libraries" && exit 1) - - # Build using MinGW Makefile - make -f Makefile.mgw - - - name: Check Windows binary created - run: | - cp /mingw32/bin/alleg44.dll . - if [ -f "lwwin.exe" ] && [ -f "lwwinsrv.exe" ] && [ -f "lwwinmap.exe" ] && [ -f "alleg44.dll" ] ; then - echo "SUCCESS: Windows .exe files created" - ls -lh lwwin*.exe - else - echo "ERROR: Windows .exe files not found" - exit 1 - fi - - - name: Upload Windows binaries - uses: actions/upload-artifact@v4 - with: - name: liquidwar-windows-binaries - path: | - lwwin*.exe - alleg44.dll - retention-days: 61 - - build-dos: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Install DJGPP cross-compiler - run: | - sudo apt-get update - sudo apt-get install -y wget bzip2 make gcc g++ unzip flex - - # Download and setup DJGPP cross-compiler - cd /tmp - wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2 - sudo tar xjf djgpp-linux64-gcc1220.tar.bz2 -C /usr/local - export PATH="/usr/local/djgpp/bin:$PATH" - - echo "DJGPP cross-compiler installed:" - i586-pc-msdosdjgpp-gcc --version - - - name: Setup Allegro 4.2.3.1 for DOS - run: | - export PATH="/usr/local/djgpp/bin:$PATH" - export DJGPP_PREFIX=i586-pc-msdosdjgpp - - # Download Allegro 4.2.3.1 source for headers - wget https://github.com/liballeg/allegro5/releases/download/v4-2-3-1/all4231.zip - unzip all4231.zip - - # Use Allegro's actual build system - cd allegro - - # Set up cross-compilation environment variables (as per docs/build/djgpp.txt) - export CROSSCOMPILE=1 - export DJDIR=/usr/local/djgpp - export NATIVEPATH=$PATH - export PATH=/usr/local/djgpp/bin:$PATH - - # Configure for DJGPP - echo "Configuring Allegro for DJGPP..." - bash fix.sh djgpp - - # Build using Allegro's Makefile with cross-compiler - # Must override CC since makefile.dj defaults to 'gcc' - # Only build the library, not utilities like setup.exe - # Add -fgnu89-inline to handle extern __inline__ in headers correctly - # Try without ALLEGRO_USE_C=1 to let assembly files compile - echo "Building Allegro with DJGPP cross-compiler..." - make lib \ - CC=${DJGPP_PREFIX}-gcc \ - CROSSCOMPILE=1 \ - TARGET_OPTS="-O2 -funroll-loops -ffast-math -fgnu89-inline" - - echo "Allegro build complete. Checking library..." - ls -lh lib/djgpp/liballeg.a || ( echo "ERROR: Allegro library not created" && exit 1 ) - cd .. - - - name: Download CWSDPMI for DOS runtime - run: | - # CWSDPMI is the DOS Protected Mode Interface server needed to run DJGPP programs - # Try multiple mirrors - wget http://www.delorie.com/pub/djgpp/current/v2misc/csdpmi7b.zip -O csdpmi7b.zip || \ - wget https://www.mirrorservice.org/sites/ftp.delorie.com/pub/djgpp/current/v2misc/csdpmi7b.zip -O csdpmi7b.zip || \ - ( echo "ERROR: Failed to download CWSDPMI" && exit 1 ) - - unzip csdpmi7b.zip - - # Find and copy to root directory - find . -iname "cwsdpmi.exe" -exec cp {} ./cwsdpmi.exe \; - - echo "CWSDPMI location:" - ls -la cwsdpmi.exe || ( echo "ERROR: cwsdpmi.exe not found after extraction" && exit 1 ) - - - name: Build Liquid War for DOS - run: | - export PATH="/usr/local/djgpp/bin:$PATH" - - # Debug: Show Allegro library location - echo "Current directory: $PWD" - echo "Allegro library path: $PWD/allegro/lib/djgpp" - ls -lh $PWD/allegro/lib/djgpp/liballeg.a || echo "Allegro library not found!" - - # Build using DJGPP cross-compiler with explicit Allegro paths - # Need -fgnu89-inline to match Allegro's build for extern __inline__ functions - echo "Building with LDFLAGS=-L$PWD/allegro/lib/djgpp" - make -f Makefile.dj \ - CC=i586-pc-msdosdjgpp-gcc \ - C_FLAGS="-O2 -fomit-frame-pointer -Wall -Werror -I./src/ -I$PWD/allegro/include -DALLEGRO_STATICLINK -fgnu89-inline" \ - LDFLAGS="-L$PWD/allegro/lib/djgpp" || ( echo "Build failed" && exit 1 ) - - echo "Checking if executable was created:" - ls -lh src/*.exe 2>/dev/null || ls -lh lwdos*.exe 2>/dev/null || ls -lh *.exe 2>/dev/null || echo "No .exe found" - find . -name "*.exe" -type f - - - name: Check DOS executable created - run: | - if [ -f "lwdos.exe" ] ; then - echo "SUCCESS: DOS executable created" - ls -lh *.exe src/*.exe 2>/dev/null || true - else - echo "ERROR: No DOS executable found" - find . -name "*.exe" - exit 1 - fi - - - name: Upload DOS binaries - uses: actions/upload-artifact@v4 - with: - name: liquidwar-dos-binaries - path: | - lwdos*.exe - cwsdpmi.exe - retention-days: 61 - build-source: runs-on: ubuntu-latest - needs: [build-fedora, build-ubuntu, build-debian, build-arch, build-freebsd, build-windows, build-dos] + needs: [build-fedora, build-ubuntu, build-debian, build-arch] steps: - name: Checkout code @@ -583,10 +333,15 @@ jobs: run: | sudo apt-get update sudo apt-get install -y \ - liballegro4-dev \ + liballegro5-dev \ + liballegro-acodec5-dev \ + liballegro-audio5-dev \ + liballegro-image5-dev \ + liballegro-physfs5-dev \ autoconf \ automake \ - build-essential + build-essential \ + pkg-config - name: Generate configure script run: autoconf diff --git a/.github/workflows/build-quick.yml b/.github/workflows/build-quick.yml index d7ab5a38..b2996cc4 100644 --- a/.github/workflows/build-quick.yml +++ b/.github/workflows/build-quick.yml @@ -17,10 +17,15 @@ jobs: run: | sudo apt-get update sudo apt-get install -y \ - liballegro4-dev \ + liballegro5-dev \ + liballegro-acodec5-dev \ + liballegro-audio5-dev \ + liballegro-image5-dev \ + liballegro-physfs5-dev \ autoconf \ automake \ - build-essential + build-essential \ + pkg-config - name: Generate configure script run: autoconf diff --git a/.gitignore b/.gitignore index 9a4e6b24..feecadc2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,21 +9,32 @@ config.status index.html begin.man liquidwar.tex +liquidwar5.tex begin.texi liquidwar.nsi +liquidwar5.nsi liquidward +liquidwar5d macosx_info.plist Makefile.dep *.o *~ *.tar.gz liquidwar +liquidwar5 liquidwar-server +liquidwar5-server liquidwar-mapgen +liquidwar5-mapgen liquidwarcol +liquidwar5col liquidwarmap +liquidwar5map liquidwartex +liquidwar5tex *.dat +.#* +*.bak /misc/docker/tables.sql doc/tex/*.aux doc/tex/*.dvi @@ -33,3 +44,13 @@ doc/tex/*.toc doc/texi/*.texi doc/txt/*.txt __pycache__ +doc/html/*.html +doc/man/*.man +doc/man/*.6 +doc/man/*.6.gz +allegro-4* +allegro-5* +__pycache__ +*.pyc +src/liquidwar.dSYM +src/liquidwar5.dSYM diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..45c06dbf --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,196 @@ +# Liquid War 5 - Project Analysis + +## Project Overview + +**Liquid War 5** is a classic multiplayer wargame originally created by Christian Mauduit (U-Foot) and first developed in 1998. The game features unique mechanics where players control armies of liquid and must absorb opposing forces to win. + +- **License**: GPL v2 +- **Language**: C (with some assembly optimizations) +- **Version**: 5.7.0 +- **Platform**: Cross-platform (Linux, Windows, macOS) +- **Graphics**: Allegro 5 game library +- **Homepage**: https://ufoot.org/liquidwar/v5 + +## Project Structure + +### Core Directories + +``` +liquidwar5/ +├── src/ # Main source code (~100+ C files) +├── data/ # Game assets (maps, textures, sounds, music) +│ ├── map/ # Game level files (.pcx/.bmp + .txt configs) +│ ├── texture/ # Background textures (.pcx files) +│ ├── music/ # MIDI background music +│ ├── sfx/ # Sound effects (.wav files) +│ ├── font/ # Game fonts (.pcx) +│ └── back/ # Background images +├── utils/ # Utility programs (map generators, converters) +├── doc/ # Documentation generation system +├── custom/ # User-customizable content +├── misc/ # Platform-specific files, icons, packaging +└── www/ # Web components (metaserver PHP code) +``` + +### Key Executables Built + +- `liquidwar` - Main game client +- `liquidwar-server` - Dedicated game server +- `liquidwar-mapgen` - Map generation utility + +## Build System + +### Dependencies + +**Required:** +- **Allegro 5** - Main graphics/audio library (5.0+ required) +- **pkg-config** - For finding Allegro +- **pthread** - Threading support +- **Standard C libraries** - Network, system headers + +**Optional:** +- **Python** - Documentation generation +- **LaTeX/PDFLaTeX** - PDF documentation +- **makeinfo** - Info page generation +- **gzip** - Compression + +### Build Process + +1. **Configure**: `./configure` (autotools-based) +2. **Build**: `make` or `gmake` +3. **Install**: `make install` + +**Configuration Options:** +- `--enable-debug` - Debug build +- `--enable-static` - Static linking +- `--disable-doc-*` - Disable specific documentation formats + +## Key Source Files + +### Game Engine Core (`src/`) + +| Module | Purpose | +|--------|---------| +| `main.c` | Program entry point | +| `game.c` | Core game logic | +| `army.c` | Army/unit management | +| `fighter.c` | Individual unit behavior | +| `move.c` | Movement algorithms | +| `mesh.c` | Game field mesh system | +| `map.c` | Level loading/management | +| `graphics.c` | Rendering system | +| `menu.c` | User interface | + +### Network System +- `network.c`, `netgame.c`, `netplay.c` - Multiplayer networking +- `server.c`, `protocol.c` - Server implementation +- `sock*.c` - Socket abstraction (Unix/Windows) + +### Platform Support +- `exec*.c` - Platform-specific execution +- `mutx*.c` - Mutex implementations per platform +- `thrd*.c` - Threading abstractions + +### Allegro 4 to Allegro 5 Migration +- `backport.h` and `backport.c` - **Backward compatibility module** containing functions that disappeared in Allegro 5 and need to be reimplemented. This includes GUI functions, input handling, and other utilities that Liquid War 5 requires. It implements only what LW5 needs from the deprecated Allegro 4 API. +- **Pixel functions**: Use `putpixel()` and `getpixel()` from the backport layer instead of `al_put_pixel()` and `al_get_pixel()`. The backport functions work identically to the original Allegro 4 functions and should be favored for compatibility. + +## Game Features + +### Core Gameplay +- **Liquid Army Control**: Unique mechanic where armies flow like liquid +- **Multiplayer Support**: Up to 6 players locally or networked +- **Network Play**: TCP/IP multiplayer with dedicated server support +- **Custom Content**: User maps, textures, and music + +### Technical Features +- **Cross-platform**: Linux, Windows, macOS support +- **Assembly Optimizations**: i386 assembly for performance-critical code +- **Flexible Graphics**: Multiple resolution support +- **Modular Design**: Extensible map and texture system + +## Development Workflow + +### Building from Source +```bash +# Configure with standard options +./configure + +# Build everything +make + +# Install system-wide +sudo make install + +# Build documentation +make -C doc +``` + +### Development Commands +- `make clean` - Clean build files +- `make dep` - Update dependencies +- `make check` - Run tests +- `make package_source` - Create source distribution + +### Testing the Build +- Run `./src/liquidwar` to test the game client +- Check `liquidwar --help` for command-line options +- Test network functionality with `liquidwar-server` + +### Building Individual Files +- Use `make -C src/ filename.o` to build individual object files from the src directory +- Example: `make -C src/ backport.o` or `make -C src/ init.o` +- This is useful for testing compilation of specific modules during development + +## Platform-Specific Notes + +### Linux/Unix +- Primary development platform +- Uses X11 for graphics (through Allegro) +- Requires development headers for dependencies + +### Windows +- MinGW/MSYS2 supported +- Visual C++ project files in `misc/` +- Uses DirectX backend through Allegro + +### macOS +- Builds as native application +- Creates `.app` bundle with `make package_macosx_tgz` +- Handles dynamic library dependencies automatically + +## Packaging System + +The project includes extensive packaging support: +- **Source tarballs** (`make package_source`) +- **Binary packages** for multiple platforms +- **RPM packages** (`make package_binary_rpm`) +- **Windows installers** (NSIS-based) +- **Docker containers** for server deployment + +## Legacy Considerations + +This is a **20+ year old codebase** with significant historical context: +- Originally developed without version control +- Migrated from SourceForge to GitHub +- **Liquid War 6** exists but this version (5) remains widely used +- Code style reflects late 1990s C programming practices +- Contains platform compatibility layers for systems no longer common + +## Current Status + +- **Maintenance mode**: No active development +- **Stable**: Still compiles and runs on modern systems +- **Package availability**: Available in major Linux distributions +- **Community**: Small but dedicated user base +- **Successor**: Liquid War 6 exists but hasn't replaced this version + +## For Contributors + +If you want to contribute or experiment: +1. Focus on bug fixes rather than major features +2. Maintain compatibility with the existing codebase style +3. Test across multiple platforms if possible +4. Contact the original author (ufoot@ufoot.org) for guidance + +The codebase, while old, demonstrates solid C programming practices and cross-platform development techniques from the era before modern game engines. diff --git a/ChangeLog b/ChangeLog index ec5591a8..9334c94b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,16 @@ 2025-11-10 Christian Mauduit (ufoot@ufoot.org) - * Bump version to 5.6.7 to avoid confusion. + * Update copyright notice (year 2025). + +2020-01-05 Christian Mauduit (ufoot@ufoot.org) + + * Update copyright notice (year 2020). + +2018-12-24 Christian Mauduit (ufoot@ufoot.org) + + * Bump version to 5.7.0. + + * Backporting Allegro 4 functions for Allegro 5 (squashed many commits) 2025-11-09 Christian Mauduit (ufoot@ufoot.org) @@ -340,7 +350,7 @@ 2004-08-22 Christian Mauduit (ufoot@ufoot.org) - * Added more strategy tips suggested by Jan Samohl. + * Added more strategy tips suggested by Jan Samoh�l. 2004-08-19 Christian Mauduit (ufoot@ufoot.org) diff --git a/Makefile.dj b/Makefile.dj index c9687658..98ac8e61 100644 --- a/Makefile.dj +++ b/Makefile.dj @@ -19,9 +19,9 @@ # Contact author : ufoot@ufoot.org # # This Makefile is used to compile the MS DOS 32-bit executable binary. -# +# # It requires a working DJGPP http://www.delorie.com/djgpp/ install to work. -# +# # Typical DJGPP requirements are: # v2/copying.dj # v2/djdev203.zip @@ -154,9 +154,6 @@ volume \ watchdog \ wave \ wwwcli \ -glouglou \ -monster \ -spread \ vbeafex OBJ_NAMES_MAPGEN=\ @@ -179,7 +176,7 @@ OBJ_NAMES_MAPGEN=\ ../utils/lwmapgen/rand_poly_cut \ ../utils/lwmapgen/street \ ../utils/lwmapgen/worms - + OBJ_FILES=$(addprefix $(OBJ_PATH),$(addsuffix $(OBJ_EXT),$(OBJ_NAMES))) OBJ_FILES_MAPGEN=$(addprefix $(OBJ_PATH),$(addsuffix $(OBJ_EXT),$(OBJ_NAMES_MAPGEN))) @@ -218,4 +215,3 @@ lwdosmap.exe: $(OBJ_FILES_MAPGEN) @echo "=== End of lwdosmap.rsp ===" $(CC) -o $@ @lwdosmap.rsp @rm -f lwdosmap.rsp - diff --git a/Makefile.in b/Makefile.in index 2a22d376..575a6269 100644 --- a/Makefile.in +++ b/Makefile.in @@ -28,9 +28,9 @@ infodir = @infodir@ BINDIR = $(bindir) GAMEDIR = $(exec_prefix)/games -DATADIR = $(datadir)/games/liquidwar +DATADIR = $(datadir)/games/liquidwar5 PIXDIR = $(datadir)/pixmaps -DOCDIR = $(datadir)/doc/liquidwar +DOCDIR = $(datadir)/doc/liquidwar5 DESKTOPDIR = $(datadir)/applications # We don't use the autoconf default mandir=$(prefix)/man man # directory since the FHS (File Hierarchy Standard recommends @@ -64,7 +64,7 @@ MAKE_DIRS = $(MAKE_BIN_DIR) $(MAKE_UTILS_DIR) $(MAKE_DATA_DIR) $(MAKE_DOC_DIR) DOCKER_DIR = ./misc/docker -PACKAGE_SOURCE_DIR = liquidwar-$(VERSION) +PACKAGE_SOURCE_DIR = liquidwar5-$(VERSION) PACKAGE_SOURCE_TAR = $(PACKAGE_SOURCE_DIR).tar PACKAGE_SOURCE_TARGZ = $(PACKAGE_SOURCE_TAR).gz @@ -72,33 +72,26 @@ PACKAGE_DOCKER_SOURCE_TARGZ = $(DOCKER_DIR)/$(PACKAGE_SOURCE_TARGZ) PACKAGE_DOCKER_METASERVER_TARGZ = $(DOCKER_DIR)/metaserver.tar.gz PACKAGE_DOCKER_TABLES_SQL = $(DOCKER_DIR)/tables.sql -PACKAGE_BINARY_TAR = liquidwar-$(VERSION).$(HOST).tar -PACKAGE_BINARY_TGZ = liquidwar-$(VERSION).$(HOST).tgz - -PACKAGE_DOS_DIR = LW5 -PACKAGE_DOS_EXE = lwdos.exe lwdosmap.exe -PACKAGE_DOS_ZIP = lw$(VERSION_COMPACT)d.zip -PACKAGE_DOS_CWSDPMI = cwsdpmi.exe +PACKAGE_BINARY_TAR = liquidwar5-$(VERSION).$(HOST).tar +PACKAGE_BINARY_TGZ = liquidwar5-$(VERSION).$(HOST).tgz PACKAGE_WIN32_DIR = LW5 -PACKAGE_WIN32_EXE = lwwin.exe lwwinsrv.exe lwwinmap.exe -PACKAGE_WIN32_ZIP = lw$(VERSION_COMPACT)w.zip +PACKAGE_WIN32_EXE = lw5.exe lw5srv.exe lw5map.exe +PACKAGE_WIN32_ZIP = lw$(VERSION_COMPACT).zip PACKAGE_WIN32_ALLEGDLL = alleg44.dll PACKAGE_NSIS_EXE = lw$(VERSION_COMPACT).exe PACKAGE_SOURCE_RPM_TARGET = $(SRPMS_DIR) -PACKAGE_SOURCE_RPM = liquidwar-$(VERSION)-$(VERSION_REL).src.rpm +PACKAGE_SOURCE_RPM = liquidwar5-$(VERSION)-$(VERSION_REL).src.rpm PACKAGE_BINARY_RPM_TARGET = $(RPMS_DIR)/$(HOST_CPU) -PACKAGE_BINARY_RPM = liquidwar-$(VERSION)-$(VERSION_REL).$(HOST_CPU).rpm +PACKAGE_BINARY_RPM = liquidwar5-$(VERSION)-$(VERSION_REL).$(HOST_CPU).rpm -PACKAGE_MACOSX_TAR = liquidwar-$(VERSION)-macosx.tar -PACKAGE_MACOSX_TGZ = liquidwar-$(VERSION)-macosx.tgz -PACKAGE_MACOSX_DMG = liquidwar-$(VERSION).dmg +PACKAGE_MACOSX_TAR = liquidwar5-$(VERSION)-macosx.tar +PACKAGE_MACOSX_TGZ = liquidwar5-$(VERSION)-macosx.tgz +PACKAGE_MACOSX_DMG = liquidwar5-$(VERSION).dmg -PACKAGE_GP2X_DIR = liquidwar-$(VERSION)-gp2x -PACKAGE_GP2X_ZIP = liquidwar-$(VERSION)-gp2x.zip PACKAGE_TMP = /tmp/liquidwar-$(VERSION).tmp @@ -107,7 +100,7 @@ all: build_bin build_data build_doc @echo "Build complete." @echo "Type \"$(GMAKE) install\" to install Liquid War $(VERSION)." -world: clean world_clean all package_source package_win32 package_dos package_binary package_source_rpm package_binary_rpm package_gp2x +world: clean world_clean all package_source package_win32 package_binary package_source_rpm package_binary_rpm build_bin: @$(GMAKE) -C $(MAKE_BIN_DIR) @@ -129,65 +122,65 @@ install_nolink: install_bin install_data install_custom_map install_custom_textu @echo "Have a good day!" @echo " U-Foot (ufoot@ufoot.org)" @echo - @echo "Type \"liquidwar\" or \"$(GAMEDIR)/liquidwar\" to play." + @echo "Type \"liquidwar5\" or \"$(GAMEDIR)/liquidwar5\" to play." install_bin: src/liquidwar src/liquidwar-server src/liquidwar-mapgen - @echo "Installing liquidwar binaries in $(GAMEDIR)." + @echo "Installing liquidwar5 binaries in $(GAMEDIR)." @install -d $(DESTDIR)$(GAMEDIR) - @install -c -s src/liquidwar $(DESTDIR)$(GAMEDIR) - @install -c -s src/liquidwar-server $(DESTDIR)$(GAMEDIR) - @install -c -s src/liquidwar-mapgen $(DESTDIR)$(GAMEDIR) + @install -c -s src/liquidwar5 $(DESTDIR)$(GAMEDIR) + @install -c -s src/liquidwar5-server $(DESTDIR)$(GAMEDIR) + @install -c -s src/liquidwar5-mapgen $(DESTDIR)$(GAMEDIR) install_link: @echo "Installing link in $(BINDIR)." @install -d $(DESTDIR)$(BINDIR) - @rm -rf $(DESTDIR)$(BINDIR)/liquidwar - @rm -rf $(DESTDIR)$(BINDIR)/liquidwar-server - @rm -rf $(DESTDIR)$(BINDIR)/liquidwar-mapgen - @ln -s $(GAMEDIR)/liquidwar $(DESTDIR)$(BINDIR)/liquidwar - @ln -s $(GAMEDIR)/liquidwar-server $(DESTDIR)$(BINDIR)/liquidwar-server - @ln -s $(GAMEDIR)/liquidwar-mapgen $(DESTDIR)$(BINDIR)/liquidwar-mapgen - -install_data: data/liquidwar.dat - @echo "Installing liquidwar datafile in $(DATADIR)." + @rm -rf $(DESTDIR)$(BINDIR)/liquidwar5 + @rm -rf $(DESTDIR)$(BINDIR)/liquidwar5-server + @rm -rf $(DESTDIR)$(BINDIR)/liquidwar5-mapgen + @ln -s $(GAMEDIR)/liquidwar5 $(DESTDIR)$(BINDIR)/liquidwar5 + @ln -s $(GAMEDIR)/liquidwar5-server $(DESTDIR)$(BINDIR)/liquidwar5-server + @ln -s $(GAMEDIR)/liquidwar5-mapgen $(DESTDIR)$(BINDIR)/liquidwar5-mapgen + +install_data: data/liquidwar5.dat + @echo "Installing liquidwar5 datafile in $(DATADIR)." @install -d $(DESTDIR)$(DATADIR) - @install -c -m 0644 data/liquidwar.dat $(DESTDIR)$(DATADIR) + @install -c -m 0644 data/liquidwar5.dat $(DESTDIR)$(DATADIR) install_custom_map: - @echo "Installing liquidwar custom maps in $(DATADIR)/map." + @echo "Installing liquidwar5 custom maps in $(DATADIR)/map." @install -d $(DESTDIR)$(DATADIR) @install -d $(DESTDIR)$(DATADIR)/map @install -c -m 0644 custom/map/*.* $(DESTDIR)$(DATADIR)/map install_custom_texture: - @echo "Installing liquidwar custom textures in $(DATADIR)/texture." + @echo "Installing liquidwar5 custom textures in $(DATADIR)/texture." @install -d $(DESTDIR)$(DATADIR) @install -d $(DESTDIR)$(DATADIR)/texture @install -c -m 0644 custom/texture/*.* $(DESTDIR)$(DATADIR)/texture install_custom_music: - @echo "Installing liquidwar custom musics in $(DATADIR)/music." + @echo "Installing liquidwar5 custom musics in $(DATADIR)/music." @install -d $(DESTDIR)$(DATADIR) @install -d $(DESTDIR)$(DATADIR)/music @install -c -m 0644 custom/music/*.* $(DESTDIR)$(DATADIR)/music install_doc: - @if [ -f $(MAKE_DOC_DIR)/txt/rules.txt ]; then echo "Installing liquidwar plain text doc in $(DOCDIR)/txt."; install -d $(DESTDIR)$(DOCDIR)/txt; install -c -m 0644 $(MAKE_DOC_DIR)/txt/*.txt $(DESTDIR)$(DOCDIR)/txt; fi - @if [ -f $(MAKE_DOC_DIR)/html/rules.html ]; then echo "Installing liquidwar HTML doc in $(DOCDIR)/html."; install -d $(DESTDIR)$(DOCDIR)/html; install -c -m 0644 $(MAKE_DOC_DIR)/html/*.html $(DESTDIR)$(DOCDIR)/html; fi - @if [ -f $(MAKE_DOC_DIR)/man/liquidwar.6.gz ]; then echo "Installing liquidwar man page in $(MANDIR)."; install -d $(DESTDIR)$(MANDIR); install -c -m 0644 $(MAKE_DOC_DIR)/man/liquidwar.6.gz $(DESTDIR)$(MANDIR); ln -s -f liquidwar.6.gz $(DESTDIR)$(MANDIR)/liquidwar-server.6.gz; ln -s -f liquidwar.6.gz $(DESTDIR)$(MANDIR)/liquidwar-mapgen.6.gz; fi - @if [ -f $(MAKE_DOC_DIR)/info/liquidwar.info.gz ]; then echo "Installing info page $(INFODIR)/liquidwar.info.gz."; install -d $(DESTDIR)$(INFODIR); install -c -m 644 $(MAKE_DOC_DIR)/info/liquidwar.info* $(DESTDIR)$(INFODIR); if which install-info; then if test -d $(DESTDIR)$(INFODIRDIR); then if test -f $(DESTDIR)$(INFODIRDIR)/dir; then echo "Installing liquidwar info entry."; install-info --info-dir=$(DESTDIR)$(INFODIRDIR) $(MAKE_DOC_DIR)/info/liquidwar.info.gz; fi; fi; fi; fi - @if [ -f $(MAKE_DOC_DIR)/ps/liquidwar.ps ]; then echo "Installing liquidwar PostScript doc in $(DOCDIR)/ps."; install -d $(DESTDIR)$(DOCDIR)/ps; install -c -m 0644 $(MAKE_DOC_DIR)/ps/*.ps $(DESTDIR)$(DOCDIR)/ps; fi - @if [ -f $(MAKE_DOC_DIR)/pdf/liquidwar.pdf ]; then echo "Installing liquidwar PDF doc in $(DOCDIR)/pdf."; install -d $(DESTDIR)$(DOCDIR)/pdf; install -c -m 0644 $(MAKE_DOC_DIR)/pdf/*.pdf $(DESTDIR)$(DOCDIR)/pdf; fi + @if [ -f $(MAKE_DOC_DIR)/txt/rules.txt ]; then echo "Installing liquidwar5 plain text doc in $(DOCDIR)/txt."; install -d $(DESTDIR)$(DOCDIR)/txt; install -c -m 0644 $(MAKE_DOC_DIR)/txt/*.txt $(DESTDIR)$(DOCDIR)/txt; fi + @if [ -f $(MAKE_DOC_DIR)/html/rules.html ]; then echo "Installing liquidwar5 HTML doc in $(DOCDIR)/html."; install -d $(DESTDIR)$(DOCDIR)/html; install -c -m 0644 $(MAKE_DOC_DIR)/html/*.html $(DESTDIR)$(DOCDIR)/html; fi + @if [ -f $(MAKE_DOC_DIR)/man/liquidwar5.6.gz ]; then echo "Installing liquidwar5 man page in $(MANDIR)."; install -d $(DESTDIR)$(MANDIR); install -c -m 0644 $(MAKE_DOC_DIR)/man/liquidwar5.6.gz $(DESTDIR)$(MANDIR); ln -s -f liquidwar5.6.gz $(DESTDIR)$(MANDIR)/liquidwar5-server.6.gz; ln -s -f liquidwar5.6.gz $(DESTDIR)$(MANDIR)/liquidwar5-mapgen.6.gz; fi + @if [ -f $(MAKE_DOC_DIR)/info/liquidwar5.info.gz ]; then echo "Installing info page $(INFODIR)/liquidwar5.info.gz."; install -d $(DESTDIR)$(INFODIR); install -c -m 644 $(MAKE_DOC_DIR)/info/liquidwar5.info* $(DESTDIR)$(INFODIR); if which install-info; then if test -d $(DESTDIR)$(INFODIRDIR); then if test -f $(DESTDIR)$(INFODIRDIR)/dir; then echo "Installing liquidwar5 info entry."; install-info --info-dir=$(DESTDIR)$(INFODIRDIR) $(MAKE_DOC_DIR)/info/liquidwar5.info.gz; fi; fi; fi; fi + @if [ -f $(MAKE_DOC_DIR)/ps/liquidwar5.ps ]; then echo "Installing liquidwar5 PostScript doc in $(DOCDIR)/ps."; install -d $(DESTDIR)$(DOCDIR)/ps; install -c -m 0644 $(MAKE_DOC_DIR)/ps/*.ps $(DESTDIR)$(DOCDIR)/ps; fi + @if [ -f $(MAKE_DOC_DIR)/pdf/liquidwar5.pdf ]; then echo "Installing liquidwar5 PDF doc in $(DOCDIR)/pdf."; install -d $(DESTDIR)$(DOCDIR)/pdf; install -c -m 0644 $(MAKE_DOC_DIR)/pdf/*.pdf $(DESTDIR)$(DOCDIR)/pdf; fi install_icon: - @echo "Installing liquidwar icon in $(PIXDIR)." + @echo "Installing liquidwar5 icon in $(PIXDIR)." @install -d $(DESTDIR)$(PIXDIR) - @install -c -m 0644 misc/liquidwar.xpm $(DESTDIR)$(PIXDIR) + @install -c -m 0644 misc/liquidwar5.xpm $(DESTDIR)$(PIXDIR) install_desktop: @echo "Installing desktop file in $(DESKTOPDIR)." @install -d $(DESTDIR)$(DESKTOPDIR) - @install -c -m 0644 misc/liquidwar.desktop $(DESTDIR)$(DESKTOPDIR) + @install -c -m 0644 misc/liquidwar5.desktop $(DESTDIR)$(DESKTOPDIR) install_gpl: @echo "Installing GPL in $(DOCDIR)." @@ -204,31 +197,31 @@ install_readme: @install -c -m 0644 README.pl $(DESTDIR)$(DOCDIR) uninstall: - @echo "Removing binary $(GAMEDIR)/liquidwar." - @rm -f $(DESTDIR)$(GAMEDIR)/liquidwar - @echo "Removing binary $(GAMEDIR)/liquidwar-server." - @rm -f $(DESTDIR)$(GAMEDIR)/liquidwar-server + @echo "Removing binary $(GAMEDIR)/liquidwar5." + @rm -f $(DESTDIR)$(GAMEDIR)/liquidwar5 + @echo "Removing binary $(GAMEDIR)/liquidwar5-server." + @rm -f $(DESTDIR)$(GAMEDIR)/liquidwar5-server @echo "Removing data directory $(DATADIR)." @rm -rf $(DESTDIR)$(DATADIR) @echo "Removing documentation directory $(DOCDIR)." @rm -rf $(DESTDIR)$(DOCDIR) - @echo "Removing man page $(MANDIR)/liquidwar.6.gz." - @rm -f $(DESTDIR)$(MANDIR)/liquidwar.6.gz - @echo "Removing man page $(MANDIR)/liquidwar-server.6.gz." - @rm -f $(DESTDIR)$(MANDIR)/liquidwar-server.6.gz - @echo "Removing man page $(MANDIR)/liquidwar-mapgen.6.gz." - @rm -f $(DESTDIR)$(MANDIR)/liquidwar-mapgen.6.gz - @echo "Removing info page $(INFODIR)/liquidwar.info.gz." - @rm -f $(DESTDIR)$(INFODIR)/liquidwar.info* - @if which install-info; then if test -d $(DESTDIR)$(INFODIRDIR); then if test -f $(DESTDIR)$(INFODIRDIR)/dir; then echo "Removing info entry."; install-info --info-dir=$(DESTDIR)$(INFODIRDIR) --remove liquidwar; fi; fi; fi - @echo "Removing icon $(PIXDIR)/liquidwar.xpm." - @rm -f $(DESTDIR)$(PIXDIR)/liquidwar.xpm - @echo "Removing desktop file $(DESKTOPDIR)/liquidwar.desktop." - @rm -f $(DESTDIR)$(DESKTOPDIR)/liquidwar.desktop - @echo "Removing link $(BINDIR)/liquidwar." - @rm -f $(DESTDIR)$(BINDIR)/liquidwar - @echo "Removing link $(BINDIR)/liquidwar-server." - @rm -f $(DESTDIR)$(BINDIR)/liquidwar-server + @echo "Removing man page $(MANDIR)/liquidwar5.6.gz." + @rm -f $(DESTDIR)$(MANDIR)/liquidwar5.6.gz + @echo "Removing man page $(MANDIR)/liquidwar5-server.6.gz." + @rm -f $(DESTDIR)$(MANDIR)/liquidwar5-server.6.gz + @echo "Removing man page $(MANDIR)/liquidwar5-mapgen.6.gz." + @rm -f $(DESTDIR)$(MANDIR)/liquidwar5-mapgen.6.gz + @echo "Removing info page $(INFODIR)/liquidwar5.info.gz." + @rm -f $(DESTDIR)$(INFODIR)/liquidwar5.info* + @if which install-info; then if test -d $(DESTDIR)$(INFODIRDIR); then if test -f $(DESTDIR)$(INFODIRDIR)/dir; then echo "Removing info entry."; install-info --info-dir=$(DESTDIR)$(INFODIRDIR) --remove liquidwar5; fi; fi; fi + @echo "Removing icon $(PIXDIR)/liquidwar5.xpm." + @rm -f $(DESTDIR)$(PIXDIR)/liquidwar5.xpm + @echo "Removing desktop file $(DESKTOPDIR)/liquidwar5.desktop." + @rm -f $(DESTDIR)$(DESKTOPDIR)/liquidwar5.desktop + @echo "Removing link $(BINDIR)/liquidwar5." + @rm -f $(DESTDIR)$(BINDIR)/liquidwar5 + @echo "Removing link $(BINDIR)/liquidwar5-server." + @rm -f $(DESTDIR)$(BINDIR)/liquidwar5-server clean: @for d in $(MAKE_DIRS); do $(GMAKE) -C $$d clean; done @@ -243,23 +236,21 @@ world_clean: @rm -f $(PACKAGE_BINARY_TGZ) @rm -f $(PACKAGE_SOURCE_RPM) @rm -f $(PACKAGE_BINARY_RPM) - @rm -f $(PACKAGE_DOS_ZIP) @rm -f $(PACKAGE_WIN32_ZIP) @rm -f $(PACKAGE_NSIS_EXE) @rm -f $(PACKAGE_MACOSX_TGZ) @rm -f $(PACKAGE_MACOSX_DMG) - @rm -f $(PACKAGE_GP2X_ZIP) # used when preparing packages packageclean: clean world_clean @rm -r -f Makefile config.cache config.status config.log autom4te.cache - @rm -f misc/liquidward misc/macosx_info.plist misc/liquidwar.nsi misc/docker/Dockerfile-build misc/docker/Dockerfile-server misc/docker/Dockerfile-metaserver + @rm -f misc/liquidwar5d misc/macosx_info.plist misc/liquidwar5.nsi misc/docker/Dockerfile-build misc/docker/Dockerfile-server misc/docker/Dockerfile-metaserver @find . -name "*.o" -o -name "*.obj" | xargs rm -f @find . -name "*.tar.gz" -o -name "*.tgz" -o -name "*.zip" -o -name "*.rpm" -o -name "*.deb" -o -name "*.tgz" | xargs rm -f @find . -name ".xvpics" | xargs rm -rf @find . -name "lwmap.bmp" | xargs rm -f - @rm -rf LW5 lwdos*exe lwwin*exe _tmpfile.arg *.log vc60.* *.idb *.pch - @rm -rf data/lwwin* data/lwdos* + @rm -rf LW5 lwwin*exe _tmpfile.arg *.log vc60.* *.idb *.pch + @rm -rf data/lwwin* @rm -rf starter @rm -rf .github @for d in $(MAKE_DIRS); do $(GMAKE) -C $$d distclean; done @@ -283,7 +274,6 @@ dep: # - a source tarball # - a static binary stored in a .tar.gz # - a win32 binary -# - a dos binary # - a source rpm # - a binary rpm # @@ -315,46 +305,6 @@ $(PACKAGE_SOURCE_TARGZ): @echo "Deleting temporary directory." @rm -rf $(PACKAGE_TMP) -package_dos: $(PACKAGE_DOS_ZIP) - -$(PACKAGE_DOS_ZIP): $(PACKAGE_DOS_EXE) $(PACKAGE_DOS_CWSDPMI) - @echo "Building data." - @$(GMAKE) -C data - @echo "Building doc." - @$(GMAKE) -C doc - @echo "Creating temporary directory." - @rm -rf $(PACKAGE_TMP) - @install -d $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR) - @echo "Copying files." - @cp $(PACKAGE_DOS_EXE) $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR) - @cp $(PACKAGE_DOS_CWSDPMI) $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR) - @cp README.md $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/readme.txt - @cp README.fr $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/readmefr.txt - @cp README.de $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/readmede.txt - @cp README.dk $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/readmedk.txt - @cp README.pl $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/readmepl.txt - @cp COPYING $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/license.txt - @cp ChangeLog $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/changes.txt - @cp misc/liquidwar.ico $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/lw.ico - @install -d $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/data - @cp data/liquidwar.dat $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/data/lw.dat - @install -d $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/custom - @cp -r custom/map $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/custom - @cp -r custom/texture $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/custom - @cp -r custom/music $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/custom - @install -d $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/doc - @cp -r doc/txt $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/doc - @echo "Cleaning up." - @touch $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR)/.cvsignore - @find $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR) -name .cvsignore -o -name CVS -o -name .arch-ids -o -name "{arch}" -o -name DUMMY -o -name "*.inc" -o -name "*.in" | xargs rm -rf - @cp fix.sh $(PACKAGE_TMP) - @cd $(PACKAGE_TMP)/$(PACKAGE_DOS_DIR) && $(PACKAGE_TMP)/fix.sh dos - @echo "Zipping." - @cd $(PACKAGE_TMP) && zip -r -9 $(PACKAGE_DOS_ZIP) $(PACKAGE_DOS_DIR) - @mv $(PACKAGE_TMP)/$(PACKAGE_DOS_ZIP) . - @echo "Deleting temporary directory." - @rm -rf $(PACKAGE_TMP) - package_win32: $(PACKAGE_WIN32_ZIP) $(PACKAGE_WIN32_ZIP): $(PACKAGE_WIN32_EXE) $(PACKAGE_WIN32_ALLEGDLL) @@ -376,7 +326,7 @@ $(PACKAGE_WIN32_ZIP): $(PACKAGE_WIN32_EXE) $(PACKAGE_WIN32_ALLEGDLL) @cp COPYING $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/license.txt @cp ChangeLog $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/changes.txt @install -d $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/data - @cp data/liquidwar.dat $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/data/lw.dat + @cp data/liquidwar5.dat $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/data/lw.dat @install -d $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/custom @cp -r custom/map $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/custom @cp -r custom/texture $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/custom @@ -403,8 +353,8 @@ $(PACKAGE_NSIS_EXE): $(PACKAGE_WIN32_ZIP) @install -d $(PACKAGE_TMP) @cp $(PACKAGE_WIN32_ZIP) $(PACKAGE_TMP) @cd $(PACKAGE_TMP) && unzip $(PACKAGE_WIN32_ZIP) - @cp misc/liquidwar.nsi $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR) - @cd $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR) && makensis liquidwar.nsi + @cp misc/liquidwar5.nsi $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR) + @cd $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR) && makensis liquidwar5.nsi @cp $(PACKAGE_TMP)/$(PACKAGE_WIN32_DIR)/$(PACKAGE_NSIS_EXE) . @rm -rf $(PACKAGE_TMP) @@ -427,7 +377,7 @@ $(PACKAGE_BINARY_TGZ): $(PACKAGE_SOURCE_TARGZ) @echo "Installing." @$(GMAKE) -C $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR) install @echo "Creating tarball." - @tar cfP $(PACKAGE_TMP)/$(PACKAGE_BINARY_TAR) $(GAMEDIR)/liquidwar $(GAMEDIR)/liquidwar-server $(GAMEDIR)/liquidwar-mapgen $(BINDIR)/liquidwar $(BINDIR)/liquidwar-server $(BINDIR)/liquidwar-mapgen $(DOCDIR) $(DATADIR) $(MANDIR)/liquidwar.6.gz $(MANDIR)/liquidwar-server.6.gz $(MANDIR)/liquidwar-mapgen.6.gz $(PIXDIR)/liquidwar.xpm $(DESKTOPDIR)/liquidwar.desktop + @tar cfP $(PACKAGE_TMP)/$(PACKAGE_BINARY_TAR) $(GAMEDIR)/liquidwar5 $(GAMEDIR)/liquidwar5-server $(GAMEDIR)/liquidwar5-mapgen $(BINDIR)/liquidwar5 $(BINDIR)/liquidwar5-server $(BINDIR)/liquidwar5-mapgen $(DOCDIR) $(DATADIR) $(MANDIR)/liquidwar5.6.gz $(MANDIR)/liquidwar5-server.6.gz $(MANDIR)/liquidwar5-mapgen.6.gz $(PIXDIR)/liquidwar5.xpm $(DESKTOPDIR)/liquidwar5.desktop @echo "Compressing." @gzip -c -9 $(PACKAGE_TMP)/$(PACKAGE_BINARY_TAR) > $(PACKAGE_BINARY_TGZ) @echo "Cleaning up install directories." @@ -476,14 +426,14 @@ $(PACKAGE_MACOSX_TGZ): $(PACKAGE_SOURCE_TARGZ) @install -d "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/custom" @install -d "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/doc" @echo "Copying files." - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar-server "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar-mapgen "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/data/liquidwar.dat "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/data/" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar5 "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar5-server "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar5-mapgen "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/data/liquidwar5.dat "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/data/" @cp -r $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/custom/map "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/custom/" @cp -r $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/custom/texture "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/custom/" @cp -r $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/custom/music "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/custom/" - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/misc/liquidwar.icns "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/misc/liquidwar5.icns "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/" @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/misc/macosx_info.plist "$(PACKAGE_TMP)/Liquid War.app/Contents/Info.plist" @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/COPYING "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/doc/" @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/COPYING "$(PACKAGE_TMP)/License.txt" @@ -494,9 +444,9 @@ $(PACKAGE_MACOSX_TGZ): $(PACKAGE_SOURCE_TARGZ) @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/README.fr "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/doc/" @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/README.pl "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/doc/" @cp -r $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/doc/html $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/doc/txt $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/doc/pdf "$(PACKAGE_TMP)/Liquid War.app/Contents/Resources/doc/" - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/doc/pdf/liquidwar.pdf "$(PACKAGE_TMP)/Liquid War.pdf" + @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/doc/pdf/liquidwar5.pdf "$(PACKAGE_TMP)/Liquid War.pdf" @echo "Updating dynamic libraries dependencies" - @if which otool; then for i in `otool -L $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar | grep dylib | grep -v /usr | grep /opt | cut -d "(" -f 1` ; do j=$${i##*/}; cp $$i "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/"; chmod 644 "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/$$j"; install_name_tool -id @executable_path/$$j "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/$$j"; install_name_tool -change $$i @executable_path/$$j "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/liquidwar"; done ; fi # yes, this is complicated, the idea is to run otool -L to find every library dependency, keep only those in /opt installed by macports or from source, then run install_name_tool to change references to a path relative to the executable path, so that it's findable within the package and does not rely on some developper's local install. One more point: we can't put libs outsite @executable_path (./MacOS) because if path is too long install_name_path won't work... See -headerpad_max_install_names option in LDFLAGS, might help too + @if which otool; then for i in `otool -L $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar5 | grep dylib | grep -v /usr | grep /opt | cut -d "(" -f 1` ; do j=$${i##*/}; cp $$i "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/"; chmod 644 "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/$$j"; install_name_tool -id @executable_path/$$j "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/$$j"; install_name_tool -change $$i @executable_path/$$j "$(PACKAGE_TMP)/Liquid War.app/Contents/MacOS/liquidwar5"; done ; fi # yes, this is complicated, the idea is to run otool -L to find every library dependency, keep only those in /opt installed by macports or from source, then run install_name_tool to change references to a path relative to the executable path, so that it's findable within the package and does not rely on some developper's local install. One more point: we can't put libs outsite @executable_path (./MacOS) because if path is too long install_name_path won't work... See -headerpad_max_install_names option in LDFLAGS, might help too @echo "Cleaning up." @find $(PACKAGE_TMP) -name DUMMY -exec rm -f "{}" \; @find $(PACKAGE_TMP) -name "*.in" -exec rm -f "{}" \; @@ -526,36 +476,6 @@ $(PACKAGE_MACOSX_DMG): $(PACKAGE_MACOSX_TGZ) @echo "Deleting temporary directory." @rm -rf $(PACKAGE_TMP) -package_gp2x: $(PACKAGE_GP2X_ZIP) - -$(PACKAGE_GP2X_ZIP): $(PACKAGE_SOURCE_TARGZ) - @echo "Compiling dat file." - @$(GMAKE) -C data - @echo "Creating temporary directory." - @rm -rf $(PACKAGE_TMP) - @install -d $(PACKAGE_TMP) - @echo "Preparing source." - @cp $(PACKAGE_SOURCE_TARGZ) $(PACKAGE_TMP) - @cd $(PACKAGE_TMP) && tar xzf $(PACKAGE_SOURCE_TARGZ) - @echo "Compiling binary." - @cd $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR) && sh -c ". /opt/open2x/bin/env-apps.sh && ./configure --prefix=/opt --build=x86_64-pc-linux-gnu --host=arm-open2x-linux && make -C src" - @install -d $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR) - @cp $(PACKAGE_TMP)/$(PACKAGE_SOURCE_DIR)/src/liquidwar* $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/ - @cp data/liquidwar.dat $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/ - @cp misc/liquidwar.gpe $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/ - @cp COPYING $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/license.txt - @cp ChangeLog $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/changes.txt - @cp README.md $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/readme.txt - @cp README.fr $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/readmefr.txt - @cp README.de $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/readmede.txt - @cp README.dk $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/readmedk.txt - @cp README.pl $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/readmepl.txt - @cp -r doc/html $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR)/doc - @find $(PACKAGE_TMP)/$(PACKAGE_GP2X_DIR) -name .cvsignore -o -name CVS -o -name .arch-ids -o -name "{arch}" -o -name DUMMY -o -name "*.inc" -o -name "*.in" | xargs rm -rf - @cd $(PACKAGE_TMP) && zip -r $(PACKAGE_GP2X_ZIP) $(PACKAGE_GP2X_DIR) - @cp $(PACKAGE_TMP)/$(PACKAGE_GP2X_ZIP) . - @rm -rf $(PACKAGE_TMP) - $(PACKAGE_DOCKER_SOURCE_TARGZ): $(PACKAGE_SOURCE_TARGZ) @cp $< $@ @@ -569,13 +489,13 @@ $(PACKAGE_DOCKER_TABLES_SQL): www/mysql/tables.sql docker: docker-build docker-server docker-metaserver docker-build: $(PACKAGE_DOCKER_SOURCE_TARGZ) - @cd $(DOCKER_DIR) && docker build -f Dockerfile-build -t ufoot/liquidwar-build:$(VERSION) . - @cd $(DOCKER_DIR) && docker build -f Dockerfile-build -t ufoot/liquidwar-build:latest . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-build -t ufoot/liquidwar5-build:$(VERSION) . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-build -t ufoot/liquidwar5-build:latest . docker-server: $(PACKAGE_DOCKER_SOURCE_TARGZ) - @cd $(DOCKER_DIR) && docker build -f Dockerfile-server -t ufoot/liquidwar-server:$(VERSION) . - @cd $(DOCKER_DIR) && docker build -f Dockerfile-server -t ufoot/liquidwar-server:latest . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-server -t ufoot/liquidwar5-server:$(VERSION) . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-server -t ufoot/liquidwar5-server:latest . docker-metaserver: $(PACKAGE_DOCKER_METASERVER_TARGZ) $(PACKAGE_DOCKER_TABLES_SQL) - @cd $(DOCKER_DIR) && docker build -f Dockerfile-metaserver -t ufoot/liquidwar-metaserver:$(VERSION) . - @cd $(DOCKER_DIR) && docker build -f Dockerfile-metaserver -t ufoot/liquidwar-metaserver:latest . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-metaserver -t ufoot/liquidwar5-metaserver:$(VERSION) . + @cd $(DOCKER_DIR) && docker build -f Dockerfile-metaserver -t ufoot/liquidwar5-metaserver:latest . diff --git a/Makefile.mgw b/Makefile.mgw index 2b95067b..27895100 100644 --- a/Makefile.mgw +++ b/Makefile.mgw @@ -143,10 +143,7 @@ volume \ watchdog \ wave \ wwwcli \ -glouglou \ -monster \ -spread \ -lwwin +lwwin OBJ_NAMES_SRV=\ basicopt \ @@ -192,8 +189,8 @@ OBJ_NAMES_MAPGEN=\ ../utils/lwmapgen/rand_poly \ ../utils/lwmapgen/rand_poly_cut \ ../utils/lwmapgen/street \ -../utils/lwmapgen/worms - +../utils/lwmapgen/worms + OBJ_FILES=$(addprefix $(OBJ_PATH),$(addsuffix $(OBJ_EXT),$(OBJ_NAMES))) OBJ_FILES_SRV=$(addprefix $(OBJ_PATH),$(addsuffix $(OBJ_EXT),$(OBJ_NAMES_SRV))) @@ -225,6 +222,3 @@ lwwinsrv.exe: $(OBJ_FILES_SRV) lwwinmap.exe: $(OBJ_FILES_MAPGEN) gcc -Wl,--subsystem,console -o $@ $(OBJ_FILES_MAPGEN) -lalleg44 - - - diff --git a/README.md b/README.md index 20a1bc43..58e2bb07 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ License ------- Liquid War is a multiplayer wargame. + Copyright (C) 1998-2025 Christian Mauduit (ufoot@ufoot.org) This program is free software; you can redistribute it and/or diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..5c4cb704 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,358 @@ +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurrence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + diff --git a/configure.ac b/configure.ac index d711b214..d1e16b21 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT() +AC_INIT AC_PROG_CC @@ -30,22 +30,27 @@ dnl Now we check if we need to use ou own snprintf function AC_CHECK_FUNC(snprintf,[SNPRINTF=yes],[SNPRINTF=no]) AC_SUBST(SNPRINTF) +dnl Checking for allegro-5. +echo -n "checking for Allegro 5... " -dnl Checking for allegro-config, the very-needed Allegro file +PKG_PROG_PKG_CONFIG([0.25]) -AC_CHECK_PROG(ALLEGRO_CONFIG,allegro-config,yes,no) +PKG_CHECK_MODULES([ALLEGRO5], + [allegro-5,allegro_primitives-5,allegro_audio-5,allegro_font-5,allegro_image-5,allegro_color-5,allegro_acodec-5], + [ALLEGRO5_VERSION=5], + [PKG_CHECK_MODULES([ALLEGRO50], + [allegro-5.0,allegro_primitives-5.0,allegro_audio-5.0,allegro_font-5.0,allegro_image-5.0,allegro_color-5.0,allegro_acodec-5.0], + [ALLEGRO5_VERSION=5.0] + )] +) -if test $ALLEGRO_CONFIG != "yes"; then - AC_MSG_ERROR(Unable to find allegro-config - this tool is normally installed by Allegro and must be placed in a directory which is in your PATH. Allegro is a game programming library required by Liquid War. It is available on http://www.talula.demon.co.uk/allegro/. You need to install the complete Allegro developpement package to build Liquid War.) -fi; +echo "using allegro-$ALLEGRO5_VERSION" -dnl Various checks for Allegro +ALCFLAGS=$(pkg-config --cflags allegro-$ALLEGRO5_VERSION allegro_primitives-$ALLEGRO5_VERSION allegro_audio-$ALLEGRO5_VERSION allegro_font-$ALLEGRO5_VERSION allegro_image-$ALLEGRO5_VERSION allegro_color-$ALLEGRO5_VERSION allegro_acodec-$ALLEGRO5_VERSION) +ALLIBS=$(pkg-config --libs allegro-$ALLEGRO5_VERSION allegro_primitives-$ALLEGRO5_VERSION allegro_audio-$ALLEGRO5_VERSION allegro_font-$ALLEGRO5_VERSION allegro_image-$ALLEGRO5_VERSION allegro_color-$ALLEGRO5_VERSION allegro_acodec-$ALLEGRO5_VERSION allegro_main-$ALLEGRO5_VERSION) +ALVERSION=$(pkg-config --modversion allegro-$ALLEGRO5_VERSION) -echo -n "checking for Allegro... " -ALCFLAGS=`allegro-config --cflags 2>/dev/null` -ALLIBS=`allegro-config --libs 2>/dev/null` -ALVERSION=`allegro-config --version 2>/dev/null` -ALDVERSION=`echo ALVERSION | awk 'BEGIN { FS = "."; } { printf "%d",($1 * 1000 + $2) * 1000 + $3;}'` +ALDVERSION=$(echo ALVERSION | awk 'BEGIN { FS = "."; } { printf "%d",($1 * 1000 + $2) * 1000 + $3;}') AC_SUBST(ALCFLAGS) AC_SUBST(ALLIBS) @@ -60,30 +65,12 @@ fi dnl dnl version check dnl -if test $ALDVERSION -gt 4002000 ; then - AC_MSG_ERROR(An old version of Allegro ($ALVERSION) has been detected - please upgrade to 4.2.0 or better.) +if test $ALDVERSION -gt 5000000 ; then + AC_MSG_ERROR(An old version of Allegro ($ALVERSION) has been detected - please upgrade to 5.0.0 or better.) else echo "found $ALVERSION". fi -dnl disabled this. assume allegro-config doesn't lie and all files are -dnl available -#AC_CHECK_HEADER(allegro.h,,[AC_MSG_ERROR(Missing some include file. Please reinstall Allegro.)]) - -dnl disabled this. assume allegro-config doesn't lie and all files are -dnl available -#AC_CHECK_LIB(alleg,main,,[AC_MSG_ERROR(Compilation probe failed. Please check your Allegro installation.)]) - -dnl very often, dat (the datafile compiler) is not installed, -dnl and we _really_ need it... -AC_CHECK_PROG(ALLEGRO_DAT,dat,yes,no) - -if test $ALLEGRO_DAT != "yes"; then - AC_MSG_ERROR(Couldn't find the allegro datafile compiler - please install the complete Allegro package with all its developper tools. The end-user package is not enough to compile Liquid War.) -fi; - - - dnl Uncomment this if you want to shock your users #cat < $@ -info/liquidwar.info.gz : texi/liquidwar.texi +info/liquidwar5.info.gz : texi/liquidwar5.texi @echo "Building $@..." - @rm -f info/liquidwar.info* - @makeinfo -o info/liquidwar.info $< - @gzip -9 info/liquidwar.info* + @rm -f info/liquidwar5.info* + @makeinfo -o info/liquidwar5.info $< + @gzip -9 info/liquidwar5.info* -texi/liquidwar.texi : $(TEXI_FILES) texi/begin.texi texi/end.texi +texi/liquidwar5.texi : $(TEXI_FILES) texi/begin.texi texi/end.texi @echo "Building $@..." @cat texi/begin.texi $(TEXI_FILES) texi/end.texi > $@ @@ -142,14 +142,14 @@ uwc/%.uwc: xml/%.xml makedoc.py dummy: clean: - @rm -f *~ */*~ + @rm -f *~ */*~ @rm -f makedoc.pyc @rm -f $(HTML_FILES) $(PHP_FILES) $(TEX_FILES) $(MAN_FILES) $(TXT_FILES) $(TEXI_FILES) $(UWC_FILES) - @rm -f tex/liquidwar.toc tex/liquidwar.log tex/liquidwar.dvi tex/liquidwar.aux ps/liquidwar.ps pdf/liquidwar.pdf man/liquidwar.6 man/liquidwar.6.gz man/liquidwar-server.6.gz man/liquidwar-mapgen.6.gz man/liquidwar.man info/liquidwar.info* texi/liquidwar.texi texi/liquidwar.info* + @rm -f tex/liquidwar5.toc tex/liquidwar5.log tex/liquidwar5.dvi tex/liquidwar5.aux ps/liquidwar5.ps pdf/liquidwar5.pdf man/liquidwar5.6 man/liquidwar5.6.gz man/liquidwar5-server.6.gz man/liquidwar5-mapgen.6.gz man/liquidwar5.man info/liquidwar5.info* texi/liquidwar5.texi texi/liquidwar5.info* -distclean: +distclean: @rm -f Makefile - @rm -f tex/liquidwar.tex man/begin.man texi/begin.texi html/index.html + @rm -f tex/liquidwar5.tex man/begin.man texi/begin.texi html/index.html config: @@ -157,6 +157,3 @@ check: @xmllint --valid --noout xml/*.xml dep: - - - diff --git a/doc/tex/liquidwar.tex.in b/doc/tex/liquidwar5.tex.in similarity index 100% rename from doc/tex/liquidwar.tex.in rename to doc/tex/liquidwar5.tex.in diff --git a/liquidwar.spec b/liquidwar5.spec similarity index 76% rename from liquidwar.spec rename to liquidwar5.spec index 5a00c7fb..b03c6663 100644 --- a/liquidwar.spec +++ b/liquidwar5.spec @@ -1,12 +1,12 @@ Summary: A unique multiplayer wargame. Summary(fr): Un "wargame" multijoueur indit. Summary(de): Ein einzigartiges Kriegspiel fr mehrere Spieler. -Name: liquidwar -Version: 5.6.5 +Name: liquidwar5 +Version: 5.7.0 Release: 1 License: GPL Group: Amusements/Games -Source: http://freesoftware.fsf.org/download/liquidwar/liquidwar-5.6.5.tar.gz +Source: https://ufoot.org/download/liquidwar/v5/5.7.0/liquidwar5-5.7.0.tar.gz URL: https://ufoot.org/liquidwar/v5 Vendor: Christian Mauduit Packager: Christian Mauduit @@ -47,13 +47,13 @@ til multiplayer, og har netv # Building the package %build -make +make # Installing the package # The "make uninstall" is important since it prevents rpm from # putting old unused files in the archive. %install -export DESTDIR=%{buildroot} && make uninstall && make install +export DESTDIR=%{buildroot} && make uninstall && make install # Cleaning %clean @@ -65,7 +65,7 @@ rm -rf %{buildroot} # Post-install script # It basically adds the info page to the Top info page. %post -if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info %{_prefix}/share/info/liquidwar.info.gz; fi; fi; fi +if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info %{_prefix}/share/info/liquidwar5.info.gz; fi; fi; fi # Pre-uninstall script %preun @@ -73,27 +73,30 @@ if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefi # Post-uninstall script # It basically removes the info page to the Top info page. %postun -if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info --remove liquidwar; fi; fi; fi +if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info --remove liquidwar5; fi; fi; fi %files %defattr(-,root,root) -%{_prefix}/games/liquidwar -%{_prefix}/games/liquidwar-server -%{_prefix}/games/liquidwar-mapgen -%{_prefix}/bin/liquidwar -%{_prefix}/bin/liquidwar-server -%{_prefix}/bin/liquidwar-mapgen -%{_prefix}/share/games/liquidwar/ -%{_prefix}/share/doc/liquidwar/ -%{_prefix}/share/man/man6/liquidwar.6* -%{_prefix}/share/man/man6/liquidwar-server.6* -%{_prefix}/share/man/man6/liquidwar-mapgen.6* -%{_prefix}/share/info/liquidwar.info* -%{_prefix}/share/pixmaps/liquidwar.xpm -%{_prefix}/share/applications/liquidwar.desktop +%{_prefix}/games/liquidwar5 +%{_prefix}/games/liquidwar5-server +%{_prefix}/games/liquidwar5-mapgen +%{_prefix}/bin/liquidwar5 +%{_prefix}/bin/liquidwar5-server +%{_prefix}/bin/liquidwar5-mapgen +%{_prefix}/share/games/liquidwar5/ +%{_prefix}/share/doc/liquidwar5/ +%{_prefix}/share/man/man6/liquidwar5.6* +%{_prefix}/share/man/man6/liquidwar5-server.6* +%{_prefix}/share/man/man6/liquidwar5-mapgen.6* +%{_prefix}/share/info/liquidwar5.info* +%{_prefix}/share/pixmaps/liquidwar5.xpm +%{_prefix}/share/applications/liquidwar5.desktop %changelog +* Sat Nov 22 2025 Christian Mauduit +- adapt to new Allegro 5 branch, call it liquidwar5 + * Thu Sep 27 2007 Christian Mauduit - Added mapgen files, fixed deprecated RPM syntax. @@ -110,15 +113,14 @@ if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefi - Fixed some buildroot bugs - Replaced install-info --infodir=... by --info-dir=... -* Mon Mar 11 2002 Christian Mauduit +* Mon Mar 11 2002 Christian Mauduit - Recompiled with Allegro's rpm (fixes the error: "/usr/lib/liballeg.so.4.0: undefined symbol: _poly_scanline_gcol8") - Fixed the post-install script -* Sat Feb 23 2002 Christian Mauduit +* Sat Feb 23 2002 Christian Mauduit - Added proper "--target" support. - Added info documentation with install and uninstall scripts -* Thu Jan 28 2002 Christian Mauduit +* Thu Jan 28 2002 Christian Mauduit - My first rpm build of Liquid War - diff --git a/liquidwar.spec.in b/liquidwar5.spec.in similarity index 76% rename from liquidwar.spec.in rename to liquidwar5.spec.in index 66ac6f39..d578ff14 100644 --- a/liquidwar.spec.in +++ b/liquidwar5.spec.in @@ -1,12 +1,12 @@ Summary: A unique multiplayer wargame. Summary(fr): Un "wargame" multijoueur indit. Summary(de): Ein einzigartiges Kriegspiel fr mehrere Spieler. -Name: liquidwar +Name: liquidwar5 Version: @VERSION@ Release: @VERSION_REL@ License: GPL Group: Amusements/Games -Source: http://freesoftware.fsf.org/download/liquidwar/liquidwar-@VERSION@.tar.gz +Source: https://ufoot.org/download/liquidwar/v5/@VERSION@/liquidwar5-@VERSION@.tar.gz URL: https://ufoot.org/liquidwar/v5 Vendor: Christian Mauduit Packager: Christian Mauduit @@ -47,13 +47,13 @@ til multiplayer, og har netv # Building the package %build -make +make # Installing the package # The "make uninstall" is important since it prevents rpm from # putting old unused files in the archive. %install -export DESTDIR=%{buildroot} && make uninstall && make install +export DESTDIR=%{buildroot} && make uninstall && make install # Cleaning %clean @@ -65,7 +65,7 @@ rm -rf %{buildroot} # Post-install script # It basically adds the info page to the Top info page. %post -if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info %{_prefix}/share/info/liquidwar.info.gz; fi; fi; fi +if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info %{_prefix}/share/info/liquidwar5.info.gz; fi; fi; fi # Pre-uninstall script %preun @@ -73,27 +73,30 @@ if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefi # Post-uninstall script # It basically removes the info page to the Top info page. %postun -if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info --remove liquidwar; fi; fi; fi +if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefix}/info/dir; then install-info --info-dir=%{_prefix}/info --remove liquidwar5; fi; fi; fi %files %defattr(-,root,root) -%{_prefix}/games/liquidwar -%{_prefix}/games/liquidwar-server -%{_prefix}/games/liquidwar-mapgen -%{_prefix}/bin/liquidwar -%{_prefix}/bin/liquidwar-server -%{_prefix}/bin/liquidwar-mapgen -%{_prefix}/share/games/liquidwar/ -%{_prefix}/share/doc/liquidwar/ -%{_prefix}/share/man/man6/liquidwar.6* -%{_prefix}/share/man/man6/liquidwar-server.6* -%{_prefix}/share/man/man6/liquidwar-mapgen.6* -%{_prefix}/share/info/liquidwar.info* -%{_prefix}/share/pixmaps/liquidwar.xpm -%{_prefix}/share/applications/liquidwar.desktop +%{_prefix}/games/liquidwar5 +%{_prefix}/games/liquidwar5-server +%{_prefix}/games/liquidwar5-mapgen +%{_prefix}/bin/liquidwar5 +%{_prefix}/bin/liquidwar5-server +%{_prefix}/bin/liquidwar5-mapgen +%{_prefix}/share/games/liquidwar5/ +%{_prefix}/share/doc/liquidwar5/ +%{_prefix}/share/man/man6/liquidwar5.6* +%{_prefix}/share/man/man6/liquidwar5-server.6* +%{_prefix}/share/man/man6/liquidwar5-mapgen.6* +%{_prefix}/share/info/liquidwar5.info* +%{_prefix}/share/pixmaps/liquidwar5.xpm +%{_prefix}/share/applications/liquidwar5.desktop %changelog +* Sat Nov 22 2025 Christian Mauduit +- adapt to new Allegro 5 branch, call it liquidwar5 + * Thu Sep 27 2007 Christian Mauduit - Added mapgen files, fixed deprecated RPM syntax. @@ -110,15 +113,14 @@ if which install-info; then if test -d %{_prefix}/info; then if test -f %{_prefi - Fixed some buildroot bugs - Replaced install-info --infodir=... by --info-dir=... -* Mon Mar 11 2002 Christian Mauduit +* Mon Mar 11 2002 Christian Mauduit - Recompiled with Allegro's rpm (fixes the error: "/usr/lib/liballeg.so.4.0: undefined symbol: _poly_scanline_gcol8") - Fixed the post-install script -* Sat Feb 23 2002 Christian Mauduit +* Sat Feb 23 2002 Christian Mauduit - Added proper "--target" support. - Added info documentation with install and uninstall scripts -* Thu Jan 28 2002 Christian Mauduit +* Thu Jan 28 2002 Christian Mauduit - My first rpm build of Liquid War - diff --git a/misc/Makefile.vc b/misc/Makefile.vc index 5e74ef5e..adfbe226 100644 --- a/misc/Makefile.vc +++ b/misc/Makefile.vc @@ -112,9 +112,6 @@ volume \ watchdog \ wave \ wwwcli \ -glouglou \ -monster \ -spread \ ../utils/snprintf/snprintf \ lwwin diff --git a/misc/allegro-gp2x/allegro-accel.html b/misc/allegro-gp2x/allegro-accel.html deleted file mode 100644 index bed19a38..00000000 --- a/misc/allegro-gp2x/allegro-accel.html +++ /dev/null @@ -1,76 +0,0 @@ - - - GP2X Hardware Acceleration in Allegro - - - -

GP2X Hardware Acceleration in Allegro

- -

Credits

- -

The hardware acceleration in GP2X Allegro is heavily based on -paeryn's code for SDL. He did all the hard work! - -

What is accelerated

- -
    - -
  • Trivial filling operations - rectfill, -hline, vline, clear_to_color - when applied to a bitmap in -video memory, i.e. the screen, a video bitmap, or a subbitmap -of either. - -
  • Blitting operations - blit, masked_blit, -draw_sprite - where the source and destination are both in -video memory. - -
- -

Acceleration is only supported in 8bpp and 16bpp modes; GP2X -Allegro only supports those modes anyway, so that's OK. - -

Allegro uses 5Mb for video memory, and you can set a graphics -mode with any virtual size you like subject to available memory. - -

To take advantage of hardware accelerated blitting, it's -easiest to use video bitmaps. First create one the size of the -visible screen (SCREEN_W x SCREEN_H), then use show_video_bitmap -to ensure the screen is scrolled properly, and do all your -drawing there. Then create additional video bitmaps for your -sprites, etc, and use blit or draw_sprite as normal to draw them -to your primary video bitmap. - -

You can combine that with page flipping by creating two -screen-sized video bitmaps, and drawing to one while the other -is visible, swapping which is which each frame. - - -

Hardware Scrolling

- -

If you're not using video bitmaps, you can scroll the visible -screen around the virtual screen, but there's a 32-bit granularity so -you're restricted to even X coordinates in 16bpp or multiples of -4 in 8bpp. - -

It's not trivial to combine this with using video bitmaps, -though it can be done. - - -

Example - Parallax Demo

- -

I've uploaded an example which uses page flipped video -bitmaps to take advantage of the hardware acceleration. It -draws lots of layers of random pipe-like tiles, using -accelerated masked blits or sprites or something, I don't -totally remember! - -

- - - - - - \ No newline at end of file diff --git a/misc/allegro-gp2x/allegro-building.html b/misc/allegro-gp2x/allegro-building.html deleted file mode 100644 index 79947018..00000000 --- a/misc/allegro-gp2x/allegro-building.html +++ /dev/null @@ -1,63 +0,0 @@ - - - Building Allegro for GP2X - - - -

Building Allegro for GP2X

- -

by George Foot - - -

Don't Panic

- -

It's really not very hard... - -

    - -
  1. Unpack the Allegro sources, e.g. tar -xzf allegro-4.2.0.tar.gz - -
  2. Apply my patches, e.g. cd allegro-4.2.0 ; patch -p1 < gp2xallegro-0.3.diff - -
  3. Configure properly - this is the hard bit, so unless you - know better, stick to the following command: - -

    LDFLAGS=-static ./configure --host arm-open2x-linux - --without-x --enable-static --disable-shared --enable-lgp2x - --disable-modules --prefix=/opt/gp2x - --enable-dbglib - -

    This will build static libraries, not shared libraries, - in debug and release modes, and link the various programs - (demo game, examples, tests) with the release version, - totally staticly. Everything gets installed to - subdirectories (bin, lib, include, share) of /opt/gp2x. - -

    If you want, you can --enable-dbgprog to build the - programs in debug mode too, and link them to the debug - library. Up to you. - -

  4. make depend - sort out dependencies, write - makefiles - -
  5. make - build everything - -
  6. make install - copy relevant stuff to /opt/gp2x or - whatever you set --prefix to -
- -After installation, you probably want to add the relevant bin -directory to your path. Don't worry about the include or lib -directories, gp2x-allegro-config handles that for you! So it -doesn't matter if you choose to install Allegro off by itself -somewhere, away from all your precious devkitgp2x libraries. - - -

Using Allegro for GP2X

- -

See Using Allegro for GP2X - - - - - diff --git a/misc/allegro-gp2x/allegro-prebuilt.html b/misc/allegro-gp2x/allegro-prebuilt.html deleted file mode 100644 index fa94ec0f..00000000 --- a/misc/allegro-gp2x/allegro-prebuilt.html +++ /dev/null @@ -1,47 +0,0 @@ - - - Pre-built GP2X Allegro v0.2 - - - -

Pre-built GP2X Allegro v0.3

- -

by George Foot - - -

Introduction

- -

This is aimed at Windows users who lack the software to -crosscompile Unix Allegro themselves. It's particularly aimed -at devkitGP2X users, but it may also work with other toolchains, -if they are sufficiently advanced; the GPH toolchain is not -advanced though, so don't use that. - - -

Download

- -

I'd recommend also installing Allegro 4.2.0, as that's what this is based on - then you'll have the docs and examples, not to mention the ability to test your games on your PC! -

- - -

Installing

- -

You can install this wherever you like, including into your -devkitGP2X directories. You need to edit the -gp2x-allegro-config script, in the bin directory, and set the -prefix to the parent of the bin directory. You may want to add -the bin directory to your path. - - -

Using Allegro for GP2X

- -

See Using Allegro for GP2X - - - - - diff --git a/misc/allegro-gp2x/allegro-using.html b/misc/allegro-gp2x/allegro-using.html deleted file mode 100644 index 3b9934f8..00000000 --- a/misc/allegro-gp2x/allegro-using.html +++ /dev/null @@ -1,56 +0,0 @@ - - - Using Allegro for GP2X - - - -

Using Allegro for GP2X

- -

Building your own programs

- -

Generally you should use the gp2x-allegro-config script in -your compile and link command lines. It fills out include and -library paths, and links the right libraries for you. The main -options are: - -

-
--cflags
pass this when compiling -
--libs
pass this when linking -
debug
pass this to enable debugging, and link - against the debug library -
- -

If it's one command which is both compiling and linking, pass -both flags. - -

As a side effect of the configure line above, -gp2x-allegro-config will also force your binaries to link -staticly. If you don't like it, edit the script and take out -the -static option. - -

Example: building the joystick example program

- -

The examples will have been built automatically, but as an -example of building your own program, try copying the exjoy.c -file from the examples directory to somewhere fresh. Then you -can compile it: - -

gcc -o exjoy.o -c exjoy.c -O2 -Wall -Werror -g -`gp2x-allegro-config --cflags debug` - -

And link it: - -

gcc -o exjoy exjoy.o `gp2x-allegro-config --libs` - -

Then write a .gpe wrapper script that runs './exjoy' and -chains back to the gp2xmenu. - -

Note that it's OK to pass 'debug' when compiling yet not when -linking - your own code's TRACE calls will then output to -allegro.log, while the library itself will not. Quite a useful -setup. - - - - -

\ No newline at end of file diff --git a/misc/allegro-gp2x/allegro.html b/misc/allegro-gp2x/allegro.html deleted file mode 100644 index 4224d9ec..00000000 --- a/misc/allegro-gp2x/allegro.html +++ /dev/null @@ -1,56 +0,0 @@ - - - GP2X Allegro - - - -

GP2X Allegro v0.3

- -

by George Foot - -

I've ported Allegro to the GP2X. Thanks must go to rlyeh, -whose "minimal" library was a great reference for -setting the video mode beyond what fbdev can do, and paeryn, -whose 2D acceleration routines in SDL provided the basis of the -routines Allegro is using now. - -

Links and Downloads

- - -

If you don't know Allegro, but want to -learn, have a look around the website, and get the main -distribution and install it on your dev PC. You might want to -get a zip version instead of the .tar.gz linked above, if you're -using Windows. Then get the binary archive above, and use that -when developing for GP2X. Use the documentation from the core -Allegro distribution, which gets built in various formats as -part of the build process. - -

If you know Allegro and just want to develop -for the GP2X, you can just get the binary package - it includes -all the headers too, but no docs. Use the documentation from -core Allegro, which you'll probably want to install on your dev -PC anyway as above (if you haven't already got it). - -

If you're an advanced user who might want to -hack the library itself, you'll need the original sources and my -patches, but not the binary archive. It's not too hard to build it yourself. - - -

Using Allegro for GP2X

- -

See Using Allegro for GP2X - -

Hardware Acceleration

- -

See GP2X Hardware Acceleration in Allegro - - - - -

\ No newline at end of file diff --git a/misc/liquidwar-jenkins.sh b/misc/liquidwar-jenkins.sh deleted file mode 100755 index cf4618b0..00000000 --- a/misc/liquidwar-jenkins.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -############################################################################# -# Liquid War is a multiplayer wargame # -# Copyright (C) 1998-2025 Christian Mauduit # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You 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 # -# # -# Liquid War homepage : https://ufoot.org/liquidwar/v5 # -# Contact author : ufoot@ufoot.org # -############################################################################# - -# Script used by Jenkins daemon to autobuild the program in -# continuous integration mode. http://jenkins-ci.org/ - -echo "******** $0 $(date) ********" -if cd liquidwar ; then - echo "******** $0 $(date) ********" - if ./bootstrap; then - echo "******** $0 $(date) ********" - if ./configure --prefix=$WORKSPACE/local ; then - echo "******** $0 $(date) ********" - if make ; then - echo "******** $0 $(date) ********" - if make install; then - echo "******** $0 $(date) ********" - if make dist; then - echo "******** $0 $(date) ********" - else - echo "make dist failed" - exit 6 - fi - else - echo "make install failed" - exit 5 - fi - else - echo "make failed" - exit 4 - fi - else - echo "./configure failed" - exit 3 - fi - else - echo "./bootstrap failed" - exit 2 - fi -else - echo "cd failed" - exit 1 -fi - -echo "OK" -exit 0 diff --git a/misc/liquidwar.gpe b/misc/liquidwar.gpe deleted file mode 100644 index dddcef2b..00000000 --- a/misc/liquidwar.gpe +++ /dev/null @@ -1,52 +0,0 @@ -#! /bin/sh - -############################################################################# -# Liquid War is a multiplayer wargame # -# Copyright (C) 1998-2025 Christian Mauduit # -# # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation; either version 2 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You 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 # -# # -# Liquid War homepage : https://ufoot.org/liquidwar/v5 # -# Contact author : ufoot@ufoot.org # -############################################################################# - -LIQUIDWAR_BIN=./liquidwar -LIQUIDWAR_DAT=./liquidwar.dat -LIQUIDWAR_LOG=./liquidwar.log -LIQUIDWAR_DEV=./liquidwar.dev - -#clear_screen () { -# dd if=/dev/zero of=/dev/fb0 count=1536 bs=100 -# dd if=/dev/zero of=/dev/fb1 count=1536 bs=100 -#} -# -#clear -#clear_screen - -if test -f $LIQUIDWAR_BIN -a -x $LIQUIDWAR_BIN -a -f $LIQUIDWAR_DAT -then - #$LIQUIDWAR_BIN -dat $LIQUIDWAR_DAT > $LIQUIDWAR_LOG 2>&1 - ls -al /dev > $LIQUIDWAR_DEV - echo mknod >> $LIQUIDWAR_DEV - mknod /dev/fb1 c 29 32 >> $LIQUIDWAR_DEV - ls -al /dev >> $LIQUIDWAR_DEV - $LIQUIDWAR_BIN -silent -dat $LIQUIDWAR_DAT > $LIQUIDWAR_LOG 2>&1 - #sync - #clear_screen -fi - -cd /usr/gp2x -exec ./gp2xmenu - diff --git a/misc/liquidwar.desktop b/misc/liquidwar5.desktop similarity index 100% rename from misc/liquidwar.desktop rename to misc/liquidwar5.desktop diff --git a/misc/liquidwar.icns b/misc/liquidwar5.icns similarity index 100% rename from misc/liquidwar.icns rename to misc/liquidwar5.icns diff --git a/misc/liquidwar.ico b/misc/liquidwar5.ico similarity index 100% rename from misc/liquidwar.ico rename to misc/liquidwar5.ico diff --git a/misc/liquidwar.nsi.in b/misc/liquidwar5.nsi.in similarity index 100% rename from misc/liquidwar.nsi.in rename to misc/liquidwar5.nsi.in diff --git a/misc/liquidwar.png b/misc/liquidwar5.png similarity index 100% rename from misc/liquidwar.png rename to misc/liquidwar5.png diff --git a/misc/liquidwar.xpm b/misc/liquidwar5.xpm similarity index 100% rename from misc/liquidwar.xpm rename to misc/liquidwar5.xpm diff --git a/misc/liquidwar_32x32.xpm b/misc/liquidwar5_32x32.xpm similarity index 100% rename from misc/liquidwar_32x32.xpm rename to misc/liquidwar5_32x32.xpm diff --git a/misc/liquidwar_notify.sh b/misc/liquidwar5_notify.sh similarity index 100% rename from misc/liquidwar_notify.sh rename to misc/liquidwar5_notify.sh diff --git a/misc/liquidward.in b/misc/liquidwar5d.in similarity index 92% rename from misc/liquidward.in rename to misc/liquidwar5d.in index e46c88d9..3e091e33 100644 --- a/misc/liquidward.in +++ b/misc/liquidwar5d.in @@ -28,11 +28,11 @@ # are started automatically when you boot your computer. # # Keep in mind that Liquid War is a *game* so its code might not be -# 100% exploit proof, and anyway, since Liquid War comes with -# NO WARRANTY at all, you simply run it at your own risks. +# 100% exploit proof, and anyway, since Liquid War comes with +# NO WARRANTY at all, you simply run it at your own risks. # This is not to scare you, but rather to insist on the fact that # you should never run Liquid War servers as root. Run it under a -# "basic" user, which has very few rights, since the only rights the +# "basic" user, which has very few rights, since the only rights the # Liquid War daemon needs are: # - be able to bind on a socket > 1024 # - be able to append stuff to a log file @@ -43,7 +43,7 @@ # will make the Liquid War server you run on your computer register # itself on the meta-server on www.ufoot.org. So people will be aware # that you have a Liquid War server on your machine. While this is good -# for people who try to automatically find other online fellows, +# for people who try to automatically find other online fellows, # you might find this behaviour somewhat intrusive. Change the $PRIVACY # value if the default behaviour does not match your needs. @@ -52,11 +52,11 @@ unset `env | sed s/=.*//` prefix=@prefix@ -NAME=liquidward +NAME=liquidwar5d PATH=/bin:/usr/bin:/sbin:/usr/sbin -DAEMON=$prefix/games/liquidwar-server -PIDFILE=/var/games/liquidwar/$NAME.pid -LOGFILE=/var/games/liquidwar/$NAME.log +DAEMON=$prefix/games/liquidwar5-server +PIDFILE=/var/games/liquidwar5/$NAME.pid +LOGFILE=/var/games/liquidwar5/$NAME.log # As start-stop-daemon seems to be a quite Debian-specific utility, # this script is in a way designed for Debian. If you want to run it @@ -83,7 +83,7 @@ PASSWORD= # the comment which will be associated to the server # by default, it contains the name of the machine, but you might # want to put your e-mail here for instance -COMMENT="Public_Liquid_War_5_server_running_on_host_"`hostname` +COMMENT="Public_Liquid_War_5_server_running_on_host_"`hostname` # the user which should be used to start the daemon # by default, it is set to "nobody:games", this assumes that @@ -95,9 +95,9 @@ USER=nobody:games # if you want the server to warn you whenever someone connects on it, # you might set up a callback script by uncommenting the line below. -# You'll also need to edit and install the liquidwar_notify.sh script +# You'll also need to edit and install the liquidwar_notify.sh script # manually -CALLBACK=$prefix/games/liquidwar_notify.sh +CALLBACK=$prefix/games/liquidwar5_notify.sh OPTIONS=" -"$NBPLAYERS" -"$PRIVACY" -log "$LOGFILE" -password "$PASSWORD" -comment \""$COMMENT"\" -callback "$CALLBACK @@ -130,4 +130,3 @@ case "$1" in esac exit 0 - diff --git a/misc/liquidward.logrotate b/misc/liquidwar5d.logrotate similarity index 100% rename from misc/liquidward.logrotate rename to misc/liquidwar5d.logrotate diff --git a/src/Makefile.in b/src/Makefile.in index ec0cc5e9..7ab2174e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -4,18 +4,17 @@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ -DATADIR = $(datadir)/games/liquidwar +DATADIR = $(datadir)/games/liquidwar5 GAMEDIR = $(exec_prefix)/games HOST_OPT = @HOST_OPT@ STATIC = @STATIC@ SNPRINTF = @SNPRINTF@ ALCFLAGS = @ALCFLAGS@ -ASM = @ASM@ DEBUG = @DEBUG@ EFENCE = @EFENCE@ PTHREAD = @PTHREAD@ -GP2X = @GP2X@ +ALLIBS = @ALLIBS@ ifeq ($(HOST_OPT),yes) HOST = @host@ @@ -34,13 +33,11 @@ endif ifeq ($(DEBUG),yes) - DEBUG_FLAGS = -g3 + DEBUG_FLAGS = -g3 -O0 DEBUG_OPTIONS = -DDEBUG - ALLEGRO_LIBRARY = debug else DEBUG_FLAGS = -O2 -fomit-frame-pointer DEBUG_OPTIONS = - ALLEGRO_LIBRARY = release endif ifeq ($(EFENCE),yes) @@ -49,12 +46,6 @@ else EFENCE_LIBRARY = endif -ifeq ($(GP2X),yes) - GP2X_OPTIONS = -DGP2X -else - GP2X_OPTIONS = -endif - ifeq ($(SNPRINTF),yes) SNPRINTF_NAMES = SNPRINTF_OPTIONS = @@ -65,13 +56,6 @@ else SNPRINTF_MODE = "using Mark Martinec's implementation" endif -ifeq ($(ASM),yes) - ASM_NAMES = glouglou monster spread - ASM_OPTIONS = -DASM -else - ASM_NAMES = - ASM_OPTIONS = -endif OBJ_NAMES = \ about \ @@ -79,9 +63,11 @@ OBJ_NAMES = \ alleg2 \ area \ army \ - asm \ autoplay \ back \ + backport \ + backportgui \ + backportguiproc \ basicopt \ bigdata \ capture \ @@ -143,7 +129,6 @@ OBJ_NAMES = \ netplay \ network \ options \ - palette \ parser \ path \ ping \ @@ -174,7 +159,6 @@ OBJ_NAMES = \ wwwcli \ x11icon \ $(SNPRINTF_NAMES) \ - $(ASM_NAMES) OBJ_NAMES_SRV = \ basicopt \ @@ -203,6 +187,8 @@ OBJ_NAMES_SRV = \ $(SNPRINTF_NAMES) OBJ_NAMES_MAPGEN = \ + backport \ + mapgen_stubs \ ../utils/lwmapgen/big_quad \ ../utils/lwmapgen/boxes \ ../utils/lwmapgen/bubbles \ @@ -227,41 +213,44 @@ OBJ_FILES = $(addsuffix .o, $(OBJ_NAMES)) OBJ_FILES_SRV = $(addsuffix .o, $(OBJ_NAMES_SRV)) OBJ_FILES_MAPGEN = $(addsuffix .o, $(OBJ_NAMES_MAPGEN)) -EXE_FILES = liquidwar liquidwar-server liquidwar-mapgen +EXE_FILES = liquidwar5 liquidwar5-server liquidwar5-mapgen ifeq ($(STATIC),yes) LINK_OPTIONS = --static - EXTERN_LIBS = `allegro-config --static $(ALLEGRO_LIBRARY)` $(EFENCE_LIBRARY) + EXTERN_LIBS = -lm $(ALLIBS) $(EFENCE_LIBRARY) else LINK_OPTIONS = - EXTERN_LIBS = `allegro-config --libs $(ALLEGRO_LIBRARY)` $(EFENCE_LIBRARY) + EXTERN_LIBS = -lm $(ALLIBS) $(EFENCE_LIBRARY) endif CONFIG_OPTIONS = \ - -DCONFIG_UNIX_CFG=\".liquidwarrc\" \ - -DCONFIG_UNIX_DAT=\"$(DATADIR)/liquidwar.dat\" \ - -DCONFIG_UNIX_MAP=\"$(DATADIR)/map/\" \ - -DCONFIG_UNIX_TEX=\"$(DATADIR)/texture/\" \ - -DCONFIG_UNIX_MID=\"$(DATADIR)/music/\" \ - -DCONFIG_UNIX_SRV=\"$(GAMEDIR)/liquidwar-server\" \ - -DCONFIG_UNIX_GEN=\"$(GAMEDIR)/liquidwar-mapgen\" + -DCONFIG_UNIX_CFG=\".liquidwar5rc\" \ + -DCONFIG_UNIX_DAT=\"$(DATADIR)/data\" \ + -DCONFIG_UNIX_MAP=\"$(DATADIR)/data/map/\" \ + -DCONFIG_UNIX_TEX=\"$(DATADIR)/data/texture/\" \ + -DCONFIG_UNIX_MID=\"$(DATADIR)/data/music/\" \ + -DCONFIG_UNIX_SRV=\"$(GAMEDIR)/liquidwar5-server\" \ + -DCONFIG_UNIX_GEN=\"$(GAMEDIR)/liquidwar5-mapgen\" -CMD_CC = $(CC) $(CFLAGS) $(ALCFLAGS) -c $(DEBUG_FLAGS) -Wall -W -Werror $(HOST_CPU_CC) $(CONFIG_OPTIONS) $(DEBUG_OPTIONS) $(SPRINTF_OPTIONS) $(ASM_OPTIONS) $(GP2X_OPTIONS) -DUNIX -D_THREAD_SAFE -CMD_AS = $(AS) $(ASFLAGS) --32 +CMD_CC = $(CC) $(CFLAGS) $(ALCFLAGS) -c $(DEBUG_FLAGS) -Wall -W -Werror $(HOST_CPU_CC) $(CONFIG_OPTIONS) $(DEBUG_OPTIONS) $(SPRINTF_OPTIONS) -DUNIX -D_THREAD_SAFE all: $(EXE_FILES) -liquidwar: $(OBJ_FILES) - @echo "Linking $@ (host=$(HOST), debug=$(DEBUG), static=$(STATIC), asm=$(ASM))" - @$(CC) $(LDFLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES) $(PTHREAD) $(EXTERN_LIBS) +liquidwar5: $(OBJ_FILES) + @echo "Linking $@ (host=$(HOST), debug=$(DEBUG), static=$(STATIC))" + @$(CC) $(LDFLAGS) $(DEBUG_FLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES) $(PTHREAD) $(EXTERN_LIBS) + @if [ "$(DEBUG)" = "yes" ] && [ "$$(uname -s)" = "Darwin" ]; then \ + echo "Generating dSYM for debugging..."; \ + dsymutil $@; \ + fi -liquidwar-server: $(OBJ_FILES_SRV) +liquidwar5-server: $(OBJ_FILES_SRV) @echo "Linking $@ (host=$(HOST), debug=$(DEBUG), static=$(STATIC))" - @$(CC) $(LDFLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES_SRV) $(PTHREAD) + @$(CC) $(LDFLAGS) $(DEBUG_FLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES_SRV) $(PTHREAD) -liquidwar-mapgen: $(OBJ_FILES_MAPGEN) +liquidwar5-mapgen: $(OBJ_FILES_MAPGEN) @echo "Linking $@ (host=$(HOST), debug=$(DEBUG), static=$(STATIC))" - @$(CC) $(LDFLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES_MAPGEN) -lm $(PTHREAD) $(EXTERN_LIBS) + @$(CC) $(LDFLAGS) $(DEBUG_FLAGS) $(LINK_OPTIONS) -o $@ $(OBJ_FILES_MAPGEN) -lm $(PTHREAD) $(EXTERN_LIBS) dep: @find . \ @@ -280,21 +269,31 @@ distclean: @rm -f Makefile Makefile.dep %.o: %.c - @echo "Compiling $< (cpu=$(HOST_CPU), debug=$(DEBUG), asm=$(ASM))" + @echo "Compiling $< (cpu=$(HOST_CPU), debug=$(DEBUG))" @$(CMD_CC) $< -o $@ -%.o: %.s - @echo "Assembling" $< - @$(CMD_AS) $< -o $@ -config: print_config print_cmd_cc print_cmd_as print_cmd_ld +config: print_config print_cmd_cc print_cmd_ld @true -check: - @echo No unit tests, blame the lazy developper. +test_backport_pixel: test_backport_pixel.o $(OBJ_FILES) + @echo "Building pixel test" + @$(CC) $(LDFLAGS) $(LINK_OPTIONS) -o $@ $^ $(PTHREAD) $(EXTERN_LIBS) + +test_path: test_path.o $(OBJ_FILES) + @echo "Building path test" + @$(CC) $(LDFLAGS) $(LINK_OPTIONS) -o $@ $^ $(PTHREAD) $(EXTERN_LIBS) + +check: test_backport_pixel test_path + @echo "Running unit tests..." + @./test_backport_pixel + @./test_path indent: @find . -name "*.[c|h]" -a ! -path "*32*" -exec indent -nut {} \; + @find . -name "*.[c|h]" -a ! -path "*32*" -exec indent -nut {} \; + +lint: @find . -name "*.[c|h]" -a ! -path "*32*" -exec splint {} \; print_config: @@ -302,19 +301,15 @@ print_config: @echo "Host :" $(HOST) @echo "Debug :" $(DEBUG) @echo "Static link :" $(STATIC) - @echo "Assembly :" $(ASM) - @echo "Snprintf :" $(SNPRINTF_MODE) + @echo "Snprintf :" $(SNPRINTF_MODE) print_cmd_cc: @echo "The command line to compile .c files in this directory is:" @echo $(CMD_CC) -print_cmd_as: - @echo "The command line to compile .s files in this directory is:" - @echo $(CMD_AS) print_cmd_ld: @echo "The command line to link .o files in this directory is:" - @echo $(CC) $(LDFLAGS) $(LINK_OPTIONS) $(PTHREAD) $(EXTERN_LIBS) + @echo $(CC) $(LDFLAGS) $(DEBUG_FLAGS) $(LINK_OPTIONS) $(PTHREAD) $(EXTERN_LIBS) include Makefile.dep diff --git a/src/advanced.c b/src/advanced.c index ee84ffb5..c40df42d 100644 --- a/src/advanced.c +++ b/src/advanced.c @@ -55,6 +55,7 @@ #include #include "advanced.h" +#include "backport.h" #include "config.h" #include "dialog.h" #include "disk.h" @@ -69,14 +70,6 @@ /*==================================================================*/ /*------------------------------------------------------------------*/ -static char * -get_asm_algorithm_str (void) -{ - if (CONFIG_ASM_ALGORITHM) - return (lw_lang_string (LW_LANG_STRING_ADVANCED_ASSEMBLY)); - else - return (lw_lang_string (LW_LANG_STRING_ADVANCED_STANDARDC)); -} /*------------------------------------------------------------------*/ static char * @@ -119,23 +112,23 @@ int advanced_options (void) { int *temp; - DIALOG d[21]; + DIALOG d[19]; int i, retour = 0, choix = 4; static int y_pos[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; memset (d, 0, sizeof (d)); - for (i = 0; i < 8; ++i) + for (i = 0; i < 7; ++i) { standard_button (d + i + 4, 0, y_pos[i], 2, 8); d[i + 4].proc = my_textbox_proc; } - for (i = 0; i < 8; ++i) + for (i = 0; i < 7; ++i) { - standard_button (d + i + 12, 1, y_pos[i], 2, 8); - d[i + 12].proc = my_slider_proc; + standard_button (d + i + 11, 1, y_pos[i], 2, 8); + d[i + 11].proc = my_slider_proc; } - d[17].proc = d[18].proc = d[19].proc = my_button_proc; + d[16].proc = d[17].proc = my_button_proc; quick_buttons (d); d[4].dp = lw_lang_string (LW_LANG_STRING_ADVANCED_ATTACK); @@ -145,18 +138,16 @@ advanced_options (void) d[8].dp = lw_lang_string (LW_LANG_STRING_ADVANCED_CPUSTRENGTH); d[9].dp = lw_lang_string (LW_LANG_STRING_ADVANCED_CPUVSHUMAN); d[10].dp = lw_lang_string (LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS); - d[11].dp = lw_lang_string (LW_LANG_STRING_ADVANCED_ASMALGORITHM); - d[12].d1 = d[13].d1 = d[14].d1 = d[15].d1 = 16; - d[16].d1 = 4; - d[12].dp3 = &CONFIG_FIGHTER_ATTACK; - d[13].dp3 = &CONFIG_FIGHTER_DEFENSE; - d[14].dp3 = &CONFIG_FIGHTER_NEW_HEALTH; - d[15].dp3 = &CONFIG_NUMBER_INFLUENCE; - d[16].dp3 = &CONFIG_CPU_ADVANTAGE; - d[17].dp = get_cpu_vs_human_str (); - d[18].dp = get_allow_network_bots_str (); - d[19].dp = get_asm_algorithm_str (); - for (i = 12; i < 17; ++i) + d[11].d1 = d[12].d1 = d[13].d1 = d[14].d1 = 16; + d[15].d1 = 4; + d[11].dp3 = &CONFIG_FIGHTER_ATTACK; + d[12].dp3 = &CONFIG_FIGHTER_DEFENSE; + d[13].dp3 = &CONFIG_FIGHTER_NEW_HEALTH; + d[14].dp3 = &CONFIG_NUMBER_INFLUENCE; + d[15].dp3 = &CONFIG_CPU_ADVANTAGE; + d[16].dp = get_cpu_vs_human_str (); + d[17].dp = get_allow_network_bots_str (); + for (i = 11; i < 16; ++i) { d[i].dp = NULL; d[i].dp2 = slider_int; @@ -164,15 +155,8 @@ advanced_options (void) d[i].d2 = *temp; } -#ifndef ASM - /* - * If no assembly code has been compiled, we disable the button - */ - d[10].flags = D_HIDDEN; - d[18].flags = D_HIDDEN; -#endif - d[20].proc = 0; + d[18].proc = 0; while (retour == 0) { @@ -193,25 +177,18 @@ advanced_options (void) case MENU_QUICK_PLAY: retour = MENU_PLAY; break; - case 17: + case 16: CONFIG_CPU_VS_HUMAN = (CONFIG_CPU_VS_HUMAN + 1) % 3; - d[17].dp = get_cpu_vs_human_str (); + d[16].dp = get_cpu_vs_human_str (); scare_mouse (); - my_button_proc (MSG_DRAW, d + 17, 0); + my_button_proc (MSG_DRAW, d + 16, 0); unscare_mouse (); break; - case 18: + case 17: CONFIG_ALLOW_NETWORK_BOTS = CONFIG_ALLOW_NETWORK_BOTS ? 0 : 1; - d[18].dp = get_allow_network_bots_str (); + d[17].dp = get_allow_network_bots_str (); scare_mouse (); - my_button_proc (MSG_DRAW, d + 18, 0); - unscare_mouse (); - break; - case 19: - CONFIG_ASM_ALGORITHM = CONFIG_ASM_ALGORITHM ? 0 : 1; - d[19].dp = get_asm_algorithm_str (); - scare_mouse (); - my_button_proc (MSG_DRAW, d + 19, 0); + my_button_proc (MSG_DRAW, d + 17, 0); unscare_mouse (); break; } diff --git a/src/alleg2.c b/src/alleg2.c index baf74a62..07e865e9 100644 --- a/src/alleg2.c +++ b/src/alleg2.c @@ -70,7 +70,7 @@ typedef char *(*my_getfuncptr) (int, int *); /*==================================================================*/ extern void _draw_scrollable_frame (DIALOG * d, int listsize, int offset, int height, - int fg_color, int bg); + ALLEGRO_COLOR fg_color, ALLEGRO_COLOR bg); extern int isspace (int c); static void my_handle_scrollable_scroll_click (DIALOG * d, int listsize, @@ -79,7 +79,6 @@ static void my_handle_scrollable_scroll (DIALOG * d, int listsize, int *index, int *offset); static void my_handle_listbox_click (DIALOG * d); - /*==================================================================*/ /* fonctions */ /*==================================================================*/ @@ -92,9 +91,9 @@ static void my_handle_listbox_click (DIALOG * d); * Draws a dotted rectangle, for showing an object has the input focus. */ static void -my_dotted_rect (int x1, int y1, int x2, int y2, int fg, int bg) +my_dotted_rect (int x1, int y1, int x2, int y2, ALLEGRO_COLOR fg, ALLEGRO_COLOR bg) { - BITMAP *gui_bmp = gui_get_screen (); + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); int x = ((x1 + y1) & 1) ? 1 : 0; int c; @@ -117,10 +116,9 @@ my_dotted_rect (int x1, int y1, int x2, int y2, int fg, int bg) static void my_draw_textbox (char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, - int disabled, int fore, int deselect, int disable) + int disabled, ALLEGRO_COLOR fore, ALLEGRO_COLOR deselect, ALLEGRO_COLOR disable) { - BITMAP *gui_bmp = gui_get_screen (); - int fg = fore; + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); int y1 = y + 4; int x1; int len; @@ -156,17 +154,10 @@ my_draw_textbox (char *thetext, int *listsize, int draw, int offset, rectfill (gui_bmp, x + 2, y + 2, x + w - 3, y1 - 1, deselect); } - /* choose the text color */ - if (disabled) - fg = disable; - - if (fg) - { - /* - * Not elegant, but test above here just to get - * rid of compiler warning about fg not being used. - */ - } + /* Suppress unused parameter warnings */ + (void)disabled; + (void)fore; + (void)disable; /* loop over the entire string */ while (1) @@ -280,7 +271,7 @@ my_draw_textbox (char *thetext, int *listsize, int draw, int offset, { usetc (s + usetc (s, ' '), 0); //textout_ex(gui_bmp, font, s, x1, y1, fg, deselect); - textout_ex (gui_bmp, font, s, x1, y1, -1, deselect); // ufoot + textout_ex (gui_bmp, font, s, x1, y1, NO_COLOR, deselect); // ufoot x1 += text_length (font, s); } break; @@ -291,7 +282,7 @@ my_draw_textbox (char *thetext, int *listsize, int draw, int offset, { usetc (s + usetc (s, ugetc (printed)), 0); //textout_ex(gui_bmp, font, s, x1, y1, fg, deselect); - textout_ex (gui_bmp, font, s, x1, y1, -1, deselect); // ufoot + textout_ex (gui_bmp, font, s, x1, y1, NO_COLOR, deselect); // ufoot x1 += text_length (font, s); } } @@ -343,8 +334,8 @@ my_textbox_proc (int msg, DIALOG * d, int c) int height, bar, ret = D_O_K; int start, top, bottom, l; int used, delta; - int fg_color; - ASSERT (d); + ALLEGRO_COLOR fg_color; + ALLEGRO_ASSERT (d); fg_color = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; /* calculate the actual height */ @@ -358,7 +349,7 @@ my_textbox_proc (int msg, DIALOG * d, int c) my_draw_textbox (d->dp, &d->d1, 0, /* DONT DRAW anything */ d->d2, !(d->flags & D_SELECTED), 8, d->x, d->y, d->w, d->h, - (d->flags & D_DISABLED), 0, 0, 0); + (d->flags & D_DISABLED), NO_COLOR, NO_COLOR, NO_COLOR); break; case MSG_DRAW: @@ -366,7 +357,7 @@ my_textbox_proc (int msg, DIALOG * d, int c) my_draw_textbox (d->dp, &d->d1, 0, /* DONT DRAW anything */ d->d2, !(d->flags & D_SELECTED), 8, d->x, d->y, d->w, d->h, - (d->flags & D_DISABLED), 0, 0, 0); + (d->flags & D_DISABLED), NO_COLOR, NO_COLOR, NO_COLOR); if (d->d1 > height && d->d1 > 1) // ufoot { @@ -440,17 +431,17 @@ my_textbox_proc (int msg, DIALOG * d, int c) else bottom--; - if ((c >> 8) == KEY_UP) + if ((c >> 8) == ALLEGRO_KEY_UP) d->d2--; - else if ((c >> 8) == KEY_DOWN) + else if ((c >> 8) == ALLEGRO_KEY_DOWN) d->d2++; - else if ((c >> 8) == KEY_HOME) + else if ((c >> 8) == ALLEGRO_KEY_HOME) d->d2 = 0; - else if ((c >> 8) == KEY_END) + else if ((c >> 8) == ALLEGRO_KEY_END) d->d2 = d->d1 - l; - else if ((c >> 8) == KEY_PGUP) + else if ((c >> 8) == ALLEGRO_KEY_PGUP) d->d2 -= (bottom - top) ? bottom - top : 1; - else if ((c >> 8) == KEY_PGDN) + else if ((c >> 8) == ALLEGRO_KEY_PGDN) d->d2 += (bottom - top) ? bottom - top : 1; else used = D_O_K; @@ -502,19 +493,20 @@ my_textbox_proc (int msg, DIALOG * d, int c) /* d_button_proc: * A button object (the dp field points to the text string). This object - * can be selected by clicking on it with the mouse or by pressing its - * keyboard shortcut. If the D_EXIT flag is set, selecting it will close + * can be selected by clicking on it with the mouse or by pressing its + * keyboard shortcut. If the D_EXIT flag is set, selecting it will close * the dialog, otherwise it will toggle on and off. */ int my_button_proc (int msg, DIALOG * d, int c) { - BITMAP *gui_bmp; - int state1, state2; - int black; + ALLEGRO_BITMAP *gui_bmp; + ALLEGRO_COLOR state1, state2; + ALLEGRO_COLOR black; int swap; + int click_state1, click_state2; // Boolean states for MSG_CLICK int g; - ASSERT (d); + ALLEGRO_ASSERT (d); LW_MACRO_NOP (c); // ufoot @@ -541,8 +533,8 @@ my_button_proc (int msg, DIALOG * d, int c) d->y + d->h - 3 + g, state2); rect (gui_bmp, d->x + g, d->y + g, d->x + d->w - 2 + g, d->y + d->h - 2 + g, state1); - //gui_textout_ex(gui_bmp, d->dp, d->x+d->w/2+g, d->y+d->h/2-text_height(font)/2+g, state1, -1, TRUE); - gui_textout_ex (gui_bmp, d->dp, d->x + d->w / 2 + g, d->y + d->h / 2 - text_height (font) / 2 + g, -1, -1, TRUE); // ufoot + //gui_textout_ex(gui_bmp, d->dp, d->x+d->w/2+g, d->y+d->h/2-text_height(font)/2+g, state1, NO_COLOR, TRUE); + gui_textout_ex (gui_bmp, d->dp, d->x + d->w / 2 + g, d->y + d->h / 2 - text_height (font) / 2 + g, NO_COLOR, NO_COLOR, TRUE); // ufoot if (d->flags & D_SELECTED) { @@ -551,7 +543,7 @@ my_button_proc (int msg, DIALOG * d, int c) } else { - black = makecol (0, 0, 0); + black = al_map_rgb(0, 0, 0); // [FIXME:ufoot] sounds a bit hardcoded, double-check this vline (gui_bmp, d->x + d->w - 1, d->y + 1, d->y + d->h - 2, black); hline (gui_bmp, d->x + 1, d->y + d->h - 1, d->x + d->w - 1, black); } @@ -578,26 +570,26 @@ my_button_proc (int msg, DIALOG * d, int c) case MSG_CLICK: /* what state was the button originally in? */ - state1 = d->flags & D_SELECTED; + click_state1 = d->flags & D_SELECTED; if (d->flags & D_EXIT) swap = FALSE; else - swap = state1; + swap = click_state1; /* track the mouse until it is released */ while (gui_mouse_b ()) { - state2 = ((gui_mouse_x () >= d->x) && (gui_mouse_y () >= d->y) && + click_state2 = ((gui_mouse_x () >= d->x) && (gui_mouse_y () >= d->y) && (gui_mouse_x () < d->x + d->w) && (gui_mouse_y () < d->y + d->h)); if (swap) - state2 = !state2; + click_state2 = !click_state2; /* redraw? */ - if (((state1) && (!state2)) || ((state2) && (!state1))) + if (((click_state1) && (!click_state2)) || ((click_state2) && (!click_state1))) { d->flags ^= D_SELECTED; - state1 = d->flags & D_SELECTED; + click_state1 = d->flags & D_SELECTED; object_message (d, MSG_DRAW, 0); } @@ -626,17 +618,17 @@ my_text_proc (int msg, DIALOG * d, int c) { LW_MACRO_NOP (c); // ufoot - ASSERT (d); + ALLEGRO_ASSERT (d); if (msg == MSG_DRAW) { //int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; // ufoot - FONT *oldfont = font; + ALLEGRO_FONT *oldfont = font; if (d->dp2) font = d->dp2; //gui_textout_ex(gui_get_screen(), d->dp, d->x, d->y, fg, d->bg, FALSE); - gui_textout_ex (gui_get_screen (), d->dp, d->x, d->y, -1, d->bg, FALSE); // ufoot + gui_textout_ex (gui_get_screen (), d->dp, d->x, d->y, NO_COLOR, d->bg, FALSE); // ufoot font = oldfont; } @@ -653,17 +645,17 @@ my_ctext_proc (int msg, DIALOG * d, int c) { LW_MACRO_NOP (c); // ufoot - ASSERT (d); + ALLEGRO_ASSERT (d); if (msg == MSG_DRAW) { // int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; // ufoot - FONT *oldfont = font; + ALLEGRO_FONT *oldfont = font; if (d->dp2) font = d->dp2; //gui_textout_ex(gui_get_screen(), d->dp, d->x + d->w/2, d->y, fg, d->bg, TRUE); - gui_textout_ex (gui_get_screen (), d->dp, d->x + d->w / 2, d->y, -1, d->bg, TRUE); // ufoot + gui_textout_ex (gui_get_screen (), d->dp, d->x + d->w / 2, d->y, NO_COLOR, d->bg, TRUE); // ufoot font = oldfont; } @@ -676,8 +668,8 @@ my_ctext_proc (int msg, DIALOG * d, int c) * A slider control object. This object returns a value in d2, in the * range from 0 to d1. It will display as a vertical slider if h is * greater than or equal to w; otherwise, it will display as a horizontal - * slider. dp can contain an optional bitmap to use for the slider handle; - * dp2 can contain an optional callback function, which is called each + * slider. dp can contain an optional bitmap to use for the slider handle; + * dp2 can contain an optional callback function, which is called each * time d2 changes. The callback function should have the following * prototype: * @@ -688,10 +680,10 @@ my_ctext_proc (int msg, DIALOG * d, int c) int my_slider_proc (int msg, DIALOG * d, int c) { - BITMAP *gui_bmp = gui_get_screen (); - BITMAP *slhan = NULL; + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + ALLEGRO_BITMAP *slhan = NULL; int oldpos, newpos; - int sfg; /* slider foreground color */ + ALLEGRO_COLOR sfg; /* slider foreground color */ int vert = TRUE; /* flag: is slider vertical? */ int hh = 7; /* handle height (width for horizontal sliders) */ int hmar; /* handle margin */ @@ -705,10 +697,10 @@ my_slider_proc (int msg, DIALOG * d, int c) int pgupkey, pgdnkey; int homekey, endkey; int delta; - fixed slratio, slmax, slpos; + al_fixed slratio, slmax, slpos; int (*proc) (void *cbpointer, int d2value); int oldval; - ASSERT (d); + ALLEGRO_ASSERT (d); /* check for slider direction */ if (d->h < d->w) @@ -717,19 +709,19 @@ my_slider_proc (int msg, DIALOG * d, int c) /* set up the metrics for the control */ if (d->dp != NULL) { - slhan = (BITMAP *) d->dp; + slhan = (ALLEGRO_BITMAP *) d->dp; if (vert) - hh = slhan->h; + hh = al_get_bitmap_height (slhan); else - hh = slhan->w; + hh = al_get_bitmap_width (slhan); } hmar = hh / 2; irange = (vert) ? d->h : d->w; - slmax = itofix (irange - hh); + slmax = al_itofix (irange - hh); slratio = slmax / (d->d1); slpos = slratio * d->d2; - slp = fixtoi (slpos); + slp = al_fixtoi (slpos); switch (msg) { @@ -766,13 +758,13 @@ my_slider_proc (int msg, DIALOG * d, int c) { if (vert) { - slx = d->x + (d->w / 2) - (slhan->w / 2); + slx = d->x + (d->w / 2) - (al_get_bitmap_width (slhan) / 2); sly = d->y + (d->h - 1) - (hh + slp); } else { slx = d->x + slp; - sly = d->y + (d->h / 2) - (slhan->h / 2); + sly = d->y + (d->h / 2) - (al_get_bitmap_height (slhan) / 2); } draw_sprite (gui_bmp, slhan, slx, sly); } @@ -826,21 +818,21 @@ my_slider_proc (int msg, DIALOG * d, int c) if (vert) { - upkey = KEY_UP; - downkey = KEY_DOWN; - pgupkey = KEY_PGUP; - pgdnkey = KEY_PGDN; - homekey = KEY_END; - endkey = KEY_HOME; + upkey = ALLEGRO_KEY_UP; + downkey = ALLEGRO_KEY_DOWN; + pgupkey = ALLEGRO_KEY_PGUP; + pgdnkey = ALLEGRO_KEY_PGDN; + homekey = ALLEGRO_KEY_END; + endkey = ALLEGRO_KEY_HOME; } else { - upkey = KEY_RIGHT; - downkey = KEY_LEFT; - pgupkey = KEY_PGDN; - pgdnkey = KEY_PGUP; - homekey = KEY_HOME; - endkey = KEY_END; + upkey = ALLEGRO_KEY_RIGHT; + downkey = ALLEGRO_KEY_LEFT; + pgupkey = ALLEGRO_KEY_PGDN; + pgdnkey = ALLEGRO_KEY_PGUP; + homekey = ALLEGRO_KEY_HOME; + endkey = ALLEGRO_KEY_END; } if (c == upkey) @@ -867,7 +859,7 @@ my_slider_proc (int msg, DIALOG * d, int c) { d->d2 = d->d2 + delta; slpos = slratio * d->d2; - slp = fixtoi (slpos); + slp = al_fixtoi (slpos); if ((slp != oldpos) || (d->d2 <= 0) || (d->d2 >= d->d1)) break; } @@ -926,9 +918,9 @@ my_slider_proc (int msg, DIALOG * d, int c) mp = 0; if (mp > irange - hh) mp = irange - hh; - slpos = itofix (mp); - slmax = fixdiv (slpos, slratio); - newpos = fixtoi (slmax); + slpos = al_itofix (mp); + slmax = al_fixdiv (slpos, slratio); + newpos = al_fixtoi (slmax); if (newpos != oldval) { d->d2 = newpos; @@ -957,20 +949,18 @@ my_slider_proc (int msg, DIALOG * d, int c) * An editable text object (the dp field points to the string). When it * has the input focus (obtained by clicking on it with the mouse), text * can be typed into this object. The d1 field specifies the maximum - * number of characters that it will accept, and d2 is the text cursor + * number of characters that it will accept, and d2 is the text cursor * position within the string. */ int my_edit_proc (int msg, DIALOG * d, int c) { static int ignore_next_uchar = FALSE; - BITMAP *gui_bmp; - int last_was_space, new_pos, i, k; + ALLEGRO_BITMAP *gui_bmp; int f, l, p, w, x, b, scroll; - int fg = 0; char buf[16]; - char *s, *t; - ASSERT (d); + char *s; + ALLEGRO_ASSERT (d); gui_bmp = gui_get_screen (); @@ -1018,7 +1008,6 @@ my_edit_proc (int msg, DIALOG * d, int c) break; case MSG_DRAW: - fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; x = 0; if (scroll) @@ -1038,7 +1027,7 @@ my_edit_proc (int msg, DIALOG * d, int c) break; f = ((p == d->d2) && (d->flags & D_GOTFOCUS)); //textout_ex(gui_bmp, font, buf, d->x+x, d->y, (f) ? d->bg : fg, (f) ? fg : d->bg); - textout_ex (gui_bmp, font, buf, d->x + x, d->y, -1, (f) ? d->fg : d->bg); // ufoot + textout_ex (gui_bmp, font, buf, d->x + x, d->y, NO_COLOR, (f) ? d->fg : d->bg); // ufoot x += w; } if (x < d->w) @@ -1076,62 +1065,34 @@ my_edit_proc (int msg, DIALOG * d, int c) case MSG_CHAR: ignore_next_uchar = FALSE; - if ((c >> 8) == KEY_LEFT) + if ((c >> 8) == ALLEGRO_KEY_LEFT) { if (d->d2 > 0) { - if (key_shifts & KB_CTRL_FLAG) - { - last_was_space = TRUE; - new_pos = 0; - t = s; - for (i = 0; i < d->d2; i++) - { - k = ugetx (&t); - if (uisspace (k)) - last_was_space = TRUE; - else if (last_was_space) - { - last_was_space = FALSE; - new_pos = i; - } - } - d->d2 = new_pos; - } - else - d->d2--; + d->d2--; } } - else if ((c >> 8) == KEY_RIGHT) + else if ((c >> 8) == ALLEGRO_KEY_RIGHT) { if (d->d2 < l) { - if (key_shifts & KB_CTRL_FLAG) - { - t = s + uoffset (s, d->d2); - for (k = ugetx (&t); uisspace (k); k = ugetx (&t)) - d->d2++; - for (; k && !uisspace (k); k = ugetx (&t)) - d->d2++; - } - else - d->d2++; + d->d2++; } } - else if ((c >> 8) == KEY_HOME) + else if ((c >> 8) == ALLEGRO_KEY_HOME) { d->d2 = 0; } - else if ((c >> 8) == KEY_END) + else if ((c >> 8) == ALLEGRO_KEY_END) { d->d2 = l; } - else if ((c >> 8) == KEY_DEL) + else if ((c >> 8) == ALLEGRO_KEY_DELETE) { if (d->d2 < l) uremove (s, d->d2); } - else if ((c >> 8) == KEY_BACKSPACE) + else if ((c >> 8) == ALLEGRO_KEY_BACKSPACE) { if (d->d2 > 0) { @@ -1139,7 +1100,7 @@ my_edit_proc (int msg, DIALOG * d, int c) uremove (s, d->d2); } } - else if ((c >> 8) == KEY_ENTER) + else if ((c >> 8) == ALLEGRO_KEY_ENTER) { if (d->flags & D_EXIT) { @@ -1149,7 +1110,7 @@ my_edit_proc (int msg, DIALOG * d, int c) else return D_O_K; } - else if ((c >> 8) == KEY_TAB) + else if ((c >> 8) == ALLEGRO_KEY_TAB) { ignore_next_uchar = TRUE; return D_O_K; @@ -1168,7 +1129,7 @@ my_edit_proc (int msg, DIALOG * d, int c) { if (l < d->d1) { - uinsert (s, d->d2, c); + uinsert (s, d->d2, c, d->d1); d->d2++; object_message (d, MSG_DRAW, 0); @@ -1178,14 +1139,6 @@ my_edit_proc (int msg, DIALOG * d, int c) break; } - if (fg) - { - /* - * Not elegant, but test above here just to get - * rid of compiler warning about fg not being used. - */ - } - return D_O_K; } @@ -1315,7 +1268,7 @@ my_handle_listbox_click (DIALOG * d) { char *sel = d->dp2; int listsize, height; - int i, j; + int i; (*(my_getfuncptr) d->dp) (-1, &listsize); if (!listsize) @@ -1345,18 +1298,7 @@ my_handle_listbox_click (DIALOG * d) { if (sel) { - if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG)) - { - if ((key_shifts & KB_SHIFT_FLAG) || (d->flags & D_INTERNAL)) - { - for (j = MIN (i, d->d1); j <= MAX (i, d->d1); j++) - sel[j] = TRUE; - } - else - sel[i] = !sel[i]; - } - else - sel[i] = TRUE; + sel[i] = TRUE; } d->d1 = i; @@ -1375,10 +1317,7 @@ my_handle_listbox_click (DIALOG * d) { if (sel) { - if ((key_shifts & KB_CTRL_FLAG)) - sel[i] = !sel[i]; - else - sel[i] = TRUE; + sel[i] = TRUE; d->flags |= D_DIRTY; } @@ -1394,10 +1333,9 @@ my_handle_listbox_click (DIALOG * d) static void my_draw_listbox (DIALOG * d) { - BITMAP *gui_bmp = gui_get_screen (); + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); int height, listsize, i, len, bar, x, y, w; - int fg_color, bg; - int fg; + ALLEGRO_COLOR fg_color, bg; char *sel = d->dp2; char s[1024]; @@ -1416,32 +1354,28 @@ my_draw_listbox (DIALOG * d) { if ((sel[d->d2 + i]) && (d->d2 + i == d->d1)) { - fg = d->bg; bg = fg_color; } else if (sel[d->d2 + i]) { - fg = d->bg; bg = gui_mg_color; } else { - fg = fg_color; bg = d->bg; } } else if (d->d2 + i == d->d1) { - fg = d->bg; bg = fg_color; } else { - fg = fg_color; bg = d->bg; } - ustrzcpy (s, sizeof (s), - (*(my_getfuncptr) d->dp) (i + d->d2, NULL)); + LW_MACRO_STRNCPY (s, + (*(my_getfuncptr) d->dp) (i + d->d2, NULL), + sizeof (s)); x = d->x + 2; y = d->y + 2 + i * text_height (font); rectfill (gui_bmp, x, y, x + 7, y + text_height (font) - 1, bg); @@ -1450,10 +1384,10 @@ my_draw_listbox (DIALOG * d) while (text_length (font, s) >= MAX (d->w - 1 - (bar ? 22 : 10), 1)) { len--; - usetat (s, len, 0); + usetat (s, len, 0, sizeof (s)); } //textout_ex(gui_bmp, font, s, x, y, fg, bg); - textout_ex (gui_bmp, font, s, x, y, -1, bg); // ufoot + textout_ex (gui_bmp, font, s, x, y, NO_COLOR, bg); // ufoot x += text_length (font, s); if (x <= d->x + w) rectfill (gui_bmp, x, y, d->x + w, y + text_height (font) - 1, @@ -1475,14 +1409,6 @@ my_draw_listbox (DIALOG * d) /* draw frame, maybe with scrollbar */ _draw_scrollable_frame (d, listsize, d->d2, height, fg_color, d->bg); - - if (fg) - { - /* - * Not elegant, but test above here just to get - * rid of compiler warning about fg not being used. - */ - } } @@ -1495,18 +1421,18 @@ my_draw_listbox (DIALOG * d) * index is negative, it should return null and list_size should be set * to the number of items in the list. The list box object will allow the * user to scroll through the list and to select items list by clicking - * on them, and if it has the input focus also by using the arrow keys. If - * the D_EXIT flag is set, double clicking on a list item will cause it to - * close the dialog. The index of the selected item is held in the d1 + * on them, and if it has the input focus also by using the arrow keys. If + * the D_EXIT flag is set, double clicking on a list item will cause it to + * close the dialog. The index of the selected item is held in the d1 * field, and d2 is used to store how far it has scrolled through the list. */ int my_list_proc (int msg, DIALOG * d, int c) { - int listsize, i, bottom, height, bar, orig; + int listsize, i, bottom, height, bar; char *sel = d->dp2; int redraw = FALSE; - ASSERT (d); + ALLEGRO_ASSERT (d); switch (msg) { @@ -1526,7 +1452,7 @@ my_list_proc (int msg, DIALOG * d, int c) bar = (listsize > height); if ((!bar) || (gui_mouse_x () < d->x + d->w - 13)) { - if ((sel) && (!(key_shifts & KB_CTRL_FLAG))) + if (sel) { for (i = 0; i < listsize; i++) { @@ -1611,24 +1537,22 @@ my_list_proc (int msg, DIALOG * d, int c) if (bottom >= listsize - 1) bottom = listsize - 1; - orig = d->d1; - - if (c == KEY_UP) + if (c == ALLEGRO_KEY_UP) d->d1--; - else if (c == KEY_DOWN) + else if (c == ALLEGRO_KEY_DOWN) d->d1++; - else if (c == KEY_HOME) + else if (c == ALLEGRO_KEY_HOME) d->d1 = 0; - else if (c == KEY_END) + else if (c == ALLEGRO_KEY_END) d->d1 = listsize - 1; - else if (c == KEY_PGUP) + else if (c == ALLEGRO_KEY_PGUP) { if (d->d1 > d->d2) d->d1 = d->d2; else d->d1 -= (bottom - d->d2) ? bottom - d->d2 : 1; } - else if (c == KEY_PGDN) + else if (c == ALLEGRO_KEY_PGDN) { if (d->d1 < bottom) d->d1 = bottom; @@ -1638,25 +1562,6 @@ my_list_proc (int msg, DIALOG * d, int c) else return D_O_K; - if (sel) - { - if (!(key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG))) - { - for (i = 0; i < listsize; i++) - sel[i] = FALSE; - } - else if (key_shifts & KB_SHIFT_FLAG) - { - for (i = MIN (orig, d->d1); i <= MAX (orig, d->d1); i++) - { - if (key_shifts & KB_CTRL_FLAG) - sel[i] = (i != d->d1); - else - sel[i] = TRUE; - } - } - } - /* if we changed something, better redraw... */ my_handle_scrollable_scroll (d, listsize, &d->d1, &d->d2); d->flags |= D_DIRTY; @@ -1669,12 +1574,38 @@ my_list_proc (int msg, DIALOG * d, int c) } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * my_create_bitmap (int w, int h) { - BITMAP *bmp; + /* + * Default to memory bitmaps for backward compatibility and performance. + * Most bitmaps in the codebase are used for pixel-by-pixel operations + * which are much faster with memory bitmaps. + */ + return my_create_memory_bitmap (w, h); +} + +/*------------------------------------------------------------------*/ +ALLEGRO_BITMAP * +my_create_memory_bitmap (int w, int h) +{ + ALLEGRO_BITMAP *bmp; + al_set_new_bitmap_flags (ALLEGRO_MEMORY_BITMAP); + bmp = al_create_bitmap (w, h); + al_set_new_bitmap_flags (ALLEGRO_VIDEO_BITMAP); + if (bmp == NULL) + my_exit (EXIT_CODE_MEM_TROUBLE); - bmp = create_bitmap (w, h); + return bmp; +} + +/*------------------------------------------------------------------*/ +ALLEGRO_BITMAP * +my_create_video_bitmap (int w, int h) +{ + ALLEGRO_BITMAP *bmp; + al_set_new_bitmap_flags (ALLEGRO_VIDEO_BITMAP); + bmp = al_create_bitmap (w, h); if (bmp == NULL) my_exit (EXIT_CODE_MEM_TROUBLE); diff --git a/src/alleg2.h b/src/alleg2.h index d314f16c..040f52c6 100644 --- a/src/alleg2.h +++ b/src/alleg2.h @@ -55,7 +55,10 @@ /* includes */ /*==================================================================*/ -#include +#include + +#include "backport.h" +#include "backportgui.h" /*==================================================================*/ /* variables globales */ @@ -72,6 +75,8 @@ int my_ctext_proc (int msg, DIALOG * d, int c); int my_slider_proc (int msg, DIALOG * d, int c); int my_edit_proc (int msg, DIALOG * d, int c); int my_list_proc (int msg, DIALOG * d, int c); -BITMAP *my_create_bitmap (int w, int h); +ALLEGRO_BITMAP *my_create_bitmap (int w, int h); +ALLEGRO_BITMAP *my_create_memory_bitmap (int w, int h); +ALLEGRO_BITMAP *my_create_video_bitmap (int w, int h); #endif diff --git a/src/asm.c b/src/asm.c deleted file mode 100644 index 1f67c30b..00000000 --- a/src/asm.c +++ /dev/null @@ -1,143 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : asm.h */ -/* contenu : assembly language related stuff */ -/********************************************************************/ - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include - -#include "asm.h" -#include "area.h" -#include "log.h" -#include "startup.h" - -/*==================================================================*/ -/* constants */ -/*==================================================================*/ - -#define LW_ASM_OFFSET_BITMAP_LINE 64 - -typedef void *ptr; -#define LW_ASM_SIZEOF_int 4 -#define LW_ASM_SIZEOF_short 2 -#define LW_ASM_SIZEOF_char 1 -#define LW_ASM_SIZEOF_ptr 4 - -#define LW_ASM_SIZEOF_MESH_UPDATE 4 -#define LW_ASM_SIZEOF_MESH_STATE 4 -#define LW_ASM_SIZEOF_MESH_INFO 8 -#define LW_ASM_SIZEOF_MESH_SIDE 4 -#define LW_ASM_SIZEOF_MESH 104 -#define LW_ASM_SIZEOF_FIGHTER 8 -#define LW_ASM_SIZEOF_PLACE 8 - -#define LW_ASM_CHECK_SIZEOF(S) \ -if (sizeof(S)!=LW_ASM_SIZEOF_ ## S) \ -{ \ -result=0; \ -log_print_str("Error: " #S " size is "); \ -log_print_int(sizeof(S)); \ -log_print_str(" and should be "); \ -log_println_int(LW_ASM_SIZEOF_ ## S); \ -} - -/*==================================================================*/ -/* fonctions */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -int -lw_asm_check_struct_align (void) -{ - int result = 1; - -#ifdef ASM - { - BITMAP *bmp = NULL; - int offset_bitmap_line; - - LW_ASM_CHECK_SIZEOF (int); - LW_ASM_CHECK_SIZEOF (short); - LW_ASM_CHECK_SIZEOF (char); - LW_ASM_CHECK_SIZEOF (ptr); - - LW_ASM_CHECK_SIZEOF (MESH_UPDATE); - LW_ASM_CHECK_SIZEOF (MESH_STATE); - LW_ASM_CHECK_SIZEOF (MESH_INFO); - LW_ASM_CHECK_SIZEOF (MESH_SIDE); - LW_ASM_CHECK_SIZEOF (MESH); - LW_ASM_CHECK_SIZEOF (FIGHTER); - LW_ASM_CHECK_SIZEOF (PLACE); - - offset_bitmap_line = ((char *) &(bmp->line)) - ((char *) bmp); - if (offset_bitmap_line != LW_ASM_OFFSET_BITMAP_LINE) - { - result = 0; - - log_print_str ("Error: offset for BITMAP->line is "); - log_print_int (offset_bitmap_line); - log_print_str (" and should be "); - log_println_int (LW_ASM_OFFSET_BITMAP_LINE); - - STARTUP_ASM = 0; - } - } -#endif - - if (!result) - { - log_println_str ("WARNING!!!"); - log_println_str - ("Liquid War might crash unexpectedly... Please read previous error messages."); - log_println (); - } - - return result; -} diff --git a/src/asm.h b/src/asm.h deleted file mode 100644 index a27b1e27..00000000 --- a/src/asm.h +++ /dev/null @@ -1,78 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : asm.h */ -/* contenu : assembly language related stuff */ -/********************************************************************/ - -#ifndef LIQUID_WAR_INCLUDE_ASM -#define LIQUID_WAR_INCLUDE_ASM - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -/*==================================================================*/ -/* constants */ -/*==================================================================*/ - -/*==================================================================*/ -/* macros */ -/*==================================================================*/ - -#ifdef WIN32 -#define LW_ASM_FUNC __cdecl -#else -/* seems useless... #define LW_ASM_FUNC __attribute__((cdecl)) */ -#define LW_ASM_FUNC -#endif - -/*==================================================================*/ -/* functions */ -/*==================================================================*/ - -extern int lw_asm_check_struct_align (void); - -#endif diff --git a/src/back.c b/src/back.c index 286f95a4..39b88431 100644 --- a/src/back.c +++ b/src/back.c @@ -52,11 +52,10 @@ /* includes */ /*==================================================================*/ -#include +#include #include "back.h" #include "disk.h" -#include "palette.h" #include "viewport.h" #include "dialog.h" @@ -70,10 +69,11 @@ /*------------------------------------------------------------------*/ void -display_a_back_image (BITMAP * bmp) +display_a_back_image (ALLEGRO_BITMAP * bmp) { scare_mouse (); - stretch_blit (bmp, screen, 0, 0, bmp->w, bmp->h, + stretch_blit (bmp, screen, 0, 0, + al_get_bitmap_width (bmp), al_get_bitmap_height (bmp), 0, PAGE_FLIP_H, SCREEN_W, SCREEN_H); unscare_mouse (); } diff --git a/src/back.h b/src/back.h index 8664d4f1..8db9534c 100644 --- a/src/back.h +++ b/src/back.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* variables globales */ @@ -65,7 +65,7 @@ /* fonctions globales */ /*==================================================================*/ -void display_a_back_image (BITMAP * bmp); +void display_a_back_image (ALLEGRO_BITMAP * bmp); void display_back_image (void); #endif diff --git a/src/backport.c b/src/backport.c new file mode 100644 index 00000000..fe20f8f6 --- /dev/null +++ b/src/backport.c @@ -0,0 +1,1953 @@ +/********************************************************************/ +/* */ +/* L I QQ U U I DD W W A RR 555 */ +/* L I Q Q U U I D D W W A A R R 5 */ +/* L I Q Q U U I D D W W W AAA RR 55 */ +/* L I Q Q U U I D D WW WW A A R R 5 */ +/* LLL I Q Q U I DD W W A A R R 55 */ +/* */ +/* b */ +/* bb y y */ +/* b b yyy */ +/* bb y */ +/* yy */ +/* */ +/* U U FFF O O TTT */ +/* U U F O O O O T */ +/* U U TIRET FF O O O O T */ +/* U U F O O O O T */ +/* U F O O T */ +/* */ +/********************************************************************/ + +/*****************************************************************************/ +/* Liquid War is a multiplayer wargame */ +/* Copyright (C) 1998-2025 Christian Mauduit */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You 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 */ +/* */ +/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ +/* Contact author : ufoot@ufoot.org */ +/*****************************************************************************/ + +/********************************************************************/ +/* name : backport.c */ +/* content : missing allegro 4 stuff */ +/* last update : Dec 24th 2018 */ +/********************************************************************/ + +/*==================================================================*/ +/* includes */ +/*==================================================================*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "backport.h" +#include "macro.h" +#include "mutxgen.h" +#include "thrdgen.h" +#include "log.h" +#include "init.h" + +/*==================================================================*/ +/* defines */ +/*==================================================================*/ + +#define _NB_TIMERS 16 +#define _ITOA_BUF_SIZE 30 + +/*==================================================================*/ +/* types */ +/*==================================================================*/ + +typedef struct +{ + int delay_ms; + void (*proc) (); +} _backport_timer_data; + +/*==================================================================*/ +/* variables globales */ +/*==================================================================*/ + +static int _allegro_errno = 0; +static int _dummy = 0; // stupid dummy to get rid of unused param warning +static _backport_timer_data _backport_timers[_NB_TIMERS]; +static LW_MUTEX_DATA _backport_timer_mutex = { NULL }; +static char *_config_file = NULL; +static ALLEGRO_CONFIG *_config = NULL; + +ALLEGRO_BITMAP *screen = NULL; +ALLEGRO_DISPLAY *allegro_display = NULL; +int SCREEN_W = 0; +int SCREEN_H = 0; +int VIRTUAL_H = 0; +ALLEGRO_FONT *font = NULL; +volatile int mouse_x = 0; +volatile int mouse_y = 0; +volatile int mouse_z = 0; +volatile int mouse_b = 0; + +// Palette-related variables (from old palette.c) +// In true color mode, we effectively have 256 intensity levels per team +// This is a placeholder - real fix is to compute colors with al_map_rgb() directly +int COLORS_PER_TEAM = 256; + +// GUI color variables for Allegro 4 compatibility +// Converted from palette indices to ALLEGRO_COLOR +ALLEGRO_COLOR gui_bg_color = {0, 0, 0, 1}; // Black +ALLEGRO_COLOR gui_fg_color = {1, 1, 1, 1}; // White +ALLEGRO_COLOR gui_mg_color = {0.5, 0.5, 0.5, 1}; // Gray +int *allegro_errno = &_allegro_errno; +volatile JOYSTICK_INFO joy[MAX_JOYSTICKS]; +int num_joysticks = 0; +char empty_string[] = { 0, 0, 0, 0 }; +volatile char key[KEY_MAX]; + +/*==================================================================*/ +/* fonctions */ +/*==================================================================*/ + +/*------------------------------------------------------------------*/ +void +scare_mouse () +{ + /* + * Using a higher level API now, looks like those disappeared. + * Keeping them so that whatever workaround those calls were + * achieving, it's easier to backport it afterwards. + */ +} + +/*------------------------------------------------------------------*/ +void +scare_mouse_area (int x, int y, int w, int h) +{ + /* + * Using a higher level API now, looks like those disappeared. + * Keeping them so that whatever workaround those calls were + * achieving, it's easier to backport it afterwards. + */ + _dummy = x; + _dummy = y; + _dummy = w; + _dummy = h; +} + +/*------------------------------------------------------------------*/ +void +unscare_mouse () +{ + /* + * Using a higher level API now, looks like those disappeared. + * Keeping them so that whatever workaround those calls were + * achieving, it's easier to backport it afterwards. + */ +} + +/*------------------------------------------------------------------*/ +int +poll_mouse (void) +{ + // https://liballeg.org/stabledocs/en/alleg004.html#poll_mouse + ALLEGRO_MOUSE_STATE mouse_state; + + memset (&mouse_state, 0, sizeof (mouse_state)); + al_get_mouse_state (&mouse_state); + int num_axes = num_axes = al_get_mouse_num_axes (); + if (num_axes >= 1) + { + mouse_x = al_get_mouse_state_axis (&mouse_state, 0); + } + if (num_axes >= 2) + { + mouse_y = al_get_mouse_state_axis (&mouse_state, 1); + } + if (num_axes >= 3) + { + mouse_z = al_get_mouse_state_axis (&mouse_state, 2); + } + mouse_b = mouse_state.buttons; + + return 0; +} + +/*------------------------------------------------------------------*/ +int +mouse_needs_poll (void) +{ + // https://liballeg.org/stabledocs/en/alleg004.html#mouse_needs_poll + /* + * Stupid answer which means "poll all the time" but this is (hopefully) + * transition code, if this is a perf bottleneck it should be easy to + * remove or change all that polling logic. + */ + return 1; +} + +/*------------------------------------------------------------------*/ +void +position_mouse (int x, int y) +{ + // https://liballeg.org/stabledocs/en/alleg004.html#position_mouse + al_set_mouse_xy (allegro_display, x, y); + mouse_x = x; + mouse_y = y; +} + +/*------------------------------------------------------------------*/ +void +set_mouse_sprite (ALLEGRO_BITMAP *sprite) +{ + // https://liballeg.org/stabledocs/en/alleg004.html#set_mouse_sprite + if (sprite) + { + al_set_mouse_cursor (allegro_display, al_create_mouse_cursor (sprite, 0, 0)); + } +} + +/*------------------------------------------------------------------*/ +void +show_mouse (ALLEGRO_BITMAP *bmp) +{ + // https://liballeg.org/stabledocs/en/alleg004.html#show_mouse + (void) bmp; // Ignore bitmap parameter since Allegro 5 handles cursor display differently + al_show_mouse_cursor (allegro_display); +} + +/*------------------------------------------------------------------*/ +void +clear_to_color (ALLEGRO_BITMAP * bitmap, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#clear_to_color + al_set_target_bitmap (bitmap); + al_clear_to_color (color); +} + +/*------------------------------------------------------------------*/ +void +putpixel (ALLEGRO_BITMAP * bitmap, int x, int y, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#putpixel + al_set_target_bitmap (bitmap); + al_put_pixel (x, y, color); +} + +/*------------------------------------------------------------------*/ +void +putpixel_fast (int x, int y, ALLEGRO_COLOR color) +{ + // Optimized version that assumes target bitmap is already set + // Use al_set_target_bitmap() before calling this in a loop + al_put_pixel (x, y, color); +} + +/*------------------------------------------------------------------*/ +ALLEGRO_COLOR +getpixel (ALLEGRO_BITMAP * bitmap, int x, int y) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#getpixel + return al_get_pixel (bitmap, x, y); +} + +/*------------------------------------------------------------------*/ +void +rect (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#rect + if (x2 < x1 || y2 < y1) + { + return; + } + al_set_target_bitmap (bitmap); + + + al_draw_filled_rectangle (x1, y1, x2, y1 + 1, color); + al_draw_filled_rectangle (x2, y1, x2 + 1, y2, color); + al_draw_filled_rectangle (x1 + 1, y2, x2 + 1, y2 + 1, color); + al_draw_filled_rectangle (x1, y1 + 1, x1 + 1, y2 + 1, color); +} + +/*------------------------------------------------------------------*/ +void +rectfill (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#rectfill + al_set_target_bitmap (bitmap); + + + // +1 on second coord because floating point vs integer + al_draw_filled_rectangle (x1, y1, x2 + 1, y2 + 1, color); +} + +/*------------------------------------------------------------------*/ +void +rectfill_dotted (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, + ALLEGRO_COLOR fg, ALLEGRO_COLOR bg) +{ + /* + * This is not a genuine Allegro function, but used to backport the behavior + * of filling zones with a pattern which is: + * +--+--+--+--+ + * +fg+bg+fg+bg+ + * +--+--+--+--+ + * +bg+fg+bg+fg+ + * +--+--+--+--+ + * +fg+bg+fg+bg+ + * +--+--+--+--+ + * +bg+fg+bg+fg+ + * +--+--+--+--+ + * etc. + * Rather than implemeting generic pattern handling, this is quicker to implement. + * and suits our limited need. + */ + ALLEGRO_COLOR color = bg; + int x = 0; + int y = 0; + + al_set_target_bitmap (bitmap); + for (y = y1; y <= y2; y++) + { + for (x = x1; x <= x2; x++) + { + color = ((x + y) % 2) != 0 ? fg : bg; + al_put_pixel (x, y, color); + } + } +} + +/*------------------------------------------------------------------*/ +void +vline (ALLEGRO_BITMAP * bitmap, int x, int y1, int y2, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#vline + if (y2 < y1) + { + int y = y2; + y2 = y1; + y1 = y; + } + al_set_target_bitmap (bitmap); + + + al_draw_filled_rectangle (x, y1, x + 1, y2 + 1, color); +} + +/*------------------------------------------------------------------*/ +void +hline (ALLEGRO_BITMAP * bitmap, int x1, int y, int x2, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#hline + if (x2 < x1) + { + int x = x2; + x2 = x1; + x1 = x; + } + al_set_target_bitmap (bitmap); + + + al_draw_filled_rectangle (x1, y, x2 + 1, y + 1, color); +} + +void +line (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, ALLEGRO_COLOR color) +{ + // https://liballeg.org/stabledocs/en/alleg013.html#line + if (x1 == x2) + { + vline (bitmap, x1, y1, y2, color); + return; + } + if (y1 == y2) + { + hline (bitmap, x1, y1, x2, color); + return; + } + + al_set_target_bitmap (bitmap); + + + + /* ugliest line drawing ever, but we don't care, this is never called */ + int w = x2 - x1; + int h = y2 - y1; + int d = ABS (w) + ABS (h); + int i = 0; + for (i = 0; i <= d; i++) + { + int x = ((i * x2) + ((d - i) * x1)) / d; + int y = ((i * y2) + ((d - i) * y1)) / d; + al_put_pixel (x, y, color); + } +} + +/*------------------------------------------------------------------*/ +int +usetc (char *s, int c) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#usetc + ALLEGRO_USTR *us = NULL; + int l = 0; + const char *s2 = NULL; + + us = al_ustr_new (s); + al_ustr_set_chr (us, 0, c); + s2 = al_cstr (us); + l = strlen (s); + LW_MACRO_STRNCPY (s, s2, l + 1); + al_ustr_free (us); + + return l; +} + +/*------------------------------------------------------------------*/ +int +ugetc (const char *s) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ugetc + ALLEGRO_USTR *us = NULL; + int c = 0; + + us = al_ustr_new (s); + c = al_ustr_get (us, 0); + al_ustr_free (us); + + return c; +} + +/*------------------------------------------------------------------*/ +int +uwidth (const char *s) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uwidth + ALLEGRO_USTR *us = NULL; + int pos = 0; + bool found = false; + + us = al_ustr_new (s); + found = al_ustr_next (us, &pos); + al_ustr_free (us); + + if (!found) + { + return 0; + } + return pos; +} + +/*------------------------------------------------------------------*/ +int +ustrlen (const char *s) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ustrlen + ALLEGRO_USTR *us = NULL; + int l = 0; + + us = al_ustr_new (s); + l = al_ustr_length (us); + al_ustr_free (us); + + return l; +} + +/*------------------------------------------------------------------*/ +int +uisspace (int c) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uisspace + /* + * Super naive impl, should do the job for the LW use-case. + */ + return c <= 32; +} + +/*------------------------------------------------------------------*/ +int +ucwidth (int c) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ucwidth + _dummy = c; + return 1; +} + +/*------------------------------------------------------------------*/ +int +ugetat (char *s, int index) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ugetat + ALLEGRO_USTR *us = NULL; + int c = 0; + + us = al_ustr_new (s); + c = al_ustr_get (us, index); + al_ustr_free (us); + + return c; +} + +/*------------------------------------------------------------------*/ +int +usetat (char *s, int index, int c, int max_size) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#usetat + /* + * Altered the protoype of that one, not giving max_size here + * is just totally super-dangerous IMHO. + */ + ALLEGRO_USTR *us = NULL; + int l = 0; + int max_len = max_size - 1; + + l = strlen (s); + if (index < 0) + { + index = l - index; + } + if (index >= max_len || index < 0) + { + return 0; + } + + us = al_ustr_new (s); + if (c == 0) + { + al_ustr_truncate (us, index); + } + else + { + al_ustr_remove_chr (us, index); + al_ustr_insert_chr (us, index, c); + } + LW_MACRO_STRNCPY (s, al_cstr (us), max_size); + al_ustr_free (us); + + return (strlen (s) - l); +} + +/*------------------------------------------------------------------*/ +int +uinsert (char *s, int index, int c, int max_size) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uinsert + /* + * Altered the protoype of that one, not giving max_size here + * is just totally super-dangerous IMHO. + */ + ALLEGRO_USTR *us = NULL; + int l = 0; + int max_len = max_size - 1; + + l = strlen (s); + if (index < 0) + { + index = l - index; + } + if (index >= max_len || index < 0) + { + return 0; + } + + us = al_ustr_new (s); + if (c == 0) + { + al_ustr_truncate (us, index); + } + else + { + al_ustr_insert_chr (us, index, c); + } + LW_MACRO_STRNCPY (s, al_cstr (us), max_size); + al_ustr_free (us); + + return (strlen (s) - l); +} + +/*------------------------------------------------------------------*/ +int +uremove (char *s, int index) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uremove + ALLEGRO_USTR *us = NULL; + int l = 0; + + l = strlen (s); + if (index < 0) + { + index = l - index; + } + if (index < 0) + { + return 0; + } + + us = al_ustr_new (s); + al_ustr_remove_chr (us, index); + LW_MACRO_STRNCPY (s, al_cstr (us), l); + al_ustr_free (us); + + return (strlen (s) - l); +} + +/*------------------------------------------------------------------*/ +int +uisok (int c) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uiosok + /* + * [FIXME:ufoot] right now does nothing real, but game handles + * UTF-8 very poorly, TBH. + */ + return ((c >= ' ') && (c <= 127)); +} + +/*------------------------------------------------------------------*/ +int +utolower (int c) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#utolower + /* + * [FIXME:ufoot] right now does nothing real, but game handles + * UTF-8 very poorly, TBH. + */ + if ((c >= 'A') && (c <= 'Z')) + { + c += 'a' - 'A'; + } + return c; +} + +/*------------------------------------------------------------------*/ +char * +ustrdup (const char *src) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ustrdup + /* + * [TODO:ufoot] find out why this was redefined in the first place. + */ + return strdup (src); +} + +/*------------------------------------------------------------------*/ +int +ugetx (char **s) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ugetx + return ugetxc ((const char **) s); +} + +/*------------------------------------------------------------------*/ +int +ugetxc (const char **s) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ugetxc + int c = *((unsigned char *) ((*s)++)); + int n, t; + + if (c & 0x80) + { + n = 1; + while (c & (0x80 >> n)) + n++; + + c &= (1 << (8 - n)) - 1; + + while (--n > 0) + { + t = *((unsigned char *) ((*s)++)); + + if ((!(t & 0x80)) || (t & 0x40)) + { + (*s)--; + return '^'; + } + + c = (c << 6) | (t & 0x3F); + } + } + + return c; +} + +/*------------------------------------------------------------------*/ +char * +ustrtok_r (char *s, AL_CONST char *set, char **last) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#ustrtok_r + char *prev_str, *tok; + AL_CONST char *setp; + int c, sc; + + ALLEGRO_ASSERT (last); + + if (!s) + { + s = *last; + + if (!s) + return NULL; + } + +skip_leading_delimiters: + + prev_str = s; + c = ugetx (&s); + + setp = set; + + while ((sc = ugetxc (&setp)) != 0) + { + if (c == sc) + goto skip_leading_delimiters; + } + + if (!c) + { + *last = NULL; + return NULL; + } + + tok = prev_str; + + for (;;) + { + prev_str = s; + c = ugetx (&s); + + setp = set; + + do + { + sc = ugetxc (&setp); + if (sc == c) + { + if (!c) + { + *last = NULL; + return tok; + } + else + { + int l = 0; + l = strlen (prev_str); + s += usetat (prev_str, 0, 0, l + 1); + *last = s; + return tok; + } + } + } + while (sc); + } +} + +/*------------------------------------------------------------------*/ +char * +uconvert_ascii (const char *s, char buf[], int size) +{ + // https://liballeg.org/stabledocs/en/alleg002.html#uconvert_ascii + /* + * Slightly altered prototype to make sure we use explicit size + */ + LW_MACRO_STRNCPY (buf, s, size); + return (char *) buf; +} + +/*------------------------------------------------------------------*/ +int +text_length (const ALLEGRO_FONT * f, const char *s) +{ + // https://liballeg.org/stabledocs/en/alleg018.html#text_length + return al_get_text_width (f, s); +} + +/*------------------------------------------------------------------*/ +int +text_height (const ALLEGRO_FONT * f) +{ + // https://liballeg.org/stabledocs/en/alleg018.html#text_height + return al_get_font_line_height (f); +} + +/*------------------------------------------------------------------*/ +void +textout_ex (ALLEGRO_BITMAP * bmp, const ALLEGRO_FONT * f, const char *s, + int x, int y, ALLEGRO_COLOR color, ALLEGRO_COLOR bg) +{ + // https://liballeg.org/stabledocs/en/alleg018.html#textout_ex + int w = 0; + int h = 0; + + w = text_length (f, s); + h = text_height (f); + rectfill (bmp, x, y, x + w - 1, y + h - 1, bg); + + al_set_target_bitmap (bmp); + al_draw_text (f, color, x, y, 0, s); +} + +/*------------------------------------------------------------------*/ +void +rest_callback (unsigned int time, void (*callback) (void)) +{ + // https://liballeg.org/stabledocs/en/alleg005.html#rest_callback + double delay; + + delay = ((double) time) / 1000.0; + if (callback == NULL) + { + al_rest (delay); + } + else + { + unsigned int i; + + for (i = 0; i < time; i++) + { + al_rest (0.001); + callback (); + } + } +} + +/*------------------------------------------------------------------*/ +void +rest (unsigned int time) +{ + // https://liballeg.org/stabledocs/en/alleg005.html#rest + rest_callback (time, NULL); +} + +/*------------------------------------------------------------------*/ +int +install_timer () +{ + // https://liballeg.org/stabledocs/en/alleg005.html#install_timer + memset (_backport_timers, 0, sizeof (_backport_timers)); + memset (&_backport_timer_mutex, 0, sizeof (_backport_timer_mutex)); + + return (lw_mutex_init (&_backport_timer_mutex) == 0) ? -1 : 0; +} + +/*------------------------------------------------------------------*/ +void +remove_timer () +{ + // https://liballeg.org/stabledocs/en/alleg005.html#remove_timer + memset (_backport_timers, 0, sizeof (_backport_timers)); + memset (&_backport_timer_mutex, 0, sizeof (_backport_timer_mutex)); +} + + +/*------------------------------------------------------------------*/ +void +_backport_timer_callback (void *ptr) +{ + _backport_timer_data *data = NULL; + + data = (_backport_timer_data *) ptr; + while (data->proc) + { + data->proc (); + rest (data->delay_ms); + } +} + +/*------------------------------------------------------------------*/ +int +install_int (void (*proc) (), int speed) +{ + // https://liballeg.org/stabledocs/en/alleg005.html#install_int + int i = 0; + bool found = false; + int ret = 0; + + if (speed <= 0) + { + speed = 1; + } + + lw_mutex_lock (&_backport_timer_mutex); + for (i = 0; i < _NB_TIMERS && !found; i++) + { + if (_backport_timers[i].proc == proc) + { + _backport_timers[i].delay_ms = speed; + found = true; + } + } + for (i = 0; i < _NB_TIMERS && !found; i++) + { + if (_backport_timers[i].proc == NULL) + { + _backport_timers[i].proc = proc; + _backport_timers[i].delay_ms = speed; + if (!lw_thread_start + (_backport_timer_callback, &(_backport_timers[i]))) + { + ret = -2; + } + found = true; + } + } + lw_mutex_unlock (&_backport_timer_mutex); + + return found ? ret : -1; +} + +/*------------------------------------------------------------------*/ +int +install_int_ex (void (*proc) (), int speed) +{ + // https://liballeg.org/stabledocs/en/alleg005.html#install_int_ex + // This is a compatibility stub - for full implementation, files should + // be migrated to use modern Allegro 5 timer APIs like al_get_time() + return install_int (proc, speed); +} + +/*------------------------------------------------------------------*/ +void +remove_int (void (*proc) ()) +{ + // https://liballeg.org/stabledocs/en/alleg005.html#remove_int + int i = 0; + bool found = false; + + lw_mutex_lock (&_backport_timer_mutex); + for (i = 0; i < _NB_TIMERS && !found; i++) + { + if (_backport_timers[i].proc == proc) + { + _backport_timers[i].proc = NULL; + found = true; + } + } + lw_mutex_unlock (&_backport_timer_mutex); +} + +/*------------------------------------------------------------------*/ +void +draw_sprite (ALLEGRO_BITMAP * bmp, ALLEGRO_BITMAP * sprite, int x, int y) +{ + // https://liballeg.org/stabledocs/en/alleg014.html#draw_sprite + al_set_target_bitmap (bmp); + al_draw_bitmap (sprite, x, y, 0); +} + +/*------------------------------------------------------------------*/ +void +blit (ALLEGRO_BITMAP * source, ALLEGRO_BITMAP * dest, + int source_x, int source_y, + int dest_x, int dest_y, int dest_width, int dest_height) +{ + // https://liballeg.org/stabledocs/en/alleg014.html#blit + al_set_target_bitmap (dest); + int sw = MAX (MIN (al_get_bitmap_width (source) - source_x, dest_width), 0); + int sh = + MAX (MIN (al_get_bitmap_height (source) - source_y, dest_height), 0); + al_draw_bitmap_region (source, source_x, source_y, sw, sh, dest_x, dest_y, + 0); +} + +/*------------------------------------------------------------------*/ +void +stretch_blit (ALLEGRO_BITMAP * source, ALLEGRO_BITMAP * dest, + int source_x, int source_y, int source_width, int source_height, + int dest_x, int dest_y, int dest_width, int dest_height) +{ + // https://liballeg.org/stabledocs/en/alleg014.html#stretch_blit + al_set_target_bitmap (dest); + al_draw_scaled_bitmap (source, source_x, source_y, source_width, + source_height, dest_x, dest_y, dest_width, + dest_height, 0); +} + +/*------------------------------------------------------------------*/ +ALLEGRO_BITMAP * +load_bitmap (const char *filename) +{ + // https://liballeg.org/stabledocs/en/alleg014.html#load_bitmap + ALLEGRO_BITMAP *bmp; + + // Try using flags to optimize loading performance + bmp = al_load_bitmap_flags(filename, ALLEGRO_MEMORY_BITMAP); + return bmp; +} + +/*------------------------------------------------------------------*/ +void +set_volume (int digi_volume, int midi_volume) +{ + // https://liballeg.org/stabledocs/en/alleg011.html#set_volume + (void) digi_volume; // Digital volume not used in this implementation + // In Allegro 5, we would set the mixer gain, but for now just ignore + // since MIDI playback uses ALLEGRO_SAMPLE which has its own volume control + (void) midi_volume; // MIDI volume handled per-sample in play_midi +} + +/*------------------------------------------------------------------*/ +int +play_midi (ALLEGRO_SAMPLE *midi, int loop) +{ + // https://liballeg.org/stabledocs/en/alleg011.html#play_midi + static ALLEGRO_SAMPLE_INSTANCE *current_music = NULL; + + // Stop any currently playing music + if (current_music) + { + al_stop_sample_instance (current_music); + al_destroy_sample_instance (current_music); + current_music = NULL; + } + + if (midi) + { + current_music = al_create_sample_instance (midi); + if (current_music) + { + al_set_sample_instance_playmode (current_music, + loop ? ALLEGRO_PLAYMODE_LOOP : ALLEGRO_PLAYMODE_ONCE); + al_attach_sample_instance_to_mixer (current_music, al_get_default_mixer ()); + return al_play_sample_instance (current_music) ? 1 : 0; + } + } + + return midi ? 0 : 1; // Return 1 for stop (NULL), 0 for failed play +} + +/*------------------------------------------------------------------*/ +int +play_sample (ALLEGRO_SAMPLE *spl, int vol, int pan, int freq, int loop) +{ + // https://liballeg.org/stabledocs/en/alleg011.html#play_sample + // Allegro 4: play_sample(sample, vol, pan, freq, loop) + // vol: 0-255, pan: 0-255 (128=center), freq: 1000=normal, loop: 0=once, 1=loop + + if (!spl) { + return -1; + } + + ALLEGRO_SAMPLE_INSTANCE *instance = al_create_sample_instance(spl); + if (!instance) { + return -1; + } + + // Set volume (0-255 -> 0.0-1.0) + float al_vol = (float)vol / 255.0f; + al_set_sample_instance_gain(instance, al_vol); + + // Set pan (0-255 -> -1.0 to 1.0, where 128 = 0.0 center) + float al_pan = ((float)pan - 128.0f) / 128.0f; + al_set_sample_instance_pan(instance, al_pan); + + // Set frequency/speed (1000 = normal speed) + float speed = (float)freq / 1000.0f; + al_set_sample_instance_speed(instance, speed); + + // Set looping + ALLEGRO_PLAYMODE playmode = loop ? ALLEGRO_PLAYMODE_LOOP : ALLEGRO_PLAYMODE_ONCE; + al_set_sample_instance_playmode(instance, playmode); + + // Attach to default mixer and play + al_attach_sample_instance_to_mixer(instance, al_get_default_mixer()); + + if (al_play_sample_instance(instance)) { + // In Allegro 4, play_sample returned the voice number (positive) + // We'll return 1 to indicate success (can't return actual voice) + return 1; + } else { + al_destroy_sample_instance(instance); + return -1; + } +} + +/*------------------------------------------------------------------*/ +void +acquire_bitmap (ALLEGRO_BITMAP * bmp) +{ + // https://liballeg.org/stabledocs/en/alleg009.html#acquire_bitmap + al_lock_bitmap (bmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_PIXEL_FORMAT_ANY); +} + +/*------------------------------------------------------------------*/ +void +acquire_screen () +{ + // https://liballeg.org/stabledocs/en/alleg009.html#acquire_screen + acquire_bitmap (screen); +} + +/*------------------------------------------------------------------*/ +void +release_bitmap (ALLEGRO_BITMAP * bmp) +{ + // https://liballeg.org/stabledocs/en/alleg009.html#release_bitmap + al_unlock_bitmap (bmp); +} + +/*------------------------------------------------------------------*/ +void +release_screen () +{ + // https://liballeg.org/stabledocs/en/alleg009.html#release_screen + release_bitmap (screen); +} + +/*------------------------------------------------------------------*/ +void +set_clip_rect (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2) +{ + // https://liballeg.org/stabledocs/en/alleg009.html#set_clip_rect + al_set_target_bitmap (bitmap); + if (x1 < 0) + { + x1 = 0; + } + if (y1 < 0) + { + y1 = 0; + } + if (x1 > al_get_bitmap_width (bitmap)) + { + x1 = al_get_bitmap_width (bitmap); + } + if (y1 > al_get_bitmap_height (bitmap)) + { + y1 = al_get_bitmap_height (bitmap); + } + if (x2 > al_get_bitmap_width (bitmap)) + { + x2 = al_get_bitmap_width (bitmap); + } + if (y2 > al_get_bitmap_height (bitmap)) + { + y2 = al_get_bitmap_height (bitmap); + } + int w = x2 - x1 + 1; + int h = y2 - y1 + 1; + if (w < 0) + { + w = 0; + } + if (h < 0) + { + h = 0; + } + al_set_clipping_rectangle (x1, y1, w, h); +} + +/*------------------------------------------------------------------*/ +int +install_joystick (int type) +{ + // https://liballeg.org/stabledocs/en/alleg007.html#install_joystick + + (void) type; // Ignore type parameter since Allegro 5 auto-detects + + if (!al_install_joystick ()) + { + return -1; + } + + num_joysticks = al_get_num_joysticks (); + return 0; +} + +/*------------------------------------------------------------------*/ +int +poll_joystick () +{ + // https://liballeg.org/stabledocs/en/alleg007.html#poll_joystick + + memset ((void *) &joy[0], 0, sizeof (joy)); + num_joysticks = al_get_num_joysticks (); + int j = 0; + for (j = 0; j < num_joysticks && j < MAX_JOYSTICKS; j++) + { + ALLEGRO_JOYSTICK *joystick = NULL; + joystick = al_get_joystick (j); + if (joystick == NULL) + { + continue; + } + joy[j].name = al_get_joystick_name (joystick); + ALLEGRO_JOYSTICK_STATE joystick_state; + memset (&joystick_state, 0, sizeof (joystick_state)); + al_get_joystick_state (joystick, &joystick_state); + int num_sticks = al_get_joystick_num_sticks (joystick); + int s = 0; + for (s = 0; s < num_sticks && s < MAX_JOYSTICK_STICKS; s++) + { + joy[j].stick[s].name = al_get_joystick_stick_name (joystick, s); + int num_axes = al_get_joystick_num_axes (joystick, s); + int a = 0; + for (a = 0; a < num_axes && a < MAX_JOYSTICK_AXIS; a++) + { + joy[j].stick[s].axis[a].name = + al_get_joystick_axis_name (joystick, s, a); + float p = joystick_state.stick[s].axis[a]; + joy[j].stick[s].axis[a].pos = (int) (p * 128.0); + if (p < 0) + { + joy[j].stick[s].axis[a].d1 = 1; + } + else if (p > 0) + { + joy[j].stick[s].axis[a].d2 = 1; + } + } + int num_buttons = al_get_joystick_num_buttons (joystick); + int b = 0; + for (b = 0; b < num_buttons && b < MAX_JOYSTICK_BUTTONS; b++) + { + joy[j].button[b].name = + al_get_joystick_button_name (joystick, b); + joy[j].button[b].b = joystick_state.button[b] ? 1 : 0; + } + } + } + + return 0; +} + +/*------------------------------------------------------------------*/ +int +keypressed () +{ + // https://liballeg.org/stabledocs/en/alleg006.html#keypressed + /* + * [FIXME:ufoot] implement this. + */ + return 0; +} + +/*------------------------------------------------------------------*/ +int +readkey () +{ + // https://liballeg.org/stabledocs/en/alleg006.html#readkey + /* + * [FIXME:ufoot] implement this. + */ + return 0; +} + +/*------------------------------------------------------------------*/ +int +ureadkey (int *scancode) +{ + // https://liballeg.org/stabledocs/en/alleg006.html#ureadkey + /* + * [FIXME:ufoot] implement this. + */ + if (scancode != NULL) + { + (*scancode) = 0; + } + return 0; +} + +/*------------------------------------------------------------------*/ +void +clear_keybuf () +{ + // https://liballeg.org/stabledocs/en/alleg006.html#clear_keybuf + /* + * [FIXME:ufoot] implement this. + */ +} + +/*------------------------------------------------------------------*/ +void +simulate_keypress (int key) +{ + // https://liballeg.org/stabledocs/en/alleg006.html#simulate_keypress + /* + * [FIXME:ufoot] implement this. + */ + _dummy = key; +} + +/*------------------------------------------------------------------*/ +int +scancode_to_ascii (int scancode) +{ + // https://liballeg.org/stabledocs/en/alleg006.html#scancode_to_ascii + /* + * Again, most unreliable and primitive impl, but should be enough + * for the limited usage we make of that function. + */ + int ascii = 0; + char *name = ustrdup (al_keycode_to_name (scancode)); + + // naive tolower + char *pos = NULL; + for (pos = name; *pos; pos++) + { + char c = *pos; + if (c >= 'A' && c <= 'Z') + { + (*pos) = c + 'a' - 'A'; + } + } + // normally it's "space" but accept " " too. + if (strcmp (name, " ") == 0 || strcmp (name, "space") == 0) + { + ascii = 0; + } + else if (strlen (name) == 1 && name[0] >= 'a' && name[0] <= 'z') + { + // standard letter, the only thing we really need to handle + ascii = name[0]; + } + free (name); + + return ascii; +} + +/*------------------------------------------------------------------*/ +void +remove_keyboard (void) +{ + // In Allegro 5, we don't need to explicitly remove keyboard + // This function is provided for compatibility and does nothing +} + +/*------------------------------------------------------------------*/ +void create_if_not_exist(char *filename) { + FILE* f=fopen (filename, "a"); + if (f==NULL) { + log_println_str("could not create file"); + return; + } + fclose(f); +} + +/*------------------------------------------------------------------*/ +void set_config_file(char *filename) { + create_if_not_exist(filename); + + _config_file = filename; + _config = al_load_config_file(filename); + if (_config == NULL) { + log_println_str("could not load config"); + } +} + +/*------------------------------------------------------------------*/ +int get_config_int(const char *section, const char *key, int def) { + const char *value = get_config_string(section, key, ""); + if (value == NULL || strlen(value) == 0) { + return def; + } + return atoi(value); +} + +/*------------------------------------------------------------------*/ +const char *get_config_string(const char *section, const char *key, const char *def) { + if (_config == NULL) { + return def; + } + const char *value = al_get_config_value(_config, section, key); + if (value == NULL) { + return def; + } + return value; +} + +/*------------------------------------------------------------------*/ +void set_config_int(const char *section, const char *key, int value) { + // The following leaks memory as this buf is never freed. However, in the + // program, set_config_int is really rarely used, only at the end of the + // program, so before it causes a critical visible leak, there is a long way. + char *buf = malloc(_ITOA_BUF_SIZE); + memset(buf, 0, _ITOA_BUF_SIZE); + snprintf(buf, _ITOA_BUF_SIZE, "%d", value); + set_config_string(section, key, buf); +} + +/*------------------------------------------------------------------*/ +void set_config_string(const char *section, const char *key, const char *value) { + if (_config == NULL) { + return; + } + al_set_config_value(_config, section, key, value); +} + +/*------------------------------------------------------------------*/ +void flush_config_file() { + if (_config == NULL) { + return ; + } + if (al_save_config_file(_config_file, _config)) { + log_println_str("saved config"); + } else { + log_println_str("could not save config"); + } +} + +/*------------------------------------------------------------------*/ +int exists(const char *filename) { + FILE *f = fopen(filename, "r"); + if (f != NULL) { + fclose(f); + return 1; + } + return 0; +} + +/*------------------------------------------------------------------*/ +// Graphics mode compatibility functions + +// Dummy graphics driver for compatibility +static char dummy_driver_name[] = "Allegro 5 Display"; +static LW_GFX_DRIVER_INFO dummy_gfx_driver = { dummy_driver_name }; + +LW_GFX_DRIVER_INFO *gfx_driver = &dummy_gfx_driver; + +// Black palette for compatibility +static PALETTE black_palette_data; +void *black_palette = &black_palette_data; + +/*------------------------------------------------------------------*/ +int set_gfx_mode(int card, int w, int h, int v_w, int v_h) { + // In Allegro 5, graphics mode setup is handled differently + // This is a compatibility stub that returns success + // Real display creation should be handled at a higher level + (void)card; + (void)v_w; // Virtual width not used in current implementation + + // Set the global screen dimensions for compatibility + SCREEN_W = w; + SCREEN_H = h; + VIRTUAL_H = v_h ? v_h : h * 2; // Set virtual height for page flipping + + return 0; // Success in Allegro 4 convention +} + +/*------------------------------------------------------------------*/ +void set_palette(void *palette) { + // In Allegro 5 without palette mode, this is a no-op + // Colors are handled as direct RGB values (0xRRGGBB format) + (void)palette; // Stub for compatibility +} + +/*------------------------------------------------------------------*/ +void set_window_title(const char *title) { + // Get the current display and set its title + ALLEGRO_DISPLAY *display = al_get_current_display(); + if (display && title) { + al_set_window_title(display, title); + } +} + +/*------------------------------------------------------------------*/ +// Global variables for Allegro 4 compatibility +char *allegro_id = "Allegro 5.x"; + +// Driver info structures (stubs for compatibility) +static LW_GFX_DRIVER_INFO timer_driver_info = {"Allegro 5 Timer"}; +static LW_GFX_DRIVER_INFO keyboard_driver_info = {"Allegro 5 Keyboard"}; +static LW_GFX_DRIVER_INFO mouse_driver_info = {"Allegro 5 Mouse"}; +static LW_GFX_DRIVER_INFO digi_driver_info = {"Allegro 5 Audio"}; +static LW_GFX_DRIVER_INFO midi_driver_info = {"Allegro 5 MIDI"}; +static LW_GFX_DRIVER_INFO joystick_driver_info = {"Allegro 5 Joystick"}; + +LW_GFX_DRIVER_INFO *timer_driver = &timer_driver_info; +LW_GFX_DRIVER_INFO *keyboard_driver = &keyboard_driver_info; +LW_GFX_DRIVER_INFO *mouse_driver = &mouse_driver_info; +LW_GFX_DRIVER_INFO *digi_driver = &digi_driver_info; +LW_GFX_DRIVER_INFO *midi_driver = &midi_driver_info; +LW_GFX_DRIVER_INFO *joystick_driver = &joystick_driver_info; + +/*------------------------------------------------------------------*/ +int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)()) { + // Allegro 4 install_allegro function compatibility + (void)system_id; + (void)errno_ptr; + (void)atexit_ptr; + + return allegro_init(); +} + +/*------------------------------------------------------------------*/ +int allegro_init(void) { + // Initialize Allegro 5 core system + log_print_str("."); + int core= al_init (); + if (!core) { + return -1; // Allegro 4 returns non-zero on failure + } + + // Initialize subsystems that the game expects to be available + // These correspond to the various install_* functions in Allegro 4 + + // Display support + log_print_str("."); + allegro_display=al_create_display(640,480); // [TODO] handle different res here + bool display_ok=allegro_display!=NULL; + if (!display_ok) { + return -1; + } + + // Keyboard support + log_print_str("."); + int keyboard=al_install_keyboard(); + if (!keyboard) { + return -1; + } + + // Mouse support + log_print_str("."); + int mouse=al_install_mouse(); + if (!mouse) { + return -1; + } + + // Joystick support (optional, will be initialized by install_joystick() when needed) + // al_install_joystick(); - removed, now handled by install_joystick() function + + // Audio support (optional) + log_print_str("."); + if (!al_install_audio()) { + return -1; + } + + log_print_str("."); + if (!al_init_acodec_addon()) { + return -1; + } + + // Image loading support + log_print_str("."); + if (!al_init_image_addon()) { + return -1; + } + + // Font support + log_print_str("."); + if (!al_init_font_addon()) { + return -1; + } + + // Primitives for drawing operations + log_print_str("."); + if (!al_init_primitives_addon()) { + return -1; + } + +#ifdef ALLEGRO_ANDROID + log_print_str("."); + al_install_touch_input(); + log_print_str("."); + al_android_set_apk_file_interface(); +#endif + + return 0; // Success in Allegro 4 style (0 = success) +} + +/*------------------------------------------------------------------*/ +void set_uformat(int format) { + // Allegro 5 doesn't require setting unicode format like Allegro 4 + // This is a stub for compatibility + (void)format; // Suppress unused parameter warning +} + +/*------------------------------------------------------------------*/ +void set_color_depth(int depth) { + // In Allegro 5, color depth is set when creating the display + // This is stored for later use in graphics mode setup + (void)depth; // Suppress unused parameter warning +} + +/*------------------------------------------------------------------*/ +void set_color_conversion(int flags) { + // Allegro 5 handles color conversion automatically + // This is a stub for compatibility + (void)flags; // Suppress unused parameter warning +} + +/*------------------------------------------------------------------*/ +int install_keyboard(void) { + // This is called from init.c but keyboard is already initialized in allegro_init + // Return success (0 in Allegro 4 style) + return al_is_keyboard_installed() ? 0 : -1; +} + +/*------------------------------------------------------------------*/ +int install_mouse(void) { + // This is called from init.c but mouse is already initialized in allegro_init + // Return success (not -1 in Allegro 4 style) + return al_is_mouse_installed() ? 1 : -1; +} + +/*------------------------------------------------------------------*/ +int install_sound(int digi_card, int midi_card, const char *cfg_path) { + // Audio is already initialized in allegro_init + // These parameters are for Allegro 4 compatibility + (void)digi_card; + (void)midi_card; + (void)cfg_path; + + return al_is_audio_installed() ? 0 : -1; +} + +/*------------------------------------------------------------------*/ +void set_close_button_callback(void (*callback)(void)) { + // In Allegro 5, this would be handled through event handling + // For now, store the callback for potential future use + (void)callback; // Stub for compatibility +} + +/*------------------------------------------------------------------*/ +void get_palette (PALETTE pal) { + // In Allegro 4, this would get the current hardware palette + // In Allegro 5, we don't have hardware palettes, so we stub this + // Initialize with a default grayscale palette using 8-bit values + int i; + for (i = 0; i < 256; i++) { + pal[i].r = i; // 8-bit grayscale (0-255) + pal[i].g = i; + pal[i].b = i; + } +} + +/*------------------------------------------------------------------*/ +void fade_in (PALETTE pal, int speed) { + // In Allegro 4, this would gradually fade the screen from black to the palette + // In Allegro 5, we simulate this by just setting the palette (no actual fading) + (void)pal; // Palette parameter ignored in Allegro 5 + (void)speed; // Speed parameter ignored + // TODO: Could implement actual screen fading using al_draw_tinted_bitmap +} + +/*------------------------------------------------------------------*/ +void fade_out (int speed) { + // In Allegro 4, this would gradually fade the screen to black + // In Allegro 5, we simulate this (no actual fading for now) + (void)speed; // Speed parameter ignored + // TODO: Could implement actual screen fading using al_draw_tinted_bitmap +} + +/*------------------------------------------------------------------*/ +void hsv_to_rgb (float h, float s, float v, int *r, int *g, int *b) { + // Convert HSV color space to RGB + // Based on standard HSV to RGB conversion algorithm + int i; + float f, p, q, t; + + if (s == 0) { + // Achromatic (grey) + *r = *g = *b = (int)(v * 255); + return; + } + + h /= 60; // sector 0 to 5 + i = (int)h; + f = h - i; // fractional part of h + p = v * (1 - s); + q = v * (1 - s * f); + t = v * (1 - s * (1 - f)); + + switch (i) { + case 0: + *r = (int)(v * 255); + *g = (int)(t * 255); + *b = (int)(p * 255); + break; + case 1: + *r = (int)(q * 255); + *g = (int)(v * 255); + *b = (int)(p * 255); + break; + case 2: + *r = (int)(p * 255); + *g = (int)(v * 255); + *b = (int)(t * 255); + break; + case 3: + *r = (int)(p * 255); + *g = (int)(q * 255); + *b = (int)(v * 255); + break; + case 4: + *r = (int)(t * 255); + *g = (int)(p * 255); + *b = (int)(v * 255); + break; + default: // case 5: + *r = (int)(v * 255); + *g = (int)(p * 255); + *b = (int)(q * 255); + break; + } +} + +/*------------------------------------------------------------------*/ +int fixsqrt (int x) { + // Fixed-point square root (Allegro 4 compatibility) + // Input and output are in 16.16 fixed-point format + // Simple implementation using floating point + if (x <= 0) return 0; + + // Convert from fixed-point to float, take sqrt, convert back + float f = (float)x / 65536.0f; + f = sqrt(f); + return (int)(f * 65536.0f); +} + +/*------------------------------------------------------------------*/ +ALLEGRO_COLOR rgb_to_allegro_color (RGB rgb) { + // Convert RGB structure to ALLEGRO_COLOR + // Both use 8-bit values (0-255) + return al_map_rgb(rgb.r, rgb.g, rgb.b); +} + +/*------------------------------------------------------------------*/ +RGB allegro_color_to_rgb (ALLEGRO_COLOR color) { + // Convert ALLEGRO_COLOR to RGB structure + RGB rgb; + unsigned char r, g, b; + + al_unmap_rgb(color, &r, &g, &b); + // Both use 8-bit values (0-255) + rgb.r = r; + rgb.g = g; + rgb.b = b; + + return rgb; +} + +/*------------------------------------------------------------------*/ +void delete_file(const char *filename) { + // Delete a file - Allegro 4 compatibility function + // Maps directly to standard C remove() function + if (filename) { + remove(filename); + } +} + +/*------------------------------------------------------------------*/ +void ellipse (ALLEGRO_BITMAP * bitmap, int x, int y, int rx, int ry, ALLEGRO_COLOR color) { + // Draw ellipse outline - Allegro 4 compatibility + + ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); + al_set_target_bitmap(bitmap); + al_draw_ellipse(x, y, rx, ry, color, 1.0); + al_set_target_bitmap(old_target); +} + +/*------------------------------------------------------------------*/ +void ellipsefill (ALLEGRO_BITMAP * bitmap, int x, int y, int rx, int ry, ALLEGRO_COLOR color) { + // Draw filled ellipse - Allegro 4 compatibility + + ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); + al_set_target_bitmap(bitmap); + al_draw_filled_ellipse(x, y, rx, ry, color); + al_set_target_bitmap(old_target); +} + +/*------------------------------------------------------------------*/ +void circlefill (ALLEGRO_BITMAP * bitmap, int x, int y, int radius, ALLEGRO_COLOR color) { + // Draw filled circle - Allegro 4 compatibility + + ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); + al_set_target_bitmap(bitmap); + al_draw_filled_circle(x, y, radius, color); + al_set_target_bitmap(old_target); +} + +/*------------------------------------------------------------------*/ +void polygon (ALLEGRO_BITMAP * bitmap, int vertices, const int *points, ALLEGRO_COLOR color) { + // Draw polygon - Allegro 4 compatibility + if (vertices < 3) { + return; + } + + // Convert int array to float array for Allegro 5 + float *float_points = malloc(vertices * 2 * sizeof(float)); + if (!float_points) return; + + for (int i = 0; i < vertices * 2; i++) { + float_points[i] = (float)points[i]; + } + + ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); + al_set_target_bitmap(bitmap); + al_draw_polygon(float_points, vertices, ALLEGRO_LINE_JOIN_NONE, color, 1.0, 0); + al_set_target_bitmap(old_target); + + free(float_points); +} + +/*------------------------------------------------------------------*/ +void fix_filename_case(char *filename) { + // Allegro 4 compatibility function - converts filename to correct case + // On case-sensitive filesystems, this would try to find the correct case + // For now, just leave the filename as-is since most modern systems handle this + (void)filename; // Stub implementation - no changes needed on modern systems +} + +/*------------------------------------------------------------------*/ +void fix_filename_slashes(char *filename) { + // Allegro 4 compatibility function - converts path separators + // Convert all backslashes to forward slashes for cross-platform compatibility + if (filename) { + char *p = filename; + while (*p) { + if (*p == '\\') { + *p = '/'; + } + p++; + } + } +} + +/*------------------------------------------------------------------*/ +int bestfit_color(PALETTE pal, int r, int g, int b) { + // Allegro 4 compatibility function - finds closest matching color in palette + int best_index = 0; + int best_distance = INT_MAX; + int i; + + for (i = 0; i < 256; i++) { + int dr = r - pal[i].r; + int dg = g - pal[i].g; + int db = b - pal[i].b; + int distance = dr*dr + dg*dg + db*db; + + if (distance < best_distance) { + best_distance = distance; + best_index = i; + if (distance == 0) break; // Exact match found + } + } + + return best_index; +} + + +/*------------------------------------------------------------------*/ +int save_bitmap(const char *filename, ALLEGRO_BITMAP *bmp) { + // Allegro 4 compatibility function - saves a bitmap to file + return al_save_bitmap(filename, bmp) ? 0 : -1; // Allegro 4 returns 0 on success +} + +/*------------------------------------------------------------------*/ +ALLEGRO_BITMAP *create_bitmap_ex(int color_depth, int w, int h) { + // Allegro 4 compatibility function - creates a bitmap with specific color depth + // In Allegro 5, we ignore the color depth parameter and create a standard bitmap + (void)color_depth; // Ignore color depth - Allegro 5 handles this automatically + return al_create_bitmap(w, h); +} + +/*------------------------------------------------------------------*/ +ALLEGRO_BITMAP *create_sub_bitmap(ALLEGRO_BITMAP *parent, int x, int y, int w, int h) { + // Allegro 4 compatibility function - creates a sub-bitmap + return al_create_sub_bitmap(parent, x, y, w, h); +} + +/*------------------------------------------------------------------*/ +void scroll_screen(int x, int y) { + // Allegro 4 compatibility function - scrolls the screen + // In Allegro 5, this is mainly used for page flipping effects + // For now, implement as a stub since modern page flipping works differently + (void)x; + (void)y; + // Note: This function was used for hardware scrolling in Allegro 4 + // Modern systems handle this through different mechanisms +} + +/*------------------------------------------------------------------*/ +/* lw_team_color: + * Computes the color for a team at a given intensity. + * Team colors (0-5): + * 0 = red (0,0,0) to (255,0,0) + * 1 = green (0,0,0) to (0,255,0) + * 2 = blue (0,0,0) to (0,0,255) + * 3 = yellow (0,0,0) to (255,255,0) + * 4 = cyan (0,0,0) to (0,255,255) + * 5 = magenta (0,0,0) to (255,0,255) + * Intensity: 0 (black) to 255 (full bright color) + */ +ALLEGRO_COLOR +lw_team_color(int team, int intensity) +{ + int r = 0, g = 0, b = 0; + + // Clamp intensity to 0-255 range + if (intensity < 0) intensity = 0; + if (intensity > 255) intensity = 255; + + // Clamp team to 0-5 range + team = team % 6; + if (team < 0) team = 0; + + switch (team) { + case 0: // Red + r = intensity; + break; + case 1: // Green + g = intensity; + break; + case 2: // Blue + b = intensity; + break; + case 3: // Yellow + r = intensity; + g = intensity; + break; + case 4: // Cyan + g = intensity; + b = intensity; + break; + case 5: // Magenta + r = intensity; + b = intensity; + break; + } + + return al_map_rgb(r, g, b); +} + +/*------------------------------------------------------------------*/ +/* is_color_light: + * Checks if a color is "light" (sum of RGB >= 3*128). + * Used to classify pixels as playable area vs walls in maps. + */ +int +is_color_light(ALLEGRO_COLOR c) +{ + int r = (int)(c.r * 255.0f); + int g = (int)(c.g * 255.0f); + int b = (int)(c.b * 255.0f); + return (r + g + b) >= (3 * 128); +} + +/*------------------------------------------------------------------*/ +/* is_color_dark: + * Checks if a color is "dark" (sum of RGB < 3*128). + * Opposite of is_color_light. + */ +int +is_color_dark(ALLEGRO_COLOR c) +{ + return !is_color_light(c); +} diff --git a/src/backport.h b/src/backport.h new file mode 100644 index 00000000..d4d83b22 --- /dev/null +++ b/src/backport.h @@ -0,0 +1,409 @@ +/********************************************************************/ +/* */ +/* L I QQ U U I DD W W A RR 555 */ +/* L I Q Q U U I D D W W A A R R 5 */ +/* L I Q Q U U I D D W W W AAA RR 55 */ +/* L I Q Q U U I D D WW WW A A R R 5 */ +/* LLL I Q Q U I DD W W A A R R 55 */ +/* */ +/* b */ +/* bb y y */ +/* b b yyy */ +/* bb y */ +/* yy */ +/* */ +/* U U FFF O O TTT */ +/* U U F O O O O T */ +/* U U TIRET FF O O O O T */ +/* U U F O O O O T */ +/* U F O O T */ +/* */ +/********************************************************************/ + +/*****************************************************************************/ +/* Liquid War is a multiplayer wargame */ +/* Copyright (C) 1998-2025 Christian Mauduit */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You 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 */ +/* */ +/* Liquid War homepage : http://www.ufoot.org/liquidwar/v5 */ +/* Contact author : ufoot@ufoot.org */ +/*****************************************************************************/ + +/********************************************************************/ +/* nom : backport.h */ +/* content : missing allegro 4 stuff */ +/* last update : Dec 24th 2018 */ +/********************************************************************/ + +#ifndef LIQUID_WAR_INCLUDE_BACKPORT +#define LIQUID_WAR_INCLUDE_BACKPORT + +/*==================================================================*/ +/* includes */ +/*==================================================================*/ + +#ifndef ALLEGRO_NO_MAIN +#define ALLEGRO_NO_MAIN +#endif + +#include +#include +#include +#include + +/*==================================================================*/ +/* defines */ +/*==================================================================*/ + +#ifndef AL_CONST +#define AL_CONST const +#endif // AL_CONST + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif // MIN +#ifndef MAX +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif // MAX +#ifndef MID +/* Returns the median of x, y, z */ +#define MID(x,y,z) ((x) > (y) ? ((y) > (z) ? (y) : ((x) > (z) ? \ + (z) : (x))) : ((y) > (z) ? ((z) > (x) ? (z) : \ + (x)): (y))) +#endif // MID +#ifndef CLAMP +/* Optimized version of MID for when x <= z. */ +#define CLAMP(x,y,z) MAX((x), MIN((y), (z))) +#endif // CLAMP +#ifndef ABS +#define ABS(x) (((x) >= 0) ? (x) : (-(x))) +#endif // ABS + +#ifndef SGN +#define SGN(x) (((x) >= 0) ? 1 : -1) +#endif // SGN + +#define _AL_MALLOC(size) al_malloc(size) +#define _AL_FREE(ptr) al_free(ptr) + +#define LOCK_DATA(d, s) +#define LOCK_CODE(c, s) +#define UNLOCK_DATA(d, s) +#define LOCK_VARIABLE(x) +#define LOCK_FUNCTION(x) + +// Special color value for "no color" or transparent (was -1 in Allegro 4) +#define NO_COLOR (al_map_rgba(0, 0, 0, 0)) + +// Color selection constants (from old palette.h) +#define CHOOSE_COLOR_NUMBER 128 +#define CHOOSE_COLOR_WHITE 120 +#define CHOOSE_COLOR_BLACK 127 + +// Palette-related variables (from old palette.h/c) +extern int COLORS_PER_TEAM; + +// Team color computation (replaces palette-based color system) +ALLEGRO_COLOR lw_team_color(int team, int intensity); + +// Color classification helpers (sum of RGB >= 3*128 is light, < 3*128 is dark) +int is_color_light(ALLEGRO_COLOR c); +int is_color_dark(ALLEGRO_COLOR c); + +/*==================================================================*/ +/* types */ +/*==================================================================*/ + +#define PALETTE_SIZE 256 + +typedef struct RGB { + unsigned char r, g, b; +} RGB; + +typedef RGB PALETTE[PALETTE_SIZE]; +typedef RGB RGB_PALETTE[PALETTE_SIZE]; // Keep for compatibility + +// Allegro 4 compatibility - BITMAP is now ALLEGRO_BITMAP +typedef ALLEGRO_BITMAP BITMAP; + +#define MAX_JOYSTICKS 8 +#define MAX_JOYSTICK_AXIS 3 +#define MAX_JOYSTICK_STICKS 5 +#define MAX_JOYSTICK_BUTTONS 32 + +#define JOY_TYPE_AUTODETECT 0 +#define JOY_TYPE_2PADS 1 +#define JOY_TYPE_4BUTTON 2 +#define JOY_TYPE_STANDARD 3 + +/* information about a single joystick axis */ +typedef struct JOYSTICK_AXIS_INFO +{ + int pos; + int d1, d2; + const char *name; +} JOYSTICK_AXIS_INFO; + +/* information about one or more axis (a slider or directional control) */ +typedef struct JOYSTICK_STICK_INFO +{ + int flags; + int num_axis; + JOYSTICK_AXIS_INFO axis[MAX_JOYSTICK_AXIS]; + const char *name; +} JOYSTICK_STICK_INFO; + +/* information about a joystick button */ +typedef struct JOYSTICK_BUTTON_INFO +{ + int b; + const char *name; +} JOYSTICK_BUTTON_INFO; + +/* information about an entire joystick */ +typedef struct JOYSTICK_INFO +{ + // int flags; + const char *name; + int num_sticks; + int num_buttons; + JOYSTICK_STICK_INFO stick[MAX_JOYSTICK_STICKS]; + JOYSTICK_BUTTON_INFO button[MAX_JOYSTICK_BUTTONS]; +} JOYSTICK_INFO; + +#define KEY_MAX 127 + +#define KB_NORMAL 0x01 +#define KB_EXTENDED 0x02 + +/*==================================================================*/ +/* variables globales */ +/*==================================================================*/ + +extern ALLEGRO_BITMAP *screen; +extern ALLEGRO_DISPLAY *allegro_display; +extern int SCREEN_W; +extern int SCREEN_H; +extern int VIRTUAL_H; +extern ALLEGRO_FONT *font; +extern volatile int mouse_x; +extern volatile int mouse_y; +extern volatile int mouse_z; +extern volatile int mouse_b; +extern int *allegro_errno; +extern volatile JOYSTICK_INFO joy[MAX_JOYSTICKS]; +extern int num_joysticks; +extern char empty_string[]; +extern volatile char key[]; + +// GUI color variables for Allegro 4 compatibility +extern ALLEGRO_COLOR gui_bg_color; +extern ALLEGRO_COLOR gui_fg_color; +extern ALLEGRO_COLOR gui_mg_color; + +/*==================================================================*/ +/* fonctions globales */ +/*==================================================================*/ + +void scare_mouse (); +void scare_mouse_area (int x, int y, int w, int h); +void unscare_mouse (); +void position_mouse (int x, int y); +void set_mouse_sprite (ALLEGRO_BITMAP *sprite); +void show_mouse (ALLEGRO_BITMAP *bmp); +int poll_mouse (void); +int mouse_needs_poll (void); + +void clear_to_color (ALLEGRO_BITMAP * bitmap, ALLEGRO_COLOR color); +void putpixel (ALLEGRO_BITMAP * bitmap, int x, int y, ALLEGRO_COLOR color); +void putpixel_fast (int x, int y, ALLEGRO_COLOR color); +ALLEGRO_COLOR getpixel (ALLEGRO_BITMAP * bitmap, int x, int y); +void rect (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, + ALLEGRO_COLOR color); +void rectfill (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, + ALLEGRO_COLOR color); +void rectfill_dotted (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, + ALLEGRO_COLOR fg, ALLEGRO_COLOR bg); +void vline (ALLEGRO_BITMAP * bitmap, int x, int y1, int y2, ALLEGRO_COLOR color); +void hline (ALLEGRO_BITMAP * bitmap, int x1, int y, int x2, ALLEGRO_COLOR color); +void line (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2, + ALLEGRO_COLOR color); +void ellipse (ALLEGRO_BITMAP * bitmap, int x, int y, int rx, int ry, ALLEGRO_COLOR color); +void ellipsefill (ALLEGRO_BITMAP * bitmap, int x, int y, int rx, int ry, ALLEGRO_COLOR color); +void circlefill (ALLEGRO_BITMAP * bitmap, int x, int y, int radius, ALLEGRO_COLOR color); +void polygon (ALLEGRO_BITMAP * bitmap, int vertices, const int *points, ALLEGRO_COLOR color); + +int usetc (char *s, int c); +int ugetc (const char *s); +int uwidth (const char *s); +int ustrlen (const char *s); +int ucwidth (int c); +int uisspace (int c); +int ugetat (char *s, int index); +int usetat (char *s, int index, int c, int max_size); +int uinsert (char *s, int index, int c, int max_size); +int uremove (char *s, int index); +int uisok (int c); +int utolower (int c); +char *ustrdup (const char *src); +int ugetx (char **s); +int ugetxc (const char **s); +char *ustrtok_r (char *s, AL_CONST char *set, char **last); +char *uconvert_ascii (const char *s, char buf[], int size); + +int text_length (const ALLEGRO_FONT * f, const char *s); +int text_height (const ALLEGRO_FONT * f); +void textout_ex (ALLEGRO_BITMAP * bmp, const ALLEGRO_FONT * f, const char *s, + int x, int y, ALLEGRO_COLOR color, ALLEGRO_COLOR bg); + +void set_volume (int digi_volume, int midi_volume); +int play_midi (ALLEGRO_SAMPLE *midi, int loop); +int play_sample (ALLEGRO_SAMPLE *spl, int vol, int pan, int freq, int loop); + +void get_palette (PALETTE pal); +void fade_in (PALETTE pal, int speed); +void fade_out (int speed); +void hsv_to_rgb (float h, float s, float v, int *r, int *g, int *b); +int fixsqrt (int x); +int bestfit_color (PALETTE pal, int r, int g, int b); + +ALLEGRO_COLOR rgb_to_allegro_color (RGB rgb); +RGB allegro_color_to_rgb (ALLEGRO_COLOR color); + +void rest_callback (unsigned int time, void (*callback) (void)); +void rest (unsigned int time); +int install_timer (); +void remove_timer (); +int install_int (void (*proc) (), int speed); +void remove_int (void (*proc) ()); +int install_int_ex (void (*proc) (), int speed); + +#define MSEC_TO_TIMER(x) (x) + +void draw_sprite (ALLEGRO_BITMAP * bmp, ALLEGRO_BITMAP * sprite, int x, + int y); +void blit (ALLEGRO_BITMAP * source, ALLEGRO_BITMAP * dest, + int source_x, int source_y, + int dest_x, int dest_y, int dest_width, int dest_height); +void stretch_blit (ALLEGRO_BITMAP * source, ALLEGRO_BITMAP * dest, + int source_x, int source_y, int source_width, + int source_height, int dest_x, int dest_y, int dest_width, + int dest_height); +ALLEGRO_BITMAP *load_bitmap (const char *filename); +int save_bitmap (const char *filename, ALLEGRO_BITMAP *bmp); +ALLEGRO_BITMAP *my_create_bitmap (int w, int h); +ALLEGRO_BITMAP *my_create_memory_bitmap (int w, int h); +ALLEGRO_BITMAP *my_create_video_bitmap (int w, int h); +ALLEGRO_BITMAP *create_bitmap_ex (int color_depth, int w, int h); +ALLEGRO_BITMAP *create_sub_bitmap (ALLEGRO_BITMAP *parent, int x, int y, int w, int h); +void scroll_screen (int x, int y); + +void acquire_bitmap (ALLEGRO_BITMAP * bmp); +void acquire_screen (); +void release_bitmap (ALLEGRO_BITMAP * bmp); +void release_screen (); +void set_clip_rect (ALLEGRO_BITMAP * bitmap, int x1, int y1, int x2, int y2); + +int install_joystick (int type); +int poll_joystick (); + +int keypressed (); +int readkey (); +int ureadkey (int *scancode); +void clear_keybuf (); +void simulate_keypress (int key); +int scancode_to_ascii (int scancode); + +void set_config_file(char *filename); +int get_config_int(const char *section, const char *key, int def); +const char *get_config_string(const char *section, const char *key, const char *def); +void set_config_int(const char *section, const char *key, int value); +void set_config_string(const char *section, const char *key, const char *value); +void flush_config_file(); + +int exists(const char *filename); +void delete_file(const char *filename); +void fix_filename_case(char *filename); +void fix_filename_slashes(char *filename); + +// Graphics mode constants (Allegro 4 compatibility) +#define GFX_AUTODETECT_FULLSCREEN 1 +#define GFX_AUTODETECT_WINDOWED 2 +#define GFX_DIRECTX 3 +#define GFX_DIRECTX_WIN 4 +#define GFX_MODEX 5 +#define GFX_VESA2L 6 + +// Graphics mode functions +int set_gfx_mode(int card, int w, int h, int v_w, int v_h); +void set_palette(void *palette); +void set_window_title(const char *title); + +// Graphics driver info +typedef struct { + char *ascii_name; +} LW_GFX_DRIVER_INFO; + +extern LW_GFX_DRIVER_INFO *gfx_driver; +extern void *black_palette; + +// Allegro 4 compatibility constants +#define U_ASCII 0 +#define SYSTEM_NONE 0 +#define COLORCONV_REDUCE_TO_256 0 + +// Audio constants +#define DIGI_NONE 0 +#define MIDI_NONE 0 +#define DIGI_AUTODETECT -1 +#define MIDI_AUTODETECT -1 + +// Driver info structures (Allegro 4 compatibility) +extern LW_GFX_DRIVER_INFO *timer_driver; +extern LW_GFX_DRIVER_INFO *keyboard_driver; +extern LW_GFX_DRIVER_INFO *mouse_driver; +extern LW_GFX_DRIVER_INFO *digi_driver; +extern LW_GFX_DRIVER_INFO *midi_driver; +extern LW_GFX_DRIVER_INFO *joystick_driver; + +// Allegro initialization functions +int allegro_init(void); +int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)()); +int install_keyboard(void); +void remove_keyboard(void); +int install_mouse(void); +int install_sound(int digi_card, int midi_card, const char *cfg_path); +void set_uformat(int format); +void set_color_depth(int depth); +void set_color_conversion(int flags); +void set_close_button_callback(void (*callback)(void)); + +// Allegro addon functions (stubs if not available) +bool al_init_acodec_addon(void); +bool al_init_image_addon(void); + +// Global variables for compatibility +extern char *allegro_id; + +#endif // LIQUID_WAR_INCLUDE_BACKPORT diff --git a/src/backportgui.c b/src/backportgui.c new file mode 100644 index 00000000..56ef11e3 --- /dev/null +++ b/src/backportgui.c @@ -0,0 +1,2665 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * The core GUI routines. + * + * By Shawn Hargreaves. + * + * Peter Pavlovic modified the drawing and positioning of menus. + * + * Menu auto-opening added by Angelo Mottola. + * + * Eric Botcazou added the support for non-blocking menus. + * + * Elias Pschernig and Sven Sandberg improved the focus algorithm. + * + * See readme.txt for copyright information. + */ + + +#include + +#include + +#include "backport.h" +#include "backportgui.h" +#include "backportguiproc.h" +#include "alleg2.h" + +static int _allegro_count = 1; // number of times allegro has been initialized. + +/* if set, the input focus follows the mouse pointer */ +int gui_mouse_focus = TRUE; + + +/* font alignment value */ +int gui_font_baseline = 0; + + +/* Pointers to the currently active dialog and menu objects. + * + * Note: active_dialog_player always points to the currently active dialog + * player. However, active_menu_player only ever points to menu players + * started by a d_menu_proc. The code also assumes that that d_menu_proc can + * be found in the currently active dialog. + * + * Note: active_dialog points to the whole dialog currently running. However, + * active_menu points to the *current item* of the currently running menu, + * and should really have been called active_menu_item. + */ +static DIALOG_PLAYER *active_dialog_player = NULL; +static MENU_PLAYER *active_menu_player = NULL; +static int active_menu_player_zombie = FALSE; +DIALOG *active_dialog = NULL; +MENU *active_menu = NULL; + + +static ALLEGRO_BITMAP *gui_screen = NULL; + + +/* list of currently active (initialized) dialog players */ +struct al_active_dialog_player +{ + DIALOG_PLAYER *player; + struct al_active_dialog_player *next; +}; + +static struct al_active_dialog_player *first_active_dialog_player = 0; +static struct al_active_dialog_player *current_active_dialog_player = 0; + + +/* forward declarations */ +static int shutdown_single_menu (MENU_PLAYER *, int *); + + + +/* hook function for reading the mouse x position */ +static int +default_mouse_x (void) +{ + if (mouse_needs_poll ()) + poll_mouse (); + + return mouse_x; +} + +/* hook function for reading the mouse y position */ +static int +default_mouse_y (void) +{ + if (mouse_needs_poll ()) + poll_mouse (); + + return mouse_y; +} + +/* hook function for reading the mouse z position */ +static int +default_mouse_z (void) +{ + if (mouse_needs_poll ()) + poll_mouse (); + + return mouse_z; +} + +/* hook function for reading the mouse button state */ +static int +default_mouse_b (void) +{ + if (mouse_needs_poll ()) + poll_mouse (); + + return mouse_b; +} + +/* hook functions for reading the mouse state */ +int (*gui_mouse_x) (void) = default_mouse_x; +int (*gui_mouse_y) (void) = default_mouse_y; +int (*gui_mouse_z) (void) = default_mouse_z; +int (*gui_mouse_b) (void) = default_mouse_b; + + +/* timer to handle menu auto-opening */ +static int gui_timer; + +static int gui_menu_opening_delay; + + +/* Checking for double clicks is complicated. The user could release the + * mouse button at almost any point, and I might miss it if I am doing some + * other processing at the same time (eg. sending the single-click message). + * To get around this I install a timer routine to do the checking for me, + * so it will notice double clicks whenever they happen. + */ + +static volatile int dclick_status, dclick_time; + +static int gui_install_count = 0; +static int gui_install_time = 0; + +#define DCLICK_START 0 +#define DCLICK_RELEASE 1 +#define DCLICK_AGAIN 2 +#define DCLICK_NOT 3 + + + +/* dclick_check: + * Double click checking user timer routine. + */ +static void +dclick_check (void) +{ + gui_timer++; + + if (dclick_status == DCLICK_START) + { /* first click... */ + if (!gui_mouse_b ()) + { + dclick_status = DCLICK_RELEASE; /* aah! released first */ + dclick_time = 0; + return; + } + } + else if (dclick_status == DCLICK_RELEASE) + { /* wait for second click */ + if (gui_mouse_b ()) + { + dclick_status = DCLICK_AGAIN; /* yes! the second click */ + dclick_time = 0; + return; + } + } + else + return; + + /* timeout? */ + if (dclick_time++ > 10) + dclick_status = DCLICK_NOT; +} + +/* position_dialog: + * Moves all the objects in a dialog to the specified position. + */ +void +position_dialog (DIALOG * dialog, int x, int y) +{ + int min_x = INT_MAX; + int min_y = INT_MAX; + int xc, yc; + int c; + ALLEGRO_ASSERT (dialog); + + /* locate the upper-left corner */ + for (c = 0; dialog[c].proc; c++) + { + if (dialog[c].x < min_x) + min_x = dialog[c].x; + + if (dialog[c].y < min_y) + min_y = dialog[c].y; + } + + /* move the dialog */ + xc = min_x - x; + yc = min_y - y; + + for (c = 0; dialog[c].proc; c++) + { + dialog[c].x -= xc; + dialog[c].y -= yc; + } +} + + + +/* centre_dialog: + * Moves all the objects in a dialog so that the dialog is centered in + * the screen. + */ +void +centre_dialog (DIALOG * dialog) +{ + int min_x = INT_MAX; + int min_y = INT_MAX; + int max_x = INT_MIN; + int max_y = INT_MIN; + int xc, yc; + int c; + ALLEGRO_ASSERT (dialog); + + /* find the extents of the dialog (done in many loops due to a bug + * in MSVC that prevents the more sensible version from working) + */ + for (c = 0; dialog[c].proc; c++) + { + if (dialog[c].x < min_x) + min_x = dialog[c].x; + } + + for (c = 0; dialog[c].proc; c++) + { + if (dialog[c].y < min_y) + min_y = dialog[c].y; + } + + for (c = 0; dialog[c].proc; c++) + { + if (dialog[c].x + dialog[c].w > max_x) + max_x = dialog[c].x + dialog[c].w; + } + + for (c = 0; dialog[c].proc; c++) + { + if (dialog[c].y + dialog[c].h > max_y) + max_y = dialog[c].y + dialog[c].h; + } + + /* how much to move by? */ + xc = (SCREEN_W - (max_x - min_x)) / 2 - min_x; + yc = (SCREEN_H - (max_y - min_y)) / 2 - min_y; + + /* move it */ + for (c = 0; dialog[c].proc; c++) + { + dialog[c].x += xc; + dialog[c].y += yc; + } +} + + + +/* set_dialog_color: + * Sets the foreground and background colors of all the objects in a dialog. + */ +void +set_dialog_color (DIALOG * dialog, ALLEGRO_COLOR fg, ALLEGRO_COLOR bg) +{ + int c; + ALLEGRO_ASSERT (dialog); + + for (c = 0; dialog[c].proc; c++) + { + dialog[c].fg = fg; + dialog[c].bg = bg; + } +} + + + +/* find_dialog_focus: + * Searches the dialog for the object which has the input focus, returning + * its index, or -1 if the focus is not set. Useful after do_dialog() exits + * if you need to know which object was selected. + */ +int +find_dialog_focus (DIALOG * dialog) +{ + int c; + ALLEGRO_ASSERT (dialog); + + for (c = 0; dialog[c].proc; c++) + if (dialog[c].flags & D_GOTFOCUS) + return c; + + return -1; +} + + + +/* object_message: + * Sends a message to a widget, automatically scaring and unscaring + * the mouse if the message is MSG_DRAW. + */ +int +object_message (DIALOG * dialog, int msg, int c) +{ +#ifdef ALLEGRO_WINDOWS + /* exported address of d_clear_proc */ + extern int (*_d_clear_proc) (int, DIALOG *, int); +#endif + + int ret; + ALLEGRO_ASSERT (dialog); + + if (msg == MSG_DRAW) + { + if (dialog->flags & D_HIDDEN) + return D_O_K; + +#ifdef ALLEGRO_WINDOWS + if (dialog->proc == _d_clear_proc) +#else + if (dialog->proc == d_clear_proc) +#endif + scare_mouse (); + else + scare_mouse_area (dialog->x, dialog->y, dialog->w, dialog->h); + + acquire_screen (); + } + + ret = dialog->proc (msg, dialog, c); + + if (msg == MSG_DRAW) + { + release_screen (); + unscare_mouse (); + } + + if (ret & D_REDRAWME) + { + dialog->flags |= D_DIRTY; + ret &= ~D_REDRAWME; + } + + return ret; +} + + + +/* dialog_message: + * Sends a message to all the objects in a dialog. If any of the objects + * return values other than D_O_K, returns the value and sets obj to the + * object which produced it. + */ +int +dialog_message (DIALOG * dialog, int msg, int c, int *obj) +{ + int count, res, r, force, try; + DIALOG *menu_dialog = NULL; + ALLEGRO_ASSERT (dialog); + + /* Note: don't acquire the screen in here. A deadlock develops in a + * situation like this: + * + * 1. this thread: acquires the screen; + * 2. timer thread: wakes up, locks the timer_mutex, and calls a + * callback to redraw the software mouse cursor, which tries to + * acquire the screen; + * 3. this thread: object_message(MSG_DRAW) calls scare_mouse() + * which calls remove_int(). + * + * So this thread has the screen acquired and wants the timer_mutex, + * whereas the timer thread holds the timer_mutex, but wants to acquire + * the screen. The problem is calling scare_mouse() with the screen + * acquired. + */ + + force = ((msg == MSG_START) || (msg == MSG_END) || (msg >= MSG_USER)); + + res = D_O_K; + + /* If a menu spawned by a d_menu_proc object is active, the dialog engine + * has effectively been shutdown for the sake of safety. This means that + * we can't send the message to the other objects in the dialog. So try + * first to send the message to the d_menu_proc object and, if the menu + * is then not active anymore, send it to the other objects as well. + */ + if (active_menu_player) + { + try = 2; + menu_dialog = active_menu_player->dialog; + } + else + try = 1; + + for (; try > 0; try--) + { + for (count = 0; dialog[count].proc; count++) + { + if ((try == 2) && (&dialog[count] != menu_dialog)) + continue; + + if ((force) || (!(dialog[count].flags & D_HIDDEN))) + { + r = object_message (&dialog[count], msg, c); + + if (r != D_O_K) + { + res |= r; + if (obj) + *obj = count; + } + + if ((msg == MSG_IDLE) + && (dialog[count].flags & (D_DIRTY | D_HIDDEN)) == D_DIRTY) + { + dialog[count].flags &= ~D_DIRTY; + object_message (dialog + count, MSG_DRAW, 0); + } + } + } + + if (active_menu_player) + break; + } + + return res; +} + + + +/* broadcast_dialog_message: + * Broadcasts a message to all the objects in the active dialog. If any of + * the dialog procedures return values other than D_O_K, it returns that + * value. + */ +int +broadcast_dialog_message (int msg, int c) +{ + int nowhere; + + if (active_dialog) + return dialog_message (active_dialog, msg, c, &nowhere); + else + return D_O_K; +} + + + +/* find_mouse_object: + * Finds which object the mouse is on top of. + */ +static int +find_mouse_object (DIALOG * d) +{ + int mouse_object = -1; + int c; + int res; + ALLEGRO_ASSERT (d); + + for (c = 0; d[c].proc; c++) + { + if ((gui_mouse_x () >= d[c].x) && (gui_mouse_y () >= d[c].y) && + (gui_mouse_x () < d[c].x + d[c].w) + && (gui_mouse_y () < d[c].y + d[c].h) + && (!(d[c].flags & (D_HIDDEN | D_DISABLED)))) + { + /* check if this object wants the mouse */ + res = object_message (d + c, MSG_WANTMOUSE, 0); + if (!(res & D_DONTWANTMOUSE)) + { + mouse_object = c; + } + } + } + + return mouse_object; +} + + + +/* offer_focus: + * Offers the input focus to a particular object. + */ +int +offer_focus (DIALOG * dialog, int obj, int *focus_obj, int force) +{ + int res = D_O_K; + ALLEGRO_ASSERT (dialog); + ALLEGRO_ASSERT (focus_obj); + + if ((obj == *focus_obj) || + ((obj >= 0) && (dialog[obj].flags & (D_HIDDEN | D_DISABLED)))) + return D_O_K; + + /* check if object wants the focus */ + if (obj >= 0) + { + res = object_message (dialog + obj, MSG_WANTFOCUS, 0); + if (res & D_WANTFOCUS) + res ^= D_WANTFOCUS; + else + obj = -1; + } + + if ((obj >= 0) || (force)) + { + /* take focus away from old object */ + if (*focus_obj >= 0) + { + res |= object_message (dialog + *focus_obj, MSG_LOSTFOCUS, 0); + if (res & D_WANTFOCUS) + { + if (obj < 0) + return D_O_K; + else + res &= ~D_WANTFOCUS; + } + dialog[*focus_obj].flags &= ~D_GOTFOCUS; + res |= object_message (dialog + *focus_obj, MSG_DRAW, 0); + } + + *focus_obj = obj; + + /* give focus to new object */ + if (obj >= 0) + { + dialog[obj].flags |= D_GOTFOCUS; + res |= object_message (dialog + obj, MSG_GOTFOCUS, 0); + res |= object_message (dialog + obj, MSG_DRAW, 0); + } + } + + return res; +} + + + +#define MAX_OBJECTS 512 + +typedef struct OBJ_LIST +{ + int index; + int diff; +} OBJ_LIST; + + +/* Weight ratio between the orthogonal direction and the main direction + when calculating the distance for the focus algorithm. */ +#define DISTANCE_RATIO 8 + +/* Maximum size (in bytes) of a dialog array. */ +#define MAX_SIZE 0x10000 /* 64 kb */ + +enum axis +{ X_AXIS, Y_AXIS }; + + + +/* obj_list_cmp: + * Callback function for qsort(). + */ +static int +obj_list_cmp (AL_CONST void *e1, AL_CONST void *e2) +{ + return (((OBJ_LIST *) e1)->diff - ((OBJ_LIST *) e2)->diff); +} + + + +/* cmp_tab: + * Comparison function for tab key movement. + */ +static int +cmp_tab (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int ret = (int) ((AL_CONST unsigned long) d2 - (AL_CONST unsigned long) d1); + + /* Wrap around if d2 is before d1 in the dialog array. */ + if (ret < 0) + ret += MAX_SIZE; + + return ret; +} + + + +/* cmp_shift_tab: + * Comparison function for shift+tab key movement. + */ +static int +cmp_shift_tab (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int ret = (int) ((AL_CONST unsigned long) d1 - (AL_CONST unsigned long) d2); + + /* Wrap around if d2 is after d1 in the dialog array. */ + if (ret < 0) + ret += MAX_SIZE; + + return ret; +} + + + +/* min_dist: + * Returns the minimum distance between dialogs 'd1' and 'd2'. 'main_axis' + * is taken account to give different weights to the axes in the distance + * formula, as well as to shift the actual position of 'd2' along the axis + * by the amount specified by 'bias'. + */ +static int +min_dist (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2, enum axis main_axis, + int bias) +{ + int x_left = d1->x - d2->x - d2->w + 1; + int x_right = d2->x - d1->x - d1->w + 1; + int y_top = d1->y - d2->y - d2->h + 1; + int y_bottom = d2->y - d1->y - d1->h + 1; + + if (main_axis == X_AXIS) + { + x_left -= bias; + x_right += bias; + y_top *= DISTANCE_RATIO; + y_bottom *= DISTANCE_RATIO; + } + else + { + x_left *= DISTANCE_RATIO; + x_right *= DISTANCE_RATIO; + y_top -= bias; + y_bottom += bias; + } + + if (x_left > 0) + { /* d2 is left of d1 */ + if (y_top > 0) /* d2 is above d1 */ + return x_left + y_top; + else if (y_bottom > 0) /* d2 is below d1 */ + return x_left + y_bottom; + else /* vertically overlapping */ + return x_left; + } + else if (x_right > 0) + { /* d2 is right of d1 */ + if (y_top > 0) /* d2 is above d1 */ + return x_right + y_top; + else if (y_bottom > 0) /* d2 is below d1 */ + return x_right + y_bottom; + else /* vertically overlapping */ + return x_right; + } + /* horizontally overlapping */ + else if (y_top > 0) /* d2 is above d1 */ + return y_top; + else if (y_bottom > 0) /* d2 is below d1 */ + return y_bottom; + else /* overlapping */ + return 0; +} + + + +/* cmp_right: + * Comparison function for right arrow key movement. + */ +static int +cmp_right (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int bias; + + /* Wrap around if d2 is not fully contained in the half-plan + delimited by d1's right edge and not containing it. */ + if (d2->x < d1->x + d1->w) + bias = +SCREEN_W; + else + bias = 0; + + return min_dist (d1, d2, X_AXIS, bias); +} + + + +/* cmp_left: + * Comparison function for left arrow key movement. + */ +static int +cmp_left (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int bias; + + /* Wrap around if d2 is not fully contained in the half-plan + delimited by d1's left edge and not containing it. */ + if (d2->x + d2->w > d1->x) + bias = -SCREEN_W; + else + bias = 0; + + return min_dist (d1, d2, X_AXIS, bias); +} + + + +/* cmp_down: + * Comparison function for down arrow key movement. + */ +static int +cmp_down (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int bias; + + /* Wrap around if d2 is not fully contained in the half-plan + delimited by d1's bottom edge and not containing it. */ + if (d2->y < d1->y + d1->h) + bias = +SCREEN_H; + else + bias = 0; + + return min_dist (d1, d2, Y_AXIS, bias); +} + + + +/* cmp_up: + * Comparison function for up arrow key movement. + */ +static int +cmp_up (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2) +{ + int bias; + + /* Wrap around if d2 is not fully contained in the half-plan + delimited by d1's top edge and not containing it. */ + if (d2->y + d2->h > d1->y) + bias = -SCREEN_H; + else + bias = 0; + + return min_dist (d1, d2, Y_AXIS, bias); +} + + + +/* move_focus: + * Handles arrow key and tab movement through a dialog, deciding which + * object should be given the input focus. + */ +static int +move_focus (DIALOG * d, int ascii, int scan, int *focus_obj) +{ + int (*cmp) (AL_CONST DIALOG * d1, AL_CONST DIALOG * d2); + OBJ_LIST obj[MAX_OBJECTS]; + int obj_count = 0; + int fobj, c; + int res = D_O_K; + + /* choose a comparison function */ + switch (scan) + { + case ALLEGRO_KEY_TAB: + cmp = (ascii == '\t') ? cmp_tab : cmp_shift_tab; + break; + case ALLEGRO_KEY_RIGHT: + cmp = cmp_right; + break; + case ALLEGRO_KEY_LEFT: + cmp = cmp_left; + break; + case ALLEGRO_KEY_DOWN: + cmp = cmp_down; + break; + case ALLEGRO_KEY_UP: + cmp = cmp_up; + break; + default: + return D_O_K; + } + + /* fill temporary table */ + for (c = 0; d[c].proc; c++) + { + if (((*focus_obj < 0) || (c != *focus_obj)) + && !(d[c].flags & (D_DISABLED | D_HIDDEN))) + { + obj[obj_count].index = c; + if (*focus_obj >= 0) + obj[obj_count].diff = cmp (d + *focus_obj, d + c); + else + obj[obj_count].diff = c; + obj_count++; + if (obj_count >= MAX_OBJECTS) + break; + } + } + + /* sort table */ + qsort (obj, obj_count, sizeof (OBJ_LIST), obj_list_cmp); + + /* find an object to give the focus to */ + fobj = *focus_obj; + for (c = 0; c < obj_count; c++) + { + res |= offer_focus (d, obj[c].index, focus_obj, FALSE); + if (fobj != *focus_obj) + break; + } + + return res; +} + + + +#define MESSAGE(i, msg, c) { \ + r = object_message(player->dialog+i, msg, c); \ + if (r != D_O_K) { \ + player->res |= r; \ + player->obj = i; \ + } \ +} + + + +/* do_dialog: + * The basic dialog manager. The list of dialog objects should be + * terminated by one with a null dialog procedure. Returns the index of + * the object which caused it to exit. + */ +int +do_dialog (DIALOG * dialog, int focus_obj) +{ + void *player; + ALLEGRO_ASSERT (dialog); + + player = init_dialog (dialog, focus_obj); + + while (update_dialog (player)) + { + /* If a menu is active, we yield here, since the dialog + * engine is shut down so no user code can be running. + */ + if (active_menu_player) + rest (1); + } + + return shutdown_dialog (player); +} + + + +/* popup_dialog: + * Like do_dialog(), but it stores the data on the screen before drawing + * the dialog and restores it when the dialog is closed. The screen area + * to be stored is calculated from the dimensions of the first object in + * the dialog, so all the other objects should lie within this one. + */ +int +popup_dialog (DIALOG * dialog, int focus_obj) +{ + ALLEGRO_BITMAP *bmp; + ALLEGRO_BITMAP *gui_bmp; + int ret; + ALLEGRO_ASSERT (dialog); + + bmp = my_create_memory_bitmap (dialog->w, dialog->h); + gui_bmp = gui_get_screen (); + if (bmp) + { + scare_mouse_area (dialog->x, dialog->y, dialog->w, dialog->h); + blit (gui_bmp, bmp, dialog->x, dialog->y, 0, 0, dialog->w, dialog->h); + unscare_mouse (); + } + else + *allegro_errno = ENOMEM; + + ret = do_dialog (dialog, focus_obj); + + if (bmp) + { + scare_mouse_area (dialog->x, dialog->y, dialog->w, dialog->h); + blit (bmp, gui_bmp, 0, 0, dialog->x, dialog->y, dialog->w, dialog->h); + unscare_mouse (); + al_destroy_bitmap (bmp); + } + + return ret; +} + + + +/* init_dialog: + * Sets up a dialog, returning a player object that can be used with + * the update_dialog() and shutdown_dialog() functions. + */ +DIALOG_PLAYER * +init_dialog (DIALOG * dialog, int focus_obj) +{ + DIALOG_PLAYER *player; + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + struct al_active_dialog_player *n; + int c; + ALLEGRO_ASSERT (dialog); + + /* close any menu opened by a d_menu_proc */ + if (active_menu_player) + object_message (active_menu_player->dialog, MSG_LOSTMOUSE, 0); + + player = _AL_MALLOC (sizeof (DIALOG_PLAYER)); + if (!player) + { + *allegro_errno = ENOMEM; + return NULL; + } + + /* append player to the list */ + n = _AL_MALLOC (sizeof (struct al_active_dialog_player)); + if (!n) + { + *allegro_errno = ENOMEM; + _AL_FREE (player); + return NULL; + } + + n->next = NULL; + n->player = player; + + if (!current_active_dialog_player) + { + current_active_dialog_player = first_active_dialog_player = n; + } + else + { + current_active_dialog_player->next = n; + current_active_dialog_player = n; + } + + player->res = D_REDRAW; + player->joy_on = TRUE; + player->click_wait = FALSE; + player->dialog = dialog; + player->obj = -1; + player->mouse_obj = -1; + player->mouse_oz = gui_mouse_z (); + player->mouse_b = gui_mouse_b (); + + /* set up the global dialog pointer */ + active_dialog_player = player; + active_dialog = dialog; + + /* set up dclick checking code */ + if (gui_install_count <= 0) + { + LOCK_VARIABLE (gui_timer); + LOCK_VARIABLE (dclick_status); + LOCK_VARIABLE (dclick_time); + LOCK_VARIABLE (gui_mouse_x); + LOCK_VARIABLE (gui_mouse_y); + LOCK_VARIABLE (gui_mouse_z); + LOCK_VARIABLE (gui_mouse_b); + LOCK_FUNCTION (default_mouse_x); + LOCK_FUNCTION (default_mouse_y); + LOCK_FUNCTION (default_mouse_z); + LOCK_FUNCTION (default_mouse_b); + LOCK_FUNCTION (dclick_check); + + install_int (dclick_check, 20); + + /* gets menu auto-opening delay (in milliseconds) from config file */ + gui_menu_opening_delay = 300; + if (gui_menu_opening_delay >= 0) + { + /* adjust for actual timer speed */ + gui_menu_opening_delay /= 20; + } + else + { + /* no auto opening */ + gui_menu_opening_delay = -1; + } + + gui_install_count = 1; + gui_install_time = _allegro_count; + } + else + gui_install_count++; + + /* initialise the dialog */ + set_clip_rect (gui_bmp, 0, 0, SCREEN_W - 1, SCREEN_H - 1); + player->res |= dialog_message (dialog, MSG_START, 0, &player->obj); + + player->mouse_obj = find_mouse_object (dialog); + if (player->mouse_obj >= 0) + dialog[player->mouse_obj].flags |= D_GOTMOUSE; + + for (c = 0; dialog[c].proc; c++) + dialog[c].flags &= ~D_GOTFOCUS; + + if (focus_obj >= 0) + c = focus_obj; + else + c = player->mouse_obj; + + if ((c >= 0) + && ((object_message (dialog + c, MSG_WANTFOCUS, 0)) & D_WANTFOCUS)) + { + dialog[c].flags |= D_GOTFOCUS; + player->focus_obj = c; + } + else + player->focus_obj = -1; + + return player; +} + + + +/* gui_set_screen: + * Changes the target bitmap for GUI drawing operations + */ +void +gui_set_screen (ALLEGRO_BITMAP * bmp) +{ + gui_screen = bmp; +} + + + +/* gui_get_screen: + * Returns the gui_screen, or the default surface if gui_screen is NULL + */ +ALLEGRO_BITMAP * +gui_get_screen (void) +{ + return gui_screen ? gui_screen : screen; +} + + + +/* check_for_redraw: + * Checks whether any parts of the current dialog need to be redraw. + */ +static void +check_for_redraw (DIALOG_PLAYER * player) +{ + struct al_active_dialog_player *iter; + int c, r; + ALLEGRO_ASSERT (player); + + /* need to redraw all active dialogs? */ + if (player->res & D_REDRAW_ALL) + { + for (iter = first_active_dialog_player; + iter != current_active_dialog_player; iter = iter->next) + dialog_message (iter->player->dialog, MSG_DRAW, 0, NULL); + + player->res &= ~D_REDRAW_ALL; + player->res |= D_REDRAW; + } + + /* need to draw it? */ + if (player->res & D_REDRAW) + { + player->res ^= D_REDRAW; + player->res |= + dialog_message (player->dialog, MSG_DRAW, 0, &player->obj); + } + + /* check if any widget has to be redrawn */ + for (c = 0; player->dialog[c].proc; c++) + { + if ((player->dialog[c].flags & (D_DIRTY | D_HIDDEN)) == D_DIRTY) + { + player->dialog[c].flags &= ~D_DIRTY; + MESSAGE (c, MSG_DRAW, 0); + } + } +} + + + +/* update_dialog: + * Updates the status of a dialog object returned by init_dialog(), + * returning TRUE if it is still active or FALSE if it has finished. + */ +int +update_dialog (DIALOG_PLAYER * player) +{ + int c, cascii, cscan, ccombo, r, ret, nowhere, z; + int new_mouse_b; + ALLEGRO_ASSERT (player); + + /* redirect to update_menu() whenever a menu is activated */ + if (active_menu_player) + { + if (!active_menu_player_zombie) + { + if (update_menu (active_menu_player)) + return TRUE; + } + + /* make sure all buttons are released before folding the menu */ + if (gui_mouse_b ()) + { + active_menu_player_zombie = TRUE; + return TRUE; + } + else + { + active_menu_player_zombie = FALSE; + + for (c = 0; player->dialog[c].proc; c++) + if (&player->dialog[c] == active_menu_player->dialog) + break; + ALLEGRO_ASSERT (player->dialog[c].proc); + + MESSAGE (c, MSG_LOSTMOUSE, 0); + goto getout; + } + } + + if (player->res & D_CLOSE) + return FALSE; + + /* deal with mouse buttons presses and releases */ + new_mouse_b = gui_mouse_b (); + if (new_mouse_b != player->mouse_b) + { + player->res |= + offer_focus (player->dialog, player->mouse_obj, &player->focus_obj, + FALSE); + + if (player->mouse_obj >= 0) + { + /* send press and release messages */ + if ((new_mouse_b & 1) && !(player->mouse_b & 1)) + MESSAGE (player->mouse_obj, MSG_LPRESS, new_mouse_b); + if (!(new_mouse_b & 1) && (player->mouse_b & 1)) + MESSAGE (player->mouse_obj, MSG_LRELEASE, new_mouse_b); + + if ((new_mouse_b & 4) && !(player->mouse_b & 4)) + MESSAGE (player->mouse_obj, MSG_MPRESS, new_mouse_b); + if (!(new_mouse_b & 4) && (player->mouse_b & 4)) + MESSAGE (player->mouse_obj, MSG_MRELEASE, new_mouse_b); + + if ((new_mouse_b & 2) && !(player->mouse_b & 2)) + MESSAGE (player->mouse_obj, MSG_RPRESS, new_mouse_b); + if (!(new_mouse_b & 2) && (player->mouse_b & 2)) + MESSAGE (player->mouse_obj, MSG_RRELEASE, new_mouse_b); + + player->mouse_b = new_mouse_b; + } + else + player->res |= dialog_message (player->dialog, MSG_IDLE, 0, &nowhere); + } + + /* need to reinstall the dclick and switch handlers? */ + if (gui_install_time != _allegro_count) + { + install_int (dclick_check, 20); + + gui_install_time = _allegro_count; + } + + /* are we dealing with a mouse click? */ + if (player->click_wait) + { + if ((ABS (player->mouse_ox - gui_mouse_x ()) > 8) || + (ABS (player->mouse_oy - gui_mouse_y ()) > 8)) + dclick_status = DCLICK_NOT; + + /* waiting... */ + if ((dclick_status != DCLICK_AGAIN) && (dclick_status != DCLICK_NOT)) + { + player->res |= + dialog_message (player->dialog, MSG_IDLE, 0, &nowhere); + check_for_redraw (player); + return TRUE; + } + + player->click_wait = FALSE; + + /* double click! */ + if ((dclick_status == DCLICK_AGAIN) && + (gui_mouse_x () >= player->dialog[player->mouse_obj].x) && + (gui_mouse_y () >= player->dialog[player->mouse_obj].y) && + (gui_mouse_x () <= + player->dialog[player->mouse_obj].x + + player->dialog[player->mouse_obj].w) + && (gui_mouse_y () <= + player->dialog[player->mouse_obj].y + + player->dialog[player->mouse_obj].h)) + { + MESSAGE (player->mouse_obj, MSG_DCLICK, 0); + } + + goto getout; + } + + player->res &= ~D_USED_CHAR; + + /* need to give the input focus to someone? */ + if (player->res & D_WANTFOCUS) + { + player->res ^= D_WANTFOCUS; + player->res |= + offer_focus (player->dialog, player->obj, &player->focus_obj, FALSE); + } + + /* has mouse object changed? */ + c = find_mouse_object (player->dialog); + if (c != player->mouse_obj) + { + if (player->mouse_obj >= 0) + { + player->dialog[player->mouse_obj].flags &= ~D_GOTMOUSE; + MESSAGE (player->mouse_obj, MSG_LOSTMOUSE, 0); + } + if (c >= 0) + { + player->dialog[c].flags |= D_GOTMOUSE; + MESSAGE (c, MSG_GOTMOUSE, 0); + } + player->mouse_obj = c; + + /* move the input focus as well? */ + if ((gui_mouse_focus) && (player->mouse_obj != player->focus_obj)) + player->res |= + offer_focus (player->dialog, player->mouse_obj, &player->focus_obj, + TRUE); + } + + /* deal with mouse button clicks */ + if (new_mouse_b) + { + player->res |= + offer_focus (player->dialog, player->mouse_obj, &player->focus_obj, + FALSE); + + if (player->mouse_obj >= 0) + { + dclick_time = 0; + dclick_status = DCLICK_START; + player->mouse_ox = gui_mouse_x (); + player->mouse_oy = gui_mouse_y (); + + /* send click message */ + MESSAGE (player->mouse_obj, MSG_CLICK, new_mouse_b); + + if (player->res == D_O_K) + player->click_wait = TRUE; + } + else + player->res |= dialog_message (player->dialog, MSG_IDLE, 0, &nowhere); + + /* goto getout; *//* to avoid an updating delay */ + } + + /* deal with mouse wheel clicks */ + z = gui_mouse_z (); + + if (z != player->mouse_oz) + { + player->res |= + offer_focus (player->dialog, player->mouse_obj, &player->focus_obj, + FALSE); + + if (player->mouse_obj >= 0) + { + MESSAGE (player->mouse_obj, MSG_WHEEL, z - player->mouse_oz); + } + else + player->res |= dialog_message (player->dialog, MSG_IDLE, 0, &nowhere); + + player->mouse_oz = z; + + /* goto getout; *//* to avoid an updating delay */ + } + + /* fake joystick input by converting it to key presses */ + if (player->joy_on) + rest (20); + + poll_joystick (); + + if (player->joy_on) + { + if ((!joy[0].stick[0].axis[0].d1) && (!joy[0].stick[0].axis[0].d2) && + (!joy[0].stick[0].axis[1].d1) && (!joy[0].stick[0].axis[1].d2) && + (!joy[0].button[0].b) && (!joy[0].button[1].b)) + { + player->joy_on = FALSE; + rest (20); + } + cascii = cscan = 0; + } + else + { + if (joy[0].stick[0].axis[0].d1) + { + cascii = 0; + cscan = ALLEGRO_KEY_LEFT; + player->joy_on = TRUE; + } + else if (joy[0].stick[0].axis[0].d2) + { + cascii = 0; + cscan = ALLEGRO_KEY_RIGHT; + player->joy_on = TRUE; + } + else if (joy[0].stick[0].axis[1].d1) + { + cascii = 0; + cscan = ALLEGRO_KEY_UP; + player->joy_on = TRUE; + } + else if (joy[0].stick[0].axis[1].d2) + { + cascii = 0; + cscan = ALLEGRO_KEY_DOWN; + player->joy_on = TRUE; + } + else if ((joy[0].button[0].b) || (joy[0].button[1].b)) + { + cascii = ' '; + cscan = ALLEGRO_KEY_SPACE; + player->joy_on = TRUE; + } + else + cascii = cscan = 0; + } + + /* deal with keyboard input */ + if ((cascii) || (cscan) || (keypressed ())) + { + if ((!cascii) && (!cscan)) + cascii = ureadkey (&cscan); + + ccombo = (cscan << 8) | ((cascii <= 255) ? cascii : '^'); + + /* let object deal with the key */ + if (player->focus_obj >= 0) + { + MESSAGE (player->focus_obj, MSG_CHAR, ccombo); + if (player->res & (D_USED_CHAR | D_CLOSE)) + goto getout; + + MESSAGE (player->focus_obj, MSG_UCHAR, cascii); + if (player->res & (D_USED_CHAR | D_CLOSE)) + goto getout; + } + + /* keyboard shortcut? */ + for (c = 0; player->dialog[c].proc; c++) + { + if ((((cascii > 0) && (cascii <= 255) && + (utolower (player->dialog[c].key) == utolower ((cascii)))) || + ((!cascii) && (player->dialog[c].key == (cscan << 8)))) && + (!(player->dialog[c].flags & (D_HIDDEN | D_DISABLED)))) + { + MESSAGE (c, MSG_KEY, ccombo); + goto getout; + } + } + + /* broadcast in case any other objects want it */ + for (c = 0; player->dialog[c].proc; c++) + { + if (!(player->dialog[c].flags & (D_HIDDEN | D_DISABLED))) + { + MESSAGE (c, MSG_XCHAR, ccombo); + if (player->res & D_USED_CHAR) + goto getout; + } + } + + /* pass or to selected object */ + if (((cascii == '\r') || (cascii == '\n') || (cascii == ' ')) && + (player->focus_obj >= 0)) + { + MESSAGE (player->focus_obj, MSG_KEY, ccombo); + goto getout; + } + + /* ESC closes dialog */ + if (cascii == 27) + { + player->res |= D_CLOSE; + player->obj = -1; + goto getout; + } + + /* move focus around the dialog */ + player->res |= + move_focus (player->dialog, cascii, cscan, &player->focus_obj); + } + + /* redraw? */ + check_for_redraw (player); + + /* send idle messages */ + player->res |= dialog_message (player->dialog, MSG_IDLE, 0, &player->obj); + +getout: + + ret = (!(player->res & D_CLOSE)); + player->res &= ~D_CLOSE; + return ret; +} + + + +/* shutdown_dialog: + * Destroys a dialog object returned by init_dialog(), returning the index + * of the object that caused it to exit. + */ +int +shutdown_dialog (DIALOG_PLAYER * player) +{ + struct al_active_dialog_player *iter, *prev; + int obj; + ALLEGRO_ASSERT (player); + + /* send the finish messages */ + dialog_message (player->dialog, MSG_END, 0, &player->obj); + + /* remove the double click handler */ + gui_install_count--; + + if (gui_install_count <= 0) + { + remove_int (dclick_check); + } + + if (player->mouse_obj >= 0) + player->dialog[player->mouse_obj].flags &= ~D_GOTMOUSE; + + /* remove dialog player from the list of active players */ + for (iter = first_active_dialog_player, prev = 0; iter != 0; + prev = iter, iter = iter->next) + { + if (iter->player == player) + { + if (prev) + prev->next = iter->next; + else + first_active_dialog_player = iter->next; + + if (iter == current_active_dialog_player) + current_active_dialog_player = prev; + + _AL_FREE (iter); + break; + } + } + + if (current_active_dialog_player) + active_dialog_player = current_active_dialog_player->player; + else + active_dialog_player = NULL; + + if (active_dialog_player) + active_dialog = active_dialog_player->dialog; + else + active_dialog = NULL; + + obj = player->obj; + + _AL_FREE (player); + + return obj; +} + + + +void (*gui_menu_draw_menu) (int x, int y, int w, int h) = NULL; +void (*gui_menu_draw_menu_item) (MENU * m, int x, int y, int w, int h, + int bar, int sel) = NULL; + +/* split_around_tab: + * Helper function for splitting a string into two tokens + * delimited by the first TAB character. + */ +static char * +split_around_tab (const char *s, char **tok1, char **tok2) +{ + char *buf, *last; + char tmp[16]; + + buf = ustrdup (s); + *tok1 = ustrtok_r (buf, uconvert_ascii ("\t", tmp, sizeof (tmp)), &last); + *tok2 = ustrtok_r (NULL, empty_string, &last); + + return buf; +} + + + +/* bar_entry_lengh: + * Helper function for calculating the length of a menu bar entry. + */ +static int +bar_entry_length (const char *text) +{ + char *buf, *tok1, *tok2; + int len; + + buf = split_around_tab (text, &tok1, &tok2); + len = gui_strlen (tok1) + 16; + if (tok2) + len += gui_strlen (tok2) + 16; + _AL_FREE (buf); + + return len; +} + + + +/* get_menu_pos: + * Calculates the coordinates of an object within a top level menu bar. + */ +static void +get_menu_pos (MENU_PLAYER * m, int c, int *x, int *y, int *w) +{ + int c2; + + if (m->bar) + { + *x = m->x + 1; + + for (c2 = 0; c2 < c; c2++) + *x += bar_entry_length (m->menu[c2].text); + + *y = m->y + 1; + *w = bar_entry_length (m->menu[c].text); + } + else + { + *x = m->x + 1; + *y = m->y + c * (text_height (font) + 4) + 1; + *w = m->w - 3; + } +} + + + +/* draw_menu_item: + * Draws an item from a popup menu onto the screen. + */ +static void +draw_menu_item (MENU_PLAYER * m, int c) +{ + ALLEGRO_COLOR fg, bg; + int x, y, w; + char *buf, *tok1, *tok2; + int my; + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + + get_menu_pos (m, c, &x, &y, &w); + + if (gui_menu_draw_menu_item) + { + gui_menu_draw_menu_item (&m->menu[c], x, y, w, text_height (font) + 4, + m->bar, (c == m->sel) ? TRUE : FALSE); + return; + } + + if (m->menu[c].flags & D_DISABLED) + { + if (c == m->sel) + { + fg = gui_mg_color; + bg = gui_fg_color; + } + else + { + fg = gui_mg_color; + bg = gui_bg_color; + } + } + else + { + if (c == m->sel) + { + fg = gui_bg_color; + bg = gui_fg_color; + } + else + { + fg = gui_fg_color; + bg = gui_bg_color; + } + } + + rectfill (gui_bmp, x, y, x + w - 1, y + text_height (font) + 3, bg); + + if (ugetc (m->menu[c].text)) + { + buf = split_around_tab (m->menu[c].text, &tok1, &tok2); + gui_textout_ex (gui_bmp, tok1, x + 8, y + 1, fg, bg, FALSE); + if (tok2) + gui_textout_ex (gui_bmp, tok2, x + w - gui_strlen (tok2) - 10, y + 1, + fg, bg, FALSE); + + if ((m->menu[c].child) && (!m->bar)) + { + my = y + text_height (font) / 2; + hline (gui_bmp, x + w - 8, my + 1, x + w - 4, fg); + hline (gui_bmp, x + w - 8, my + 0, x + w - 5, fg); + hline (gui_bmp, x + w - 8, my - 1, x + w - 6, fg); + hline (gui_bmp, x + w - 8, my - 2, x + w - 7, fg); + putpixel (gui_bmp, x + w - 8, my - 3, fg); + hline (gui_bmp, x + w - 8, my + 2, x + w - 5, fg); + hline (gui_bmp, x + w - 8, my + 3, x + w - 6, fg); + hline (gui_bmp, x + w - 8, my + 4, x + w - 7, fg); + putpixel (gui_bmp, x + w - 8, my + 5, fg); + } + + _AL_FREE (buf); + } + else + hline (gui_bmp, x, y + text_height (font) / 2 + 2, x + w, fg); + + if (m->menu[c].flags & D_SELECTED) + { + line (gui_bmp, x + 1, y + text_height (font) / 2 + 1, x + 3, + y + text_height (font) + 1, fg); + line (gui_bmp, x + 3, y + text_height (font) + 1, x + 6, y + 2, fg); + } +} + + + +/* draw_menu: + * Draws a popup menu onto the screen. + */ +static void +draw_menu (MENU_PLAYER * m) +{ + int c; + + if (gui_menu_draw_menu) + gui_menu_draw_menu (m->x, m->y, m->w, m->h); + else + { + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + rectfill (gui_bmp, m->x, m->y, m->x + m->w - 2, m->y + m->h - 2, + gui_bg_color); + rect (gui_bmp, m->x, m->y, m->x + m->w - 2, m->y + m->h - 2, + gui_fg_color); + vline (gui_bmp, m->x + m->w - 1, m->y + 1, m->y + m->h - 1, + gui_fg_color); + hline (gui_bmp, m->x + 1, m->y + m->h - 1, m->x + m->w - 1, + gui_fg_color); + } + + for (c = 0; m->menu[c].text; c++) + draw_menu_item (m, c); +} + + + +/* menu_mouse_object: + * Returns the index of the object the mouse is currently on top of. + */ +static int +menu_mouse_object (MENU_PLAYER * m) +{ + int c; + int x, y, w; + + for (c = 0; c < m->size; c++) + { + get_menu_pos (m, c, &x, &y, &w); + + if ((gui_mouse_x () >= x) && (gui_mouse_x () < x + w) && + (gui_mouse_y () >= y) + && (gui_mouse_y () < y + (text_height (font) + 4))) + return (ugetc (m->menu[c].text)) ? c : -1; + } + + return -1; +} + + + +/* mouse_in_single_menu: + * Checks if the mouse is inside a single menu. + */ +static INLINE int +mouse_in_single_menu (MENU_PLAYER * m) +{ + if ((gui_mouse_x () >= m->x) && (gui_mouse_x () < m->x + m->w) && + (gui_mouse_y () >= m->y) && (gui_mouse_y () < m->y + m->h)) + return TRUE; + else + return FALSE; +} + + + +/* mouse_in_parent_menu: + * Recursively checks if the mouse is inside a menu (or any of its parents) + * and simultaneously not on the selected item of the menu. + */ +static int +mouse_in_parent_menu (MENU_PLAYER * m) +{ + int c; + + if (!m) + return FALSE; + + c = menu_mouse_object (m); + if ((c >= 0) && (c != m->sel)) + return TRUE; + + return mouse_in_parent_menu (m->parent); +} + + + +/* layout_menu: + * Calculates the layout of the menu. + */ +static void +layout_menu (MENU_PLAYER * m, MENU * menu, int bar, int x, int y, int minw, + int minh) +{ + char *buf, *tok1, *tok2; + int extra = 0; + int c; + int child = FALSE; + + m->menu = menu; + m->bar = bar; + m->x = x; + m->y = y; + m->w = 3; + m->h = (m->bar) ? (text_height (font) + 7) : 3; + m->proc = NULL; + m->sel = -1; + + /* calculate size of the menu */ + for (m->size = 0; m->menu[m->size].text; m->size++) + { + + if (m->bar) + { + m->w += bar_entry_length (m->menu[m->size].text); + } + else + { + if (m->menu[m->size].child) + child = TRUE; + + if (ugetc (m->menu[m->size].text)) + { + buf = split_around_tab (m->menu[m->size].text, &tok1, &tok2); + c = gui_strlen (tok1); + } + else + { + buf = NULL; + c = 0; + } + + m->h += text_height (font) + 4; + m->w = MAX (m->w, c + 16); + + if (buf) + { + if (tok2) + { + c = gui_strlen (tok2); + extra = MAX (extra, c); + } + + _AL_FREE (buf); + } + } + } + + if (extra) + m->w += extra + 16; + + if (child) + m->w += 22; + + m->w = MAX (m->w, minw); + m->h = MAX (m->h, minh); +} + + + +/* menu_key_shortcut: + * Returns true if c is indicated as a keyboard shortcut by a '&' character + * in the specified string. + */ +static int +menu_key_shortcut (int c, AL_CONST char *s) +{ + int d; + + while ((d = ugetxc (&s)) != 0) + { + if (d == '&') + { + d = ugetc (s); + if ((d != '&') && (utolower (d) == utolower (c & 0xFF))) + return TRUE; + } + } + + return FALSE; +} + + + +/* menu_alt_key: + * Searches a menu for keyboard shortcuts, for the alt+letter to bring + * up a menu. + */ +static int +menu_alt_key (int k, MENU * m) +{ + static unsigned char alt_table[] = { + ALLEGRO_KEY_A, ALLEGRO_KEY_B, ALLEGRO_KEY_C, ALLEGRO_KEY_D, ALLEGRO_KEY_E, + ALLEGRO_KEY_F, ALLEGRO_KEY_G, ALLEGRO_KEY_H, ALLEGRO_KEY_I, + ALLEGRO_KEY_J, ALLEGRO_KEY_K, ALLEGRO_KEY_L, ALLEGRO_KEY_M, ALLEGRO_KEY_N, + ALLEGRO_KEY_O, ALLEGRO_KEY_P, ALLEGRO_KEY_Q, ALLEGRO_KEY_R, + ALLEGRO_KEY_S, ALLEGRO_KEY_T, ALLEGRO_KEY_U, ALLEGRO_KEY_V, ALLEGRO_KEY_W, + ALLEGRO_KEY_X, ALLEGRO_KEY_Y, ALLEGRO_KEY_Z + }; + + AL_CONST char *s; + int c, d; + + if (k & 0xFF) + return 0; + + k >>= 8; + + c = scancode_to_ascii (k); + if (c) + { + k = c; + } + else + { + for (c = 0; c < (int) sizeof (alt_table); c++) + { + if (k == alt_table[c]) + { + k = c + 'a'; + break; + } + } + + if (c >= (int) sizeof (alt_table)) + return 0; + } + + for (c = 0; m[c].text; c++) + { + s = m[c].text; + while ((d = ugetxc (&s)) != 0) + { + if (d == '&') + { + d = ugetc (s); + if ((d != '&') && (utolower (d) == utolower (k))) + return k; + } + } + } + + return 0; +} + + + +/* do_menu: + * Displays and animates a popup menu at the specified screen position, + * returning the index of the item that was selected, or -1 if it was + * dismissed. If the menu crosses the edge of the screen it will be moved. + */ +int +do_menu (MENU * menu, int x, int y) +{ + MENU_PLAYER *player; + int ret; + ALLEGRO_ASSERT (menu); + + player = init_menu (menu, x, y); + + while (update_menu (player)) + rest (1); + + ret = shutdown_menu (player); + + do + { + } + while (gui_mouse_b ()); + + return ret; +} + + + +/* init_single_menu: + * Worker function for initialising a menu. + */ +static MENU_PLAYER * +init_single_menu (MENU * menu, MENU_PLAYER * parent, DIALOG * dialog, int bar, + int x, int y, int repos, int minw, int minh) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + MENU_PLAYER *player; + ALLEGRO_ASSERT (menu); + int scare = 0; + + player = _AL_MALLOC (sizeof (MENU_PLAYER)); + if (!player) + { + *allegro_errno = ENOMEM; + return NULL; + } + + layout_menu (player, menu, bar, x, y, minw, minh); + + if (repos) + { + if (parent && !parent->bar) + { + if (player->x + player->w >= SCREEN_W) + player->x = parent->x - player->w + 1; + } + player->x = CLAMP (0, player->x, SCREEN_W - player->w - 1); + player->y = CLAMP (0, player->y, SCREEN_H - player->h - 1); + } + + if (scare) + scare_mouse_area (player->x, player->y, player->w, player->h); + + /* save screen under the menu */ + player->saved = my_create_memory_bitmap (player->w, player->h); + + if (player->saved) + blit (gui_bmp, player->saved, player->x, player->y, 0, 0, player->w, + player->h); + else + *allegro_errno = ENOMEM; + + /* setup state variables */ + player->sel = menu_mouse_object (player); + + if (scare) + unscare_mouse (); + + player->mouse_button_was_pressed = gui_mouse_b (); + player->back_from_child = FALSE; + player->timestamp = gui_timer; + player->mouse_sel = player->sel; + player->redraw = TRUE; + player->auto_open = TRUE; + player->ret = -1; + + player->dialog = dialog; + + player->parent = parent; + player->child = NULL; + + return player; +} + + + +/* init_menu: + * Sets up a menu, returning a menu player object that can be used + * with the update_menu() and shutdown_menu() functions. + */ +MENU_PLAYER * +init_menu (MENU * menu, int x, int y) +{ + return init_single_menu (menu, NULL, NULL, FALSE, x, y, TRUE, 0, 0); +} + + + +/* update_menu: + * Updates the status of a menu player object returned by init_menu(), + * returning TRUE if it is still active or FALSE if it has finished. + * + * The navigation through the arborescence of menus can be done: + * - with the arrow keys, + * - with mouse point-and-clicks, + * - with mouse movements when the mouse button is being held down, + * - with mouse movements only if gui_menu_opening_delay is non negative. + */ +int +update_menu (MENU_PLAYER * player) +{ + MENU_PLAYER *i; + int c, c2; + int old_sel, child_ret; + int child_x, child_y; + ALLEGRO_ASSERT (player); + + /* find activated menu */ + while (player->child) + player = player->child; + + old_sel = player->sel; + + c = menu_mouse_object (player); + + if ((gui_mouse_b ()) || (c != player->mouse_sel)) + { + player->sel = player->mouse_sel = c; + player->auto_open = TRUE; + } + + if (gui_mouse_b ()) + { /* button pressed? */ + /* Dismiss menu if: + * - the mouse cursor is outside the menu and inside the parent menu, or + * - the mouse cursor is outside the menu and the button has just been pressed. + */ + if (!mouse_in_single_menu (player)) + { + if (mouse_in_parent_menu (player->parent) + || (!player->mouse_button_was_pressed)) + { + player->ret = -2; + goto End; + } + } + + if ((player->sel >= 0) && (player->menu[player->sel].child)) /* bring up child menu? */ + player->ret = player->sel; + + /* don't trigger the 'select' event on button press for non menu item */ + player->mouse_button_was_pressed = TRUE; + + clear_keybuf (); + } + else + { /* button not pressed */ + /* trigger the 'select' event only on button release for non menu item */ + if (player->mouse_button_was_pressed) + { + player->ret = player->sel; + player->mouse_button_was_pressed = FALSE; + } + + if (keypressed ()) + { /* keyboard input */ + player->timestamp = gui_timer; + player->auto_open = FALSE; + + c = readkey (); + + if ((c & 0xFF) == 27) + { + player->ret = -2; + goto End; + } + + switch (c >> 8) + { + + case ALLEGRO_KEY_LEFT: + if (player->parent) + { + if (player->parent->bar) + { + simulate_keypress (ALLEGRO_KEY_LEFT << 8); + simulate_keypress (ALLEGRO_KEY_DOWN << 8); + } + player->ret = -2; + goto End; + } + /* fall through */ + + case ALLEGRO_KEY_UP: + if ((((c >> 8) == ALLEGRO_KEY_LEFT) && (player->bar)) || + (((c >> 8) == ALLEGRO_KEY_UP) && (!player->bar))) + { + c = player->sel; + do + { + c--; + if (c < 0) + c = player->size - 1; + } + while ((!ugetc (player->menu[c].text)) + && (c != player->sel)); + player->sel = c; + } + break; + + case ALLEGRO_KEY_RIGHT: + if (((player->sel < 0) || (!player->menu[player->sel].child)) && + (player->parent) && (player->parent->bar)) + { + simulate_keypress (ALLEGRO_KEY_RIGHT << 8); + simulate_keypress (ALLEGRO_KEY_DOWN << 8); + player->ret = -2; + goto End; + } + /* fall through */ + + case ALLEGRO_KEY_DOWN: + if ((player->sel >= 0) && (player->menu[player->sel].child) && + ((((c >> 8) == ALLEGRO_KEY_RIGHT) && (!player->bar)) || + (((c >> 8) == ALLEGRO_KEY_DOWN) && (player->bar)))) + { + player->ret = player->sel; + } + else if ((((c >> 8) == ALLEGRO_KEY_RIGHT) && (player->bar)) || + (((c >> 8) == ALLEGRO_KEY_DOWN) && (!player->bar))) + { + c = player->sel; + do + { + c++; + if (c >= player->size) + c = 0; + } + while ((!ugetc (player->menu[c].text)) + && (c != player->sel)); + player->sel = c; + } + break; + + case ALLEGRO_KEY_SPACE: + case ALLEGRO_KEY_ENTER: + if (player->sel >= 0) + player->ret = player->sel; + break; + + default: + if ((!player->parent) && ((c & 0xFF) == 0)) + c = menu_alt_key (c, player->menu); + for (c2 = 0; player->menu[c2].text; c2++) + { + if (menu_key_shortcut (c, player->menu[c2].text)) + { + player->ret = player->sel = c2; + break; + } + } + if (player->parent) + { + i = player->parent; + for (c2 = 0; i->parent; c2++) + i = i->parent; + c = menu_alt_key (c, i->menu); + if (c) + { + while (c2-- > 0) + simulate_keypress (27); + simulate_keypress (c); + player->ret = -2; + goto End; + } + } + break; + } + } + } /* end of input processing */ + + if ((player->redraw) || (player->sel != old_sel)) + { /* selection changed? */ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + player->timestamp = gui_timer; + + acquire_bitmap (gui_bmp); + + if (player->redraw) + { + draw_menu (player); + player->redraw = FALSE; + } + else + { + if (old_sel >= 0) + draw_menu_item (player, old_sel); + + if (player->sel >= 0) + draw_menu_item (player, player->sel); + } + + release_bitmap (gui_bmp); + } + + if (player->auto_open && (gui_menu_opening_delay >= 0)) + { /* menu auto-opening on? */ + if (!mouse_in_single_menu (player)) + { + if (mouse_in_parent_menu (player->parent)) + { + /* automatically goes back to parent */ + player->ret = -3; + goto End; + } + } + + if ((player->mouse_sel >= 0) && (player->menu[player->mouse_sel].child)) + { + if (player->bar) + { + /* top level menu auto-opening if back from child */ + if (player->back_from_child) + { + player->timestamp = gui_timer; + player->ret = player->mouse_sel; + } + } + else + { + /* sub menu auto-opening if enough time has passed */ + if ((gui_timer - player->timestamp) > gui_menu_opening_delay) + player->ret = player->mouse_sel; + } + } + + player->back_from_child = FALSE; + } + +End: + if (player->ret >= 0) + { /* item selected? */ + if (player->menu[player->ret].flags & D_DISABLED) + { + return TRUE; /* continue */ + } + else if (player->menu[player->ret].child) + { /* child menu? */ + if (player->bar) + { + get_menu_pos (player, player->ret, &child_x, &child_y, &c); + child_x += 6; + child_y += text_height (font) + 7; + } + else + { + child_x = player->x + player->w - 3; + child_y = + player->y + (text_height (font) + 4) * player->ret + + text_height (font) / 4 + 1; + } + + /* recursively call child menu */ + player->child = + init_single_menu (player->menu[player->ret].child, player, NULL, + FALSE, child_x, child_y, TRUE, 0, 0); + return TRUE; /* continue */ + } + + while (player->parent) + { /* parent menu? */ + player = player->parent; + shutdown_single_menu (player->child, NULL); + player->child = NULL; + } + + return FALSE; /* item selected */ + } + + if (player->ret < -1) + { /* dismiss menu ? */ + if (player->parent) + { + child_ret = player->ret; /* needed below */ + player = player->parent; + shutdown_single_menu (player->child, NULL); + player->child = NULL; + player->ret = -1; + player->mouse_button_was_pressed = FALSE; + player->mouse_sel = menu_mouse_object (player); + + if (child_ret == -3) + { /* return caused by mouse movement? */ + player->sel = player->mouse_sel; + player->redraw = TRUE; + player->timestamp = gui_timer; + player->back_from_child = TRUE; + } + + return TRUE; /* return to parent */ + } + + return FALSE; /* menu dismissed */ + } + + /* special kludge for menu bar */ + if ((player->bar) && (!gui_mouse_b ()) && (!keypressed ()) + && (!mouse_in_single_menu (player))) + return FALSE; + + return TRUE; +} + + + +/* shutdown_single_menu: + * Worker function for shutting down a menu. + */ +static int +shutdown_single_menu (MENU_PLAYER * player, int *dret) +{ + int ret; + ALLEGRO_ASSERT (player); + + if (dret) + *dret = 0; + + if ((!player->proc) && (player->ret >= 0)) + { /* callback function? */ + active_menu = &player->menu[player->ret]; + player->proc = active_menu->proc; + } + + if (player->ret >= 0) + { + if (player->parent) + player->parent->proc = player->proc; + else + { + if (player->proc) + { + ret = player->proc (); + if (dret) + *dret = ret; + } + } + } + + /* restore screen */ + if (player->saved) + { + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + blit (player->saved, gui_bmp, 0, 0, player->x, player->y, player->w, + player->h); + al_destroy_bitmap (player->saved); + } + + ret = player->ret; + + _AL_FREE (player); + + return ret; +} + + + +/* shutdown_tree_menu: + * Destroys a menu player object returned by init_single_menu(), after + * recursively closing all the sub-menus if necessary, and returns the + * index of the item that was selected, or -1 if it was dismissed. + */ +static int +shutdown_tree_menu (MENU_PLAYER * player, int *dret) +{ + ALLEGRO_ASSERT (player); + + if (player->child) + { + shutdown_tree_menu (player->child, dret); + player->child = NULL; + } + + return shutdown_single_menu (player, dret); +} + + + +/* shutdown_menu: + * Destroys a menu player object returned by init_menu() and returns + * the index of the item that was selected, or -1 if it was dismissed. + */ +int +shutdown_menu (MENU_PLAYER * player) +{ + return shutdown_tree_menu (player, NULL); +} + + + +/* d_menu_proc: + * Dialog procedure for adding drop down menus to a GUI dialog. This + * displays the top level menu items as a horizontal bar (eg. across the + * top of the screen), and pops up child menus when they are clicked. + * When it executes one of the menu callback routines, it passes the + * return value back to the dialog manager, so these can return D_O_K, + * D_CLOSE, D_REDRAW, etc. + */ +int +d_menu_proc (int msg, DIALOG * d, int c) +{ + MENU_PLAYER m, *mp; + int ret = D_O_K; + int x, i; + ALLEGRO_ASSERT (d); + + switch (msg) + { + + case MSG_START: + layout_menu (&m, d->dp, TRUE, d->x, d->y, d->w, d->h); + d->w = m.w; + d->h = m.h; + break; + + case MSG_DRAW: + layout_menu (&m, d->dp, TRUE, d->x, d->y, d->w, d->h); + draw_menu (&m); + break; + + case MSG_XCHAR: + x = menu_alt_key (c, d->dp); + if (!x) + break; + + ret |= D_USED_CHAR; + simulate_keypress (x); + /* fall through */ + + case MSG_GOTMOUSE: + case MSG_CLICK: + /* steal the mouse */ + for (i = 0; active_dialog[i].proc; i++) + if (active_dialog[i].flags & D_GOTMOUSE) + { + active_dialog[i].flags &= ~D_GOTMOUSE; + object_message (active_dialog + i, MSG_LOSTMOUSE, 0); + break; + } + + /* initialize the menu */ + active_menu_player = + init_single_menu (d->dp, NULL, d, TRUE, d->x, d->y, FALSE, d->w, + d->h); + break; + + case MSG_LOSTMOUSE: + case MSG_END: + if (active_menu_player) + { + /* shutdown_tree_menu may call nested dialogs */ + mp = active_menu_player; + active_menu_player = NULL; + shutdown_tree_menu (mp, &x); + ret |= x; + + /* put the mouse */ + i = find_mouse_object (active_dialog); + if ((i >= 0) && (&active_dialog[i] != d)) + { + active_dialog[i].flags |= D_GOTMOUSE; + object_message (active_dialog + i, MSG_GOTMOUSE, 0); + } + } + break; + } + + return ret; +} + + + +static DIALOG alert_dialog[] = { + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + {_gui_shadow_box_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL}, + {_gui_ctext_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL}, + {_gui_ctext_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL}, + {_gui_ctext_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL}, + {_gui_button_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, D_EXIT, 0, 0, NULL, NULL, NULL}, + {_gui_button_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, D_EXIT, 0, 0, NULL, NULL, NULL}, + {_gui_button_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, D_EXIT, 0, 0, NULL, NULL, NULL}, + {d_yield_proc, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL}, + {NULL, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, NULL, NULL, NULL} +}; + + +#define A_S1 1 +#define A_S2 2 +#define A_S3 3 +#define A_B1 4 +#define A_B2 5 +#define A_B3 6 + + + +/* alert3: + * Displays a simple alert box, containing three lines of text (s1-s3), + * and with either one, two, or three buttons. The text for these buttons + * is passed in b1, b2, and b3 (NULL for buttons which are not used), and + * the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on + * which button was selected. + */ +int +alert3 (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, + AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, + int c2, int c3) +{ + char tmp[16]; + int avg_w, avg_h; + int len1, len2, len3; + int maxlen = 0; + int buttons = 0; + int b[3]; + int c; + +#define SORT_OUT_BUTTON(x) { \ + if (b##x) { \ + alert_dialog[A_B##x].flags &= ~D_HIDDEN; \ + alert_dialog[A_B##x].key = c##x; \ + alert_dialog[A_B##x].dp = (char *)b##x; \ + len##x = gui_strlen(b##x); \ + b[buttons++] = A_B##x; \ + } \ + else { \ + alert_dialog[A_B##x].flags |= D_HIDDEN; \ + len##x = 0; \ + } \ + } + + usetc (tmp + usetc (tmp, ' '), 0); + + avg_w = text_length (font, tmp); + avg_h = text_height (font); + + alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = + alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string; + + if (s1) + { + alert_dialog[A_S1].dp = (char *) s1; + maxlen = text_length (font, s1); + } + + if (s2) + { + alert_dialog[A_S2].dp = (char *) s2; + len1 = text_length (font, s2); + if (len1 > maxlen) + maxlen = len1; + } + + if (s3) + { + alert_dialog[A_S3].dp = (char *) s3; + len1 = text_length (font, s3); + if (len1 > maxlen) + maxlen = len1; + } + + SORT_OUT_BUTTON (1); + SORT_OUT_BUTTON (2); + SORT_OUT_BUTTON (3); + + len1 = MAX (len1, MAX (len2, len3)) + avg_w * 3; + if (len1 * buttons > maxlen) + maxlen = len1 * buttons; + + maxlen += avg_w * 4; + alert_dialog[0].w = maxlen; + alert_dialog[A_S1].w = alert_dialog[A_S2].w = alert_dialog[A_S3].w = + maxlen - avg_w * 2; + alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = + alert_dialog[0].x + avg_w; + + alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1; + + alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = + alert_dialog[0].x + maxlen / 2 - len1 / 2; + + if (buttons == 3) + { + alert_dialog[b[0]].x = + alert_dialog[0].x + maxlen / 2 - len1 * 3 / 2 - avg_w; + alert_dialog[b[2]].x = + alert_dialog[0].x + maxlen / 2 + len1 / 2 + avg_w; + } + else if (buttons == 2) + { + alert_dialog[b[0]].x = alert_dialog[0].x + maxlen / 2 - len1 - avg_w; + alert_dialog[b[1]].x = alert_dialog[0].x + maxlen / 2 + avg_w; + } + + alert_dialog[0].h = avg_h * 8; + alert_dialog[A_S1].y = alert_dialog[0].y + avg_h; + alert_dialog[A_S2].y = alert_dialog[0].y + avg_h * 2; + alert_dialog[A_S3].y = alert_dialog[0].y + avg_h * 3; + alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h; + alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = + alert_dialog[0].y + avg_h * 5; + alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = + avg_h * 2; + + centre_dialog (alert_dialog); + set_dialog_color (alert_dialog, gui_fg_color, gui_bg_color); + for (c = 0; alert_dialog[c].proc; c++) + if (alert_dialog[c].proc == _gui_ctext_proc) + alert_dialog[c].bg = NO_COLOR; + + clear_keybuf (); + + do + { + } + while (gui_mouse_b ()); + + c = popup_dialog (alert_dialog, A_B1); + + if (c == A_B1) + return 1; + else if (c == A_B2) + return 2; + else + return 3; +} + + + +/* alert: + * Displays a simple alert box, containing three lines of text (s1-s3), + * and with either one or two buttons. The text for these buttons is passed + * in b1 and b2 (b2 may be null), and the keyboard shortcuts in c1 and c2. + * Returns 1 or 2 depending on which button was selected. + */ +int +alert (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, + AL_CONST char *b1, AL_CONST char *b2, int c1, int c2) +{ + int ret; + + ret = alert3 (s1, s2, s3, b1, b2, NULL, c1, c2, 0); + + if (ret > 2) + ret = 2; + + return ret; +} diff --git a/src/backportgui.h b/src/backportgui.h new file mode 100644 index 00000000..bdc2fad5 --- /dev/null +++ b/src/backportgui.h @@ -0,0 +1,243 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * GUI routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GUI_H +#define ALLEGRO_GUI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + struct ALLEGRO_BITMAP; + struct DIALOG; + + typedef AL_METHOD (int, DIALOG_PROC, (int msg, struct DIALOG * d, int c)); + + typedef struct DIALOG + { + DIALOG_PROC proc; + int x, y, w, h; /* position and size of the object */ + ALLEGRO_COLOR fg, bg; /* foreground and background colors */ + int key; /* keyboard shortcut (ASCII code) */ + int flags; /* flags about the object state */ + int d1, d2; /* any data the object might require */ + void *dp, *dp2, *dp3; /* pointers to more object data */ + } DIALOG; + + +/* a popup menu */ + typedef struct MENU + { + char *text; /* menu item text */ + AL_METHOD (int, proc, (void)); /* callback function */ + struct MENU *child; /* to allow nested menus */ + int flags; /* flags about the menu state */ + void *dp; /* any data the menu might require */ + } MENU; + + +/* stored information about the state of an active GUI dialog */ + typedef struct DIALOG_PLAYER + { + int obj; + int res; + int mouse_obj; + int focus_obj; + int joy_on; + int click_wait; + int mouse_ox, mouse_oy; + int mouse_oz; + int mouse_b; + DIALOG *dialog; + } DIALOG_PLAYER; + + +/* stored information about the state of an active GUI menu */ + typedef struct MENU_PLAYER + { + MENU *menu; /* the menu itself */ + int bar; /* set if it is a top level menu bar */ + int size; /* number of items in the menu */ + int sel; /* selected item */ + int x, y, w, h; /* screen position of the menu */ + int (*proc) (void); /* callback function */ + ALLEGRO_BITMAP *saved; /* saved what was underneath it */ + + int mouse_button_was_pressed; /* set if mouse button pressed on last iteration */ + int back_from_child; /* set if a child was activated on last iteration */ + int timestamp; /* timestamp for gui_timer events */ + int mouse_sel; /* item the mouse is currently over */ + int redraw; /* set if redrawing is required */ + int auto_open; /* set if menu auto-opening is activated */ + int ret; /* return value */ + + DIALOG *dialog; /* d_menu_proc() parent dialog (if any) */ + + struct MENU_PLAYER *parent; /* the parent menu, or NULL for root */ + struct MENU_PLAYER *child; /* the child menu, or NULL for none */ + } MENU_PLAYER; + + +/* bits for the flags field */ +#define D_EXIT 1 /* object makes the dialog exit */ +#define D_SELECTED 2 /* object is selected */ +#define D_GOTFOCUS 4 /* object has the input focus */ +#define D_GOTMOUSE 8 /* mouse is on top of object */ +#define D_HIDDEN 16 /* object is not visible */ +#define D_DISABLED 32 /* object is visible but inactive */ +#define D_DIRTY 64 /* object needs to be redrawn */ +#define D_INTERNAL 128 /* reserved for internal use */ +#define D_USER 256 /* from here on is free for your own use */ + + +/* return values for the dialog procedures */ +#define D_O_K 0 /* normal exit status */ +#define D_CLOSE 1 /* request to close the dialog */ +#define D_REDRAW 2 /* request to redraw the dialog */ +#define D_REDRAWME 4 /* request to redraw this object */ +#define D_WANTFOCUS 8 /* this object wants the input focus */ +#define D_USED_CHAR 16 /* object has used the keypress */ +#define D_REDRAW_ALL 32 /* request to redraw all active dialogs */ +#define D_DONTWANTMOUSE 64 /* this object does not want mouse focus */ + + +/* messages for the dialog procedures */ +#define MSG_START 1 /* start the dialog, initialise */ +#define MSG_END 2 /* dialog is finished - cleanup */ +#define MSG_DRAW 3 /* draw the object */ +#define MSG_CLICK 4 /* mouse click on the object */ +#define MSG_DCLICK 5 /* double click on the object */ +#define MSG_KEY 6 /* keyboard shortcut */ +#define MSG_CHAR 7 /* other keyboard input */ +#define MSG_UCHAR 8 /* unicode keyboard input */ +#define MSG_XCHAR 9 /* broadcast character to all objects */ +#define MSG_WANTFOCUS 10 /* does object want the input focus? */ +#define MSG_GOTFOCUS 11 /* got the input focus */ +#define MSG_LOSTFOCUS 12 /* lost the input focus */ +#define MSG_GOTMOUSE 13 /* mouse on top of object */ +#define MSG_LOSTMOUSE 14 /* mouse moved away from object */ +#define MSG_IDLE 15 /* update any background stuff */ +#define MSG_RADIO 16 /* clear radio buttons */ +#define MSG_WHEEL 17 /* mouse wheel moved */ +#define MSG_LPRESS 18 /* mouse left button pressed */ +#define MSG_LRELEASE 19 /* mouse left button released */ +#define MSG_MPRESS 20 /* mouse middle button pressed */ +#define MSG_MRELEASE 21 /* mouse middle button released */ +#define MSG_RPRESS 22 /* mouse right button pressed */ +#define MSG_RRELEASE 23 /* mouse right button released */ +#define MSG_WANTMOUSE 24 /* does object want the mouse? */ +#define MSG_USER 25 /* from here on are free... */ + + +/* some dialog procedures */ + AL_FUNC (int, d_yield_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_clear_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_box_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_shadow_box_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_bitmap_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_text_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_ctext_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_rtext_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_button_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_check_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_radio_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_icon_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_keyboard_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_edit_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_list_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_text_list_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_textbox_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_slider_proc, (int msg, DIALOG * d, int c)); + AL_FUNC (int, d_menu_proc, (int msg, DIALOG * d, int c)); + + AL_VAR (DIALOG_PROC, gui_shadow_box_proc); + AL_VAR (DIALOG_PROC, gui_ctext_proc); + AL_VAR (DIALOG_PROC, gui_button_proc); + AL_VAR (DIALOG_PROC, gui_edit_proc); + AL_VAR (DIALOG_PROC, gui_list_proc); + AL_VAR (DIALOG_PROC, gui_text_list_proc); + + AL_FUNCPTR (void, gui_menu_draw_menu, (int x, int y, int w, int h)); + AL_FUNCPTR (void, gui_menu_draw_menu_item, + (MENU * m, int x, int y, int w, int h, int bar, int sel)); + + AL_VAR (DIALOG *, active_dialog); + AL_VAR (MENU *, active_menu); + + AL_VAR (int, gui_mouse_focus); + + AL_VAR (ALLEGRO_COLOR, gui_fg_color); + AL_VAR (ALLEGRO_COLOR, gui_mg_color); + AL_VAR (ALLEGRO_COLOR, gui_bg_color); + + AL_VAR (int, gui_font_baseline); + + AL_FUNCPTR (int, gui_mouse_x, (void)); + AL_FUNCPTR (int, gui_mouse_y, (void)); + AL_FUNCPTR (int, gui_mouse_z, (void)); + AL_FUNCPTR (int, gui_mouse_b, (void)); + + AL_FUNC (void, gui_set_screen, (ALLEGRO_BITMAP * bmp)); + AL_FUNC (ALLEGRO_BITMAP *, gui_get_screen, (void)); + AL_FUNC (int, gui_textout_ex, + (struct ALLEGRO_BITMAP * bmp, AL_CONST char *s, int x, int y, + ALLEGRO_COLOR color, ALLEGRO_COLOR bg, int centre)); + AL_FUNC (int, gui_strlen, (AL_CONST char *s)); + AL_FUNC (void, position_dialog, (DIALOG * dialog, int x, int y)); + AL_FUNC (void, centre_dialog, (DIALOG * dialog)); + AL_FUNC (void, set_dialog_color, (DIALOG * dialog, ALLEGRO_COLOR fg, ALLEGRO_COLOR bg)); + AL_FUNC (int, find_dialog_focus, (DIALOG * dialog)); + AL_FUNC (int, offer_focus, + (DIALOG * dialog, int obj, int *focus_obj, int force)); + AL_FUNC (int, object_message, (DIALOG * dialog, int msg, int c)); + AL_FUNC (int, dialog_message, + (DIALOG * dialog, int msg, int c, int *obj)); + AL_FUNC (int, broadcast_dialog_message, (int msg, int c)); + AL_FUNC (int, do_dialog, (DIALOG * dialog, int focus_obj)); + AL_FUNC (int, popup_dialog, (DIALOG * dialog, int focus_obj)); + AL_FUNC (DIALOG_PLAYER *, init_dialog, (DIALOG * dialog, int focus_obj)); + AL_FUNC (int, update_dialog, (DIALOG_PLAYER * player)); + AL_FUNC (int, shutdown_dialog, (DIALOG_PLAYER * player)); + AL_FUNC (int, do_menu, (MENU * menu, int x, int y)); + AL_FUNC (MENU_PLAYER *, init_menu, (MENU * menu, int x, int y)); + AL_FUNC (int, update_menu, (MENU_PLAYER * player)); + AL_FUNC (int, shutdown_menu, (MENU_PLAYER * player)); + AL_FUNC (int, alert, + (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, + AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)); + AL_FUNC (int, alert3, + (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, + AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, + int c2, int c3)); + AL_FUNC (int, file_select_ex, + (AL_CONST char *message, char *path, AL_CONST char *ext, + int size, int w, int h)); + + AL_FUNC (int, gfx_mode_select, (int *card, int *w, int *h)); + AL_FUNC (int, gfx_mode_select_ex, + (int *card, int *w, int *h, int *color_depth)); + AL_FUNC (int, gfx_mode_select_filter, + (int *card, int *w, int *h, int *color_depth, + int (*filter) (int, int, int, int))); + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef ALLEGRO_GUI_H */ diff --git a/src/backportguiproc.c b/src/backportguiproc.c new file mode 100644 index 00000000..99e23823 --- /dev/null +++ b/src/backportguiproc.c @@ -0,0 +1,2117 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * The standard GUI dialog object procedures. + * + * By Shawn Hargreaves. + * + * Radio button, icon, and slider objects by Chris La Mantia. + * + * Scrolling d_edit_proc by VolkerOth. + * + * Text box object by Doug Eleveld. + * + * d_text_list_proc by Andy Goth. + * + * See readme.txt for copyright information. + */ + + +#include "backport.h" +#include "backportgui.h" +#include "backportguiproc.h" +#include "macro.h" + + +#ifdef ALLEGRO_WINDOWS +/* exported address of d_clear_proc */ +int (*_d_clear_proc) (int, DIALOG *, int) = NULL; +#endif + +/* typedef for the listbox callback functions */ +typedef char *(*getfuncptr) (int, int *); + +static int _dummy_c = 0; + +/* gui_textout_ex: + * Wrapper function for drawing text to the screen, which interprets the + * & character as an underbar for displaying keyboard shortcuts. Returns + * the width of the output string in pixels. + */ +int +gui_textout_ex (ALLEGRO_BITMAP * bmp, AL_CONST char *s, int x, int y, + ALLEGRO_COLOR color, ALLEGRO_COLOR bg, int centre) +{ + char tmp[1024]; + int hline_pos = -1; + int len = 0; + int in_pos = 0; + int out_pos = 0; + int pix_len, c; + ALLEGRO_ASSERT (s); + + while (((c = ugetc (s + in_pos)) != 0) + && (out_pos < (int) (sizeof (tmp) - ucwidth (0)))) + { + if (c == '&') + { + in_pos += uwidth (s + in_pos); + c = ugetc (s + in_pos); + if (c == '&') + { + out_pos += usetc (tmp + out_pos, '&'); + in_pos += uwidth (s + in_pos); + len++; + } + else + hline_pos = len; + } + else + { + out_pos += usetc (tmp + out_pos, c); + in_pos += uwidth (s + in_pos); + len++; + } + } + + usetc (tmp + out_pos, 0); + pix_len = text_length (font, tmp); + + if (centre) + x -= pix_len / 2; + + if (bmp) + { + textout_ex (bmp, font, tmp, x, y, color, bg); + + if (hline_pos >= 0) + { + c = ugetat (tmp, hline_pos); + usetat (tmp, hline_pos, 0, sizeof (tmp)); + hline_pos = text_length (font, tmp); + c = usetc (tmp, c); + usetc (tmp + c, 0); + c = text_length (font, tmp); + hline (bmp, x + hline_pos, + y + text_height (font) - gui_font_baseline, + x + hline_pos + c - 1, color); + } + } + + return pix_len; +} + + + +/* gui_strlen: + * Returns the length of a string in pixels, ignoring '&' characters. + */ +int +gui_strlen (AL_CONST char *s) +{ + ALLEGRO_ASSERT (s); + return gui_textout_ex (NULL, s, 0, 0, NO_COLOR, NO_COLOR, 0); +} + + + +/* dotted_rect: + * Draws a dotted rectangle, for showing an object has the input focus. + */ +static void +dotted_rect (int x1, int y1, int x2, int y2, ALLEGRO_COLOR fg, ALLEGRO_COLOR bg) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + int x = ((x1 + y1) & 1) ? 1 : 0; + int c; + + /* two loops to avoid bank switches */ + for (c = x1; c <= x2; c++) + putpixel (gui_bmp, c, y1, (((c + y1) & 1) == x) ? fg : bg); + for (c = x1; c <= x2; c++) + putpixel (gui_bmp, c, y2, (((c + y2) & 1) == x) ? fg : bg); + + for (c = y1 + 1; c < y2; c++) + { + putpixel (gui_bmp, x1, c, (((c + x1) & 1) == x) ? fg : bg); + putpixel (gui_bmp, x2, c, (((c + x2) & 1) == x) ? fg : bg); + } +} + + + +/* d_yield_proc: + * Simple dialog procedure which just yields the timeslice when the dialog + * is idle. + */ +int +d_yield_proc (int msg, DIALOG * d, int c) +{ + if (d == NULL || msg == MSG_IDLE) + rest (1); + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_clear_proc: + * Simple dialog procedure which just clears the screen. Useful as the + * first object in a dialog. + */ +int +d_clear_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + + _dummy_c = c; + +#ifdef ALLEGRO_WINDOWS + /* kludge to get the exported address of d_clear_proc */ + if (!_d_clear_proc) + _d_clear_proc = d->proc; +#endif + + if (msg == MSG_DRAW) + { + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + int w, h; + + /* Get width and height of target bitmap. We can't use SCREEN_W and + * SCREEN_H because the target might not be the screen, but we cannot use + * bmp->w and bmp->h either because if it is the screen these are actually + * wrong. Ugh! + */ + w = (gui_bmp == screen) ? SCREEN_W : al_get_bitmap_width (gui_bmp); + h = (gui_bmp == screen) ? SCREEN_H : al_get_bitmap_height (gui_bmp); + + set_clip_rect (gui_bmp, 0, 0, w - 1, h - 1); + clear_to_color (gui_bmp, d->bg); + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_box_proc: + * Simple dialog procedure: just draws a box. + */ +int +d_box_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + if (msg == MSG_DRAW) + { + ALLEGRO_COLOR fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + + rectfill (gui_bmp, d->x + 1, d->y + 1, d->x + d->w - 2, d->y + d->h - 2, + d->bg); + rect (gui_bmp, d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, fg); + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_shadow_box_proc: + * Simple dialog procedure: draws a box with a shadow. + */ +int +d_shadow_box_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + if (msg == MSG_DRAW) + { + ALLEGRO_COLOR fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + ALLEGRO_COLOR black = al_map_rgb(0, 0, 0); // [FIXME:ufoot] sounds a bit hardcoded, double-check this + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + + rectfill (gui_bmp, d->x + 1, d->y + 1, d->x + d->w - 3, d->y + d->h - 3, + d->bg); + rect (gui_bmp, d->x, d->y, d->x + d->w - 2, d->y + d->h - 2, fg); + vline (gui_bmp, d->x + d->w - 1, d->y + 1, d->y + d->h - 1, black); + hline (gui_bmp, d->x + 1, d->y + d->h - 1, d->x + d->w - 1, black); + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_bitmap_proc: + * Simple dialog procedure: draws the bitmap which is pointed to by dp. + */ +int +d_bitmap_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_BITMAP *b; + ALLEGRO_ASSERT (d); + + b = (ALLEGRO_BITMAP *) d->dp; + if (msg == MSG_DRAW) + blit (b, gui_get_screen (), 0, 0, d->x, d->y, d->w, d->h); + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_text_proc: + * Simple dialog procedure: draws the text string which is pointed to by dp. + */ +int +d_text_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + if (msg == MSG_DRAW) + { + ALLEGRO_COLOR fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + ALLEGRO_FONT *oldfont = font; + + if (d->dp2) + font = d->dp2; + + gui_textout_ex (gui_get_screen (), d->dp, d->x, d->y, fg, d->bg, FALSE); + + font = oldfont; + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_ctext_proc: + * Simple dialog procedure: draws the text string which is pointed to by dp, + * centering it around the object's x coordinate. + */ +int +d_ctext_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + if (msg == MSG_DRAW) + { + ALLEGRO_COLOR fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + ALLEGRO_FONT *oldfont = font; + + if (d->dp2) + font = d->dp2; + + gui_textout_ex (gui_get_screen (), d->dp, d->x + d->w / 2, d->y, fg, + d->bg, TRUE); + + font = oldfont; + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_rtext_proc: + * Simple dialog procedure: draws the text string which is pointed to by dp, + * right aligning it. + */ +int +d_rtext_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_ASSERT (d); + if (msg == MSG_DRAW) + { + ALLEGRO_COLOR fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + ALLEGRO_FONT *oldfont = font; + + if (d->dp2) + font = d->dp2; + + gui_textout_ex (gui_get_screen (), d->dp, + d->x + d->w - gui_strlen (d->dp), d->y, fg, d->bg, + FALSE); + + font = oldfont; + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_button_proc: + * A button object (the dp field points to the text string). This object + * can be selected by clicking on it with the mouse or by pressing its + * keyboard shortcut. If the D_EXIT flag is set, selecting it will close + * the dialog, otherwise it will toggle on and off. + */ +int +d_button_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_BITMAP *gui_bmp; + ALLEGRO_COLOR state1, state2; + ALLEGRO_COLOR black; + int swap; + int g; + int click_state1, click_state2; // Boolean states for MSG_CLICK + ALLEGRO_ASSERT (d); + + gui_bmp = gui_get_screen (); + + switch (msg) + { + + case MSG_DRAW: + if (d->flags & D_SELECTED) + { + g = 1; + state1 = d->bg; + state2 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + } + else + { + g = 0; + state1 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + state2 = d->bg; + } + + rectfill (gui_bmp, d->x + 1 + g, d->y + 1 + g, d->x + d->w - 3 + g, + d->y + d->h - 3 + g, state2); + rect (gui_bmp, d->x + g, d->y + g, d->x + d->w - 2 + g, + d->y + d->h - 2 + g, state1); + gui_textout_ex (gui_bmp, d->dp, d->x + d->w / 2 + g, + d->y + d->h / 2 - text_height (font) / 2 + g, state1, + NO_COLOR, TRUE); + + if (d->flags & D_SELECTED) + { + vline (gui_bmp, d->x, d->y, d->y + d->h - 2, d->bg); + hline (gui_bmp, d->x, d->y, d->x + d->w - 2, d->bg); + } + else + { + black = al_map_rgb(0, 0, 0); // [FIXME:ufoot] sounds a bit hardcoded, double-check this + vline (gui_bmp, d->x + d->w - 1, d->y + 1, d->y + d->h - 2, black); + hline (gui_bmp, d->x + 1, d->y + d->h - 1, d->x + d->w - 1, black); + } + if ((d->flags & D_GOTFOCUS) && + (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) + dotted_rect (d->x + 1 + g, d->y + 1 + g, d->x + d->w - 3 + g, + d->y + d->h - 3 + g, state1, state2); + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + /* close dialog? */ + if (d->flags & D_EXIT) + { + return D_CLOSE; + } + + /* or just toggle */ + d->flags ^= D_SELECTED; + object_message (d, MSG_DRAW, 0); + break; + + case MSG_CLICK: + /* what state was the button originally in? */ + click_state1 = d->flags & D_SELECTED; + if (d->flags & D_EXIT) + swap = FALSE; + else + swap = click_state1; + + /* track the mouse until it is released */ + while (gui_mouse_b ()) + { + click_state2 = ((gui_mouse_x () >= d->x) && (gui_mouse_y () >= d->y) && + (gui_mouse_x () < d->x + d->w) + && (gui_mouse_y () < d->y + d->h)); + if (swap) + click_state2 = !click_state2; + + /* redraw? */ + if (((click_state1) && (!click_state2)) || ((click_state2) && (!click_state1))) + { + d->flags ^= D_SELECTED; + click_state1 = d->flags & D_SELECTED; + object_message (d, MSG_DRAW, 0); + } + + /* let other objects continue to animate */ + broadcast_dialog_message (MSG_IDLE, 0); + } + + /* should we close the dialog? */ + if ((d->flags & D_SELECTED) && (d->flags & D_EXIT)) + { + d->flags ^= D_SELECTED; + return D_CLOSE; + } + break; + } + + _dummy_c = c; + + return D_O_K; +} + + + +/* d_check_proc: + * Who needs C++ after all? This is derived from d_button_proc, + * but overrides the drawing routine to provide a check box. + */ +int +d_check_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + int x, y, h; + ALLEGRO_COLOR fg, bg; + ALLEGRO_ASSERT (d); + + if (msg == MSG_DRAW) + { + fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + // Check if bg is NO_COLOR (transparent) by comparing components + if (d->bg.r == 0 && d->bg.g == 0 && d->bg.b == 0 && d->bg.a == 0) + bg = gui_bg_color; + else + bg = d->bg; + + h = text_height (font); + + rectfill (gui_bmp, d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, bg); + if (d->flags & D_GOTFOCUS) + dotted_rect (d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, fg, bg); + + y = d->y + ((d->h - (h - gui_font_baseline)) / 2); + x = + d->x + + ((d->d1) ? 0 : gui_textout_ex (gui_bmp, d->dp, d->x, y, fg, NO_COLOR, + FALSE) + h / 2); + + rect (gui_bmp, x, y, x + h - 1, y + h - 1, fg); + if (d->d1) + gui_textout_ex (gui_bmp, d->dp, x + h + h / 2, y, fg, NO_COLOR, FALSE); + if (d->flags & D_SELECTED) + { + line (gui_bmp, x, y, x + h - 1, y + h - 1, fg); + line (gui_bmp, x, y + h - 1, x + h - 1, y, fg); + } + + return D_O_K; + } + + _dummy_c = c; + + return d_button_proc (msg, d, 0); +} + + +/* d_icon_proc: + * Allows graphic icons to be used as buttons. + * + * Parameters: + * fg = color dotted line showing focus will be drawn in + * bg = shadow color used to fill in top and left sides of + * button when "pressed" + * d1 = "push depth": number of pixels icon will be shifted + * to right and down when selected (default=2) if there is + * no "selected" image + * d2 = distance dotted line showing focus is indented (default=2) + * dp = pointer to a bitmap for the icon + * dp2 = pointer to a "selected" bitmap for the icon (OPTIONAL) + * dp3 = pointer to a "disabled" bitmap for the icon (OPTIONAL) + */ +int +d_icon_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_BITMAP *butimage; + ALLEGRO_BITMAP *gui_bmp; + int butx; + int buty; + int index; + int indent; + int depth; + ALLEGRO_ASSERT (d); + + butimage = (ALLEGRO_BITMAP *) d->dp; + gui_bmp = gui_get_screen (); + if ((msg == MSG_DRAW) && (!(d->flags & D_HIDDEN))) + { + depth = 0; + if ((d->dp2 == NULL) && (d->flags & D_SELECTED)) + { + depth = d->d1; + if (depth < 1) + depth = 2; + } + if ((d->dp2 != NULL) && (d->flags & D_SELECTED)) + { + butimage = (ALLEGRO_BITMAP *) d->dp2; + } + if ((d->dp3 != NULL) && (d->flags & D_DISABLED)) + { + butimage = (ALLEGRO_BITMAP *) d->dp3; + } + indent = d->d2; + if (indent == 0) + indent = 2; + + /* put the graphic on screen, scaled as needed */ + butx = al_get_bitmap_width (butimage); + buty = al_get_bitmap_height (butimage); + stretch_blit (butimage, gui_bmp, 0, 0, butx - depth, buty - depth, + d->x + depth, d->y + depth, d->w - depth, d->h - depth); + + if ((d->flags & D_GOTFOCUS) && + (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) + { + /* draw focus lines */ + for (index = indent; index < d->w - (indent + 1); index += 2) + { + putpixel (gui_bmp, d->x + index + depth, d->y + indent + depth, + d->fg); + putpixel (gui_bmp, d->x + index + depth, + d->y + d->h - (indent + 1) + depth, d->fg); + } + for (index = indent; index < d->h - (indent + 1); index += 2) + { + putpixel (gui_bmp, d->x + indent + depth, d->y + index + depth, + d->fg); + putpixel (gui_bmp, d->x + d->w - (indent + 1) + depth, + d->y + index + depth, d->fg); + } + } + + /* draw shadowing */ + for (index = 0; index < depth; index++) + { + hline (gui_bmp, d->x, d->y + index, d->x + d->w - 1, d->bg); + vline (gui_bmp, d->x + index, d->y, d->y + d->h - 1, d->bg); + } + + return D_O_K; + } + + return d_button_proc (msg, d, c); +} + + + +/* d_keyboard_proc: + * Invisible object for implementing keyboard shortcuts. When its key + * is pressed, it calls the function pointed to by dp. This should return + * an integer, which will be passed back to the dialog manager. The key + * can be specified by putting an ASCII code in the key field or by + * putting scancodes in d1 and d2. + */ +int +d_keyboard_proc (int msg, DIALOG * d, int c) +{ + int (*proc) (void); + int ret = D_O_K; + ALLEGRO_ASSERT (d); + + switch (msg) + { + + case MSG_START: + d->w = d->h = 0; + break; + + case MSG_XCHAR: + if (((c >> 8) != d->d1) && ((c >> 8) != d->d2)) + break; + + ret |= D_USED_CHAR; + /* fall through */ + + case MSG_KEY: + proc = d->dp; + ret |= (*proc) (); + break; + } + + return ret; +} + + + +/* d_edit_proc: + * An editable text object (the dp field points to the string). When it + * has the input focus (obtained by clicking on it with the mouse), text + * can be typed into this object. The d1 field specifies the maximum + * number of characters that it will accept, and d2 is the text cursor + * position within the string. + */ +int +d_edit_proc (int msg, DIALOG * d, int c) +{ + static int ignore_next_uchar = FALSE; + ALLEGRO_BITMAP *gui_bmp; + int f, l, p, w, x, b, scroll; + ALLEGRO_COLOR fg; + char buf[16]; + char *s; + ALLEGRO_ASSERT (d); + + gui_bmp = gui_get_screen (); + + s = d->dp; + l = ustrlen (s); + if (d->d2 > l) + d->d2 = l; + + /* calculate maximal number of displayable characters */ + if (d->d2 == l) + { + usetc (buf + usetc (buf, ' '), 0); + x = text_length (font, buf); + } + else + x = 0; + + b = 0; + + for (p = d->d2; p >= 0; p--) + { + usetc (buf + usetc (buf, ugetat (s, p)), 0); + x += text_length (font, buf); + b++; + if (x > d->w) + break; + } + + if (x <= d->w) + { + b = l; + scroll = FALSE; + } + else + { + b--; + scroll = TRUE; + } + + switch (msg) + { + + case MSG_START: + d->d2 = l; + break; + + case MSG_DRAW: + fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + x = 0; + + if (scroll) + { + p = d->d2 - b + 1; + b = d->d2; + } + else + p = 0; + + for (; p <= b; p++) + { + f = ugetat (s, p); + usetc (buf + usetc (buf, (f) ? f : ' '), 0); + w = text_length (font, buf); + if (x + w > d->w) + break; + f = ((p == d->d2) && (d->flags & D_GOTFOCUS)); + textout_ex (gui_bmp, font, buf, d->x + x, d->y, (f) ? d->bg : fg, + (f) ? fg : d->bg); + x += w; + } + if (x < d->w) + rectfill (gui_bmp, d->x + x, d->y, d->x + d->w - 1, + d->y + text_height (font) - 1, d->bg); + break; + + case MSG_CLICK: + x = d->x; + + if (scroll) + { + p = d->d2 - b + 1; + b = d->d2; + } + else + p = 0; + + for (; p < b; p++) + { + usetc (buf + usetc (buf, ugetat (s, p)), 0); + x += text_length (font, buf); + if (x > gui_mouse_x ()) + break; + } + d->d2 = CLAMP (0, p, l); + object_message (d, MSG_DRAW, 0); + break; + + case MSG_WANTFOCUS: + case MSG_LOSTFOCUS: + case MSG_KEY: + return D_WANTFOCUS; + + case MSG_CHAR: + ignore_next_uchar = FALSE; + + if ((c >> 8) == ALLEGRO_KEY_LEFT) + { + if (d->d2 > 0) + { + d->d2--; + } + } + else if ((c >> 8) == ALLEGRO_KEY_RIGHT) + { + if (d->d2 < l) + { + d->d2++; + } + } + else if ((c >> 8) == ALLEGRO_KEY_HOME) + { + d->d2 = 0; + } + else if ((c >> 8) == ALLEGRO_KEY_END) + { + d->d2 = l; + } + else if ((c >> 8) == ALLEGRO_KEY_DELETE) + { + if (d->d2 < l) + uremove (s, d->d2); + } + else if ((c >> 8) == ALLEGRO_KEY_BACKSPACE) + { + if (d->d2 > 0) + { + d->d2--; + uremove (s, d->d2); + } + } + else if ((c >> 8) == ALLEGRO_KEY_ENTER) + { + if (d->flags & D_EXIT) + { + object_message (d, MSG_DRAW, 0); + return D_CLOSE; + } + else + return D_O_K; + } + else if ((c >> 8) == ALLEGRO_KEY_TAB) + { + ignore_next_uchar = TRUE; + return D_O_K; + } + else + { + /* don't process regular keys here: MSG_UCHAR will do that */ + break; + } + object_message (d, MSG_DRAW, 0); + return D_USED_CHAR; + + case MSG_UCHAR: + if ((c >= ' ') && (uisok (c)) && (!ignore_next_uchar)) + { + if (l < d->d1) + { + uinsert (s, d->d2, c, d->d1 + 1); + d->d2++; + + object_message (d, MSG_DRAW, 0); + } + return D_USED_CHAR; + } + break; + } + + return D_O_K; +} + + + +/* _handle_scrollable_click: + * Helper to process a click on a scrollable object. + */ +void +_handle_scrollable_scroll_click (DIALOG * d, int listsize, int *offset, + int height) +{ + int xx, yy; + int hh = d->h - 5; + + while (gui_mouse_b ()) + { + int i = (hh * height + listsize / 2) / listsize; + int len = (hh * (*offset) + listsize / 2) / listsize + 2; + + if ((gui_mouse_y () >= d->y + len) + && (gui_mouse_y () <= d->y + len + i)) + { + xx = gui_mouse_y () - len + 2; + while (gui_mouse_b ()) + { + yy = (listsize * (gui_mouse_y () - xx) + hh / 2) / hh; + if (yy > listsize - height) + yy = listsize - height; + + if (yy < 0) + yy = 0; + + if (yy != *offset) + { + *offset = yy; + object_message (d, MSG_DRAW, 0); + } + + /* let other objects continue to animate */ + broadcast_dialog_message (MSG_IDLE, 0); + } + } + else + { + if (gui_mouse_y () <= d->y + len) + yy = *offset - height; + else + yy = *offset + height; + + if (yy > listsize - height) + yy = listsize - height; + + if (yy < 0) + yy = 0; + + if (yy != *offset) + { + *offset = yy; + object_message (d, MSG_DRAW, 0); + } + } + + /* let other objects continue to animate */ + broadcast_dialog_message (MSG_IDLE, 0); + } +} + + + +/* _handle_scrollable_scroll: + * Helper function to scroll through a scrollable object. + */ +void +_handle_scrollable_scroll (DIALOG * d, int listsize, int *index, int *offset) +{ + int height = (d->h - 4) / text_height (font); + + if (listsize <= 0) + { + *index = *offset = 0; + return; + } + + /* check selected item */ + if (*index < 0) + *index = 0; + else if (*index >= listsize) + *index = listsize - 1; + + /* check scroll position */ + while ((*offset > 0) && (*offset + height > listsize)) + (*offset)--; + + if (*offset >= *index) + { + if (*index < 0) + *offset = 0; + else + *offset = *index; + } + else + { + while ((*offset + height - 1) < *index) + (*offset)++; + } +} + + + +/* idle_cb: + * rest_callback() routine to keep dialogs animating nice and smoothly. + */ +static void +idle_cb (void) +{ + broadcast_dialog_message (MSG_IDLE, 0); +} + + + +/* _handle_listbox_click: + * Helper to process a click on a listbox, doing hit-testing and moving + * the selection. + */ +void +_handle_listbox_click (DIALOG * d) +{ + char *sel = d->dp2; + int listsize, height; + int i; + + (*(getfuncptr) d->dp) (-1, &listsize); + if (!listsize) + return; + + height = (d->h - 4) / text_height (font); + + i = CLAMP (0, ((gui_mouse_y () - d->y - 2) / text_height (font)), + ((d->h - 4) / text_height (font) - 1)); + i += d->d2; + if (i < d->d2) + i = d->d2; + else + { + if (i > d->d2 + height - 1) + i = d->d2 + height - 1; + if (i >= listsize) + i = listsize - 1; + } + + if (gui_mouse_y () <= d->y) + i = MAX (i - 1, 0); + else if (gui_mouse_y () >= d->y + d->h - 1) + i = MIN (i + 1, listsize - 1); + + if (i != d->d1) + { + if (sel) + { + sel[i] = TRUE; + } + + d->d1 = i; + i = d->d2; + _handle_scrollable_scroll (d, listsize, &d->d1, &d->d2); + + d->flags |= D_DIRTY; + + if (i != d->d2) + rest_callback (CLAMP (10, text_height (font) * 16 - d->h - 1, 100), + idle_cb); + } + else + { + if (!(d->flags & D_INTERNAL)) + { + if (sel) + { + sel[i] = TRUE; + + d->flags |= D_DIRTY; + } + } + } +} + + + +/* _draw_scrollable_frame: + * Helper function to draw a frame for all objects with vertical scrollbars. + */ +void +_draw_scrollable_frame (DIALOG * d, int listsize, int offset, int height, + ALLEGRO_COLOR fg_color, ALLEGRO_COLOR bg) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + int i, len; + int xx, yy; + + /* draw frame */ + rect (gui_bmp, d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, fg_color); + + /* possibly draw scrollbar */ + if (listsize > height) + { + vline (gui_bmp, d->x + d->w - 13, d->y + 1, d->y + d->h - 2, fg_color); + + /* scrollbar with focus */ + if (d->flags & D_GOTFOCUS) + { + dotted_rect (d->x + 1, d->y + 1, d->x + d->w - 14, d->y + d->h - 2, + fg_color, bg); + dotted_rect (d->x + d->w - 12, d->y + 1, d->x + d->w - 2, + d->y + d->h - 2, fg_color, bg); + } + else + { + rect (gui_bmp, d->x + 1, d->y + 1, d->x + d->w - 14, + d->y + d->h - 2, bg); + rect (gui_bmp, d->x + d->w - 12, d->y + 1, d->x + d->w - 2, + d->y + d->h - 2, bg); + } + + /* create and draw the scrollbar */ + i = ((d->h - 5) * height + listsize / 2) / listsize; + xx = d->x + d->w - 11; + yy = d->y + 2; + + if (offset > 0) + { + len = (((d->h - 5) * offset) + listsize / 2) / listsize; + rectfill (gui_bmp, xx, yy, xx + 8, yy + len, bg); + yy += len; + } + if (yy + i < d->y + d->h - 3) + { + rectfill_dotted (gui_bmp, xx, yy, xx + 8, yy + i, fg_color, bg); + yy += i + 1; + rectfill (gui_bmp, xx, yy, xx + 8, d->y + d->h - 3, bg); + } + else + { + rectfill_dotted (gui_bmp, xx, yy, xx + 8, d->y + d->h - 3, fg_color, + bg); + } + } + else + { + /* no scrollbar necessary */ + if (d->flags & D_GOTFOCUS) + dotted_rect (d->x + 1, d->y + 1, d->x + d->w - 2, d->y + d->h - 2, + fg_color, bg); + else + rect (gui_bmp, d->x + 1, d->y + 1, d->x + d->w - 2, d->y + d->h - 2, + bg); + } +} + + + +/* draw_listbox: + * Helper function to draw a listbox object. + */ +void +_draw_listbox (DIALOG * d) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + int height, listsize, i, len, bar, x, y, w; + ALLEGRO_COLOR fg_color, fg, bg; + char *sel = d->dp2; + char s[1024]; + + (*(getfuncptr) d->dp) (-1, &listsize); + height = (d->h - 4) / text_height (font); + bar = (listsize > height); + w = (bar ? d->w - 15 : d->w - 3); + fg_color = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + + /* draw box contents */ + for (i = 0; i < height; i++) + { + if (d->d2 + i < listsize) + { + if (sel) + { + if ((sel[d->d2 + i]) && (d->d2 + i == d->d1)) + { + fg = d->bg; + bg = fg_color; + } + else if (sel[d->d2 + i]) + { + fg = d->bg; + bg = gui_mg_color; + } + else + { + fg = fg_color; + bg = d->bg; + } + } + else if (d->d2 + i == d->d1) + { + fg = d->bg; + bg = fg_color; + } + else + { + fg = fg_color; + bg = d->bg; + } + LW_MACRO_STRNCPY (s, (*(getfuncptr) d->dp) (i + d->d2, NULL), + sizeof (s)); + x = d->x + 2; + y = d->y + 2 + i * text_height (font); + rectfill (gui_bmp, x, y, x + 7, y + text_height (font) - 1, bg); + x += 8; + len = ustrlen (s); + while (text_length (font, s) >= MAX (d->w - 1 - (bar ? 22 : 10), 1)) + { + len--; + usetat (s, len, 0, sizeof (s)); + } + textout_ex (gui_bmp, font, s, x, y, fg, bg); + x += text_length (font, s); + if (x <= d->x + w) + rectfill (gui_bmp, x, y, d->x + w, y + text_height (font) - 1, + bg); + if (d->d2 + i == d->d1) + dotted_rect (d->x + 2, y, d->x + d->w - (bar ? 15 : 3), + y + text_height (font) - 1, d->fg, d->bg); + } + else + { + rectfill (gui_bmp, d->x + 2, d->y + 2 + i * text_height (font), + d->x + w, d->y + 1 + (i + 1) * text_height (font), d->bg); + } + } + + if (d->y + 2 + i * text_height (font) <= d->y + d->h - 3) + rectfill (gui_bmp, d->x + 2, d->y + 2 + i * text_height (font), + d->x + w, d->y + d->h - 3, d->bg); + + /* draw frame, maybe with scrollbar */ + _draw_scrollable_frame (d, listsize, d->d2, height, fg_color, d->bg); +} + + + +/* d_list_proc: + * A list box object. The dp field points to a function which it will call + * to obtain information about the list. This should follow the form: + * const char * (int index, int *list_size); + * If index is zero or positive, the function should return a pointer to + * the string which is to be displayed at position index in the list. If + * index is negative, it should return null and list_size should be set + * to the number of items in the list. The list box object will allow the + * user to scroll through the list and to select items list by clicking + * on them, and if it has the input focus also by using the arrow keys. If + * the D_EXIT flag is set, double clicking on a list item will cause it to + * close the dialog. The index of the selected item is held in the d1 + * field, and d2 is used to store how far it has scrolled through the list. + */ +int +d_list_proc (int msg, DIALOG * d, int c) +{ + int listsize, i, bottom, height, bar; + ALLEGRO_ASSERT (d); + + switch (msg) + { + + case MSG_START: + (*(getfuncptr) d->dp) (-1, &listsize); + _handle_scrollable_scroll (d, listsize, &d->d1, &d->d2); + break; + + case MSG_DRAW: + _draw_listbox (d); + break; + + case MSG_CLICK: + (*(getfuncptr) d->dp) (-1, &listsize); + height = (d->h - 4) / text_height (font); + bar = (listsize > height); + if ((!bar) || (gui_mouse_x () < d->x + d->w - 13)) + { + _handle_listbox_click (d); + while (gui_mouse_b ()) + { + broadcast_dialog_message (MSG_IDLE, 0); + d->flags |= D_INTERNAL; + _handle_listbox_click (d); + d->flags &= ~D_INTERNAL; + } + } + else + { + _handle_scrollable_scroll_click (d, listsize, &d->d2, height); + } + break; + + case MSG_DCLICK: + (*(getfuncptr) d->dp) (-1, &listsize); + height = (d->h - 4) / text_height (font); + bar = (listsize > height); + if ((!bar) || (gui_mouse_x () < d->x + d->w - 13)) + { + if (d->flags & D_EXIT) + { + if (listsize) + { + i = d->d1; + object_message (d, MSG_CLICK, 0); + if (i == d->d1) + return D_CLOSE; + } + } + } + break; + + case MSG_WHEEL: + (*(getfuncptr) d->dp) (-1, &listsize); + height = (d->h - 4) / text_height (font); + if (height < listsize) + { + int delta = (height > 3) ? 3 : 1; + if (c > 0) + i = MAX (0, d->d2 - delta); + else + i = MIN (listsize - height, d->d2 + delta); + if (i != d->d2) + { + d->d2 = i; + object_message (d, MSG_DRAW, 0); + } + } + break; + + case MSG_KEY: + (*(getfuncptr) d->dp) (-1, &listsize); + if ((listsize) && (d->flags & D_EXIT)) + return D_CLOSE; + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_CHAR: + (*(getfuncptr) d->dp) (-1, &listsize); + + if (listsize) + { + c >>= 8; + + bottom = d->d2 + (d->h - 4) / text_height (font) - 1; + if (bottom >= listsize - 1) + bottom = listsize - 1; + + if (c == ALLEGRO_KEY_UP) + d->d1--; + else if (c == ALLEGRO_KEY_DOWN) + d->d1++; + else if (c == ALLEGRO_KEY_HOME) + d->d1 = 0; + else if (c == ALLEGRO_KEY_END) + d->d1 = listsize - 1; + else if (c == ALLEGRO_KEY_PGUP) + { + if (d->d1 > d->d2) + d->d1 = d->d2; + else + d->d1 -= (bottom - d->d2) ? bottom - d->d2 : 1; + } + else if (c == ALLEGRO_KEY_PGDN) + { + if (d->d1 < bottom) + d->d1 = bottom; + else + d->d1 += (bottom - d->d2) ? bottom - d->d2 : 1; + } + else + return D_O_K; + + /* if we changed something, better redraw... */ + _handle_scrollable_scroll (d, listsize, &d->d1, &d->d2); + d->flags |= D_DIRTY; + return D_USED_CHAR; + } + break; + } + + return D_O_K; +} + + + +/* d_text_list_proc: + * Like d_list_proc, but allows the user to type in the first few characters + * of a listbox entry in order to select it. Uses dp3 internally, so you + * mustn't store anything important there yourself. + */ +int +d_text_list_proc (int msg, DIALOG * d, int c) +{ + int listsize, i, a, failure; + char *selected, *thisitem; + char *sel = d->dp2; + ALLEGRO_ASSERT (d); + + switch (msg) + { + + case MSG_START: + case MSG_CLICK: + case MSG_DCLICK: + case MSG_WANTFOCUS: + case MSG_LOSTFOCUS: + d->dp3 = 0; + break; + + case MSG_CHAR: + if ((c & 0xFF) < ' ') + d->dp3 = 0; + break; + + case MSG_UCHAR: + (*(getfuncptr) d->dp) (-1, &listsize); + + if (listsize) + { + if (c >= ' ') + { + selected = (*(getfuncptr) d->dp) (d->d1, NULL); + + i = d->d1; + + do + { + thisitem = (*(getfuncptr) d->dp) (i, NULL); + failure = FALSE; + + if ((int) ((unsigned long) d->dp3) < ustrlen (thisitem)) + { + for (a = 0; a < (int) ((unsigned long) d->dp3); a++) + { + if (utolower (ugetat (thisitem, a)) != + utolower (ugetat (selected, a))) + { + failure = TRUE; + break; + } + } + + if ((!failure) + && + (utolower + (ugetat (thisitem, (int) (unsigned long) d->dp3)) + == utolower (c))) + { + d->d1 = i; + d->dp3 = (void *) ((unsigned long) d->dp3 + 1); + + if (sel) + { + for (i = 0; i < listsize; i++) + sel[i] = FALSE; + } + + _handle_scrollable_scroll (d, listsize, &d->d1, + &d->d2); + object_message (d, MSG_DRAW, 0); + return D_USED_CHAR; + } + } + + i++; + if (i >= listsize) + i = 0; + + } + while (i != d->d1); + + if (d->dp3) + { + d->dp3 = 0; + return d_text_list_proc (msg, d, c); + } + } + } + break; + } + + return d_list_proc (msg, d, c); +} + + + +/* _draw_textbox: + * Helper function to draw a textbox object. + */ +void +_draw_textbox (char *thetext, int *listsize, int draw, int offset, + int wword, int tabsize, int x, int y, int w, int h, + int disabled, ALLEGRO_COLOR fore, ALLEGRO_COLOR deselect, ALLEGRO_COLOR disable) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + ALLEGRO_COLOR fg = fore; + int y1 = y + 4; + int x1; + int len; + int ww = w - 6; + char s[16]; + char text[16]; + char space[16]; + char *printed = text; + char *scanned = text; + char *oldscan = text; + char *ignore = NULL; + char *tmp, *ptmp; + int width; + int line = 0; + int i = 0; + int noignore; + + usetc (s + usetc (s, '.'), 0); + usetc (text + usetc (text, ' '), 0); + usetc (space + usetc (space, ' '), 0); + + /* find the correct text */ + if (thetext != NULL) + { + printed = thetext; + scanned = thetext; + } + + /* do some drawing setup */ + if (draw) + { + /* initial start blanking at the top */ + rectfill (gui_bmp, x + 2, y + 2, x + w - 3, y1 - 1, deselect); + } + + /* choose the text color */ + if (disabled) + fg = disable; + + /* loop over the entire string */ + while (1) + { + width = 0; + + /* find the next break */ + while (ugetc (scanned)) + { + /* check for a forced break */ + if (ugetc (scanned) == '\n') + { + scanned += uwidth (scanned); + + /* we are done parsing the line end */ + break; + } + + /* the next character length */ + usetc (s + usetc (s, ugetc (scanned)), 0); + len = text_length (font, s); + + /* modify length if its a tab */ + if (ugetc (s) == '\t') + len = tabsize * text_length (font, space); + + /* check for the end of a line by excess width of next char */ + if (width + len >= ww) + { + /* we have reached end of line do we go back to find start */ + if (wword) + { + /* remember where we were */ + oldscan = scanned; + noignore = FALSE; + + /* go backwards looking for start of word */ + while (!uisspace (ugetc (scanned))) + { + /* don't wrap too far */ + if (scanned == printed) + { + /* the whole line is filled, so stop here */ + tmp = ptmp = scanned; + while (ptmp != oldscan) + { + ptmp = tmp; + tmp += uwidth (tmp); + } + scanned = ptmp; + noignore = TRUE; + break; + } + /* look further backwards to wrap */ + tmp = ptmp = printed; + while (tmp < scanned) + { + ptmp = tmp; + tmp += uwidth (tmp); + } + scanned = ptmp; + } + /* put the space at the end of the line */ + if (!noignore) + { + ignore = scanned; + scanned += uwidth (scanned); + } + else + ignore = NULL; + + /* check for endline at the convenient place */ + if (ugetc (scanned) == '\n') + scanned += uwidth (scanned); + } + /* we are done parsing the line end */ + break; + } + + /* the character can be added */ + scanned += uwidth (scanned); + width += len; + } + + /* check if we are to print it */ + if ((draw) && (line >= offset) + && (y1 + text_height (font) < (y + h - 3))) + { + x1 = x + 4; + + /* the initial blank bit */ + rectfill (gui_bmp, x + 2, y1, x1 - 1, y1 + text_height (font), + deselect); + + /* print up to the marked character */ + while (printed != scanned) + { + /* do special stuff for each charater */ + switch (ugetc (printed)) + { + + case '\r': + case '\n': + /* don't print endlines in the text */ + break; + + /* possibly expand the tabs */ + case '\t': + for (i = 0; i < tabsize; i++) + { + usetc (s + usetc (s, ' '), 0); + textout_ex (gui_bmp, font, s, x1, y1, fg, deselect); + x1 += text_length (font, s); + } + break; + + /* print a normal character */ + default: + if (printed != ignore) + { + usetc (s + usetc (s, ugetc (printed)), 0); + textout_ex (gui_bmp, font, s, x1, y1, fg, deselect); + x1 += text_length (font, s); + } + } + + /* goto the next character */ + printed += uwidth (printed); + } + /* the last blank bit */ + if (x1 <= x + w - 3) + rectfill (gui_bmp, x1, y1, x + w - 3, y1 + text_height (font) - 1, + deselect); + + /* print the line end */ + y1 += text_height (font); + } + printed = scanned; + + /* we have done a line */ + line++; + + /* check if we are at the end of the string */ + if (!ugetc (printed)) + { + /* the under blank bit */ + if (draw) + rectfill (gui_bmp, x + 1, y1, x + w - 3, y + h - 1, deselect); + + /* tell how many lines we found */ + *listsize = line; + return; + } + } + +} + + + +/* d_textbox_proc: + * A text box object. The dp field points to a char * which is the text + * to be displayed in the text box. If the text is long, there will be + * a vertical scrollbar on the right hand side of the object which can + * be used to scroll through the text. The default is to print the text + * with word wrapping, but if the D_SELECTED flag is set, the text will + * be printed with character wrapping. The d1 field is used internally + * to store the number of lines of text, and d2 is used to store how far + * it has scrolled through the text. + */ +int +d_textbox_proc (int msg, DIALOG * d, int c) +{ + int height, bar, ret = D_O_K; + int start, top, bottom, l; + int used, delta; + ALLEGRO_COLOR fg_color; + ALLEGRO_ASSERT (d); + + fg_color = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + /* calculate the actual height */ + height = (d->h - 8) / text_height (font); + + switch (msg) + { + + case MSG_START: + /* measure how many lines of text we contain */ + _draw_textbox (d->dp, &d->d1, 0, /* DONT DRAW anything */ + d->d2, !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w, d->h, + (d->flags & D_DISABLED), NO_COLOR, NO_COLOR, NO_COLOR); + break; + + case MSG_DRAW: + /* tell the object to sort of draw, but only calculate the listsize */ + _draw_textbox (d->dp, &d->d1, 0, /* DONT DRAW anything */ + d->d2, !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w, d->h, + (d->flags & D_DISABLED), NO_COLOR, NO_COLOR, NO_COLOR); + + if (d->d1 > height) + { + bar = 12; + } + else + { + bar = 0; + d->d2 = 0; + } + + /* now do the actual drawing */ + _draw_textbox (d->dp, &d->d1, 1, d->d2, + !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w - bar, d->h, + (d->flags & D_DISABLED), fg_color, d->bg, gui_mg_color); + + /* draw the frame around */ + _draw_scrollable_frame (d, d->d1, d->d2, height, fg_color, d->bg); + break; + + case MSG_CLICK: + /* figure out if it's on the text or the scrollbar */ + bar = (d->d1 > height); + + if ((!bar) || (gui_mouse_x () < d->x + d->w - 13)) + { + /* clicked on the text area */ + ret = D_O_K; + } + else + { + /* clicked on the scroll area */ + _handle_scrollable_scroll_click (d, d->d1, &d->d2, height); + } + break; + + case MSG_CHAR: + start = d->d2; + used = D_USED_CHAR; + + if (d->d1 > 0) + { + if (d->d2 > 0) + top = d->d2 + 1; + else + top = 0; + + l = (d->h - 8) / text_height (font); + + bottom = d->d2 + l - 1; + if (bottom >= d->d1 - 1) + bottom = d->d1 - 1; + else + bottom--; + + if ((c >> 8) == ALLEGRO_KEY_UP) + d->d2--; + else if ((c >> 8) == ALLEGRO_KEY_DOWN) + d->d2++; + else if ((c >> 8) == ALLEGRO_KEY_HOME) + d->d2 = 0; + else if ((c >> 8) == ALLEGRO_KEY_END) + d->d2 = d->d1 - l; + else if ((c >> 8) == ALLEGRO_KEY_PGUP) + d->d2 -= (bottom - top) ? bottom - top : 1; + else if ((c >> 8) == ALLEGRO_KEY_PGDN) + d->d2 += (bottom - top) ? bottom - top : 1; + else + used = D_O_K; + + /* make sure that the list stays in bounds */ + if (d->d2 > d->d1 - l) + d->d2 = d->d1 - l; + if (d->d2 < 0) + d->d2 = 0; + } + else + used = D_O_K; + + /* if we changed something, better redraw... */ + if (d->d2 != start) + d->flags |= D_DIRTY; + + ret = used; + break; + + case MSG_WHEEL: + l = (d->h - 8) / text_height (font); + delta = (l > 3) ? 3 : 1; + + /* scroll, making sure that the list stays in bounds */ + start = d->d2; + d->d2 = + (c > 0) ? MAX (0, d->d2 - delta) : MIN (d->d1 - l, d->d2 + delta); + + /* if we changed something, better redraw... */ + if (d->d2 != start) + d->flags |= D_DIRTY; + + ret = D_O_K; + break; + + case MSG_WANTFOCUS: + /* if we don't have a scrollbar we can't do anything with the focus */ + if (d->d1 > height) + ret = D_WANTFOCUS; + break; + + default: + ret = D_O_K; + } + + return ret; +} + + + +/* d_slider_proc: + * A slider control object. This object returns a value in d2, in the + * range from 0 to d1. It will display as a vertical slider if h is + * greater than or equal to w; otherwise, it will display as a horizontal + * slider. dp can contain an optional bitmap to use for the slider handle; + * dp2 can contain an optional callback function, which is called each + * time d2 changes. The callback function should have the following + * prototype: + * + * int function(void *dp3, int d2); + * + * The d_slider_proc object will return the value of the callback function. + */ +int +d_slider_proc (int msg, DIALOG * d, int c) +{ + ALLEGRO_BITMAP *gui_bmp = gui_get_screen (); + ALLEGRO_BITMAP *slhan = NULL; + int oldpos, newpos; + ALLEGRO_COLOR sfg; /* slider foreground color */ + int vert = TRUE; /* flag: is slider vertical? */ + int hh = 7; /* handle height (width for horizontal sliders) */ + int hmar; /* handle margin */ + int slp; /* slider position */ + int mp; /* mouse position */ + int irange; + int slx, sly, slh, slw; + int msx, msy; + int retval = D_O_K; + int upkey, downkey; + int pgupkey, pgdnkey; + int homekey, endkey; + int delta; + al_fixed slratio, slmax, slpos; + int (*proc) (void *cbpointer, int d2value); + int oldval; + ALLEGRO_ASSERT (d); + + /* check for slider direction */ + if (d->h < d->w) + vert = FALSE; + + /* set up the metrics for the control */ + if (d->dp != NULL) + { + slhan = (ALLEGRO_BITMAP *) d->dp; + if (vert) + hh = al_get_bitmap_height (slhan); + else + hh = al_get_bitmap_width (slhan); + } + + hmar = hh / 2; + irange = (vert) ? d->h : d->w; + slmax = al_itofix (irange - hh); + slratio = slmax / (d->d1); + slpos = slratio * d->d2; + slp = al_fixtoi (slpos); + + switch (msg) + { + + case MSG_DRAW: + sfg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + + if (vert) + { + rectfill (gui_bmp, d->x, d->y, d->x + d->w / 2 - 2, d->y + d->h - 1, + d->bg); + rectfill (gui_bmp, d->x + d->w / 2 - 1, d->y, d->x + d->w / 2 + 1, + d->y + d->h - 1, sfg); + rectfill (gui_bmp, d->x + d->w / 2 + 2, d->y, d->x + d->w - 1, + d->y + d->h - 1, d->bg); + } + else + { + rectfill (gui_bmp, d->x, d->y, d->x + d->w - 1, d->y + d->h / 2 - 2, + d->bg); + rectfill (gui_bmp, d->x, d->y + d->h / 2 - 1, d->x + d->w - 1, + d->y + d->h / 2 + 1, sfg); + rectfill (gui_bmp, d->x, d->y + d->h / 2 + 2, d->x + d->w - 1, + d->y + d->h - 1, d->bg); + } + + /* okay, background and slot are drawn, now draw the handle */ + if (slhan) + { + if (vert) + { + slx = d->x + (d->w / 2) - (al_get_bitmap_width (slhan) / 2); + sly = d->y + (d->h - 1) - (hh + slp); + } + else + { + slx = d->x + slp; + sly = d->y + (d->h / 2) - (al_get_bitmap_height (slhan) / 2); + } + draw_sprite (gui_bmp, slhan, slx, sly); + } + else + { + /* draw default handle */ + if (vert) + { + slx = d->x; + sly = d->y + (d->h) - (hh + slp); + slw = d->w - 1; + slh = hh - 1; + } + else + { + slx = d->x + slp; + sly = d->y; + slw = hh - 1; + slh = d->h - 1; + } + + /* draw body */ + rectfill (gui_bmp, slx + 2, sly, slx + (slw - 2), sly + slh, sfg); + vline (gui_bmp, slx + 1, sly + 1, sly + slh - 1, sfg); + vline (gui_bmp, slx + slw - 1, sly + 1, sly + slh - 1, sfg); + vline (gui_bmp, slx, sly + 2, sly + slh - 2, sfg); + vline (gui_bmp, slx + slw, sly + 2, sly + slh - 2, sfg); + vline (gui_bmp, slx + 1, sly + 2, sly + slh - 2, d->bg); + hline (gui_bmp, slx + 2, sly + 1, slx + slw - 2, d->bg); + putpixel (gui_bmp, slx + 2, sly + 2, d->bg); + } + + if (d->flags & D_GOTFOCUS) + dotted_rect (d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, sfg, + d->bg); + break; + + case MSG_WANTFOCUS: + case MSG_LOSTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + if (!(d->flags & D_GOTFOCUS)) + return D_WANTFOCUS; + else + return D_O_K; + + case MSG_CHAR: + /* handle movement keys to move slider */ + c >>= 8; + + if (vert) + { + upkey = ALLEGRO_KEY_UP; + downkey = ALLEGRO_KEY_DOWN; + pgupkey = ALLEGRO_KEY_PGUP; + pgdnkey = ALLEGRO_KEY_PGDN; + homekey = ALLEGRO_KEY_END; + endkey = ALLEGRO_KEY_HOME; + } + else + { + upkey = ALLEGRO_KEY_RIGHT; + downkey = ALLEGRO_KEY_LEFT; + pgupkey = ALLEGRO_KEY_PGDN; + pgdnkey = ALLEGRO_KEY_PGUP; + homekey = ALLEGRO_KEY_HOME; + endkey = ALLEGRO_KEY_END; + } + + if (c == upkey) + delta = 1; + else if (c == downkey) + delta = -1; + else if (c == pgdnkey) + delta = -d->d1 / 16; + else if (c == pgupkey) + delta = d->d1 / 16; + else if (c == homekey) + delta = -d->d2; + else if (c == endkey) + delta = d->d1 - d->d2; + else + delta = 0; + + if (delta) + { + oldpos = slp; + oldval = d->d2; + + while (1) + { + d->d2 = d->d2 + delta; + slpos = slratio * d->d2; + slp = al_fixtoi (slpos); + if ((slp != oldpos) || (d->d2 <= 0) || (d->d2 >= d->d1)) + break; + } + + if (d->d2 < 0) + d->d2 = 0; + if (d->d2 > d->d1) + d->d2 = d->d1; + + retval = D_USED_CHAR; + + if (d->d2 != oldval) + { + /* call callback function here */ + if (d->dp2) + { + proc = d->dp2; + retval |= (*proc) (d->dp3, d->d2); + } + + object_message (d, MSG_DRAW, 0); + } + } + break; + + case MSG_WHEEL: + oldval = d->d2; + d->d2 = CLAMP (0, d->d2 + c, d->d1); + if (d->d2 != oldval) + { + /* call callback function here */ + if (d->dp2) + { + proc = d->dp2; + retval |= (*proc) (d->dp3, d->d2); + } + + object_message (d, MSG_DRAW, 0); + } + break; + + case MSG_CLICK: + /* track the mouse until it is released */ + mp = slp; + + while (gui_mouse_b ()) + { + msx = gui_mouse_x (); + msy = gui_mouse_y (); + oldval = d->d2; + if (vert) + mp = (d->y + d->h - hmar) - msy; + else + mp = msx - (d->x + hmar); + if (mp < 0) + mp = 0; + if (mp > irange - hh) + mp = irange - hh; + slpos = al_itofix (mp); + slmax = al_fixdiv (slpos, slratio); + newpos = al_fixtoi (slmax); + if (newpos != oldval) + { + d->d2 = newpos; + + /* call callback function here */ + if (d->dp2 != NULL) + { + proc = d->dp2; + retval |= (*proc) (d->dp3, d->d2); + } + + object_message (d, MSG_DRAW, 0); + } + + /* let other objects continue to animate */ + broadcast_dialog_message (MSG_IDLE, 0); + } + break; + } + + return retval; +} + + + +/* Overridable procedures used by standard GUI dialogs. */ + +#define MAKE_PROC(proc, default) \ +int (*proc)(int, DIALOG *, int); \ +int _##proc(int msg, DIALOG *d, int c) \ +{ \ + return proc ? proc(msg, d, c) : default(msg, d, c); \ +} + +MAKE_PROC (gui_shadow_box_proc, d_shadow_box_proc); +MAKE_PROC (gui_ctext_proc, d_ctext_proc); +MAKE_PROC (gui_button_proc, d_button_proc); +MAKE_PROC (gui_edit_proc, d_edit_proc); +MAKE_PROC (gui_list_proc, d_text_list_proc); +MAKE_PROC (gui_text_list_proc, d_text_list_proc); diff --git a/src/backportguiproc.h b/src/backportguiproc.h new file mode 100644 index 00000000..276e218f --- /dev/null +++ b/src/backportguiproc.h @@ -0,0 +1,35 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * GUI routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GUIPROC_H +#define ALLEGRO_GUIPROC_H + +/* + * [DISCLAIMER:ufoot] this is not really from the allegro source tree. + * Those functions are defined in guiproc.c then exposed in aintern.h. + * But I won't backport all of aintern.h so just extracted those gui funcs. + */ + +int _gui_shadow_box_proc (int msg, DIALOG * d, int c); +int _gui_ctext_proc (int msg, DIALOG * d, int c); +int _gui_button_proc (int msg, DIALOG * d, int c); +int _gui_edit_proc (int msg, DIALOG * d, int c); +int _gui_list_proc (int msg, DIALOG * d, int c); +int _gui_text_list_proc (int msg, DIALOG * d, int c); + +#endif // ALLEGRO_GUIPROC_H diff --git a/src/base.h b/src/base.h index f00b211b..3a325552 100644 --- a/src/base.h +++ b/src/base.h @@ -75,7 +75,7 @@ #define DIR_NNW 11 #define LW_PROGRAM "liquidwar" -#define LW_VERSION "5.6.5" +#define LW_VERSION "5.7.0" #define NAME_SIZE 10 #define PASSWORD_SIZE 20 diff --git a/src/bigdata.c b/src/bigdata.c index a8a0400b..f6a2b4d6 100644 --- a/src/bigdata.c +++ b/src/bigdata.c @@ -53,7 +53,7 @@ /*==================================================================*/ #include -#include +#include #include #include "alleg2.h" @@ -221,11 +221,11 @@ free_last_big_data_top (void) int check_free_memory (void) { - BITMAP *result; + ALLEGRO_BITMAP *result; - result = my_create_bitmap (MEMORY_TO_LEAVE / 2, 1024); + result = my_create_memory_bitmap (MEMORY_TO_LEAVE / 2, 1024); if (result) - destroy_bitmap (result); + al_destroy_bitmap (result); return result != NULL; } diff --git a/src/capture.c b/src/capture.c index da4a0e55..93ae401b 100644 --- a/src/capture.c +++ b/src/capture.c @@ -54,13 +54,13 @@ #include #include -#include +#include +#include "backport.h" #include "capture.h" #include "viewport.h" #include "log.h" #include "init.h" -#include "palette.h" #include "config.h" #include "ticker.h" #include "macro.h" @@ -137,9 +137,9 @@ lw_capture_dump_menu () * Now we check manually for F9 for there's no way * to do it easily within the generic menu code. */ - if (key[KEY_F9]) + if (key[ALLEGRO_KEY_F9]) { - while (key[KEY_F9]) + while (key[ALLEGRO_KEY_F9]) { /* * Force a all to poll_keyboard if needed @@ -164,7 +164,7 @@ lw_capture_dump_game () int result = 1; char buffer[LW_CAPTURE_FILENAME_BUFFER_SIZE]; static int frame_number = 0; - BITMAP *screenshot; + ALLEGRO_BITMAP *screenshot; /* * We do nothing if we're not in capture mode @@ -188,15 +188,15 @@ lw_capture_dump_game () * Create a sub-bitmap with the right size */ screenshot = - create_sub_bitmap (screen, 0, PAGE_FLIP_H, SCREEN_W, SCREEN_H); + al_create_sub_bitmap (screen, 0, PAGE_FLIP_H, SCREEN_W, SCREEN_H); if (screenshot) { /* * Write to disk */ - result = !save_bitmap (buffer, screenshot, GLOBAL_PALETTE); - destroy_bitmap (screenshot); + result = !al_save_bitmap (buffer, screenshot); + al_destroy_bitmap (screenshot); } else { diff --git a/src/code.c b/src/code.c index f109305f..27621d34 100644 --- a/src/code.c +++ b/src/code.c @@ -53,7 +53,7 @@ /*==================================================================*/ #include -#include +#include #include "config.h" #include "decal.h" @@ -91,7 +91,7 @@ display_special_info (void) { int global, spread, move, disp, flip; - if (WATCHDOG_SCANCODE[KEY_F5]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F5]) { global = get_profile (GLOBAL_PROFILE); if (global <=0) @@ -100,7 +100,7 @@ display_special_info (void) 1000 / global); } - if (WATCHDOG_SCANCODE[KEY_F6]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F6]) { global = get_logic_rate (); if (global <=0) @@ -109,7 +109,7 @@ display_special_info (void) 1000 / global); } - if (WATCHDOG_SCANCODE[KEY_F7]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F7]) { global = get_profile (GLOBAL_PROFILE); spread = get_profile (SPREAD_PROFILE); @@ -120,7 +120,7 @@ display_special_info (void) (100 * (spread + move)) / global); } - if (WATCHDOG_SCANCODE[KEY_F8]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F8]) { global = get_profile (GLOBAL_PROFILE); disp = get_profile (DISP_PROFILE); @@ -211,7 +211,7 @@ check_boolean_codes (void) /* * If we press F3 and we're not in network mode -> toggle pause mode */ - if (WATCHDOG_SCANCODE[KEY_F3] && !LW_NETWORK_ON) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F3] && !LW_NETWORK_ON) { if (PAUSE_ON) { @@ -224,7 +224,7 @@ check_boolean_codes (void) message_str (lw_lang_string (LW_LANG_STRING_CODE_PAUSEON)); } } - if (WATCHDOG_SCANCODE[KEY_F4]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F4]) { if (CONFIG_WAVE_ON) { @@ -237,7 +237,7 @@ check_boolean_codes (void) message_str (lw_lang_string (LW_LANG_STRING_CODE_WAVEEFFECTSON)); } } - if (WATCHDOG_SCANCODE[KEY_F9]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F9]) { if (lw_capture_get_mode ()) { diff --git a/src/config.c b/src/config.c index 11bf0339..f3341621 100644 --- a/src/config.c +++ b/src/config.c @@ -52,15 +52,15 @@ /* includes */ /*==================================================================*/ -#include +#include #include +#include "backport.h" #include "config.h" #include "disk.h" #include "joystick.h" #include "keyboard.h" #include "mouse.h" -#include "palette.h" #include "startup.h" #include "server.h" #include "lang.h" @@ -96,10 +96,10 @@ #define LABEL_LEVEL_FG "LEVEL_FG" #define LABEL_LEVEL_BG "LEVEL_BG" #define LABEL_FIGHTER_NUMBER "FIGHTER_NUMBER" -#define LABEL_KEY_UP "KEY_UP" -#define LABEL_KEY_LEFT "KEY_LEFT" -#define LABEL_KEY_DOWN "KEY_DOWN" -#define LABEL_KEY_RIGHT "KEY_RIGHT" +#define LABEL_KEY_UP "ALLEGRO_KEY_UP" +#define LABEL_KEY_LEFT "ALLEGRO_KEY_LEFT" +#define LABEL_KEY_DOWN "ALLEGRO_KEY_DOWN" +#define LABEL_KEY_RIGHT "ALLEGRO_KEY_RIGHT" #define LABEL_TEAM_COLOR "TEAM_COLOR" #define LABEL_CONTROL_TYPE "CONTROL_TYPE" #define LABEL_PLAYER_NAME "PLAYER_NAME" @@ -116,7 +116,6 @@ #define LABEL_ROUNDS_PER_SEC_LIMIT "ROUNDS_PER_SEC_LIMIT" #define LABEL_SERVER_ADDRESS "SERVER_ADDRESS" #define LABEL_SERVER_PORT "SERVER_PORT" -#define LABEL_ASM_ALGORITHM "ASM_ALGORITHM" #define LABEL_PASSWORD "PASSWORD" #define LABEL_MIN_MAP_RES "MIN_MAP_RES" #define LABEL_USE_DEFAULT_TEXTURE "USE_DEFAULT_TEXTURE" @@ -166,7 +165,6 @@ int CONFIG_FRAMES_PER_SEC_LIMIT; int CONFIG_ROUNDS_PER_SEC_LIMIT; char CONFIG_SERVER_ADDRESS[SERVER_ADDRESS_SIZE + 1]; int CONFIG_SERVER_PORT; -int CONFIG_ASM_ALGORITHM; char CONFIG_PASSWORD[PASSWORD_SIZE + 1]; int CONFIG_MIN_MAP_RES; int CONFIG_USE_DEFAULT_TEXTURE; @@ -198,13 +196,8 @@ int MIN_MAP_RES_H[9] = { 0, 60, 90, 120, 150, 180, 240, 360, 480 }; void load_default_options (void) { -#ifdef DOS - CONFIG_GFX_GAME = 0; - CONFIG_GFX_MENU = 2; -#else CONFIG_GFX_GAME = 2; CONFIG_GFX_MENU = 2; -#endif #ifdef UNIX /* * Under UNIX/X11, we default to windowed mode since @@ -242,42 +235,42 @@ load_default_options (void) CONFIG_LEVEL_FG = 135; CONFIG_LEVEL_BG = 131; - CONFIG_KEY_UP[0] = KEY_UP; - CONFIG_KEY_DOWN[0] = KEY_DOWN; - CONFIG_KEY_LEFT[0] = KEY_LEFT; - CONFIG_KEY_RIGHT[0] = KEY_RIGHT; + CONFIG_KEY_UP[0] = ALLEGRO_KEY_UP; + CONFIG_KEY_DOWN[0] = ALLEGRO_KEY_DOWN; + CONFIG_KEY_LEFT[0] = ALLEGRO_KEY_LEFT; + CONFIG_KEY_RIGHT[0] = ALLEGRO_KEY_RIGHT; CONFIG_TEAM_COLOR[0] = 0; CONFIG_CONTROL_TYPE[0] = CONFIG_CONTROL_TYPE_HUMAN; LW_MACRO_STRCPY (CONFIG_PLAYER_NAME[0], "Napoleon"); - CONFIG_KEY_UP[1] = KEY_I; - CONFIG_KEY_DOWN[1] = KEY_K; - CONFIG_KEY_LEFT[1] = KEY_J; - CONFIG_KEY_RIGHT[1] = KEY_L; + CONFIG_KEY_UP[1] = ALLEGRO_KEY_I; + CONFIG_KEY_DOWN[1] = ALLEGRO_KEY_K; + CONFIG_KEY_LEFT[1] = ALLEGRO_KEY_J; + CONFIG_KEY_RIGHT[1] = ALLEGRO_KEY_L; CONFIG_TEAM_COLOR[1] = 4; CONFIG_CONTROL_TYPE[1] = CONFIG_CONTROL_TYPE_OFF; LW_MACRO_STRCPY (CONFIG_PLAYER_NAME[1], "Clovis"); - CONFIG_KEY_UP[2] = KEY_UP; - CONFIG_KEY_DOWN[2] = KEY_DOWN; - CONFIG_KEY_LEFT[2] = KEY_LEFT; - CONFIG_KEY_RIGHT[2] = KEY_RIGHT; + CONFIG_KEY_UP[2] = ALLEGRO_KEY_UP; + CONFIG_KEY_DOWN[2] = ALLEGRO_KEY_DOWN; + CONFIG_KEY_LEFT[2] = ALLEGRO_KEY_LEFT; + CONFIG_KEY_RIGHT[2] = ALLEGRO_KEY_RIGHT; CONFIG_TEAM_COLOR[2] = 8; CONFIG_CONTROL_TYPE[2] = CONFIG_CONTROL_TYPE_OFF; LW_MACRO_STRCPY (CONFIG_PLAYER_NAME[2], "Henri IV"); - CONFIG_KEY_UP[3] = KEY_Q; - CONFIG_KEY_DOWN[3] = KEY_A; - CONFIG_KEY_LEFT[3] = KEY_Z; - CONFIG_KEY_RIGHT[3] = KEY_X; + CONFIG_KEY_UP[3] = ALLEGRO_KEY_Q; + CONFIG_KEY_DOWN[3] = ALLEGRO_KEY_A; + CONFIG_KEY_LEFT[3] = ALLEGRO_KEY_Z; + CONFIG_KEY_RIGHT[3] = ALLEGRO_KEY_X; CONFIG_TEAM_COLOR[3] = 6; CONFIG_CONTROL_TYPE[3] = CONFIG_CONTROL_TYPE_OFF; LW_MACRO_STRCPY (CONFIG_PLAYER_NAME[3], "Cesar"); - CONFIG_KEY_UP[4] = KEY_8_PAD; - CONFIG_KEY_DOWN[4] = KEY_5_PAD; - CONFIG_KEY_LEFT[4] = KEY_4_PAD; - CONFIG_KEY_RIGHT[4] = KEY_6_PAD; + CONFIG_KEY_UP[4] = ALLEGRO_KEY_PAD_8; + CONFIG_KEY_DOWN[4] = ALLEGRO_KEY_PAD_5; + CONFIG_KEY_LEFT[4] = ALLEGRO_KEY_PAD_4; + CONFIG_KEY_RIGHT[4] = ALLEGRO_KEY_PAD_6; CONFIG_TEAM_COLOR[4] = 10; CONFIG_CONTROL_TYPE[4] = CONFIG_CONTROL_TYPE_OFF; LW_MACRO_STRCPY (CONFIG_PLAYER_NAME[4], "Geronimo"); @@ -338,7 +331,6 @@ load_default_rules (void) CONFIG_GAME_TIME = 8; CONFIG_CPU_ADVANTAGE = 0; CONFIG_CPU_VS_HUMAN = CONFIG_CPU_VS_HUMAN_RANDOM; - CONFIG_ASM_ALGORITHM = 1; CONFIG_MIN_MAP_RES = 4; CONFIG_ALLOW_NETWORK_BOTS = 0; } @@ -483,9 +475,6 @@ load_disk_options (void) CONFIG_SERVER_PORT = get_config_int (LABEL_MAIN, LABEL_SERVER_PORT, CONFIG_SERVER_PORT); - CONFIG_ASM_ALGORITHM = - get_config_int (LABEL_MAIN, LABEL_ASM_ALGORITHM, - CONFIG_ASM_ALGORITHM); strncpy (CONFIG_PASSWORD, get_config_string (LABEL_MAIN, LABEL_PASSWORD, @@ -613,7 +602,6 @@ save_config_options (void) set_config_string (LABEL_MAIN, LABEL_SERVER_ADDRESS, CONFIG_SERVER_ADDRESS); set_config_int (LABEL_MAIN, LABEL_SERVER_PORT, CONFIG_SERVER_PORT); - set_config_int (LABEL_MAIN, LABEL_ASM_ALGORITHM, CONFIG_ASM_ALGORITHM); set_config_string (LABEL_MAIN, LABEL_PASSWORD, CONFIG_PASSWORD); @@ -627,6 +615,8 @@ save_config_options (void) set_config_int (LABEL_MAIN, LABEL_LW6_ADVERTISING_DONE, CONFIG_LW6_ADVERTISING_DONE); + flush_config_file(); + return 0; } @@ -661,6 +651,5 @@ lw_config_set_current_rules_to_default (void) config->game_time = CONFIG_GAME_TIME; config->cpu_advantage = CONFIG_CPU_ADVANTAGE; config->cpu_vs_human = CONFIG_CPU_VS_HUMAN; - config->asm_algorithm = CONFIG_ASM_ALGORITHM && STARTUP_ASM; config->min_map_res = CONFIG_MIN_MAP_RES; } diff --git a/src/config.h b/src/config.h index 22241cad..0bd26dbc 100644 --- a/src/config.h +++ b/src/config.h @@ -110,7 +110,6 @@ extern int CONFIG_FRAMES_PER_SEC_LIMIT; extern int CONFIG_ROUNDS_PER_SEC_LIMIT; extern char CONFIG_SERVER_ADDRESS[SERVER_ADDRESS_SIZE + 1]; extern int CONFIG_SERVER_PORT; -extern int CONFIG_ASM_ALGORITHM; extern char CONFIG_PASSWORD[PASSWORD_SIZE + 1]; extern int CONFIG_MIN_MAP_RES; extern int CONFIG_USE_DEFAULT_TEXTURE; diff --git a/src/connect.c b/src/connect.c index b8727598..4081ed65 100644 --- a/src/connect.c +++ b/src/connect.c @@ -208,7 +208,7 @@ lw_connect_menu (int sock) dp = my_init_dialog (d, choix); while (my_update_dialog (dp) && !data->finished) { - show_mouse (screen); + lw_mouse_show (); if (!data->thread_running && !data->finished) { if (!first_getinfo) @@ -311,7 +311,7 @@ lw_connect_menu (int sock) while (data->thread_running) { /* - * Here, we wait until the thread is over, it shouldn't be very + * Here, we wait until the thread is over, it shouldn't be very * long since we just wait for the server's answer */ rest (100); @@ -405,7 +405,7 @@ update_connect_menu (DIALOG * d, d[7].proc (MSG_DRAW, d + 7, 0); unscare_mouse (); - show_mouse (screen); + lw_mouse_show (); /* * If there are more teams connected than last times, we're likely @@ -414,8 +414,8 @@ update_connect_menu (DIALOG * d, if (connected_teams > 0 && connected_teams > *connected_teams_prev) { /* - * We check if this is not the first time - * (*connected_teams_prev==-1) and in this case we play + * We check if this is not the first time + * (*connected_teams_prev==-1) and in this case we play * nothing */ if ((*connected_teams_prev) >= 0) diff --git a/src/cursor.c b/src/cursor.c index e98988b9..4d25456b 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -55,11 +55,11 @@ #include #include +#include "backport.h" #include "army.h" #include "grad.h" #include "cursor.h" #include "mesh.h" -#include "palette.h" /*==================================================================*/ /* variables globales */ diff --git a/src/decal.c b/src/decal.c index 52b73614..9daab791 100644 --- a/src/decal.c +++ b/src/decal.c @@ -65,7 +65,7 @@ int PLAYING_TEAMS = 0; int ACTIVE_FIGHTERS[NB_TEAMS]; -int COLOR_FIRST_ENTRY[NB_TEAMS]; +// COLOR_FIRST_ENTRY removed - colors are now computed dynamically with lw_team_color() /*==================================================================*/ /* fonctions */ @@ -109,7 +109,7 @@ eliminate_team (int team) for (j = team; j < PLAYING_TEAMS; ++j) { ACTIVE_FIGHTERS[j] = ACTIVE_FIGHTERS[j + 1]; - COLOR_FIRST_ENTRY[j] = COLOR_FIRST_ENTRY[j + 1]; + // COLOR_FIRST_ENTRY removed - colors are computed dynamically for (i = 0; i < CURRENT_MESH_SIZE; ++i) { diff --git a/src/decal.h b/src/decal.h index 61f64d7c..04c0e3aa 100644 --- a/src/decal.h +++ b/src/decal.h @@ -63,7 +63,7 @@ extern int PLAYING_TEAMS; extern int ACTIVE_FIGHTERS[NB_TEAMS]; -extern int COLOR_FIRST_ENTRY[NB_TEAMS]; +// COLOR_FIRST_ENTRY removed - colors are now computed dynamically with lw_team_color() /*==================================================================*/ /* fonctions globales */ diff --git a/src/dialog.h b/src/dialog.h index e3d46970..9e86d187 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -55,10 +55,11 @@ /* includes */ /*==================================================================*/ -#include +#include +#include "backport.h" +#include "backportgui.h" #include "alleg2.h" -#include "palette.h" /*==================================================================*/ /* variables globales */ @@ -79,6 +80,15 @@ #define MENU_VIRTUAL_W 320 #define MENU_VIRTUAL_H 240 +// Menu colors - converted from palette indices to ALLEGRO_COLOR +// MENU_BG was palette index 16 (dark gray), MENU_FG was index 17 (light gray) +#define MENU_BG (al_map_rgb(64, 64, 64)) +#define MENU_FG (al_map_rgb(192, 192, 192)) + +// Special color value for "no color" or transparent (was -1 in Allegro 4) +// Use black with 0 alpha for now +#define NO_COLOR (al_map_rgba(0, 0, 0, 0)) + #define MENU_H_STANDARD 15 #define MENU_H_QUICK 15 #define MENU_H_SPACE 3 diff --git a/src/disk.c b/src/disk.c index ff92535d..93e2d3db 100644 --- a/src/disk.c +++ b/src/disk.c @@ -52,18 +52,23 @@ /* includes */ /*==================================================================*/ +#include #include -#include +#include +#include +#include +#include #include "alleg2.h" #include "init.h" #include "disk.h" #include "log.h" #include "map.h" -#include "palette.h" #include "startup.h" #include "texture.h" #include "macro.h" +#include "path.h" +#include "thrdgen.h" /*==================================================================*/ /* defines */ @@ -81,6 +86,8 @@ int RAW_MAPTEX_NUMBER = 0; int RAW_MAP_NUMBER = 0; int MIDI_MUSIC_NUMBER = 0; +int LOADED_FONT = 0; +int LOADED_MAP = 0; int LOADED_BACK = 0; int LOADED_TEXTURE = 0; int LOADED_MAPTEX = 0; @@ -88,30 +95,30 @@ int LOADED_SFX = 0; int LOADED_WATER = 0; int LOADED_MUSIC = 0; -SAMPLE *SAMPLE_SFX_TIME = NULL; -SAMPLE *SAMPLE_SFX_WIN = NULL; -SAMPLE *SAMPLE_SFX_GO = NULL; -SAMPLE *SAMPLE_SFX_CLICK = NULL; -SAMPLE *SAMPLE_SFX_LOOSE = NULL; -SAMPLE *SAMPLE_SFX_CONNECT = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_TIME = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_WIN = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_GO = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_CLICK = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_LOOSE = NULL; +ALLEGRO_SAMPLE *SAMPLE_SFX_CONNECT = NULL; -SAMPLE *SAMPLE_WATER[SAMPLE_WATER_MAX_NUMBER]; +ALLEGRO_SAMPLE *SAMPLE_WATER[SAMPLE_WATER_MAX_NUMBER]; void *RAW_MAP[RAW_MAP_MAX_NUMBER]; void *RAW_MAP_ORDERED[RAW_MAP_MAX_NUMBER]; void *RAW_TEXTURE[RAW_TEXTURE_MAX_NUMBER]; void *RAW_MAPTEX[RAW_TEXTURE_MAX_NUMBER]; -MIDI *MIDI_MUSIC[MIDI_MUSIC_MAX_NUMBER]; +ALLEGRO_SAMPLE *MIDI_MUSIC[MIDI_MUSIC_MAX_NUMBER]; -BITMAP *BACK_IMAGE = NULL; +ALLEGRO_BITMAP *BACK_IMAGE = NULL; -FONT *BIG_FONT = NULL; -FONT *SMALL_FONT = NULL; -BITMAP *BIG_MOUSE_CURSOR = NULL; -BITMAP *SMALL_MOUSE_CURSOR = NULL; -BITMAP *INVISIBLE_MOUSE_CURSOR = NULL; +ALLEGRO_FONT *BIG_FONT = NULL; +ALLEGRO_FONT *SMALL_FONT = NULL; +ALLEGRO_BITMAP *BIG_MOUSE_CURSOR = NULL; +ALLEGRO_BITMAP *SMALL_MOUSE_CURSOR = NULL; +ALLEGRO_BITMAP *INVISIBLE_MOUSE_CURSOR = NULL; -static RGB *FONT_PALETTE = NULL; -static RGB *BACK_PALETTE = NULL; +//static RGB *FONT_PALETTE = NULL; +//static RGB *BACK_PALETTE = NULL; static int CUSTOM_TEXTURE_OK = 0; static int CUSTOM_MAP_OK = 0; @@ -123,7 +130,7 @@ static int CUSTOM_MUSIC_OK = 0; /*------------------------------------------------------------------*/ static void -lock_sound (SAMPLE * smp) +lock_sound (ALLEGRO_SAMPLE * smp) { LOCK_VARIABLE (*smp); #ifdef DOS @@ -134,52 +141,66 @@ lock_sound (SAMPLE * smp) } /*------------------------------------------------------------------*/ -static void -read_sfx_dat (DATAFILE * df) -{ - SAMPLE *list[SAMPLE_SFX_NUMBER]; - int i; - - /* - * First, we associate the _first_ sound of the sub datafile - * to all sounds. This will operate as default value which - * will prevent the game from segfaulting if we use it with - * an outdated or too recent datafile - */ - for (i = 0; i < SAMPLE_SFX_NUMBER && df[i].type != DAT_END; ++i) - { - list[i] = df[0].dat; - } - - /* - * Now we associate the real sounds, provided that they exist... - */ - for (i = 0; i < 6 && df[i].type != DAT_END; ++i) - { - list[i] = df[i].dat; - lock_sound (list[i]); - } +static ALLEGRO_SAMPLE *read_sfx(const char *filename) { + ALLEGRO_SAMPLE *ret = NULL; + + char * path = lw_path_join3(STARTUP_DAT_PATH, "sfx", filename); + if (path == NULL) { + return NULL; + } + log_print_str("."); + ret = al_load_sample(path); + free(path); + return ret; +} - SAMPLE_SFX_TIME = list[0]; - SAMPLE_SFX_WIN = list[1]; - SAMPLE_SFX_CONNECT = list[2]; - SAMPLE_SFX_GO = list[3]; - SAMPLE_SFX_CLICK = list[4]; - SAMPLE_SFX_LOOSE = list[5]; +/*------------------------------------------------------------------*/ +static bool +read_sfx_dat () +{ + SAMPLE_SFX_TIME = read_sfx("clock1.wav"); + SAMPLE_SFX_WIN = read_sfx("crowd1.wav"); + SAMPLE_SFX_CONNECT = read_sfx("cuckoo.wav"); + SAMPLE_SFX_GO = read_sfx("foghorn.wav"); + SAMPLE_SFX_CLICK = read_sfx("spash1.wav"); + SAMPLE_SFX_LOOSE = read_sfx("war.wav"); + + return SAMPLE_SFX_TIME != NULL && + SAMPLE_SFX_WIN != NULL && + SAMPLE_SFX_CONNECT != NULL && + SAMPLE_SFX_GO != NULL && + SAMPLE_SFX_CLICK != NULL && + SAMPLE_SFX_LOOSE != NULL; } /*------------------------------------------------------------------*/ -static void -read_water_dat (DATAFILE * df) +static bool +read_water_dat () { + char water_files[][16] = { + "amb3.wav", "amb4.wav", "bath1.wav", "bath2.wav", + "bubble.wav", "flush.wav", "forest1.wav", "kitch4.wav", + "lavaflow.wav", "niagara.wav", "shower1.wav", "sodapor.wav", + "thundr2.wav", "thundr3.wav", "tidal.wav", "water.wav" + }; + int num_files = sizeof(water_files) / sizeof(water_files[0]); int i; - for (i = 0; i < SAMPLE_WATER_DAT_NUMBER && df[i].type != DAT_END; ++i) + SAMPLE_WATER_NUMBER = 0; + for (i = 0; i < num_files && i < SAMPLE_WATER_MAX_NUMBER; ++i) { - SAMPLE_WATER[i] = df[i].dat; - lock_sound (SAMPLE_WATER[i]); - SAMPLE_WATER_NUMBER++; + char * path = lw_path_join3(STARTUP_DAT_PATH, "water", water_files[i]); + if (path != NULL) { + log_print_str("."); + SAMPLE_WATER[i] = al_load_sample(path); + if (SAMPLE_WATER[i] != NULL) { + lock_sound (SAMPLE_WATER[i]); + SAMPLE_WATER_NUMBER++; + } + free(path); + } } + return SAMPLE_WATER_NUMBER > 0; } /*------------------------------------------------------------------*/ @@ -187,118 +208,449 @@ read_water_dat (DATAFILE * df) /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ -static void -read_texture_dat (DATAFILE * df) +static bool +read_texture_dat () { + char texture_files[][32] = { + "amethyst.bmp", "bricks.bmp", "crash1.bmp", + "electricblue.bmp", "granite2.bmp", "greenmess.bmp", + "lumps.bmp", "marble3.bmp", "pebbles.bmp", + "pine.bmp", "poolbottom.bmp", "qbert.bmp", + "redcubes.bmp", "smallsquares.bmp", "terra.bmp", + "wood2.bmp" + }; + int num_files = sizeof(texture_files) / sizeof(texture_files[0]); int i; RAW_TEXTURE_NUMBER = 0; - for (i = 0; i < RAW_TEXTURE_DAT_NUMBER && df[i].type != DAT_END; ++i) + for (i = 0; i < num_files && i < RAW_TEXTURE_MAX_NUMBER; ++i) { - RAW_TEXTURE[i] = df[i].dat; - RAW_TEXTURE_NUMBER++; + log_print_str("."); + char * path = lw_path_join3(STARTUP_DAT_PATH, "texture", texture_files[i]); + if (path != NULL) { + void *texture = lw_texture_archive_raw(path); + if (texture != NULL) { + RAW_TEXTURE[i] = texture; + RAW_TEXTURE_NUMBER++; + } + free(path); + } } + return RAW_TEXTURE_NUMBER > 0; } /*------------------------------------------------------------------*/ -static void -read_maptex_dat (DATAFILE * df) +static bool +read_maptex_dat () { - int i; - RAW_MAPTEX_NUMBER = 0; - for (i = 0; i < RAW_TEXTURE_DAT_NUMBER && df[i].type != DAT_END; ++i) - { - RAW_MAPTEX[i] = df[i].dat; - RAW_MAPTEX_NUMBER++; + + char * maptex_path = lw_path_join2(STARTUP_DAT_PATH, "maptex"); + if (maptex_path == NULL) { + return false; + } + + ALLEGRO_FS_ENTRY *dir = al_create_fs_entry(maptex_path); + free(maptex_path); + + if (!dir || !al_open_directory(dir)) { + if (dir) al_destroy_fs_entry(dir); + return false; + } + + ALLEGRO_FS_ENTRY *entry; + while ((entry = al_read_directory(dir)) != NULL && RAW_MAPTEX_NUMBER < RAW_TEXTURE_MAX_NUMBER) { + log_print_str("."); + if (al_get_fs_entry_mode(entry) & ALLEGRO_FILEMODE_ISFILE) { + const char *filename = al_get_fs_entry_name(entry); + void *maptex = lw_texture_archive_raw(filename); + if (maptex != NULL) { + RAW_MAPTEX[RAW_MAPTEX_NUMBER] = maptex; + RAW_MAPTEX_NUMBER++; + } } + al_destroy_fs_entry(entry); + } + + al_close_directory(dir); + al_destroy_fs_entry(dir); + return RAW_MAPTEX_NUMBER > 0; } /*------------------------------------------------------------------*/ +/* Structure to hold map file info for load balancing */ +typedef struct { + char *filename; + off_t size; + int index; + ALLEGRO_BITMAP *bmp; /* Pre-loaded bitmap (loaded on main thread) */ +} map_file_info; + +/*------------------------------------------------------------------*/ +/* Structure for worker's job list */ +typedef struct { + map_file_info **files; /* Array of pointers to files to process */ + int file_count; /* Number of files assigned to this worker */ + off_t total_size; /* Total bytes to process */ +} worker_job; + +/*------------------------------------------------------------------*/ +/* Worker thread function to process pre-loaded map bitmaps */ static void -read_map_dat (DATAFILE * df) +map_load_worker(void *arg) { - int i; - - RAW_MAP_NUMBER = 0; - for (i = 0; i < RAW_MAP_DAT_NUMBER && df[i].type != DAT_END; ++i) - { - RAW_MAP[i] = df[i].dat; - RAW_MAP_NUMBER++; + worker_job *job = (worker_job *)arg; + + if (job && job->files) { + for (int i = 0; i < job->file_count; i++) { + map_file_info *file = job->files[i]; + if (file && file->bmp) { + log_print_str("."); + /* Process the pre-loaded bitmap (CPU-intensive, thread-safe) */ + void *map = lw_map_archive_raw_bmp(file->bmp, file->filename); + if (map != NULL) { + RAW_MAP[file->index] = map; + log_print_str("+"); + } else { + log_print_str("-"); + } + /* Note: bmp is consumed by lw_map_archive_raw_bmp, don't free it here */ + } } + free(job->files); + } + /* Note: job itself is part of jobs[] array, freed by main thread */ } /*------------------------------------------------------------------*/ -static void -read_back_dat (DATAFILE * df) +/* Comparison function for qsort - sort by size descending */ +static int +compare_map_size(const void *a, const void *b) { - int i, x, y; + const map_file_info *fa = (const map_file_info *)a; + const map_file_info *fb = (const map_file_info *)b; - BACK_PALETTE = df[1].dat; - BACK_IMAGE = df[0].dat; + /* Sort descending (largest first) */ + if (fa->size > fb->size) return -1; + if (fa->size < fb->size) return 1; + return 0; +} + +/*------------------------------------------------------------------*/ +/* Simple integer square root for worker count calculation */ +static int __attribute__((unused)) +isqrt(int n) +{ + int x = n; + int y = (x + 1) / 2; + while (y < x) { + x = y; + y = (x + n / x) / 2; + } + return x; +} + +/*------------------------------------------------------------------*/ +static bool +read_map_dat () +{ + RAW_MAP_NUMBER = 0; + + char * map_path = lw_path_join2(STARTUP_DAT_PATH, "map"); + if (map_path == NULL) { + return false; + } + + ALLEGRO_FS_ENTRY *dir = al_create_fs_entry(map_path); + free(map_path); + + if (!dir || !al_open_directory(dir)) { + if (dir) al_destroy_fs_entry(dir); + return false; + } + + /* First pass: collect all filenames and their sizes */ + /* Allocate on heap to avoid stack overflow (each entry contains a 768-byte PALETTE) */ + map_file_info *files = calloc(RAW_MAP_MAX_NUMBER, sizeof(map_file_info)); + if (!files) { + al_close_directory(dir); + al_destroy_fs_entry(dir); + return false; + } + int file_count = 0; + + ALLEGRO_FS_ENTRY *entry; + while ((entry = al_read_directory(dir)) != NULL && file_count < RAW_MAP_MAX_NUMBER) { + if (al_get_fs_entry_mode(entry) & ALLEGRO_FILEMODE_ISFILE) { + const char *filename = al_get_fs_entry_name(entry); + const char *ext = strrchr(filename, '.'); + if (ext && (strcmp(ext, ".bmp") == 0)) { + files[file_count].filename = strdup(filename); + if (files[file_count].filename) { + files[file_count].size = al_get_fs_entry_size(entry); + files[file_count].index = file_count; + file_count++; + } + } + } + al_destroy_fs_entry(entry); + } + + al_close_directory(dir); + al_destroy_fs_entry(dir); + + if (file_count == 0) { + free(files); + return false; + } + + /* Sort files by size (largest first) for better load balancing */ + qsort(files, file_count, sizeof(map_file_info), compare_map_size); /* - * strange, with Allegro 4.0, the liquidwarcol utility - * and the datafile compiler do not work so well together, - * and so the palette stored in the datafile always - * start at color 0, which explains the "18 shift" + * Load all bitmaps on the main thread (Allegro 5's al_load_bitmap is not thread-safe). + * Worker threads will process these pre-loaded bitmaps in parallel. + * This separates the I/O (main thread) from CPU-intensive processing (worker threads). */ + for (int i = 0; i < file_count; i++) { + log_print_str("."); + files[i].bmp = al_load_bitmap_flags(files[i].filename, ALLEGRO_MEMORY_BITMAP); + /* If bitmap fails to load, bmp will be NULL and worker will skip it */ + } + + /* Calculate optimal worker count: sqrt(file_count), min 1, max file_count */ + /* TEMPORARY: Force single-threaded to test if threading is causing the Metal error */ + int worker_count = 1; + /* int worker_count = isqrt(file_count); + if (worker_count < 1) worker_count = 1; + if (worker_count > file_count) worker_count = file_count; */ + + /* Allocate worker job structures */ + worker_job *jobs = calloc(worker_count, sizeof(worker_job)); + if (!jobs) { + /* Cleanup filenames and bitmaps */ + for (int i = 0; i < file_count; i++) { + if (files[i].bmp) { + al_destroy_bitmap(files[i].bmp); + } + free(files[i].filename); + } + return false; + } + + /* Allocate file lists for each worker */ + for (int i = 0; i < worker_count; i++) { + jobs[i].files = malloc(sizeof(map_file_info *) * file_count); + if (!jobs[i].files) { + /* Cleanup on allocation failure */ + for (int j = 0; j < i; j++) { + free(jobs[j].files); + } + free(jobs); + for (int j = 0; j < file_count; j++) { + if (files[j].bmp) { + al_destroy_bitmap(files[j].bmp); + } + free(files[j].filename); + } + return false; + } + jobs[i].file_count = 0; + jobs[i].total_size = 0; + } + + /* Greedy bin-packing: assign each file to worker with smallest current load */ + for (int i = 0; i < file_count; i++) { + /* Find worker with minimum load */ + int min_worker = 0; + off_t min_size = jobs[0].total_size; + for (int w = 1; w < worker_count; w++) { + if (jobs[w].total_size < min_size) { + min_size = jobs[w].total_size; + min_worker = w; + } + } - for (i = 0; i <= 45; ++i) - GLOBAL_PALETTE[i + 18] = BACK_PALETTE[i]; - - for (x = 0; x < BACK_IMAGE->w; ++x) - for (y = 0; y < BACK_IMAGE->w; ++y) - { - putpixel (BACK_IMAGE, x, y, getpixel (BACK_IMAGE, x, y) + 18); + /* Assign this file to the least loaded worker */ + jobs[min_worker].files[jobs[min_worker].file_count] = &files[i]; + jobs[min_worker].file_count++; + jobs[min_worker].total_size += files[i].size; + } + + /* Launch worker threads */ + LW_THREAD_HANDLE *threads = malloc(sizeof(LW_THREAD_HANDLE) * worker_count); + if (!threads) { + /* Cleanup */ + for (int i = 0; i < worker_count; i++) { + free(jobs[i].files); + } + free(jobs); + for (int i = 0; i < file_count; i++) { + if (files[i].bmp) { + al_destroy_bitmap(files[i].bmp); } -} + free(files[i].filename); + } + return false; + } + + int threads_created = 0; + for (int i = 0; i < worker_count; i++) { + if (lw_thread_create(&threads[threads_created], map_load_worker, &jobs[i])) { + threads_created++; + } else { + /* Thread creation failed, fall back to synchronous processing */ + map_load_worker(&jobs[i]); + } + } -/*------------------------------------------------------------------*/ -static void -create_default_back (void) -{ - static RGB back_coul; + /* Wait for all threads to complete */ + for (int i = 0; i < threads_created; i++) { + lw_thread_join(&threads[i]); + } + + free(threads); + + /* Workers free their own job->files, but free jobs array */ + free(jobs); - memset (&back_coul, 0, sizeof (RGB)); - back_coul.r = 1; - back_coul.g = 1; - back_coul.b = 8; + /* Free filenames */ + for (int i = 0; i < file_count; i++) { + free(files[i].filename); + } - BACK_IMAGE = my_create_bitmap (1, 1); - putpixel (BACK_IMAGE, 0, 0, 18); - GLOBAL_PALETTE[18] = back_coul; + /* Count successfully loaded maps */ + RAW_MAP_NUMBER = 0; + for (int i = 0; i < file_count; i++) { + if (RAW_MAP[i] != NULL) { + RAW_MAP_NUMBER++; + } + } + + log_print_str(" ["); + log_print_int(RAW_MAP_NUMBER); + log_print_str("/"); + log_print_int(file_count); + log_print_str("]"); + log_flush(); + + /* Free the files array */ + free(files); + + return RAW_MAP_NUMBER > 0; } /*------------------------------------------------------------------*/ -static void -read_font_dat (DATAFILE * df) +static bool +read_back_dat () { - int i; - - FONT_PALETTE = df[4].dat; - SMALL_FONT = df[0].dat; - BIG_FONT = df[1].dat; - SMALL_MOUSE_CURSOR = df[2].dat; - BIG_MOUSE_CURSOR = df[3].dat; - INVISIBLE_MOUSE_CURSOR = df[5].dat; - - for (i = 1; i <= 17; ++i) - GLOBAL_PALETTE[i] = FONT_PALETTE[i]; + int errno; + + char * path = lw_path_join3(STARTUP_DAT_PATH, "back", "lw5back.bmp"); + if (path == NULL) { + return false; + } + if (!exists(path)) { + return false; + } + + log_print_str("."); + BACK_IMAGE = al_load_bitmap(path); + free(path); + if (BACK_IMAGE == NULL) { + return false; + } + + return true; } /*------------------------------------------------------------------*/ -static void -read_music_dat (DATAFILE * df) +static bool +read_font_dat () { - int i; + char * small_font_path = lw_path_join3(STARTUP_DAT_PATH, "font", "degrad10.bmp"); + char * big_font_path = lw_path_join3(STARTUP_DAT_PATH, "font", "degrad20.bmp"); + char * small_cursor_path = lw_path_join3(STARTUP_DAT_PATH, "font", "mouse20.bmp"); + char * big_cursor_path = lw_path_join3(STARTUP_DAT_PATH, "font", "mouse40.bmp"); + char * void_cursor_path = lw_path_join3(STARTUP_DAT_PATH, "font", "void1.bmp"); + + bool success = true; + + if (small_font_path) { + log_print_str("."); + SMALL_FONT = al_load_bitmap_font(small_font_path); + free(small_font_path); + if (!SMALL_FONT) success = false; + } else { + success = false; + } + + if (big_font_path) { + log_print_str("."); + BIG_FONT = al_load_bitmap_font(big_font_path); + free(big_font_path); + if (!BIG_FONT) success = false; + } else { + success = false; + } + + if (small_cursor_path) { + log_print_str("."); + SMALL_MOUSE_CURSOR = al_load_bitmap(small_cursor_path); + free(small_cursor_path); + if (!SMALL_MOUSE_CURSOR) success = false; + } else { + success = false; + } + + if (big_cursor_path) { + log_print_str("."); + BIG_MOUSE_CURSOR = al_load_bitmap(big_cursor_path); + free(big_cursor_path); + if (!BIG_MOUSE_CURSOR) success = false; + } else { + success = false; + } + + if (void_cursor_path) { + log_print_str("."); + INVISIBLE_MOUSE_CURSOR = al_load_bitmap(void_cursor_path); + free(void_cursor_path); + if (!INVISIBLE_MOUSE_CURSOR) success = false; + } else { + success = false; + } + + return success; +} +/*------------------------------------------------------------------*/ +static bool +read_music_dat () +{ + /* Music loading disabled for now */ MIDI_MUSIC_NUMBER = 0; - for (i = 0; i < MIDI_MUSIC_DAT_NUMBER && df[i].type != DAT_END; ++i) - { - MIDI_MUSIC[i] = df[i].dat; - MIDI_MUSIC_NUMBER++; - } + return true; +} + + +/*------------------------------------------------------------------*/ +static int check_loadable() { + int loadable = 0; + + loadable = exists (STARTUP_DAT_PATH); + + // Checking for the existence of this file, to quickly spot whether + // this is a genuine data folder. If that text file is not there, we + // can just leave and assume this is an unkown random place. + char * path = lw_path_join2(STARTUP_DAT_PATH, "liquidwar-data.txt"); + if (path == NULL) { + return 0; + } + loadable = exists(path); + free(path); + + return loadable; } /*------------------------------------------------------------------*/ @@ -306,128 +658,100 @@ int load_dat (void) { int result = 1; - int loadable; - DATAFILE *df; + int loadable = 0; - log_print_str ("Loading data from \""); + log_print_str ("Searching for data in \""); log_print_str (STARTUP_DAT_PATH); log_print_str ("\""); + log_flush (); -#ifdef DOS - loadable = 1; -#else - loadable = exists (STARTUP_DAT_PATH); -#endif - + loadable = check_loadable(); display_success (loadable); + if (loadable && STARTUP_BACK_STATE) + { + log_print_str ("Loading background bitmap"); + log_flush (); + LOADED_BACK = read_back_dat(); + display_success(LOADED_BACK); + result &= LOADED_BACK; + } if (loadable) { log_print_str ("Loading fonts"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "font_dat"); - if (result &= (df != NULL)) - read_font_dat (df[0].dat); - display_success (df != NULL); + LOADED_FONT = read_font_dat (); + display_success (LOADED_FONT); + result &= LOADED_FONT; } if (loadable) { log_print_str ("Loading maps"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "map_dat"); - if (result &= (df != NULL)) - read_map_dat (df[0].dat); - display_success (df != NULL); + LOADED_MAP = read_map_dat (); + display_success (LOADED_MAP); + result &= LOADED_MAP; } - if (loadable && STARTUP_BACK_STATE) - { - log_print_str ("Loading background bitmap"); - log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "back_dat"); - if (df != NULL) - { - read_back_dat (df[0].dat); - LOADED_BACK = 1; - } - else - { - create_default_back (); - result &= !STARTUP_CHECK; - } - display_success (df != NULL); - } - else - create_default_back (); if (loadable && STARTUP_SFX_STATE) { log_print_str ("Loading sound fx"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "sfx_dat"); - if (df != NULL) + if (read_sfx_dat()) { - read_sfx_dat (df[0].dat); LOADED_SFX = 1; + display_success(1); } else - result &= !STARTUP_CHECK; - display_success (df != NULL); + { + result &= !STARTUP_CHECK; + display_success(0); + } } if (loadable && STARTUP_TEXTURE_STATE) { log_print_str ("Loading textures"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "texture_dat"); - if (df != NULL) - { - read_texture_dat (df[0].dat); - LOADED_TEXTURE = 1; - } - else + LOADED_TEXTURE = read_texture_dat(); + display_success(LOADED_TEXTURE); + if (!LOADED_TEXTURE) { result &= !STARTUP_CHECK; - display_success (df != NULL); + } log_print_str ("Loading map textures"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "maptex_dat"); - if (df != NULL) - { - read_maptex_dat (df[0].dat); - LOADED_MAPTEX = 1; - } - else + LOADED_MAPTEX = read_maptex_dat(); + display_success(LOADED_MAPTEX); + if (!LOADED_MAPTEX) { result &= !STARTUP_CHECK; - display_success (df != NULL); + } } if (loadable && STARTUP_WATER_STATE) { log_print_str ("Loading water sounds"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "water_dat"); - if (df != NULL) - { - read_water_dat (df[0].dat); - LOADED_WATER = 1; - } - else + LOADED_WATER = read_water_dat(); + display_success(LOADED_WATER); + if (!LOADED_WATER) { result &= !STARTUP_CHECK; - display_success (df != NULL); + } } if (loadable && STARTUP_MUSIC_STATE) { log_print_str ("Loading midi music"); log_flush (); - df = load_datafile_object (STARTUP_DAT_PATH, "music_dat"); - if (df != NULL) + if (read_music_dat()) { - read_music_dat (df[0].dat); LOADED_MUSIC = 1; + display_success(1); } else - result &= !STARTUP_CHECK; - display_success (df != NULL); + { + result &= !STARTUP_CHECK; + display_success(0); + } } return loadable && result; @@ -461,19 +785,26 @@ load_custom_texture_callback (const char *file, int mode, void *unused) static int load_custom_texture (void) { - int result = 1; - char buf[512]; - - LW_MACRO_SPRINTF1 (buf, "%s\\*.*", STARTUP_TEX_PATH); - - fix_filename_case (buf); - fix_filename_slashes (buf); - CUSTOM_TEXTURE_OK = 0; - for_each_file_ex (buf, 0, FA_DIREC, load_custom_texture_callback, NULL); - result = CUSTOM_TEXTURE_OK; - return result; + ALLEGRO_FS_ENTRY *dir = al_create_fs_entry(STARTUP_TEX_PATH); + if (!dir || !al_open_directory(dir)) { + if (dir) al_destroy_fs_entry(dir); + return 0; + } + + ALLEGRO_FS_ENTRY *entry; + while ((entry = al_read_directory(dir)) != NULL && RAW_TEXTURE_NUMBER < RAW_TEXTURE_MAX_NUMBER) { + if (al_get_fs_entry_mode(entry) & ALLEGRO_FILEMODE_ISFILE) { + const char *filename = al_get_fs_entry_name(entry); + load_custom_texture_callback(filename, 0, NULL); + } + al_destroy_fs_entry(entry); + } + + al_close_directory(dir); + al_destroy_fs_entry(dir); + return CUSTOM_TEXTURE_OK; } /*------------------------------------------------------------------*/ @@ -503,40 +834,38 @@ load_custom_map_callback (const char *file, int mode, void *unused) static int load_custom_map (void) { - int result = 1; - char buf[512]; - - LW_MACRO_SPRINTF1 (buf, "%s\\*.*", STARTUP_MAP_PATH); - - fix_filename_case (buf); - fix_filename_slashes (buf); - CUSTOM_MAP_OK = 0; - for_each_file_ex (buf, 0, FA_DIREC, load_custom_map_callback, NULL); - result = CUSTOM_MAP_OK; - return result; + ALLEGRO_FS_ENTRY *dir = al_create_fs_entry(STARTUP_MAP_PATH); + if (!dir || !al_open_directory(dir)) { + if (dir) al_destroy_fs_entry(dir); + return 0; + } + + ALLEGRO_FS_ENTRY *entry; + while ((entry = al_read_directory(dir)) != NULL && RAW_MAP_NUMBER < RAW_MAP_MAX_NUMBER) { + if (al_get_fs_entry_mode(entry) & ALLEGRO_FILEMODE_ISFILE) { + const char *filename = al_get_fs_entry_name(entry); + load_custom_map_callback(filename, 0, NULL); + } + al_destroy_fs_entry(entry); + } + + al_close_directory(dir); + al_destroy_fs_entry(dir); + return CUSTOM_MAP_OK; } /*------------------------------------------------------------------*/ static int load_custom_music_callback (const char *file, int mode, void *unused) { - void *pointeur; - LW_MACRO_NOP (mode); LW_MACRO_NOP (unused); + LW_MACRO_NOP (file); - if ((pointeur = load_midi (file)) != NULL) - { - MIDI_MUSIC[MIDI_MUSIC_NUMBER++] = pointeur; - log_print_str ("+"); - CUSTOM_MUSIC_OK = 1; - } - else - { - log_print_str ("-"); - } + /* Music loading disabled for now */ + log_print_str ("-"); log_flush (); return 0; @@ -546,19 +875,26 @@ load_custom_music_callback (const char *file, int mode, void *unused) static int load_custom_music (void) { - int result = 1; - char buf[512]; - - LW_MACRO_SPRINTF1 (buf, "%s\\*.*", STARTUP_MID_PATH); - - fix_filename_case (buf); - fix_filename_slashes (buf); - CUSTOM_MUSIC_OK = 0; - for_each_file_ex (buf, 0, FA_DIREC, load_custom_music_callback, NULL); - result = CUSTOM_MUSIC_OK; - return result; + ALLEGRO_FS_ENTRY *dir = al_create_fs_entry(STARTUP_MID_PATH); + if (!dir || !al_open_directory(dir)) { + if (dir) al_destroy_fs_entry(dir); + return 0; + } + + ALLEGRO_FS_ENTRY *entry; + while ((entry = al_read_directory(dir)) != NULL && MIDI_MUSIC_NUMBER < MIDI_MUSIC_MAX_NUMBER) { + if (al_get_fs_entry_mode(entry) & ALLEGRO_FILEMODE_ISFILE) { + const char *filename = al_get_fs_entry_name(entry); + load_custom_music_callback(filename, 0, NULL); + } + al_destroy_fs_entry(entry); + } + + al_close_directory(dir); + al_destroy_fs_entry(dir); + return CUSTOM_MUSIC_OK; } /*------------------------------------------------------------------*/ diff --git a/src/disk.h b/src/disk.h index 36cc62ac..bde22265 100644 --- a/src/disk.h +++ b/src/disk.h @@ -55,7 +55,9 @@ /* includes */ /*==================================================================*/ -#include +#include +#include +#include /*==================================================================*/ /* constantes */ @@ -89,27 +91,27 @@ extern int LOADED_MAPTEX; extern int LOADED_SFX; extern int LOADED_WATER; -extern SAMPLE *SAMPLE_SFX_TIME; -extern SAMPLE *SAMPLE_SFX_WIN; -extern SAMPLE *SAMPLE_SFX_GO; -extern SAMPLE *SAMPLE_SFX_CLICK; -extern SAMPLE *SAMPLE_SFX_LOOSE; -extern SAMPLE *SAMPLE_SFX_CONNECT; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_TIME; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_WIN; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_GO; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_CLICK; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_LOOSE; +extern ALLEGRO_SAMPLE *SAMPLE_SFX_CONNECT; -extern SAMPLE *SAMPLE_WATER[SAMPLE_WATER_MAX_NUMBER]; +extern ALLEGRO_SAMPLE *SAMPLE_WATER[SAMPLE_WATER_MAX_NUMBER]; extern void *RAW_MAP[RAW_MAP_MAX_NUMBER]; extern void *RAW_MAP_ORDERED[RAW_MAP_MAX_NUMBER]; extern void *RAW_TEXTURE[RAW_TEXTURE_MAX_NUMBER]; extern void *RAW_MAPTEX[RAW_TEXTURE_MAX_NUMBER]; -extern MIDI *MIDI_MUSIC[MIDI_MUSIC_MAX_NUMBER]; +extern ALLEGRO_SAMPLE *MIDI_MUSIC[MIDI_MUSIC_MAX_NUMBER]; -extern BITMAP *BACK_IMAGE; +extern ALLEGRO_BITMAP *BACK_IMAGE; -extern FONT *BIG_FONT; -extern FONT *SMALL_FONT; -extern BITMAP *BIG_MOUSE_CURSOR; -extern BITMAP *SMALL_MOUSE_CURSOR; -extern BITMAP *INVISIBLE_MOUSE_CURSOR; +extern ALLEGRO_FONT *BIG_FONT; +extern ALLEGRO_FONT *SMALL_FONT; +extern ALLEGRO_BITMAP *BIG_MOUSE_CURSOR; +extern ALLEGRO_BITMAP *SMALL_MOUSE_CURSOR; +extern ALLEGRO_BITMAP *INVISIBLE_MOUSE_CURSOR; /*==================================================================*/ /* fonctions globales */ diff --git a/src/disp.c b/src/disp.c index 8af9d244..54c4b5d4 100644 --- a/src/disp.c +++ b/src/disp.c @@ -52,6 +52,8 @@ /* includes */ /*==================================================================*/ +#include + #include "area.h" #include "config.h" #include "disp.h" @@ -59,6 +61,7 @@ #include "viewport.h" #include "wave.h" #include "distor.h" +#include "alleg2.h" /*==================================================================*/ /* variables globales */ @@ -74,7 +77,7 @@ disp_stretch_area (void) { stretch_blit (CURRENT_AREA_DISP, NEXT_SCREEN, 0, 0, CURRENT_AREA_W, CURRENT_AREA_H, - 0, 0, NEXT_SCREEN->w, NEXT_SCREEN->h); + 0, 0, al_get_bitmap_width(NEXT_SCREEN), al_get_bitmap_height(NEXT_SCREEN)); } /*------------------------------------------------------------------*/ @@ -93,14 +96,14 @@ display_area (void) void display_gradient (int i) { - BITMAP *bmp; + ALLEGRO_BITMAP *bmp; bmp = create_gradient_bitmap (i); if (bmp) { - stretch_blit (bmp, NEXT_SCREEN, 0, 0, bmp->w, bmp->h, - 0, 0, NEXT_SCREEN->w, NEXT_SCREEN->h); - destroy_bitmap (bmp); + stretch_blit (bmp, NEXT_SCREEN, 0, 0, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp), + 0, 0, al_get_bitmap_width(NEXT_SCREEN), al_get_bitmap_height(NEXT_SCREEN)); + al_destroy_bitmap (bmp); } } @@ -108,13 +111,13 @@ display_gradient (int i) void display_mesh (int i) { - BITMAP *bmp; + ALLEGRO_BITMAP *bmp; bmp = create_mesh_bitmap (i); if (bmp) { - stretch_blit (bmp, NEXT_SCREEN, 0, 0, bmp->w, bmp->h, - 0, 0, NEXT_SCREEN->w, NEXT_SCREEN->h); - destroy_bitmap (bmp); + stretch_blit (bmp, NEXT_SCREEN, 0, 0, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp), + 0, 0, al_get_bitmap_width(NEXT_SCREEN), al_get_bitmap_height(NEXT_SCREEN)); + al_destroy_bitmap (bmp); } } diff --git a/src/distor.c b/src/distor.c index e547084a..fae9bdc0 100644 --- a/src/distor.c +++ b/src/distor.c @@ -52,12 +52,15 @@ /* includes */ /*==================================================================*/ +#include +#include + #include "alleg2.h" +#include "backport.h" #include "area.h" #include "config.h" #include "distor.h" #include "gfxmode.h" -#include "glouglou.h" #include "profile.h" #include "startup.h" #include "lwtime.h" @@ -78,7 +81,7 @@ static int DISTORSION_W; static int DISTORSION_H; -static BITMAP *DISTORSION_TARGET = NULL; +static ALLEGRO_BITMAP *DISTORSION_TARGET = NULL; static int WAVE_SHAPE_WX[MAX_W_DISPLAY]; static int WAVE_SHAPE_WY[DISTORSION_MAX + 2][MAX_W_DISPLAY]; @@ -100,16 +103,16 @@ init_distorsion_target (void) { if (DISTORSION_TARGET == NULL) { - DISTORSION_TARGET = my_create_bitmap (NEXT_SCREEN->w, NEXT_SCREEN->h); + DISTORSION_TARGET = my_create_memory_bitmap (al_get_bitmap_width(NEXT_SCREEN), al_get_bitmap_height(NEXT_SCREEN)); } else { - if (DISTORSION_TARGET->w != NEXT_SCREEN->w || - DISTORSION_TARGET->h != NEXT_SCREEN->h) + if (al_get_bitmap_width(DISTORSION_TARGET) != al_get_bitmap_width(NEXT_SCREEN) || + al_get_bitmap_height(DISTORSION_TARGET) != al_get_bitmap_height(NEXT_SCREEN)) { - destroy_bitmap (DISTORSION_TARGET); - DISTORSION_TARGET = my_create_bitmap (NEXT_SCREEN->w, - NEXT_SCREEN->h); + al_destroy_bitmap (DISTORSION_TARGET); + DISTORSION_TARGET = my_create_memory_bitmap (al_get_bitmap_width(NEXT_SCREEN), + al_get_bitmap_height(NEXT_SCREEN)); } } } @@ -122,8 +125,8 @@ init_distorsion_displayer (void) init_distorsion_target (); - w = DISTORSION_TARGET->w; - h = DISTORSION_TARGET->h; + w = al_get_bitmap_width(DISTORSION_TARGET); + h = al_get_bitmap_height(DISTORSION_TARGET); DISTORSION_W = (CONFIG_WAVE_AMPLI[0] + CONFIG_WAVE_AMPLI[3]) / WAVE_SIZE_SCALE + 1; @@ -194,17 +197,17 @@ create_wave_line (int *buffer, cycle_tmp /= 2; speed--; } - cycle_tmp = fixsqrt (fixsqrt (cycle_tmp)) / 2; + cycle_tmp = (int)(sqrt(sqrt(cycle_tmp)) / 2); cycle_tmp /= SCREEN_W; cycle_tmp *= period; if (cycle_tmp <= 0) { cycle_tmp = 1; } - cycle_coef = sens * 256 * (itofix (GLOBAL_TICKER % cycle_tmp) / cycle_tmp); + cycle_coef = sens * 256 * ((GLOBAL_TICKER % cycle_tmp) * 65536 / cycle_tmp); - f0 = fixsin (cycle_coef + freq_coef * period2); - fp0x0 = (PI_1024 * fixcos (cycle_coef + freq_coef * period2)) / 1024; + f0 = (int)(sin((cycle_coef + freq_coef * period2) / 65536.0 * 2 * M_PI) * 65536); + fp0x0 = (PI_1024 * (int)(cos((cycle_coef + freq_coef * period2) / 65536.0 * 2 * M_PI) * 65536)) / (1024 * 65536); alphax03 = (ampli_cst / 256) * ((fp0x0 - 2 * f0) / 256); betax02 = (ampli_cst / 256) * ((-fp0x0 + 3 * f0) / 256); @@ -218,7 +221,7 @@ create_wave_line (int *buffer, for (i = period2; i < real_length - period2; ++i) { temp = - ((ampli_cos) / 256) * (fixcos (cycle_coef + freq_coef * i) / 256); + ((ampli_cos) / 256) * ((int)(cos((cycle_coef + freq_coef * i) / 65536.0 * 2 * M_PI) * 65536) / 256); buffer2[i] = temp / WAVE_SIZE_SCALE; } @@ -245,8 +248,8 @@ prepare_wave_shapes (void) { int w, h, x, y, i; - w = DISTORSION_TARGET->w; - h = DISTORSION_TARGET->h; + w = al_get_bitmap_width(DISTORSION_TARGET); + h = al_get_bitmap_height(DISTORSION_TARGET); create_wave_line (WAVE_SHAPE_WX, w, CONFIG_WAVE_NUMBER[0], @@ -289,26 +292,16 @@ prepare_wave_shapes (void) void disp_distorted_area (void) { - char *src; int x, y, w, h, lim_w, lim_h, init_w, init_h; int *y_corres; int fp_x, fp_y, fp_y0, ip_y0; int fp_x0[MAX_W_DISPLAY]; int reste_x; -#ifdef ASM - int ip_x, ip_y; - int temp = 0; - int bmp_color_depth; - int bmp_linear; - int bmp_memory; - - bmp_color_depth = bitmap_color_depth (DISTORSION_TARGET); - bmp_linear = is_linear_bitmap (DISTORSION_TARGET); - bmp_memory = is_memory_bitmap (DISTORSION_TARGET); -#endif - - w = DISTORSION_TARGET->w; - h = DISTORSION_TARGET->h; + int src_x, src_y; + ALLEGRO_COLOR pixel_color; + + w = al_get_bitmap_width(DISTORSION_TARGET); + h = al_get_bitmap_height(DISTORSION_TARGET); lim_w = DISTORSION_PRECISION * w; lim_h = DISTORSION_PRECISION * h; init_w = (CURRENT_AREA_W * DISTORSION_PRECISION) / 2; @@ -320,68 +313,55 @@ disp_distorted_area (void) fp_y0 = init_h; ip_y0 = 0; + + // Lock bitmaps for pixel access + al_set_target_bitmap(DISTORSION_TARGET); + for (y = 0; y < h; ++y) { fp_y = fp_y0; fp_x = init_w; - src = (char *) CURRENT_AREA_DISP->dat + ip_y0 * CURRENT_AREA_W; + src_x = init_w / DISTORSION_PRECISION; + src_y = ip_y0; y_corres = WAVE_SHAPE_Y_CORRES[y]; -#ifdef ASM - ip_x = 0; - ip_y = ip_y0; - /* - * draw_distor_line works on memory 8-bit bitmaps only - */ - if (STARTUP_ASM && bmp_memory && bmp_linear && bmp_color_depth == 8) + for (x = 0; x < w; ++x) { - draw_distor_line (DISTORSION_TARGET, - CURRENT_AREA_W, - w, - y, - fp_x, - ip_x, - fp_y, - ip_y, - lim_w, - lim_h, - fp_x0, - y_corres, - WAVE_SHAPE_WX, - WAVE_SHAPE_X_CORRES, - src, temp, temp, temp, temp, temp); - } - else -#endif - for (x = 0; x < w; ++x) - { - putpixel (DISTORSION_TARGET, x, y, *src); - - reste_x = fp_x0[x] += WAVE_SHAPE_X_CORRES[x][y]; - fp_x += WAVE_SHAPE_WX[x]; - while (reste_x < -fp_x) - { - fp_x += lim_w; - src--; - } - while (reste_x + fp_x >= lim_w) - { - fp_x -= lim_w; - src++; - } - - fp_y += y_corres[x]; - while (fp_y < 0) - { - fp_y += lim_h; - src -= CURRENT_AREA_W; - } - while (fp_y >= lim_h) - { - fp_y -= lim_h; - src += CURRENT_AREA_W; - } + // Get pixel from source area + if (src_x >= 0 && src_x < CURRENT_AREA_W && + src_y >= 0 && src_y < CURRENT_AREA_H) { + pixel_color = al_get_pixel(CURRENT_AREA_DISP, src_x, src_y); + } else { + pixel_color = al_map_rgb(0, 0, 0); // Black for out-of-bounds } + + al_put_pixel(x, y, pixel_color); + + reste_x = fp_x0[x] += WAVE_SHAPE_X_CORRES[x][y]; + fp_x += WAVE_SHAPE_WX[x]; + while (reste_x < -fp_x) + { + fp_x += lim_w; + src_x--; + } + while (reste_x + fp_x >= lim_w) + { + fp_x -= lim_w; + src_x++; + } + + fp_y += y_corres[x]; + while (fp_y < 0) + { + fp_y += lim_h; + src_y--; + } + while (fp_y >= lim_h) + { + fp_y -= lim_h; + src_y++; + } + } fp_y0 += WAVE_SHAPE_HY[y]; while (fp_y0 >= lim_h) @@ -392,5 +372,5 @@ disp_distorted_area (void) } blit (DISTORSION_TARGET, NEXT_SCREEN, 0, 0, 0, 0, - DISTORSION_TARGET->w, DISTORSION_TARGET->h); + al_get_bitmap_width(DISTORSION_TARGET), al_get_bitmap_height(DISTORSION_TARGET)); } diff --git a/src/distor.h b/src/distor.h index 3e809902..87b34180 100644 --- a/src/distor.h +++ b/src/distor.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* fonctions globales */ diff --git a/src/error.c b/src/error.c index d07d827d..09e3b20a 100644 --- a/src/error.c +++ b/src/error.c @@ -53,12 +53,14 @@ /*==================================================================*/ #include +#include #include "dialog.h" #include "error.h" #include "help.h" #include "base.h" #include "lang.h" +#include "alleg2.h" /*==================================================================*/ /* variables globales */ @@ -98,8 +100,8 @@ standard_error (char *str) d[1].proc = d_keyboard_proc; d[1].dp = return_d_close; d[1].key = ' '; - d[1].d1 = KEY_ENTER; - d[1].d2 = KEY_ESC; + d[1].d1 = ALLEGRO_KEY_ENTER; + d[1].d2 = ALLEGRO_KEY_ESCAPE; d[2].proc = NULL; diff --git a/src/exit.c b/src/exit.c index 3ca6b3cc..b6b3fc18 100644 --- a/src/exit.c +++ b/src/exit.c @@ -52,7 +52,7 @@ /* includes */ /*==================================================================*/ -#include +#include #ifdef WIN32 #include "popupgen.h" @@ -62,6 +62,7 @@ #include #endif +#include "backport.h" #include "basicopt.h" #include "config.h" #include "exit.h" @@ -102,23 +103,19 @@ exit_all (void) * This is an attempt to get rid of a hideous bug under X-Win, * which said that there was a "bad file descriptor" */ - rest (10); + al_rest (0.01); last_flip (); - set_gfx_mode (GFX_TEXT, 0, 0, 0, 0); - rest (10); + al_rest (0.01); log_println (); log_println_str - ("Leaving Allegro (http://www.talula.demon.co.uk/allegro)"); + ("Leaving Allegro (https://liballeg.org/)"); save_config_options (); stop_water (); stop_ticker (); - remove_sound (); - remove_mouse (); clear_keybuf (); - remove_keyboard (); remove_timer (); - allegro_exit (); + al_uninstall_system (); lw_sock_exit (); } } @@ -276,7 +273,7 @@ my_exit_poll () * We exit if the close button has been clicked or * F10 has been pressed */ - if (LW_EXIT_FORCE_SHUTDOWN || key[KEY_F10]) + if (LW_EXIT_FORCE_SHUTDOWN || key[ALLEGRO_KEY_F10]) { my_exit (EXIT_CODE_OK); } diff --git a/src/fighter.c b/src/fighter.c index f8359c7e..128a88f3 100644 --- a/src/fighter.c +++ b/src/fighter.c @@ -52,17 +52,17 @@ /* includes */ /*==================================================================*/ -#include +#include +#include #include "army.h" +#include "backport.h" #include "config.h" #include "cursor.h" #include "decal.h" #include "grad.h" #include "mesh.h" #include "fighter.h" -#include "monster.h" -#include "palette.h" #include "startup.h" #include "lwtime.h" @@ -136,9 +136,9 @@ erase_fighter (FIGHTER * f) static void disp_fighter (FIGHTER * f) { + int intensity = (f->health * 255) / MAX_FIGHTER_HEALTH; putpixel (CURRENT_AREA_DISP, f->x, f->y, - COLOR_FIRST_ENTRY[(int) (f->team)] - + (f->health * COLORS_PER_TEAM) / MAX_FIGHTER_HEALTH); + lw_team_color((int)(f->team), intensity)); } /*------------------------------------------------------------------*/ @@ -306,9 +306,6 @@ move_fighters (void) int *move_offset, *move_x, *move_y; int sens, start, table; int cpu_influence[NB_TEAMS] = { 0, 0, 0, 0, 0, 0 }; -#ifdef ASM - int temp = 0; -#endif sens = 0; @@ -337,30 +334,30 @@ move_fighters (void) coef += 256; attack[i] = (coef * - fixsqrt (fixsqrt - (1 << + (int)(sqrt (sqrt + ((double)(1 << (LW_CONFIG_CURRENT_RULES.fighter_attack + - cpu_influence[i])))) / (256 * 8); + cpu_influence[i])))))) / (256 * 8); if (attack[i] >= MAX_FIGHTER_HEALTH) attack[i] = MAX_FIGHTER_HEALTH - 1; if (attack[i] < 1) attack[i] = 1; defense[i] = (coef * - fixsqrt (fixsqrt - (1 << + (int)(sqrt (sqrt + ((double)(1 << (LW_CONFIG_CURRENT_RULES.fighter_defense + - cpu_influence[i])))) / (256 * 256); + cpu_influence[i])))))) / (256 * 256); if (defense[i] >= MAX_FIGHTER_HEALTH) defense[i] = MAX_FIGHTER_HEALTH - 1; if (defense[i] < 1) defense[i] = 1; new_health[i] = (coef * - fixsqrt (fixsqrt - (1 << + (int)(sqrt (sqrt + ((double)(1 << (LW_CONFIG_CURRENT_RULES.fighter_new_health + - cpu_influence[i])))) / (256 * 4); + cpu_influence[i])))))) / (256 * 4); if (new_health[i] >= MAX_FIGHTER_HEALTH) new_health[i] = MAX_FIGHTER_HEALTH - 1; if (new_health[i] < 1) @@ -372,30 +369,6 @@ move_fighters (void) table = (GLOBAL_CLOCK / 3) % 2; f = CURRENT_ARMY; -#ifdef ASM - if (STARTUP_ASM && LW_CONFIG_CURRENT_RULES.asm_algorithm) - boost_move_fighters (CURRENT_ARMY, - CURRENT_ARMY_SIZE, - CURRENT_AREA, - CURRENT_AREA_W, - ACTIVE_FIGHTERS, - attack, - defense, - new_health, - MAX_FIGHTER_HEALTH - 1, - sens, - start, - -GLOBAL_CLOCK, - FIGHTER_MOVE_XY_ASM[table], - FIGHTER_MOVE_OFFSET_ASM[table], - CURRENT_AREA_BACK->dat, - CURRENT_AREA_DISP->dat, - COLOR_FIRST_ENTRY, - COLORS_PER_TEAM, - LOCAL_DIR, - temp, temp, temp, temp, temp, temp, temp, temp); - else -#endif for (i = 0; i < CURRENT_ARMY_SIZE; ++i) { team = f->team; diff --git a/src/game.c b/src/game.c index 14c3727c..dfe33899 100644 --- a/src/game.c +++ b/src/game.c @@ -56,8 +56,9 @@ #ifdef UNIX #include #endif -#include +#include +#include "backport.h" #include "area.h" #include "autoplay.h" #include "back.h" @@ -118,15 +119,13 @@ int LW_GAME_RUNNING = 0; void calc_playing_teams (void) { - int i; - PLAYING_TEAMS = 0; /* * loop for all the possible teams, that's to say each of the * 6 areas in the "teams" menu */ - for (i = 0; i < NB_TEAMS; ++i) + for (int i = 0; i < NB_TEAMS; ++i) { if (LW_NETWORK_ON) { @@ -233,7 +232,7 @@ check_loose_team (void) */ play_loose (); /* - * remove the team from the info bar, so that room if freed for + * remove the team from the info bar, so that room if freed for * other teams */ free_info_bar (); @@ -254,7 +253,6 @@ check_loose_team (void) char * init_game (void) { - int i; int big_data; int max_mem_reached = 0; int last_try = 0; @@ -304,9 +302,8 @@ init_game (void) if (!message) { - for (i = 0; !max_mem_reached && !ok; ++i) + while (!max_mem_reached && !ok) { - (void)i; /* Loop counter not currently used, suppress warning */ message = NULL; reset_big_data (); @@ -388,7 +385,7 @@ init_game (void) if (!message) { /* - * these are basically initialization which need to be done + * these are basically initialization which need to be done * and should never fail * check each function to know what it does!!! */ @@ -435,7 +432,7 @@ free_game_memory (void) */ if (CURRENT_AREA_DISP) { - destroy_bitmap (CURRENT_AREA_DISP); + al_destroy_bitmap (CURRENT_AREA_DISP); CURRENT_AREA_DISP = 0; } /* @@ -443,7 +440,7 @@ free_game_memory (void) */ if (CURRENT_AREA_BACK) { - destroy_bitmap (CURRENT_AREA_BACK); + al_destroy_bitmap (CURRENT_AREA_BACK); CURRENT_AREA_BACK = 0; } } @@ -637,11 +634,11 @@ logic (void) * everything which is not directly linked to a game cycle */ static void -display (void) +display_game (void) { /* * the watchdog waits for secret codes to be entered - * + * * It's also very important to call this for it will call * keypressed() and so will also automatically call poll_keyboard() * if needed. @@ -671,7 +668,7 @@ display (void) /* * updates some time values, telling how many weeks this tremendous - * liquid war session has been running 8-) + * liquid war session has been running 8-) */ update_play_time (); @@ -684,7 +681,7 @@ display (void) /* * We're in capture mode: we display info before the dump * for we want it to be there but we display the messages - * after the dump since they are ugly and useless in a + * after the dump since they are ugly and useless in a * video capture. */ display_info (); @@ -761,7 +758,7 @@ game (void) * - there are less than 2 teams playing, ie there's a winner * - the game time is elapsed */ - while ((!WATCHDOG_SCANCODE[KEY_ESC]) + while ((!WATCHDOG_SCANCODE[ALLEGRO_KEY_ESCAPE]) && (PLAYING_TEAMS >= 2) && (TIME_LEFT > 0) && (!LW_NETWORK_ERROR_DETECTED)) { @@ -813,7 +810,7 @@ game (void) * if CONFIG_FPS_LIMIT is 0 we stop right away, ie * there will be one logic() operation for each display() * if it is 1, we keep going until we exceed the - * CONFIG_FPS_LIMIT value. this way we avoid drawing + * CONFIG_FPS_LIMIT value. this way we avoid drawing * 300 frames / second, which is useless * this method speeds the game on powerfull machines * for one can limit the display to 20 frames / seconds @@ -829,7 +826,7 @@ game (void) update_logic_rate (lr); /* - * we get the information "when has the last call to display() + * we get the information "when has the last call to display() * been done" */ last_display_time = get_ticker (); @@ -837,7 +834,7 @@ game (void) /* * now we really display stuff, (takes time...) */ - display (); + display_game (); /* * Now we check if the "Close" button has been clicked diff --git a/src/game.h b/src/game.h index 54e7a708..845da182 100644 --- a/src/game.h +++ b/src/game.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* definitions de constantes */ diff --git a/src/gfxmode.c b/src/gfxmode.c index c5bd92ef..7ed5e9e4 100644 --- a/src/gfxmode.c +++ b/src/gfxmode.c @@ -52,8 +52,9 @@ /* includes */ /*==================================================================*/ -#include +#include +#include "backport.h" #include "base.h" #include "disk.h" #include "log.h" @@ -79,14 +80,9 @@ int GFX_MODE_H[5] = { 240, 384, 480, 600, 768 }; #endif #ifdef UNIX -#ifdef GP2X -int GFX_MODE_W[5] = { 320, 320, 320, 320, 320 }; -int GFX_MODE_H[5] = { 240, 240, 240, 240, 240 }; -#else int GFX_MODE_W[5] = { 320, 512, 640, 800, 1024 }; int GFX_MODE_H[5] = { 240, 384, 480, 600, 768 }; #endif -#endif #ifdef DOS static int GFX_MODE_TYPE_FULLSCREEN[] = { GFX_MODEX, @@ -121,21 +117,25 @@ static int GFX_MODE_TYPE_WINDOWED[] = { GFX_DIRECTX_WIN, #endif #ifdef UNIX -#ifdef GP2X -static int GFX_MODE_TYPE_FULLSCREEN[] = { GFX_GP2X, - GFX_GP2X, - GFX_GP2X, - GFX_GP2X, - GFX_GP2X +static int GFX_MODE_TYPE_FULLSCREEN[] = { GFX_AUTODETECT_FULLSCREEN, + GFX_AUTODETECT_FULLSCREEN, + GFX_AUTODETECT_FULLSCREEN, + GFX_AUTODETECT_FULLSCREEN, + GFX_AUTODETECT_FULLSCREEN }; -static int GFX_MODE_TYPE_WINDOWED[] = { GFX_GP2X, - GFX_GP2X, - GFX_GP2X, - GFX_GP2X, - GFX_GP2X +static int GFX_MODE_TYPE_WINDOWED[] = { GFX_AUTODETECT_WINDOWED, + GFX_AUTODETECT_WINDOWED, + GFX_AUTODETECT_WINDOWED, + GFX_AUTODETECT_WINDOWED, + GFX_AUTODETECT_WINDOWED }; -#else +#endif + +#ifndef DOS +#ifndef WIN32 +#ifndef UNIX +// Default fallback graphics mode types static int GFX_MODE_TYPE_FULLSCREEN[] = { GFX_AUTODETECT_FULLSCREEN, GFX_AUTODETECT_FULLSCREEN, GFX_AUTODETECT_FULLSCREEN, @@ -151,6 +151,7 @@ static int GFX_MODE_TYPE_WINDOWED[] = { GFX_AUTODETECT_WINDOWED, }; #endif #endif +#endif /*==================================================================*/ /* fonctions */ @@ -214,10 +215,6 @@ set_resolution (int res, int flip, int fullscreen, int *flip_enabled) int toggle; int i; -#ifdef GP2X - fullscreen = 1; -#endif - if (flip_enabled) { *flip_enabled = 0; diff --git a/src/glouglou.h b/src/glouglou.h deleted file mode 100644 index c22b64ca..00000000 --- a/src/glouglou.h +++ /dev/null @@ -1,84 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : glouglou.h */ -/* contenu : affichage avec vagues accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -#ifndef LIQUID_WAR_INCLUDE_GLOUGLOU -#define LIQUID_WAR_INCLUDE_GLOUGLOU - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include -#include "asm.h" - -/*==================================================================*/ -/* types */ -/*==================================================================*/ - -extern void LW_ASM_FUNC draw_distor_line (BITMAP * distorsion_target, - int current_area_w, - int w, - int u, - int fp_x, - int ip_x, - int fp_y, - int ip_y, - int lim_w, - int lim_h, - int *fp_x0, - int *y_corres, - int *WAVE_SHAPE_WX, - int **WAVE_SHAPE_X_CORRES, - char *src, - int temp1, - int temp2, - int temp3, int temp4, int temp5); - -#endif diff --git a/src/glouglou.s b/src/glouglou.s deleted file mode 100644 index 00fa1ae2..00000000 --- a/src/glouglou.s +++ /dev/null @@ -1,242 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : glouglou.s */ -/* contenu : affichage avec vagues accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -.equ BMP_W, 0 -.equ BMP_H, 4 -.equ BMP_CLIP, 8 -.equ BMP_CL, 12 -.equ BMP_CR, 16 -.equ BMP_CT, 20 -.equ BMP_CB, 24 -.equ BMP_VTABLE, 28 -.equ BMP_WBANK, 32 -.equ BMP_RBANK, 36 -.equ BMP_DAT, 40 -.equ BMP_ID, 44 -.equ BMP_EXTRA, 48 -.equ BMP_XOFS, 52 -.equ BMP_YOFS, 56 -.equ BMP_SEG, 60 -.equ BMP_LINE, 64 - -.equ VTABLE_UNBANK, 8 - -.equ ARG_DISTORSION_TARGET, 8 -.equ ARG_CURRENT_AREA_W, 12 -.equ ARG_W, 16 -.equ ARG_Y, 20 -.equ ARG_FP_X, 24 -.equ ARG_IP_X, 28 -.equ ARG_FP_Y, 32 -.equ ARG_IP_Y, 36 -.equ ARG_LIM_W, 40 -.equ ARG_LIM_H, 44 -.equ ARG_FP_X0, 48 -.equ ARG_Y_CORRES, 52 -.equ ARG_WAVE_SHAPE_WX, 56 -.equ ARG_WAVE_SHAPE_X_CORRES, 60 -.equ ARG_SRC, 64 -.equ ARG_TEMP1, 68 # pointeur debut ligne -.equ ARG_TEMP2, 72 # pointeur sur fc aff -.equ ARG_TEMP3, 76 -.equ ARG_TEMP4, 80 -.equ ARG_TEMP5, 84 - -.text - - -/*==================================================================*/ -/* affichage de jolies distorsions */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -/* void draw_distor_line (BITMAP *distorsion_target, */ -/* int current_area_w, */ -/* int w, */ -/* int y, */ -/* int fp_x, */ -/* int ip_x, */ -/* int fp_y, */ -/* int ip_y, */ -/* int lim_w, */ -/* int lim_h, */ -/* int *fp_x0, */ -/* int *y_corres, */ -/* int *WAVE_SHAPE_WX, */ -/* int **WAVE_SHAPE_X_CORRES, */ -/* char *src, */ -/* int temp1, */ -/* int temp2, */ -/* int temp3, */ -/* int temp4, */ -/* int temp5); */ -/*------------------------------------------------------------------*/ -.globl __draw_distor_line -.globl _draw_distor_line -.globl draw_distor_line - .align 4 -__draw_distor_line: -_draw_distor_line: -draw_distor_line: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - pushw %fs - - mov ARG_SRC(%ebp),%esi - mov ARG_CURRENT_AREA_W(%ebp),%edi - - movl ARG_DISTORSION_TARGET(%ebp), %edx # edx = bmp - movl ARG_Y(%ebp), %eax # eax = y - movl BMP_LINE(%edx, %eax, 4), %eax - movl %eax,ARG_TEMP1(%ebp) # ARG_TEMP1 = ptr debut ligne - - xor %ecx,%ecx # ecx va servir pour stocker x -main_loop: - - # putpixel (DISTORSION_TARGET, x,y *src) - - movl %ds:(%esi),%ebx # bl = color - movl ARG_TEMP1(%ebp), %eax - movb %bl, %ds:(%eax, %ecx) # store the pixel - - mov ARG_WAVE_SHAPE_X_CORRES(%ebp),%eax #eax=wave_shape_x_corres - mov %ds:(%eax,%ecx,4),%eax # eax=wave_shape_x_corres[x] - mov ARG_Y(%ebp),%ebx # ebx=y - mov %ds:(%eax,%ebx,4),%eax # eax=wave_shape_x_corres[x][y] - mov ARG_FP_X0(%ebp),%ebx # ebx=arg_fp_x0 - mov %ds:(%ebx,%ecx,4),%edx # edx=arg_fp_x0[x] - add %eax,%edx # edx+=eax - mov %edx,%ds:(%ebx,%ecx,4) # on memorise en ram - neg %edx - - # a ce stade edx contient -reste_x - - mov ARG_FP_X(%ebp),%eax # eax=fp_x - mov ARG_WAVE_SHAPE_WX(%ebp),%ebx # ebx=wave_shape_wx - add %ds:(%ebx,%ecx,4),%eax # fp_x+=wave_shape_wx[x] - - mov ARG_LIM_W(%ebp),%ebx # ebx=lim_w -loop_while_1: - cmp %edx,%eax # fp_x<-reste_x - jnl exit_while_1 - add %ebx,%eax # fp_x+=lim_w - dec %esi # src-- - jmp loop_while_1 -exit_while_1: - - add %ebx,%edx -loop_while_2: - cmp %edx,%eax # fp_x>=-reste_x+lim_w - jnge exit_while_2 - sub %ebx,%eax # fp_x-=lim_w - inc %esi # src++ - jmp loop_while_2 -exit_while_2: - - mov %eax,ARG_FP_X(%ebp) # on sauve fp_x - - mov ARG_FP_Y(%ebp),%eax # eax=fp_y - mov ARG_Y_CORRES(%ebp),%ebx # ebx=y_corres - add %ds:(%ebx,%ecx,4),%eax # fp_y+=y_corres[x] - - mov ARG_LIM_H(%ebp),%ebx # ebx=lim_h -loop_while_3: - cmp $0,%eax # fp_y<0 - jnl exit_while_3 - add %ebx,%eax # fp_x+=lim_h - sub %edi,%esi # src-=current_area_w - jmp loop_while_3 -exit_while_3: - -loop_while_4: - cmp %ebx,%eax # fp_y>=lim_h - jnge exit_while_4 - sub %ebx,%eax # fp_y-=lim_h - add %edi,%esi # src+=current_area_w - jmp loop_while_4 -exit_while_4: - - mov %eax,ARG_FP_Y(%ebp) # on sauve fp_y - -/* mov ARG_TEMP1(%ebp),%ecx # ecx=x */ - incl %ecx # x++ - cmp ARG_W(%ebp),%ecx # x!=w ? - je the_end - jmp main_loop - -the_end: - - popw %fs - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret # retour au c - -/*------------------------------------------------------------------*/ -/* affichage pour bitmap lineaire, golee dans allegro */ -/*------------------------------------------------------------------*/ -linear_putpixel8_for_distor_line: - - - ret - diff --git a/src/grad.c b/src/grad.c index 9c3db07d..3e126adb 100644 --- a/src/grad.c +++ b/src/grad.c @@ -54,11 +54,11 @@ #include "alleg2.h" #include "area.h" +#include "backport.h" #include "decal.h" +#include "dialog.h" #include "grad.h" #include "mesh.h" -#include "palette.h" -#include "spread.h" #include "startup.h" #include "lwtime.h" #include "config.h" @@ -74,17 +74,18 @@ /*==================================================================*/ /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * create_gradient_bitmap (int team) { - BITMAP *result; + ALLEGRO_BITMAP *result; int x, y, i, color; MESH *temp; - result = my_create_bitmap (CURRENT_AREA_W, CURRENT_AREA_H); + result = my_create_memory_bitmap (CURRENT_AREA_W, CURRENT_AREA_H); if (result) { + al_set_target_bitmap (result); i = 0; for (y = 0; y < CURRENT_AREA_H; ++y) for (x = 0; x < CURRENT_AREA_W; ++x) @@ -93,10 +94,12 @@ create_gradient_bitmap (int team) { color = (temp->info[team].state.grad + AREA_START_GRADIENT) % COLORS_PER_TEAM; - putpixel (result, x, y, color + COLOR_FIRST_ENTRY[team]); + // Convert gradient value (0-COLORS_PER_TEAM) to intensity (0-255) + int intensity = (color * 255) / COLORS_PER_TEAM; + putpixel_fast (x, y, lw_team_color(team, intensity)); } else - putpixel (result, x, y, MENU_BG); + putpixel_fast (x, y, MENU_BG); } } @@ -104,23 +107,30 @@ create_gradient_bitmap (int team) } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * create_dir_bitmap (int team) { - BITMAP *result; + ALLEGRO_BITMAP *result; int x, y, i; MESH *temp; - result = my_create_bitmap (CURRENT_AREA_W, CURRENT_AREA_H); + result = my_create_memory_bitmap (CURRENT_AREA_W, CURRENT_AREA_H); + al_set_target_bitmap (result); i = 0; for (y = 0; y < CURRENT_AREA_H; ++y) for (x = 0; x < CURRENT_AREA_W; ++x) { if ((temp = CURRENT_AREA[i++].mesh) != NULL) - putpixel (result, x, y, 134 - + (temp->info[team].state.dir / 4) * 42 - + (temp->info[team].state.dir % 4) * 10); + { + // Old palette code: 134 + (dir/4)*42 + (dir%4)*10 + // This was generating different colors based on direction + // For now, map direction to an intensity value + int dir_value = (temp->info[team].state.dir / 4) * 42 + + (temp->info[team].state.dir % 4) * 10; + int intensity = (dir_value * 255) / 134; // Scale to 0-255 + putpixel_fast (x, y, lw_team_color(team, intensity)); + } } return result; @@ -149,33 +159,6 @@ spread_single_gradient (void) case DIR_SW: pos = CURRENT_MESH; last = CURRENT_MESH + CURRENT_MESH_SIZE; -#ifdef ASM - if (STARTUP_ASM && LW_CONFIG_CURRENT_RULES.asm_algorithm) - switch (PLAYING_TEAMS) - { - case 6: - boost_gradient_down_6 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 5: - boost_gradient_down_5 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 4: - boost_gradient_down_4 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 3: - boost_gradient_down_3 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - default: - boost_gradient_down_2 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - } - else -#endif while (pos != last) { for (i = 0; i < PLAYING_TEAMS; ++i) @@ -195,33 +178,6 @@ spread_single_gradient (void) case DIR_NE: pos = CURRENT_MESH + CURRENT_MESH_SIZE - 1; last = CURRENT_MESH - 1; -#ifdef ASM - if (STARTUP_ASM && LW_CONFIG_CURRENT_RULES.asm_algorithm) - switch (PLAYING_TEAMS) - { - case 6: - boost_gradient_up_6 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 5: - boost_gradient_up_5 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 4: - boost_gradient_up_4 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - case 3: - boost_gradient_up_3 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - default: - boost_gradient_up_2 - (pos, CURRENT_MESH_SIZE - 1, OFFSET_TO_FIRST_LINK + dir * 4); - break; - } - else -#endif while (pos != last) { for (i = 0; i < PLAYING_TEAMS; ++i) diff --git a/src/grad.h b/src/grad.h index 45a87568..a2321426 100644 --- a/src/grad.h +++ b/src/grad.h @@ -62,14 +62,14 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* fonctions globales */ /*==================================================================*/ -BITMAP *create_gradient_bitmap (int team); -BITMAP *create_dir_bitmap (int team); +ALLEGRO_BITMAP *create_gradient_bitmap (int team); +ALLEGRO_BITMAP *create_dir_bitmap (int team); void spread_single_gradient (void); #endif diff --git a/src/graphics.c b/src/graphics.c index 7d9ff372..43dad237 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -63,6 +63,7 @@ #include "graphics.h" #include "help.h" #include "menu.h" +#include "mouse.h" #include "sound.h" #include "wave.h" #include "lang.h" @@ -163,7 +164,7 @@ slider_menu_res (void *dp3, int d2) changed = dp3; *changed = 1; - my_set_palette (); + // my_set_palette (); // No longer needed in true color mode return 0; } @@ -177,7 +178,7 @@ slider_brightness (void *dp3, int d2) play_click (); CONFIG_BRIGHTNESS = d2; - my_set_palette (); + // my_set_palette (); // No longer needed in true color mode return 0; } @@ -251,16 +252,7 @@ graphic_options (void) d[11].proc = my_button_proc; d[11].dp = get_fullscreen_str (); -#ifdef DOS - /* - * Under DOS, fullscreen or windowed makes no sense, so we simply - * remove the button to avoid confusion. - */ - d[4].flags |= D_HIDDEN; - d[11].flags = D_EXIT | D_HIDDEN; -#else d[11].flags = D_EXIT; -#endif d[16].proc = my_button_proc; d[16].dp = get_page_flip_str (); @@ -279,12 +271,12 @@ graphic_options (void) fullscreen_changed = 0; display_back_image (); dp = my_init_dialog (d, choix); - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode } else dp = my_init_dialog (d, choix); - show_mouse (screen); + lw_mouse_show (); while ((menu_res_changed == 0) && (game_res_changed == 0) && my_update_dialog (dp)) ; @@ -295,7 +287,7 @@ graphic_options (void) { if (d[13].d2 != CONFIG_GFX_MENU) { - my_fade_out (); + // my_fade_out (); // No longer needed in true color mode if (set_resolution (d[13].d2, 0, CONFIG_FULLSCREEN, NULL)) CONFIG_GFX_MENU = 0; else @@ -339,7 +331,7 @@ graphic_options (void) my_button_proc (MSG_DRAW, d + 11, 0); unscare_mouse (); fullscreen_changed = 1; - my_fade_out (); + // my_fade_out (); // No longer needed in true color mode set_resolution (d[13].d2, 0, CONFIG_FULLSCREEN, NULL); break; case 16: diff --git a/src/info.c b/src/info.c index c5056ef2..e6ab3411 100644 --- a/src/info.c +++ b/src/info.c @@ -52,15 +52,16 @@ /* includes */ /*==================================================================*/ -#include +#include +#include "backport.h" #include "alleg2.h" +#include "dialog.h" #include "army.h" #include "back.h" #include "config.h" #include "info.h" #include "decal.h" -#include "palette.h" #include "maptex.h" #include "texture.h" #include "lwtime.h" @@ -77,8 +78,8 @@ #define INFO_BAR_W 50 #define INFO_BAR_H 15 -static BITMAP *INFO_BAR_BACK = NULL; -static BITMAP *INFO_BAR = NULL; +static ALLEGRO_BITMAP *INFO_BAR_BACK = NULL; +static ALLEGRO_BITMAP *INFO_BAR = NULL; static int INFO_BAR_POS_X[NB_TEAMS]; static int INFO_BAR_POS_Y[NB_TEAMS]; static int INFO_BAR_POS_W; @@ -97,12 +98,12 @@ int init_info_bar (int w, int h, int epaisseur) { int i, x, y; - BITMAP *front, *back; + ALLEGRO_BITMAP *front, *back; if (INFO_BAR) - destroy_bitmap (INFO_BAR); - INFO_BAR = my_create_bitmap (w, h); - INFO_BAR_BACK = my_create_bitmap (w, h); + al_destroy_bitmap (INFO_BAR); + INFO_BAR = my_create_memory_bitmap (w, h); + INFO_BAR_BACK = my_create_memory_bitmap (w, h); if (INFO_BAR && INFO_BAR_BACK) { @@ -120,12 +121,13 @@ init_info_bar (int w, int h, int epaisseur) LW_NETWORK_ON, LW_RANDOM_ON, CONFIG_USE_DEFAULT_TEXTURE); - for (y = 0; y < h; y += front->h) - for (x = epaisseur + 1; x < w; x += front->w) + for (y = 0; y < h; y += al_get_bitmap_height(front)) + for (x = epaisseur + 1; x < w; x += al_get_bitmap_width(front)) draw_sprite (INFO_BAR, front, x, y); INFO_BAR_POS_W = w - epaisseur - 5; INFO_BAR_POS_H = (h - 1) / PLAYING_TEAMS - 1; + al_set_target_bitmap (INFO_BAR); for (i = 0; i < PLAYING_TEAMS; ++i) { INFO_BAR_POS_X[i] = epaisseur + 3; @@ -137,14 +139,14 @@ init_info_bar (int w, int h, int epaisseur) y < INFO_BAR_POS_Y[i] + INFO_BAR_POS_H; y++) for (x = INFO_BAR_POS_X[i]; x < INFO_BAR_POS_X[i] + INFO_BAR_POS_W; x++) - putpixel (INFO_BAR, x, y, + putpixel_fast (x, y, getpixel (back, - (x - epaisseur - 1) % back->w, - y % back->h)); + (x - epaisseur - 1) % al_get_bitmap_width(back), + y % al_get_bitmap_height(back))); } - destroy_bitmap (back); - destroy_bitmap (front); + al_destroy_bitmap (back); + al_destroy_bitmap (front); } else { @@ -160,12 +162,13 @@ init_info_bar (int w, int h, int epaisseur) LW_NETWORK_ON, LW_RANDOM_ON, CONFIG_USE_DEFAULT_TEXTURE); - for (y = epaisseur + 1; y < h; y += front->h) - for (x = 0; x < w; x += front->w) + for (y = epaisseur + 1; y < h; y += al_get_bitmap_height(front)) + for (x = 0; x < w; x += al_get_bitmap_width(front)) draw_sprite (INFO_BAR, front, x, y); INFO_BAR_POS_W = (w - 1) / PLAYING_TEAMS - 1; INFO_BAR_POS_H = h - epaisseur - 5; + al_set_target_bitmap (INFO_BAR); for (i = 0; i < PLAYING_TEAMS; ++i) { INFO_BAR_POS_X[i] = (w + 1 - PLAYING_TEAMS @@ -177,14 +180,14 @@ init_info_bar (int w, int h, int epaisseur) y < INFO_BAR_POS_Y[i] + INFO_BAR_POS_H; y++) for (x = INFO_BAR_POS_X[i]; x < INFO_BAR_POS_X[i] + INFO_BAR_POS_W; x++) - putpixel (INFO_BAR, x, y, + putpixel_fast (x, y, getpixel (back, - x % back->w, - (y - epaisseur - 1) % back->h)); + x % al_get_bitmap_width(back), + (y - epaisseur - 1) % al_get_bitmap_height(back))); } - destroy_bitmap (back); - destroy_bitmap (front); + al_destroy_bitmap (back); + al_destroy_bitmap (front); } draw_sprite (INFO_BAR_BACK, INFO_BAR, 0, 0); } @@ -197,12 +200,12 @@ free_info_bar (void) { if (INFO_BAR) { - destroy_bitmap (INFO_BAR); + al_destroy_bitmap (INFO_BAR); INFO_BAR = NULL; } if (INFO_BAR_BACK) { - destroy_bitmap (INFO_BAR_BACK); + al_destroy_bitmap (INFO_BAR_BACK); INFO_BAR_BACK = NULL; } } @@ -233,7 +236,7 @@ display_time (int x, int y, int w, int h) buffer[4] = '0' + sec % 10; buffer[5] = 0; - textout_ex (INFO_BAR, font, buffer, x + 1, y + 1, -1, -1); + textout_ex (INFO_BAR, font, buffer, x + 1, y + 1, NO_COLOR, NO_COLOR); } /*------------------------------------------------------------------*/ @@ -260,7 +263,7 @@ display_horizontal_info (int w, int h, int epaisseur) barre_y, barre_x + barre_w - 1, barre_y + INFO_BAR_POS_H - 1, - COLOR_FIRST_ENTRY[i] + COLORS_PER_TEAM - 1); + lw_team_color(i, 255)); // Full brightness for team color } } @@ -288,7 +291,7 @@ display_vertical_info (int w, int h, int epaisseur) barre_y, barre_x + INFO_BAR_POS_W - 1, barre_y + barre_h - 1, - COLOR_FIRST_ENTRY[i] + COLORS_PER_TEAM - 1); + lw_team_color(i, 255)); // Full brightness for team color } } @@ -423,7 +426,7 @@ check_info_state (void) { static int changed; - if (WATCHDOG_SCANCODE[KEY_F1]) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F1]) { if (CONFIG_INFO_BAR >= 4) CONFIG_INFO_BAR -= 4; @@ -433,7 +436,7 @@ check_info_state (void) changed = CONFIG_PAGE_FLIP ? 2 : 1; lw_viewport_register_change (changed); } - if (WATCHDOG_SCANCODE[KEY_F2] && CONFIG_INFO_BAR < 4) + if (WATCHDOG_SCANCODE[ALLEGRO_KEY_F2] && CONFIG_INFO_BAR < 4) { CONFIG_INFO_BAR++; if (CONFIG_INFO_BAR == 4) diff --git a/src/init.c b/src/init.c index 98422135..a3d2aa2d 100644 --- a/src/init.c +++ b/src/init.c @@ -52,12 +52,11 @@ /* includes */ /*==================================================================*/ -#include +#include #include -#ifdef DOS -#include -#endif +#include +#include "backport.h" #include "base.h" #include "initrand.h" #include "config.h" @@ -70,7 +69,6 @@ #include "ticker.h" #include "sockgen.h" #include "lang.h" -#include "asm.h" #include "capture.h" /*==================================================================*/ @@ -113,7 +111,7 @@ int init_all () { int result = 0; - int graphics = 1, assembly = 1, config = 1, timer = 1, keyboard = 1, + int graphics = 1, config = 1, timer = 1, keyboard = 1, mouse = 1, sound = 1, joystick = 1, network = 1; /* @@ -126,7 +124,7 @@ init_all () lw_lang_init (); set_uformat (U_ASCII); - log_print_str ("Starting Allegro (http://www.talula.demon.co.uk/allegro)"); + log_print_str ("Starting Allegro (https://liballeg.org/)"); display_success (graphics = !allegro_init ()); log_println (); @@ -134,9 +132,6 @@ init_all () { LW_INIT_ALLEGRO_OK = 1; -#ifdef DOS - set_gfx_mode (GFX_TEXT, 0, 0, 0, 0); -#endif log_print_str ("Allegro ID : "); log_println_str (allegro_id); log_println (); @@ -144,11 +139,6 @@ init_all () set_color_depth (8); set_color_conversion (COLORCONV_REDUCE_TO_256); - /* - * We check for potential struct size errors - */ - assembly = lw_asm_check_struct_align (); - log_print_str ("Loading config options from \""); log_print_str (STARTUP_CFG_PATH); log_print_str ("\""); @@ -246,7 +236,6 @@ init_all () } result = graphics - && (assembly || !STARTUP_CHECK) && timer && keyboard && mouse && (sound || !STARTUP_CHECK) && (joystick || !STARTUP_CHECK); diff --git a/src/joystick.c b/src/joystick.c index 7a5c3f6d..3bed6112 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -52,8 +52,7 @@ /* includes */ /*==================================================================*/ -#include - +#include "backport.h" #include "config.h" #include "joystick.h" #include "startup.h" @@ -249,7 +248,7 @@ my_poll_joystick (void) { JOY2_MIN_X = MIN (joy[1].stick[0].axis[0].pos, JOY2_MIN_X); JOY2_MAX_X = MAX (joy[1].stick[0].axis[0].pos, JOY2_MAX_X); - JOY2_MID_Y = (JOY2_MIN_X + JOY2_MAX_X) / 2; + JOY2_MID_X = (JOY2_MIN_X + JOY2_MAX_X) / 2; JOY2_MIN_Y = MIN (joy[1].stick[0].axis[1].pos, JOY2_MIN_Y); JOY2_MAX_Y = MAX (joy[1].stick[0].axis[1].pos, JOY2_MAX_Y); JOY2_MID_Y = (JOY2_MIN_Y + JOY2_MAX_Y) / 2; @@ -268,7 +267,7 @@ my_poll_joystick (void) (JOY2_MIN_X + 2 * JOY2_MID_X) / 3) ? 1 : 0; } } - if (joy[0].num_buttons >= 2) + if (joy[1].num_buttons >= 2) { JOYSTICK_CONTROL_JOY2_B1 = joy[1].button[0].b; JOYSTICK_CONTROL_JOY2_B2 = joy[1].button[1].b; diff --git a/src/keyboard.c b/src/keyboard.c index f4ad7d0d..76cb8735 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -52,8 +52,7 @@ /* includes */ /*==================================================================*/ -#include - +#include "backport.h" #include "config.h" #include "joystick.h" #include "keyboard.h" diff --git a/src/lang.h b/src/lang.h index 089bfc30..8841af96 100644 --- a/src/lang.h +++ b/src/lang.h @@ -90,206 +90,202 @@ #define LW_LANG_STRING_MENU_OPTIONS 10 #define LW_LANG_STRING_MENU_ABOUT 11 #define LW_LANG_STRING_MENU_EXIT 12 -#define LW_LANG_STRING_MENU_EXITDOS 13 -#define LW_LANG_STRING_MENU_EXITWINDOWS 14 -#define LW_LANG_STRING_MENU_EXITUNIX 15 -#define LW_LANG_STRING_MENU_BACK 16 - -#define LW_LANG_STRING_DIALOG_QUIT 17 -#define LW_LANG_STRING_DIALOG_BACK 18 -#define LW_LANG_STRING_DIALOG_PLAY 19 -#define LW_LANG_STRING_DIALOG_MAIN 20 - -#define LW_LANG_STRING_PLAY_GETREADY 21 - -#define LW_LANG_STRING_NETGAME_STARTGAME 22 -#define LW_LANG_STRING_NETGAME_SERVERADDR 23 -#define LW_LANG_STRING_NETGAME_SERVERPORT 24 -#define LW_LANG_STRING_NETGAME_SEARCH 25 -#define LW_LANG_STRING_NETGAME_PASSWORD 26 -#define LW_LANG_STRING_NETGAME_WEAKPASSWORD 27 - -#define LW_LANG_STRING_LANGUAGE_AUTO 28 - -#define LW_LANG_STRING_TEAM_OFF 29 -#define LW_LANG_STRING_TEAM_HUMAN 30 -#define LW_LANG_STRING_TEAM_CPU 31 - -#define LW_LANG_STRING_OPTIONS_GRAPHICS 32 -#define LW_LANG_STRING_OPTIONS_SOUND 33 -#define LW_LANG_STRING_OPTIONS_RULES 34 -#define LW_LANG_STRING_OPTIONS_SPEEDS 35 -#define LW_LANG_STRING_OPTIONS_CONTROLS 36 -#define LW_LANG_STRING_OPTIONS_LANGUAGE 37 -#define LW_LANG_STRING_OPTIONS_DEFAULT 38 - -#define LW_LANG_STRING_GRAPHICS_GAME 39 -#define LW_LANG_STRING_GRAPHICS_MENU 40 -#define LW_LANG_STRING_GRAPHICS_ON 41 -#define LW_LANG_STRING_GRAPHICS_OFF 42 -#define LW_LANG_STRING_GRAPHICS_FULLSCREEN 43 -#define LW_LANG_STRING_GRAPHICS_WINDOWED 44 -#define LW_LANG_STRING_GRAPHICS_ADVANCED 45 -#define LW_LANG_STRING_GRAPHICS_VIDEOMODE 46 -#define LW_LANG_STRING_GRAPHICS_BRIGHTNESS 47 -#define LW_LANG_STRING_GRAPHICS_VIEWPORTSIZE 48 -#define LW_LANG_STRING_GRAPHICS_PAGEFLIPPING 49 -#define LW_LANG_STRING_GRAPHICS_WAVES 50 - -#define LW_LANG_STRING_VOLUME_SFX 51 -#define LW_LANG_STRING_VOLUME_CLICK 52 -#define LW_LANG_STRING_VOLUME_GAMEWATER 53 -#define LW_LANG_STRING_VOLUME_MENUWATER 54 -#define LW_LANG_STRING_VOLUME_MUSIC 55 - -#define LW_LANG_STRING_RULES_TIME 56 -#define LW_LANG_STRING_RULES_ADVANCED 57 -#define LW_LANG_STRING_RULES_ARMYSIZE 58 -#define LW_LANG_STRING_RULES_CURSOR 59 -#define LW_LANG_STRING_RULES_DEFAULT 60 -#define LW_LANG_STRING_RULES_MINMAPRES 61 - -#define LW_LANG_STRING_ADVANCED_ATTACK 62 -#define LW_LANG_STRING_ADVANCED_DEFENSE 63 -#define LW_LANG_STRING_ADVANCED_BASEHEALTH 64 -#define LW_LANG_STRING_ADVANCED_WINNERHELP 65 -#define LW_LANG_STRING_ADVANCED_CPUSTRENGTH 66 -#define LW_LANG_STRING_ADVANCED_CPUVSHUMAN 67 -#define LW_LANG_STRING_ADVANCED_ALWAYS 68 -#define LW_LANG_STRING_ADVANCED_RANDOM 69 -#define LW_LANG_STRING_ADVANCED_NEVER 70 -#define LW_LANG_STRING_ADVANCED_ASMALGORITHM 71 -#define LW_LANG_STRING_ADVANCED_ASSEMBLY 72 -#define LW_LANG_STRING_ADVANCED_STANDARDC 73 -#define LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS 74 -#define LW_LANG_STRING_ADVANCED_YES 75 -#define LW_LANG_STRING_ADVANCED_NO 76 - -#define LW_LANG_STRING_SPEEDS_FPS 77 -#define LW_LANG_STRING_SPEEDS_NOFPSLIMIT 78 -#define LW_LANG_STRING_SPEEDS_RPS 79 -#define LW_LANG_STRING_SPEEDS_NORPSLIMIT 80 - -#define LW_LANG_STRING_CONTROLS_JOYSTICK 81 -#define LW_LANG_STRING_CONTROLS_OFF 82 -#define LW_LANG_STRING_CONTROLS_2JOYSTICKS 83 -#define LW_LANG_STRING_CONTROLS_4BUTTONS 84 -#define LW_LANG_STRING_CONTROLS_STANDARD 85 -#define LW_LANG_STRING_CONTROLS_MOUSESENSIB 86 - -#define LW_LANG_STRING_ABOUT_CREDITS 87 -#define LW_LANG_STRING_ABOUT_COPYRIGHT 88 -#define LW_LANG_STRING_ABOUT_LICENSE 89 -#define LW_LANG_STRING_ABOUT_VERSION 90 - -#define LW_LANG_STRING_INTERNET_REFRESH 91 -#define LW_LANG_STRING_INTERNET_JOINNOW 92 -#define LW_LANG_STRING_INTERNET_PORT 93 -#define LW_LANG_STRING_INTERNET_PASSWORD 94 -#define LW_LANG_STRING_INTERNET_YES 95 -#define LW_LANG_STRING_INTERNET_NO 96 -#define LW_LANG_STRING_INTERNET_UPTIME 97 -#define LW_LANG_STRING_INTERNET_DAYS 98 -#define LW_LANG_STRING_INTERNET_DAY 99 -#define LW_LANG_STRING_INTERNET_HOURS 100 -#define LW_LANG_STRING_INTERNET_MINUTES 101 -#define LW_LANG_STRING_INTERNET_SECONDS 102 -#define LW_LANG_STRING_INTERNET_UNREACHABLE 103 -#define LW_LANG_STRING_INTERNET_PING 104 -#define LW_LANG_STRING_INTERNET_MSEC 105 - -#define LW_LANG_STRING_WAVE_AMPLI 106 -#define LW_LANG_STRING_WAVE_NUMBER 107 -#define LW_LANG_STRING_WAVE_SPEED 108 -#define LW_LANG_STRING_WAVE_WX 109 -#define LW_LANG_STRING_WAVE_HY 110 -#define LW_LANG_STRING_WAVE_WY 111 -#define LW_LANG_STRING_WAVE_HX 112 - -#define LW_LANG_STRING_CONNECT_STARTNOW 113 -#define LW_LANG_STRING_CONNECT_WAITING 114 -#define LW_LANG_STRING_CONNECT_WAITINGFOR 115 -#define LW_LANG_STRING_CONNECT_TEAMS 116 -#define LW_LANG_STRING_CONNECT_SENDMESSAGE 117 - -#define LW_LANG_STRING_NETPLAY_CONNECT 118 -#define LW_LANG_STRING_NETPLAY_PING 119 -#define LW_LANG_STRING_NETPLAY_CHECKPROGRAM 120 -#define LW_LANG_STRING_NETPLAY_CHECKVERSION 121 -#define LW_LANG_STRING_NETPLAY_SENDPASSWORD 122 -#define LW_LANG_STRING_NETPLAY_FREETEAMS 123 -#define LW_LANG_STRING_NETPLAY_RESERVETEAMS 124 -#define LW_LANG_STRING_NETPLAY_SENDCONFIG 125 -#define LW_LANG_STRING_NETPLAY_SENDMAP 126 -#define LW_LANG_STRING_NETPLAY_WAITING 127 -#define LW_LANG_STRING_NETPLAY_WHOPLAYS 128 -#define LW_LANG_STRING_NETPLAY_RECVCONFIG 129 -#define LW_LANG_STRING_NETPLAY_RECVMAP 130 - -#define LW_LANG_STRING_LEVEL_USEDEFAULTTEXTURE 131 -#define LW_LANG_STRING_LEVEL_ON 132 -#define LW_LANG_STRING_LEVEL_OFF 133 -#define LW_LANG_STRING_LEVEL_RANDOMMAP 134 - -#define LW_LANG_STRING_CODE_FPS 135 -#define LW_LANG_STRING_CODE_RPS 136 -#define LW_LANG_STRING_CODE_PERCENTCALC 137 -#define LW_LANG_STRING_CODE_PERCENTDISPLAY 138 -#define LW_LANG_STRING_CODE_SPREADGRADTIME 139 -#define LW_LANG_STRING_CODE_MOVEARMYTIME 140 -#define LW_LANG_STRING_CODE_DISPLAYTIME 141 -#define LW_LANG_STRING_CODE_FLIPTIME 142 -#define LW_LANG_STRING_CODE_OTHERCALCTIME 143 -#define LW_LANG_STRING_CODE_GLOBALTIME 144 -#define LW_LANG_STRING_CODE_STANDARDDISPLAY 145 -#define LW_LANG_STRING_CODE_GRADIENT1 146 -#define LW_LANG_STRING_CODE_GRADIENT2 147 -#define LW_LANG_STRING_CODE_GRADIENT3 148 -#define LW_LANG_STRING_CODE_GRADIENT4 149 -#define LW_LANG_STRING_CODE_GRADIENT5 150 -#define LW_LANG_STRING_CODE_GRADIENT6 151 -#define LW_LANG_STRING_CODE_MESHSIZE 152 -#define LW_LANG_STRING_CODE_MESHSTRUCTURE 153 -#define LW_LANG_STRING_CODE_PAUSEOFF 154 -#define LW_LANG_STRING_CODE_PAUSEON 155 -#define LW_LANG_STRING_CODE_WAVEEFFECTSOFF 156 -#define LW_LANG_STRING_CODE_WAVEEFFECTSON 157 -#define LW_LANG_STRING_CODE_CAPTUREOFF 158 -#define LW_LANG_STRING_CODE_CAPTUREON 159 - -#define LW_LANG_STRING_SCORE_WINNER 160 - -#define LW_LANG_STRING_GAME_BACKMEMFAIL 161 -#define LW_LANG_STRING_GAME_DISPMEMFAIL 162 -#define LW_LANG_STRING_GAME_MESHMEMFAIL 163 -#define LW_LANG_STRING_GAME_AREAMEMFAIL 164 -#define LW_LANG_STRING_GAME_ARMYMEMFAIL 165 - -#define LW_LANG_STRING_ERROR_NOTENOUGHTEAMS 166 -#define LW_LANG_STRING_ERROR_NOTENOUGHBIGDATA 167 -#define LW_LANG_STRING_ERROR_GRAPHICSINITFAILED 168 -#define LW_LANG_STRING_ERROR_NONETWORKSUPPORT 169 -#define LW_LANG_STRING_ERROR_UNABLETOCONNECT 170 -#define LW_LANG_STRING_ERROR_NOTALIQUIDWARSERVER 171 -#define LW_LANG_STRING_ERROR_WRONGVERSION 172 -#define LW_LANG_STRING_ERROR_NETWORKPROBLEM 173 -#define LW_LANG_STRING_ERROR_CANTSENDMAP 174 -#define LW_LANG_STRING_ERROR_CANTRECEIVEMAP 175 -#define LW_LANG_STRING_ERROR_SERVERFULL 176 -#define LW_LANG_STRING_ERROR_BADPASSWORD 177 -#define LW_LANG_STRING_ERROR_BADCONFIGRANGE 178 - -#define LW_LANG_STRING_POPUP_INITFAIL 179 -#define LW_LANG_STRING_POPUP_MEMTROUBLE 180 -#define LW_LANG_STRING_POPUP_BIGDATA 181 -#define LW_LANG_STRING_POPUP_LOADFAIL 182 -#define LW_LANG_STRING_POPUP_CUSTOMFAIL 183 -#define LW_LANG_STRING_POPUP_GRAPHICSFAIL 184 - -#define LW_LANG_STRING_LW6_INFO 185 -#define LW_LANG_STRING_LW6_OK 186 - -#define LW_LANG_NB_STRINGS 187 +#define LW_LANG_STRING_MENU_EXITWINDOWS 13 +#define LW_LANG_STRING_MENU_EXITUNIX 14 +#define LW_LANG_STRING_MENU_BACK 15 + +#define LW_LANG_STRING_DIALOG_QUIT 16 +#define LW_LANG_STRING_DIALOG_BACK 17 +#define LW_LANG_STRING_DIALOG_PLAY 18 +#define LW_LANG_STRING_DIALOG_MAIN 19 + +#define LW_LANG_STRING_PLAY_GETREADY 20 + +#define LW_LANG_STRING_NETGAME_STARTGAME 21 +#define LW_LANG_STRING_NETGAME_SERVERADDR 22 +#define LW_LANG_STRING_NETGAME_SERVERPORT 23 +#define LW_LANG_STRING_NETGAME_SEARCH 24 +#define LW_LANG_STRING_NETGAME_PASSWORD 25 +#define LW_LANG_STRING_NETGAME_WEAKPASSWORD 26 + +#define LW_LANG_STRING_LANGUAGE_AUTO 27 + +#define LW_LANG_STRING_TEAM_OFF 28 +#define LW_LANG_STRING_TEAM_HUMAN 29 +#define LW_LANG_STRING_TEAM_CPU 30 + +#define LW_LANG_STRING_OPTIONS_GRAPHICS 31 +#define LW_LANG_STRING_OPTIONS_SOUND 32 +#define LW_LANG_STRING_OPTIONS_RULES 33 +#define LW_LANG_STRING_OPTIONS_SPEEDS 34 +#define LW_LANG_STRING_OPTIONS_CONTROLS 35 +#define LW_LANG_STRING_OPTIONS_LANGUAGE 36 +#define LW_LANG_STRING_OPTIONS_DEFAULT 37 + +#define LW_LANG_STRING_GRAPHICS_GAME 38 +#define LW_LANG_STRING_GRAPHICS_MENU 39 +#define LW_LANG_STRING_GRAPHICS_ON 40 +#define LW_LANG_STRING_GRAPHICS_OFF 41 +#define LW_LANG_STRING_GRAPHICS_FULLSCREEN 42 +#define LW_LANG_STRING_GRAPHICS_WINDOWED 43 +#define LW_LANG_STRING_GRAPHICS_ADVANCED 44 +#define LW_LANG_STRING_GRAPHICS_VIDEOMODE 45 +#define LW_LANG_STRING_GRAPHICS_BRIGHTNESS 46 +#define LW_LANG_STRING_GRAPHICS_VIEWPORTSIZE 47 +#define LW_LANG_STRING_GRAPHICS_PAGEFLIPPING 48 +#define LW_LANG_STRING_GRAPHICS_WAVES 49 + +#define LW_LANG_STRING_VOLUME_SFX 50 +#define LW_LANG_STRING_VOLUME_CLICK 51 +#define LW_LANG_STRING_VOLUME_GAMEWATER 52 +#define LW_LANG_STRING_VOLUME_MENUWATER 53 +#define LW_LANG_STRING_VOLUME_MUSIC 54 + +#define LW_LANG_STRING_RULES_TIME 55 +#define LW_LANG_STRING_RULES_ADVANCED 56 +#define LW_LANG_STRING_RULES_ARMYSIZE 57 +#define LW_LANG_STRING_RULES_CURSOR 58 +#define LW_LANG_STRING_RULES_DEFAULT 59 +#define LW_LANG_STRING_RULES_MINMAPRES 60 + +#define LW_LANG_STRING_ADVANCED_ATTACK 61 +#define LW_LANG_STRING_ADVANCED_DEFENSE 62 +#define LW_LANG_STRING_ADVANCED_BASEHEALTH 63 +#define LW_LANG_STRING_ADVANCED_WINNERHELP 64 +#define LW_LANG_STRING_ADVANCED_CPUSTRENGTH 65 +#define LW_LANG_STRING_ADVANCED_CPUVSHUMAN 66 +#define LW_LANG_STRING_ADVANCED_ALWAYS 67 +#define LW_LANG_STRING_ADVANCED_RANDOM 68 +#define LW_LANG_STRING_ADVANCED_NEVER 69 +#define LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS 70 +#define LW_LANG_STRING_ADVANCED_YES 71 +#define LW_LANG_STRING_ADVANCED_NO 72 + +#define LW_LANG_STRING_SPEEDS_FPS 73 +#define LW_LANG_STRING_SPEEDS_NOFPSLIMIT 74 +#define LW_LANG_STRING_SPEEDS_RPS 75 +#define LW_LANG_STRING_SPEEDS_NORPSLIMIT 76 + +#define LW_LANG_STRING_CONTROLS_JOYSTICK 77 +#define LW_LANG_STRING_CONTROLS_OFF 78 +#define LW_LANG_STRING_CONTROLS_2JOYSTICKS 79 +#define LW_LANG_STRING_CONTROLS_4BUTTONS 80 +#define LW_LANG_STRING_CONTROLS_STANDARD 81 +#define LW_LANG_STRING_CONTROLS_MOUSESENSIB 82 + +#define LW_LANG_STRING_ABOUT_CREDITS 83 +#define LW_LANG_STRING_ABOUT_COPYRIGHT 84 +#define LW_LANG_STRING_ABOUT_LICENSE 85 +#define LW_LANG_STRING_ABOUT_VERSION 86 + +#define LW_LANG_STRING_INTERNET_REFRESH 87 +#define LW_LANG_STRING_INTERNET_JOINNOW 88 +#define LW_LANG_STRING_INTERNET_PORT 89 +#define LW_LANG_STRING_INTERNET_PASSWORD 90 +#define LW_LANG_STRING_INTERNET_YES 91 +#define LW_LANG_STRING_INTERNET_NO 92 +#define LW_LANG_STRING_INTERNET_UPTIME 93 +#define LW_LANG_STRING_INTERNET_DAYS 94 +#define LW_LANG_STRING_INTERNET_DAY 95 +#define LW_LANG_STRING_INTERNET_HOURS 96 +#define LW_LANG_STRING_INTERNET_MINUTES 97 +#define LW_LANG_STRING_INTERNET_SECONDS 98 +#define LW_LANG_STRING_INTERNET_UNREACHABLE 99 +#define LW_LANG_STRING_INTERNET_PING 100 +#define LW_LANG_STRING_INTERNET_MSEC 101 + +#define LW_LANG_STRING_WAVE_AMPLI 102 +#define LW_LANG_STRING_WAVE_NUMBER 103 +#define LW_LANG_STRING_WAVE_SPEED 104 +#define LW_LANG_STRING_WAVE_WX 105 +#define LW_LANG_STRING_WAVE_HY 106 +#define LW_LANG_STRING_WAVE_WY 107 +#define LW_LANG_STRING_WAVE_HX 108 + +#define LW_LANG_STRING_CONNECT_STARTNOW 109 +#define LW_LANG_STRING_CONNECT_WAITING 110 +#define LW_LANG_STRING_CONNECT_WAITINGFOR 111 +#define LW_LANG_STRING_CONNECT_TEAMS 112 +#define LW_LANG_STRING_CONNECT_SENDMESSAGE 113 + +#define LW_LANG_STRING_NETPLAY_CONNECT 114 +#define LW_LANG_STRING_NETPLAY_PING 115 +#define LW_LANG_STRING_NETPLAY_CHECKPROGRAM 116 +#define LW_LANG_STRING_NETPLAY_CHECKVERSION 117 +#define LW_LANG_STRING_NETPLAY_SENDPASSWORD 118 +#define LW_LANG_STRING_NETPLAY_FREETEAMS 119 +#define LW_LANG_STRING_NETPLAY_RESERVETEAMS 120 +#define LW_LANG_STRING_NETPLAY_SENDCONFIG 121 +#define LW_LANG_STRING_NETPLAY_SENDMAP 122 +#define LW_LANG_STRING_NETPLAY_WAITING 123 +#define LW_LANG_STRING_NETPLAY_WHOPLAYS 124 +#define LW_LANG_STRING_NETPLAY_RECVCONFIG 125 +#define LW_LANG_STRING_NETPLAY_RECVMAP 126 + +#define LW_LANG_STRING_LEVEL_USEDEFAULTTEXTURE 127 +#define LW_LANG_STRING_LEVEL_ON 128 +#define LW_LANG_STRING_LEVEL_OFF 129 +#define LW_LANG_STRING_LEVEL_RANDOMMAP 130 + +#define LW_LANG_STRING_CODE_FPS 131 +#define LW_LANG_STRING_CODE_RPS 132 +#define LW_LANG_STRING_CODE_PERCENTCALC 133 +#define LW_LANG_STRING_CODE_PERCENTDISPLAY 134 +#define LW_LANG_STRING_CODE_SPREADGRADTIME 135 +#define LW_LANG_STRING_CODE_MOVEARMYTIME 136 +#define LW_LANG_STRING_CODE_DISPLAYTIME 137 +#define LW_LANG_STRING_CODE_FLIPTIME 138 +#define LW_LANG_STRING_CODE_OTHERCALCTIME 139 +#define LW_LANG_STRING_CODE_GLOBALTIME 140 +#define LW_LANG_STRING_CODE_STANDARDDISPLAY 141 +#define LW_LANG_STRING_CODE_GRADIENT1 142 +#define LW_LANG_STRING_CODE_GRADIENT2 143 +#define LW_LANG_STRING_CODE_GRADIENT3 144 +#define LW_LANG_STRING_CODE_GRADIENT4 145 +#define LW_LANG_STRING_CODE_GRADIENT5 146 +#define LW_LANG_STRING_CODE_GRADIENT6 147 +#define LW_LANG_STRING_CODE_MESHSIZE 148 +#define LW_LANG_STRING_CODE_MESHSTRUCTURE 149 +#define LW_LANG_STRING_CODE_PAUSEOFF 150 +#define LW_LANG_STRING_CODE_PAUSEON 151 +#define LW_LANG_STRING_CODE_WAVEEFFECTSOFF 152 +#define LW_LANG_STRING_CODE_WAVEEFFECTSON 153 +#define LW_LANG_STRING_CODE_CAPTUREOFF 154 +#define LW_LANG_STRING_CODE_CAPTUREON 155 + +#define LW_LANG_STRING_SCORE_WINNER 156 + +#define LW_LANG_STRING_GAME_BACKMEMFAIL 157 +#define LW_LANG_STRING_GAME_DISPMEMFAIL 158 +#define LW_LANG_STRING_GAME_MESHMEMFAIL 159 +#define LW_LANG_STRING_GAME_AREAMEMFAIL 160 +#define LW_LANG_STRING_GAME_ARMYMEMFAIL 161 + +#define LW_LANG_STRING_ERROR_NOTENOUGHTEAMS 162 +#define LW_LANG_STRING_ERROR_NOTENOUGHBIGDATA 163 +#define LW_LANG_STRING_ERROR_GRAPHICSINITFAILED 164 +#define LW_LANG_STRING_ERROR_NONETWORKSUPPORT 165 +#define LW_LANG_STRING_ERROR_UNABLETOCONNECT 166 +#define LW_LANG_STRING_ERROR_NOTALIQUIDWARSERVER 167 +#define LW_LANG_STRING_ERROR_WRONGVERSION 168 +#define LW_LANG_STRING_ERROR_NETWORKPROBLEM 169 +#define LW_LANG_STRING_ERROR_CANTSENDMAP 170 +#define LW_LANG_STRING_ERROR_CANTRECEIVEMAP 171 +#define LW_LANG_STRING_ERROR_SERVERFULL 172 +#define LW_LANG_STRING_ERROR_BADPASSWORD 173 +#define LW_LANG_STRING_ERROR_BADCONFIGRANGE 174 + +#define LW_LANG_STRING_POPUP_INITFAIL 175 +#define LW_LANG_STRING_POPUP_MEMTROUBLE 176 +#define LW_LANG_STRING_POPUP_BIGDATA 177 +#define LW_LANG_STRING_POPUP_LOADFAIL 178 +#define LW_LANG_STRING_POPUP_CUSTOMFAIL 179 +#define LW_LANG_STRING_POPUP_GRAPHICSFAIL 180 + +#define LW_LANG_STRING_LW6_INFO 181 +#define LW_LANG_STRING_LW6_OK 182 + +#define LW_LANG_NB_STRINGS 183 /*==================================================================*/ /* globals */ diff --git a/src/langde.c b/src/langde.c index c1bb6cf3..57732be2 100644 --- a/src/langde.c +++ b/src/langde.c @@ -123,7 +123,6 @@ lw_langde_init () LW_LANGDE_DATA[LW_LANG_STRING_MENU_OPTIONS] = "Optionen"; LW_LANGDE_DATA[LW_LANG_STRING_MENU_ABOUT] = "Informationen"; LW_LANGDE_DATA[LW_LANG_STRING_MENU_EXIT] = "Quit"; - LW_LANGDE_DATA[LW_LANG_STRING_MENU_EXITDOS] = "Exit"; LW_LANGDE_DATA[LW_LANG_STRING_MENU_EXITWINDOWS] = "Quit"; LW_LANGDE_DATA[LW_LANG_STRING_MENU_EXITUNIX] = "Quit"; LW_LANGDE_DATA[LW_LANG_STRING_MENU_BACK] = "Zurueck zu LW"; @@ -192,9 +191,6 @@ lw_langde_init () LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_ALWAYS] = "Immer"; LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_RANDOM] = "Normal"; LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_NEVER] = "Nie"; - LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_ASMALGORITHM] = "Algorithmus"; - LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_ASSEMBLY] = "Assembly"; - LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_STANDARDC] = "C-Standard"; LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS] = "Netzbots"; LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_YES] = "An"; LW_LANGDE_DATA[LW_LANG_STRING_ADVANCED_NO] = "Aus"; diff --git a/src/langdk.c b/src/langdk.c index 65896297..fd9a0c5c 100644 --- a/src/langdk.c +++ b/src/langdk.c @@ -104,7 +104,6 @@ lw_langdk_init () LW_LANGDK_DATA[LW_LANG_STRING_MENU_OPTIONS] = "Indstillinger"; LW_LANGDK_DATA[LW_LANG_STRING_MENU_ABOUT] = "Om spillet"; LW_LANGDK_DATA[LW_LANG_STRING_MENU_EXIT] = "Afslut"; - LW_LANGDK_DATA[LW_LANG_STRING_MENU_EXITDOS] = "Ud til DOS"; LW_LANGDK_DATA[LW_LANG_STRING_MENU_EXITWINDOWS] = "Afslut"; LW_LANGDK_DATA[LW_LANG_STRING_MENU_EXITUNIX] = "Afslut"; LW_LANGDK_DATA[LW_LANG_STRING_MENU_BACK] = "Tilbage til LW"; @@ -173,9 +172,6 @@ lw_langdk_init () LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_ALWAYS] = "Altid"; LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_RANDOM] = "Tilfaeldigt"; LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_NEVER] = "Aldrig"; - LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_ASMALGORITHM] = "Algoritme"; - LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_ASSEMBLY] = "Assembly"; - LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_STANDARDC] = "Standard C"; LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS] = "Bots i netspil"; LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_YES] = "Ja"; LW_LANGDK_DATA[LW_LANG_STRING_ADVANCED_NO] = "Nej"; diff --git a/src/langen.c b/src/langen.c index 0901a80c..8822feb1 100644 --- a/src/langen.c +++ b/src/langen.c @@ -97,7 +97,6 @@ lw_langen_init () LW_LANGEN_DATA[LW_LANG_STRING_MENU_OPTIONS] = "Options"; LW_LANGEN_DATA[LW_LANG_STRING_MENU_ABOUT] = "About"; LW_LANGEN_DATA[LW_LANG_STRING_MENU_EXIT] = "Exit"; - LW_LANGEN_DATA[LW_LANG_STRING_MENU_EXITDOS] = "Exit to DOS"; LW_LANGEN_DATA[LW_LANG_STRING_MENU_EXITWINDOWS] = "Exit"; LW_LANGEN_DATA[LW_LANG_STRING_MENU_EXITUNIX] = "Exit"; LW_LANGEN_DATA[LW_LANG_STRING_MENU_BACK] = "Back to LW"; @@ -166,9 +165,6 @@ lw_langen_init () LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_ALWAYS] = "Always"; LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_RANDOM] = "Random"; LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_NEVER] = "Never"; - LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_ASMALGORITHM] = "Algorithm"; - LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_ASSEMBLY] = "Assembly"; - LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_STANDARDC] = "Standard C"; LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS] = "Allow net bots"; LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_YES] = "Yes"; LW_LANGEN_DATA[LW_LANG_STRING_ADVANCED_NO] = "No"; diff --git a/src/langfr.c b/src/langfr.c index b481b838..01a667d0 100644 --- a/src/langfr.c +++ b/src/langfr.c @@ -116,7 +116,6 @@ lw_langfr_init () LW_LANGFR_DATA[LW_LANG_STRING_MENU_OPTIONS] = "Options"; LW_LANGFR_DATA[LW_LANG_STRING_MENU_ABOUT] = "A propos"; LW_LANGFR_DATA[LW_LANG_STRING_MENU_EXIT] = "Quitter"; - LW_LANGFR_DATA[LW_LANG_STRING_MENU_EXITDOS] = "Revenir a DOS"; LW_LANGFR_DATA[LW_LANG_STRING_MENU_EXITWINDOWS] = "Quitter"; LW_LANGFR_DATA[LW_LANG_STRING_MENU_EXITUNIX] = "Quitter"; LW_LANGFR_DATA[LW_LANG_STRING_MENU_BACK] = "Retour a LW"; @@ -186,9 +185,6 @@ lw_langfr_init () LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_ALWAYS] = "Toujours"; LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_RANDOM] = "Au hasard"; LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_NEVER] = "Jamais"; - LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_ASMALGORITHM] = "Algorithme"; - LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_ASSEMBLY] = "Assembleur"; - LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_STANDARDC] = "C standard"; LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS] = "Bots reseau"; LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_YES] = "Oui"; LW_LANGFR_DATA[LW_LANG_STRING_ADVANCED_NO] = "Non"; diff --git a/src/langpl.c b/src/langpl.c index f5de7068..023c6bfd 100644 --- a/src/langpl.c +++ b/src/langpl.c @@ -79,7 +79,7 @@ lw_langpl_init () LW_LANGPL_DATA[LW_LANG_STRING_HELP_CREDITS] = "Idea:: \n* Thomas Colcombet\n\nKod: \n* Christian Mauduit\n\nMuzyka:\n* Tim Chadburn\n\nInni:\n* Alstar\n* Peter Wang\n* Cort Danger Stratton\n* Jan Gretschuskin (www.game-factor.de)\n* Mouse\n* Rene Stach\n* Roderick Schertler\n* Ryan D. Brown\n* Eduard Bloch\n* Michael Terry\n* Kasper Hviid\n* David Redick\n* Alexandre Pineau\n* Michael Wagner\n* Peter Williams\n* Jan Samohyl\n* Gavin\n* Dave Vasilevsky\n* 2 of Omega\n* 666-REFIZUL-666\n* Thomas Klausner\n* Joan Dolc\n* Mikhail Yakshin\n* Valerie Mauduit\n* Florence Mauduit\n* Joey Dodson\n* Jan Szenborn\n\nWiecej informacji na www.ufoot.org/liquidwar/v5\n"; LW_LANGPL_DATA[LW_LANG_STRING_HELP_COPYRIGHT] = - "Liquid War jest wojenna gra multiplayer.\nCopyright (C) 1998-2025 Christian Mauduit (ufoot@ufoot.org)\n\nTen program jest darmowy; mozesz go rozpowszechniac i/lub modyfikowac zgodnie z zasadami GNU General Public License wydanej przez Free Software Foundation, zgodnie z wersja druga tej licencji albo (wedlug Twojego wyboru) pozniejsza wersja.\n\nTen program jest rozpowszechniany z nadzieja na bycie uzytecznym, ale CALKOWICIE BEZ GWARANCJI; nawet bez gwarancji PRZYDATNOSCI HANDLOWEJ albo PRZYDATNOSCI DO OKRESLONYCH ZASTOSOWAN. Zobacz GNU General Public License po wiecej szczegolow.\n\nPowinienes dostac kopie licencji GNU razem z tym programem; jezeli nie, napisz do Free Software Foundation, Inc., 51 Franklin St, 5 pietro, Boston, MA 02110-1301 USA\n\nWiecej informacji na www.ufoot.org/liquidwar/v5\n"; + "Liquid War jest wojenną grą multiplayer.\nCopyright (C) 1998-2025 Christian Mauduit (ufoot@ufoot.org)\n\nTen program jest darmowy; możesz go rozpowszechniać i/lub modyfikować zgodnie z zasadami GNU General Public License wydanej przez Free Software Foundation, zgodnie z wersją drugą tej licencji albo (według Twojego wyboru) późniejszą wersją.\n\nTen program jest rozpowszechniany z nadzieją na bycie użytecznym, ale CAŁKOWICIE BEZ GWARANCJI; nawet bez gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. Zobacz GNU General Public License po więcej szczegółów.\n\nPowinieneś dostać kopię licencji GNU razem z tym programem; jeżeli nie, napisz do Free Software Foundation, Inc., 51 Franklin St, 5 piętro, Boston, MA 02110-1301 USA\n\nWięcej informacji na www.ufoot.org/liquidwar/v5\n"; /* * Stupid Microsoft VC++ can't handle strings over 2048 chars correctly, * (compiler error C2026) so we had to split this one... @@ -98,7 +98,6 @@ lw_langpl_init () LW_LANGPL_DATA[LW_LANG_STRING_MENU_OPTIONS] = "Opcje"; LW_LANGPL_DATA[LW_LANG_STRING_MENU_ABOUT] = "Informacje"; LW_LANGPL_DATA[LW_LANG_STRING_MENU_EXIT] = "Wyjscie"; - LW_LANGPL_DATA[LW_LANG_STRING_MENU_EXITDOS] = "Wyjdz do DOS"; LW_LANGPL_DATA[LW_LANG_STRING_MENU_EXITWINDOWS] = "Wyjscie"; LW_LANGPL_DATA[LW_LANG_STRING_MENU_EXITUNIX] = "Wyjscie"; LW_LANGPL_DATA[LW_LANG_STRING_MENU_BACK] = "Wroc do LW"; @@ -169,9 +168,6 @@ lw_langpl_init () LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_ALWAYS] = "Zawsze"; LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_RANDOM] = "Losowo"; LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_NEVER] = "Nigdy"; - LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_ASMALGORITHM] = "Algorytm"; - LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_ASSEMBLY] = "Wbudowany"; - LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_STANDARDC] = "Standardowy C"; LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_ALLOWNETWORKBOTS] = "Zezwol na boty w sieci"; LW_LANGPL_DATA[LW_LANG_STRING_ADVANCED_YES] = "Tak"; diff --git a/src/level.c b/src/level.c index dd24a44e..30d90c1b 100644 --- a/src/level.c +++ b/src/level.c @@ -55,6 +55,8 @@ #include #include +#include "backport.h" +#include "backportgui.h" #include "back.h" #include "config.h" #include "dialog.h" @@ -64,7 +66,6 @@ #include "map.h" #include "maptex.h" #include "menu.h" -#include "palette.h" #include "sound.h" #include "texture.h" #include "macro.h" @@ -102,7 +103,11 @@ palette_128 (DIALOG * d, int x, int y, int w, int h) d[k].h = h2; d[k].fg = MENU_FG; d[k].flags = D_EXIT; - d[k].bg = k + 128; + // Map k (0-127) to a team color with intensity + // Divide into 6 teams with gradients for each + int team = k / (128 / 6); + int intensity = (k % (128 / 6)) * 255 / (128 / 6); + d[k].bg = lw_team_color(team, intensity); } k = 0; for (i = 0; i < 12; ++i) @@ -167,7 +172,7 @@ display_chosen_level (void) int y1, y2, y3, y4, y5, y6, y7, y8; int sample_x, sample_y, sample_w, sample_h; int max_w, max_h, bmp_w, bmp_h; - BITMAP *pour_voir; + ALLEGRO_BITMAP *pour_voir; retrieve_choose_level_xy (&x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &y1, &y2, &y3, &y4, &y5, &y6, &y7, &y8); rectfill (screen, menu_real_x (x4), menu_real_y (y1), @@ -177,7 +182,7 @@ display_chosen_level (void) LW_RANDOM_ON, CONFIG_USE_DEFAULT_TEXTURE); lw_maptex_set_bg_palette (CONFIG_LEVEL_MAP, CONFIG_LEVEL_BG, 0, LW_RANDOM_ON, CONFIG_USE_DEFAULT_TEXTURE); - my_set_palette (); + // my_set_palette (); // No longer needed in true color mode pour_voir = lw_maptex_create_map (CONFIG_LEVEL_MAP, CONFIG_LEVEL_FG, CONFIG_LEVEL_BG, 0, LW_RANDOM_ON, MIN_MAP_RES_W[CONFIG_MIN_MAP_RES], MIN_MAP_RES_H[CONFIG_MIN_MAP_RES], @@ -187,8 +192,8 @@ display_chosen_level (void) { max_w = menu_real_x (MENU_W_SAMPLE); max_h = menu_real_y (MENU_H_SAMPLE); - bmp_w = pour_voir->w; - bmp_h = pour_voir->h; + bmp_w = al_get_bitmap_width (pour_voir); + bmp_h = al_get_bitmap_height (pour_voir); if (max_w * bmp_h < max_h * bmp_w) { @@ -206,7 +211,7 @@ display_chosen_level (void) sample_y = menu_real_y (y1) + (max_h - sample_h) / 2; stretch_blit (pour_voir, screen, 0, 0, bmp_w, bmp_h, sample_x, sample_y, sample_w, sample_h); - destroy_bitmap (pour_voir); + al_destroy_bitmap (pour_voir); } if (!lw_maptex_is_custom_texture_used (CONFIG_LEVEL_MAP, CONFIG_LEVEL_FG, 0, LW_RANDOM_ON, @@ -222,11 +227,11 @@ display_chosen_level (void) if (pour_voir) { - stretch_blit (pour_voir, screen, 0, 0, pour_voir->w, pour_voir->h, + stretch_blit (pour_voir, screen, 0, 0, al_get_bitmap_width (pour_voir), al_get_bitmap_height (pour_voir), menu_real_x (x1), menu_real_x (y1), menu_real_x (MENU_W_LEVEL), menu_real_x (MENU_W_LEVEL)); - destroy_bitmap (pour_voir); + al_destroy_bitmap (pour_voir); } } if (!lw_maptex_is_custom_texture_used @@ -243,11 +248,11 @@ display_chosen_level (void) if (pour_voir) { - stretch_blit (pour_voir, screen, 0, 0, pour_voir->w, pour_voir->h, + stretch_blit (pour_voir, screen, 0, 0, al_get_bitmap_width (pour_voir), al_get_bitmap_height (pour_voir), menu_real_x (x8), menu_real_x (y1), menu_real_x (MENU_W_LEVEL), menu_real_x (MENU_W_LEVEL)); - destroy_bitmap (pour_voir); + al_destroy_bitmap (pour_voir); } } } @@ -604,7 +609,7 @@ choose_map (void) buf1[0] = 0; buf2[0] = 0; display_back_image (); - set_palette_for_choose_color (); + // set_palette_for_choose_color (); // No longer needed in true color mode quick_buttons (d); retrieve_choose_level_xy (&x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &y1, &y2, &y3, &y4, &y5, &y6, &y7, &y8); diff --git a/src/logcli.c b/src/logcli.c index 45bb2dc3..c7f1b0aa 100644 --- a/src/logcli.c +++ b/src/logcli.c @@ -53,7 +53,7 @@ /*==================================================================*/ /* - * Note: we must *not* include allegro.h here, or everything's + * Note: we must *not* include allegro5/allegro.h here, or everything's * wrecked with the use of windows.h... */ #ifdef WIN32 @@ -237,9 +237,6 @@ log_println_int (int i) void log_flush () { -#ifdef GP2X - usleep (100); -#endif #ifndef WIN32 fflush (stdout); #endif diff --git a/src/lw6.c b/src/lw6.c index 71ab5d2f..7572a79d 100644 --- a/src/lw6.c +++ b/src/lw6.c @@ -83,7 +83,7 @@ lw6_advertise_menu (int fade_in) if (fade_in) { - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode } d[2].proc = NULL; diff --git a/src/lwwin.rc b/src/lwwin.rc index 51f11895..cc58aba1 100644 --- a/src/lwwin.rc +++ b/src/lwwin.rc @@ -3,8 +3,8 @@ allegro_icon ICON "./misc/liquidwar.ico" 1 VERSIONINFO -FILEVERSION 5, 6, 5, 1 -PRODUCTVERSION 5, 6, 5, 1 +FILEVERSION 5, 7, 0, 1 +PRODUCTVERSION 5, 7, 0, 1 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS VOS__WINDOWS32 @@ -17,13 +17,13 @@ BEGIN BEGIN VALUE "Comments", "A unique multiplayer wargame\0" VALUE "CompanyName", "N/A\0" - VALUE "FileDescription", "Liquid War 5.6.5 for Microsoft Windows\0" - VALUE "FileVersion", "5.6.5-1\0" + VALUE "FileDescription", "Liquid War 5.7.0 for Microsoft Windows\0" + VALUE "FileVersion", "5.7.0-1\0" VALUE "InternalName", "liquidwar\0" VALUE "LegalCopyright", "Copyright (C) 1998-2025 Christian Mauduit\0" VALUE "OriginalFilename", "lwwin.exe\0" VALUE "ProductName", "Liquid War\0" - VALUE "ProductVersion", "5.6.5\0" + VALUE "ProductVersion", "5.7.0\0" END END END diff --git a/src/main.c b/src/main.c index 18338bfe..30eb8638 100644 --- a/src/main.c +++ b/src/main.c @@ -52,11 +52,8 @@ /* includes */ /*==================================================================*/ -#include -#ifdef DOS -#include -#endif - +#define ALLEGRO_NO_MAIN +#include "backport.h" #include "bigdata.h" #include "config.h" #include "disk.h" @@ -70,37 +67,11 @@ #include "startup.h" #include "basicopt.h" -/*==================================================================*/ -/* construct pour reduire la place d'allegro */ -/*==================================================================*/ -#ifdef DOS - -BEGIN_GFX_DRIVER_LIST - GFX_DRIVER_VGA - GFX_DRIVER_MODEX - GFX_DRIVER_VBEAF - GFX_DRIVER_VESA2L - GFX_DRIVER_VESA2B - GFX_DRIVER_VESA1 - END_GFX_DRIVER_LIST - BEGIN_COLOR_DEPTH_LIST - COLOR_DEPTH_8 - COLOR_DEPTH_15 - COLOR_DEPTH_16 - COLOR_DEPTH_24 - COLOR_DEPTH_32 - END_COLOR_DEPTH_LIST - BEGIN_DIGI_DRIVER_LIST - DIGI_DRIVER_SB - DIGI_DRIVER_SOUNDSCAPE - DIGI_DRIVER_AUDIODRIVE - END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST END_MIDI_DRIVER_LIST -#endif /*==================================================================*/ /* functions */ /*==================================================================*/ /*------------------------------------------------------------------*/ - int +int main (int argc, char **argv) { int init_success = 0; @@ -122,13 +93,6 @@ main (int argc, char **argv) log_println (); load_custom_success = load_custom (); log_println (); - -#ifdef DOS - if (STARTUP_STOP) - readkey (); - else - delay (500); -#endif } if (!init_success) @@ -162,10 +126,3 @@ main (int argc, char **argv) return 0; } - -#ifdef WIN32 -END_OF_MAIN () -#endif -#ifdef UNIX - END_OF_MAIN (); -#endif diff --git a/src/map.c b/src/map.c index b1c00cf0..1165d57a 100644 --- a/src/map.c +++ b/src/map.c @@ -72,9 +72,10 @@ /*==================================================================*/ #define LIGHT_OR_DARK_TRESHOLD 315 -#define CONSIDERED_AS_DARK 0 -#define CONSIDERED_AS_LIGHT 2 -#define PLAYABLE_AREA 1 +// Color constants converted to ALLEGRO_COLOR - these are now created inline where needed +#define CONSIDERED_AS_DARK_RGB 0x000000 /* Black RGB */ +#define CONSIDERED_AS_LIGHT_RGB 0xFFFFFF /* White RGB */ +#define PLAYABLE_AREA_RGB 0x010101 /* Very dark gray RGB for playable */ #define MINI_SIDE_SIZE 4 #define MINI_PLAYABLE_AREA 1024 @@ -82,6 +83,14 @@ /* fonctions */ /*==================================================================*/ +/*------------------------------------------------------------------*/ +/* Helper function to compare ALLEGRO_COLOR values */ +static int +colors_equal(ALLEGRO_COLOR c1, ALLEGRO_COLOR c2) +{ + return (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a); +} + /*------------------------------------------------------------------*/ static int calc_zoom_factor (int w, int h, int min_w, int min_h) @@ -104,39 +113,56 @@ calc_zoom_factor (int w, int h, int min_w, int min_h) /*------------------------------------------------------------------*/ static void -sort_light_and_dark (BITMAP * bmp, PALETTE pal) +sort_light_and_dark (ALLEGRO_BITMAP * bmp) { - char table[256]; - int i, x, y; - - for (i = 0; i < 256; ++i) - { - if (6 * pal[i].r + 3 * pal[i].g + pal[i].b > LIGHT_OR_DARK_TRESHOLD) - table[i] = CONSIDERED_AS_LIGHT; - else - table[i] = CONSIDERED_AS_DARK; - } - - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - putpixel (bmp, x, y, table[getpixel (bmp, x, y)]); + int x, y; + ALLEGRO_COLOR pixel_color; + float r, g, b, a; + int brightness; + ALLEGRO_COLOR light_color, dark_color; + + /* Create actual RGB colors from constants */ + light_color = al_map_rgb((CONSIDERED_AS_LIGHT_RGB >> 16) & 0xFF, + (CONSIDERED_AS_LIGHT_RGB >> 8) & 0xFF, + CONSIDERED_AS_LIGHT_RGB & 0xFF); + dark_color = al_map_rgb((CONSIDERED_AS_DARK_RGB >> 16) & 0xFF, + (CONSIDERED_AS_DARK_RGB >> 8) & 0xFF, + CONSIDERED_AS_DARK_RGB & 0xFF); + + /* Set target bitmap once for efficiency */ + al_set_target_bitmap (bmp); + + for (y = 0; y < al_get_bitmap_height (bmp); ++y) + for (x = 0; x < al_get_bitmap_width (bmp); ++x) + { + pixel_color = al_get_pixel (bmp, x, y); + al_unmap_rgba_f (pixel_color, &r, &g, &b, &a); + + /* Apply weighted brightness formula with 0-255 scaling */ + brightness = (int)(6 * (r * 255) + 3 * (g * 255) + (b * 255)); + + if (brightness > LIGHT_OR_DARK_TRESHOLD) + al_put_pixel (x, y, light_color); + else + al_put_pixel (x, y, dark_color); + } } /*------------------------------------------------------------------*/ -static BITMAP * -extract_significant_part (BITMAP * src) +static ALLEGRO_BITMAP * +extract_significant_part (ALLEGRO_BITMAP * src) { - int min_x = src->w; - int min_y = src->h; + int min_x = al_get_bitmap_width (src); + int min_y = al_get_bitmap_height (src); int max_x = -1; int max_y = -1; int dst_x, dst_y, dst_w, dst_h; int x, y; - BITMAP *result; + ALLEGRO_BITMAP *result; - for (y = 0; y < src->h; ++y) - for (x = 0; x < src->w; ++x) - if (getpixel (src, x, y) == CONSIDERED_AS_DARK) + for (y = 0; y < al_get_bitmap_height (src); ++y) + for (x = 0; x < al_get_bitmap_width (src); ++x) + if (is_color_dark(getpixel (src, x, y))) { if (min_x > x) min_x = x; @@ -156,7 +182,7 @@ extract_significant_part (BITMAP * src) result = NULL; else { - result = my_create_bitmap (dst_w, dst_h); + result = my_create_memory_bitmap (dst_w, dst_h); if (result) blit (src, result, dst_x, dst_y, 0, 0, dst_w, dst_h); } @@ -166,45 +192,46 @@ extract_significant_part (BITMAP * src) /*-----------------------------------------------------------------*/ static int -spread_color_down (BITMAP * bmp, int color1, int color2) +spread_color_down (ALLEGRO_BITMAP * bmp, ALLEGRO_COLOR color1, ALLEGRO_COLOR color2) { int x, y, x1, y1, x2, y2, found = 0; - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - if (getpixel (bmp, x, y) == color2) + al_set_target_bitmap (bmp); + for (y = 0; y < al_get_bitmap_height (bmp); ++y) + for (x = 0; x < al_get_bitmap_width (bmp); ++x) + if (colors_equal(getpixel (bmp, x, y), color2)) { x1 = x - 1; if (x1 < 0) x1 = 0; x2 = x + 1; - if (x2 > bmp->w - 1) - x2 = bmp->w - 1; + if (x2 > al_get_bitmap_width (bmp) - 1) + x2 = al_get_bitmap_width (bmp) - 1; y1 = y - 1; if (y1 < 0) y1 = 0; y2 = y + 1; - if (y2 > bmp->h - 1) - y2 = bmp->h - 1; + if (y2 > al_get_bitmap_height (bmp) - 1) + y2 = al_get_bitmap_height (bmp) - 1; - if (getpixel (bmp, x2, y) == color1) + if (colors_equal(getpixel (bmp, x2, y), color1)) { - putpixel (bmp, x2, y, color2); + putpixel_fast (x2, y, color2); found++; } - if (getpixel (bmp, x2, y2) == color1) + if (colors_equal(getpixel (bmp, x2, y2), color1)) { - putpixel (bmp, x2, y2, color2); + putpixel_fast (x2, y2, color2); found++; } - if (getpixel (bmp, x, y2) == color1) + if (colors_equal(getpixel (bmp, x, y2), color1)) { - putpixel (bmp, x, y2, color2); + putpixel_fast (x, y2, color2); found++; } - if (getpixel (bmp, x1, y2) == color1) + if (colors_equal(getpixel (bmp, x1, y2), color1)) { - putpixel (bmp, x1, y2, color2); + putpixel_fast (x1, y2, color2); found++; } } @@ -214,45 +241,46 @@ spread_color_down (BITMAP * bmp, int color1, int color2) /*-----------------------------------------------------------------*/ static int -spread_color_up (BITMAP * bmp, int color1, int color2) +spread_color_up (ALLEGRO_BITMAP * bmp, ALLEGRO_COLOR color1, ALLEGRO_COLOR color2) { int x, y, x1, y1, x2, y2, found = 0; - for (y = bmp->h - 1; y >= 0; --y) - for (x = bmp->w - 1; x >= 0; --x) - if (getpixel (bmp, x, y) == color2) + al_set_target_bitmap (bmp); + for (y = al_get_bitmap_height (bmp) - 1; y >= 0; --y) + for (x = al_get_bitmap_width (bmp) - 1; x >= 0; --x) + if (colors_equal(getpixel (bmp, x, y), color2)) { x1 = x - 1; if (x1 < 0) x1 = 0; x2 = x + 1; - if (x2 > bmp->w - 1) - x2 = bmp->w - 1; + if (x2 > al_get_bitmap_width (bmp) - 1) + x2 = al_get_bitmap_width (bmp) - 1; y1 = y - 1; if (y1 < 0) y1 = 0; y2 = y + 1; - if (y2 > bmp->h - 1) - y2 = bmp->h - 1; + if (y2 > al_get_bitmap_height (bmp) - 1) + y2 = al_get_bitmap_height (bmp) - 1; - if (getpixel (bmp, x1, y) == color1) + if (colors_equal(getpixel (bmp, x1, y), color1)) { - putpixel (bmp, x1, y, color2); + putpixel_fast (x1, y, color2); found++; } - if (getpixel (bmp, x1, y1) == color1) + if (colors_equal(getpixel (bmp, x1, y1), color1)) { - putpixel (bmp, x1, y1, color2); + putpixel_fast (x1, y1, color2); found++; } - if (getpixel (bmp, x, y1) == color1) + if (colors_equal(getpixel (bmp, x, y1), color1)) { - putpixel (bmp, x, y1, color2); + putpixel_fast (x, y1, color2); found++; } - if (getpixel (bmp, x2, y1) == color1) + if (colors_equal(getpixel (bmp, x2, y1), color1)) { - putpixel (bmp, x2, y1, color2); + putpixel_fast (x2, y1, color2); found++; } } @@ -263,25 +291,37 @@ spread_color_up (BITMAP * bmp, int color1, int color2) /*-----------------------------------------------------------------*/ static int -check_if_playable (BITMAP * bmp) +check_if_playable (ALLEGRO_BITMAP * bmp) { int x = 0, y = 0, x0, y0; int unplayable = 0; int playable_place = 0; + ALLEGRO_COLOR light_color, dark_color, playable_color; + + /* Create ALLEGRO_COLOR from RGB constants */ + light_color = al_map_rgb((CONSIDERED_AS_LIGHT_RGB >> 16) & 0xFF, + (CONSIDERED_AS_LIGHT_RGB >> 8) & 0xFF, + CONSIDERED_AS_LIGHT_RGB & 0xFF); + dark_color = al_map_rgb((CONSIDERED_AS_DARK_RGB >> 16) & 0xFF, + (CONSIDERED_AS_DARK_RGB >> 8) & 0xFF, + CONSIDERED_AS_DARK_RGB & 0xFF); + playable_color = al_map_rgb((PLAYABLE_AREA_RGB >> 16) & 0xFF, + (PLAYABLE_AREA_RGB >> 8) & 0xFF, + PLAYABLE_AREA_RGB & 0xFF); /* * Now we draw the "outside" of the map. This is usefull * to avoid bugs (core dumps) if the map is not correctly drawn. */ - hline (bmp, 0, 0, bmp->w - 1, CONSIDERED_AS_DARK); - hline (bmp, 0, bmp->h - 1, bmp->w - 1, CONSIDERED_AS_DARK); - vline (bmp, 0, 0, bmp->h - 1, CONSIDERED_AS_DARK); - vline (bmp, bmp->w - 1, 0, bmp->h - 1, CONSIDERED_AS_DARK); + hline (bmp, 0, 0, al_get_bitmap_width (bmp) - 1, dark_color); + hline (bmp, 0, al_get_bitmap_height (bmp) - 1, al_get_bitmap_width (bmp) - 1, dark_color); + vline (bmp, 0, 0, al_get_bitmap_height (bmp) - 1, dark_color); + vline (bmp, al_get_bitmap_width (bmp) - 1, 0, al_get_bitmap_height (bmp) - 1, dark_color); x0 = y0 = -1; - for (y = 0; y < bmp->h && y0 < 0; ++y) - for (x = 0; x < bmp->w && x0 < 0; ++x) - if (getpixel (bmp, x, y) == CONSIDERED_AS_LIGHT) + for (y = 0; y < al_get_bitmap_height (bmp) && y0 < 0; ++y) + for (x = 0; x < al_get_bitmap_width (bmp) && x0 < 0; ++x) + if (is_color_light(getpixel (bmp, x, y))) { x0 = x; y0 = y; @@ -289,19 +329,23 @@ check_if_playable (BITMAP * bmp) if (x0 > 0 && y0 > 0) { - putpixel (bmp, x, y, PLAYABLE_AREA); - while (spread_color_down (bmp, CONSIDERED_AS_LIGHT, - PLAYABLE_AREA) - + spread_color_up (bmp, CONSIDERED_AS_LIGHT, PLAYABLE_AREA)); + putpixel (bmp, x, y, playable_color); + while (spread_color_down (bmp, light_color, playable_color) + + spread_color_up (bmp, light_color, playable_color)); } - else + else { + log_print_str("L"); unplayable |= 1; + } - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - if (getpixel (bmp, x, y) == PLAYABLE_AREA) + for (y = 0; y < al_get_bitmap_height (bmp); ++y) + for (x = 0; x < al_get_bitmap_width (bmp); ++x) + if (is_color_light(getpixel (bmp, x, y))) ++playable_place; + if (playable_place < MINI_PLAYABLE_AREA) { + log_print_str("S"); + } unplayable |= (playable_place < MINI_PLAYABLE_AREA); return (!unplayable); @@ -309,58 +353,67 @@ check_if_playable (BITMAP * bmp) /*-----------------------------------------------------------------*/ static void -fill_with_fg_and_bg (BITMAP * bmp, int fg, int bg) +fill_with_fg_and_bg (ALLEGRO_BITMAP * bmp, ALLEGRO_COLOR fg, ALLEGRO_COLOR bg) { int x, y; /* * We set up the real fg and bg color instead of the * CONSIDERED_AS_... constants. + * Light pixels become bg (playable area), dark pixels become fg (walls). */ - for (y = 0; y < bmp->h; ++y) + al_set_target_bitmap (bmp); + for (y = 0; y < al_get_bitmap_height (bmp); ++y) { - for (x = 0; x < bmp->w; ++x) + for (x = 0; x < al_get_bitmap_width (bmp); ++x) { - putpixel (bmp, x, y, - getpixel (bmp, x, y) == PLAYABLE_AREA ? bg : fg); + putpixel_fast (x, y, + is_color_light(getpixel (bmp, x, y)) ? bg : fg); } } } /*-----------------------------------------------------------------*/ static void -convert_to_buffer (BITMAP * bmp, char *buffer, int *size, int *bg_size) +convert_to_buffer (ALLEGRO_BITMAP * bmp, char *buffer, int *size, + int *bg_size) { - int pos_src, l, wh; - char *data; + int x, y, l, w, h; + int is_light; - wh = bmp->h * bmp->w; - data = bmp->dat; - pos_src = 0; + w = al_get_bitmap_width (bmp); + h = al_get_bitmap_height (bmp); (*size) = 0; (*bg_size) = 0; - while (pos_src < wh) + for (y = 0; y < h; ++y) { - l = 0; - if (data[pos_src] != PLAYABLE_AREA) + for (x = 0; x < w; ) { - while (pos_src < wh && (data[pos_src] != PLAYABLE_AREA) && l < 127) + l = 0; + is_light = is_color_light(getpixel(bmp, x, y)); + + if (is_light) { - l++; - pos_src++; + // Count consecutive light (playable) pixels + while (x < w && is_color_light(getpixel(bmp, x, y)) && l < 127) + { + l++; + x++; + } + buffer[(*size)++] = -l; + (*bg_size) += l; } - buffer[(*size)++] = l; - } - else - { - while (pos_src < wh && (data[pos_src] == PLAYABLE_AREA) && l < 127) + else { - l++; - pos_src++; + // Count consecutive dark (wall) pixels + while (x < w && is_color_dark(getpixel(bmp, x, y)) && l < 127) + { + l++; + x++; + } + buffer[(*size)++] = l; } - buffer[(*size)++] = -l; - (*bg_size) += l; } } buffer[(*size)++] = 0; @@ -368,34 +421,49 @@ convert_to_buffer (BITMAP * bmp, char *buffer, int *size, int *bg_size) /*------------------------------------------------------------------*/ void * -lw_map_archive_raw_bmp (BITMAP * bmp, PALETTE pal, const char *filename) +lw_map_archive_raw_bmp (ALLEGRO_BITMAP * bmp, const char *filename) { int w = 0, h = 0, size = 0, bg_size = 0; - BITMAP *sub_bmp; + ALLEGRO_BITMAP *sub_bmp; char *temp = NULL; char *result = NULL; static int index = 1; char readable_name_buffer[LW_MAP_READABLE_NAME_SIZE + 1]; char system_name_buffer[LW_MAP_SYSTEM_NAME_SIZE + 1]; - if (bmp) - { - sort_light_and_dark (bmp, pal); - sub_bmp = extract_significant_part (bmp); - if (sub_bmp) - { - w = sub_bmp->w; - h = sub_bmp->h; - if (check_if_playable (sub_bmp)) - { - temp = malloc_in_big_data_bottom (w * h + 1); - if (temp) - convert_to_buffer (sub_bmp, temp, &size, &bg_size); - } - destroy_bitmap (sub_bmp); - } - destroy_bitmap (bmp); - } + if (!bmp) { + log_print_str("B"); + return NULL; + } + + sort_light_and_dark (bmp); + sub_bmp = extract_significant_part (bmp); + if (!sub_bmp) { + log_print_str("E"); + al_destroy_bitmap (bmp); + return NULL; + } + + w = al_get_bitmap_width (sub_bmp); + h = al_get_bitmap_height (sub_bmp); + if (!check_if_playable (sub_bmp)) { + log_print_str("P"); + al_destroy_bitmap (sub_bmp); + al_destroy_bitmap (bmp); + return NULL; + } + + temp = malloc_in_big_data_bottom (w * h + 1); + if (!temp) { + log_print_str("M"); + al_destroy_bitmap (sub_bmp); + al_destroy_bitmap (bmp); + return NULL; + } + + convert_to_buffer (sub_bmp, temp, &size, &bg_size); + al_destroy_bitmap (sub_bmp); + al_destroy_bitmap (bmp); if (temp) { @@ -453,14 +521,13 @@ lw_map_archive_raw_bmp (BITMAP * bmp, PALETTE pal, const char *filename) void * lw_map_archive_raw (const char *filename) { - BITMAP *bmp; - PALETTE pal; + ALLEGRO_BITMAP *bmp; void *result = NULL; - bmp = load_bitmap (filename, pal); + bmp = al_load_bitmap_flags(filename, ALLEGRO_MEMORY_BITMAP); if (bmp) { - result = lw_map_archive_raw_bmp (bmp, pal, filename); + result = lw_map_archive_raw_bmp (bmp, filename); } return result; @@ -498,26 +565,32 @@ lw_map_get_safe (int num, int network, int random) } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_map_create_bicolor (int num, int fg, int bg, int network, int random, int min_w, int min_h, int *zoom_factor) { - int pos_dst, pos_src, i, j, l, color; + int pos_dst, pos_src, i, j, l; + ALLEGRO_COLOR color; short w, h; - signed char *data_dst, *data_src; - BITMAP *result = NULL; - BITMAP *temp; + signed char *data_src; + ALLEGRO_BITMAP *result = NULL; + ALLEGRO_BITMAP *temp; void *raw_map; int size, surface; int x, y; + ALLEGRO_COLOR fg_color, bg_color; raw_map = lw_map_get_safe (num, network, random); + /* Convert int colors to ALLEGRO_COLOR - fg/bg are palette indices or RGB values */ + fg_color = al_map_rgb((fg >> 16) & 0xFF, (fg >> 8) & 0xFF, fg & 0xFF); + bg_color = al_map_rgb((bg >> 16) & 0xFF, (bg >> 8) & 0xFF, bg & 0xFF); + data_src = raw_map; data_src += 8 + LW_MAP_SYSTEM_NAME_SIZE + LW_MAP_READABLE_NAME_SIZE; - /* + /* * We read the header (size + geometry) */ lw_serial_get_map_header (raw_map, &size, &w, &h); @@ -526,22 +599,37 @@ lw_map_create_bicolor (int num, int fg, int bg, *zoom_factor = calc_zoom_factor (w, h, min_w, min_h); pos_src = pos_dst = 0; - temp = my_create_bitmap (w, h); + temp = my_create_memory_bitmap (w, h); if (temp) { - data_dst = temp->dat; + ALLEGRO_COLOR dark_color, light_color, pixel_color; + int px, py; + + dark_color = al_map_rgb((CONSIDERED_AS_DARK_RGB >> 16) & 0xFF, + (CONSIDERED_AS_DARK_RGB >> 8) & 0xFF, + CONSIDERED_AS_DARK_RGB & 0xFF); + light_color = al_map_rgb((CONSIDERED_AS_LIGHT_RGB >> 16) & 0xFF, + (CONSIDERED_AS_LIGHT_RGB >> 8) & 0xFF, + CONSIDERED_AS_LIGHT_RGB & 0xFF); + + al_set_target_bitmap(temp); while (pos_src < size && (l = data_src[pos_src++]) != 0) { if (l > 0) - color = CONSIDERED_AS_DARK; + pixel_color = dark_color; else { l = -l; - color = CONSIDERED_AS_LIGHT; + pixel_color = light_color; } for (i = 0; i < l && pos_dst < surface; ++i) - data_dst[pos_dst++] = color; + { + px = pos_dst % w; + py = pos_dst / w; + putpixel_fast(px, py, pixel_color); + pos_dst++; + } } /* @@ -550,9 +638,9 @@ lw_map_create_bicolor (int num, int fg, int bg, */ if (check_if_playable (temp)) { - fill_with_fg_and_bg (temp, fg, bg); + fill_with_fg_and_bg (temp, fg_color, bg_color); - result = my_create_bitmap (w * (*zoom_factor), h * (*zoom_factor)); + result = my_create_memory_bitmap (w * (*zoom_factor), h * (*zoom_factor)); if (result) { @@ -560,6 +648,7 @@ lw_map_create_bicolor (int num, int fg, int bg, * Not we magnify the map if needed, so that very small * maps are interesting to play on fast fancy computers */ + al_set_target_bitmap (result); for (y = 0; y < h; ++y) for (x = 0; x < w; ++x) { @@ -567,8 +656,7 @@ lw_map_create_bicolor (int num, int fg, int bg, for (i = 0; i < *zoom_factor; ++i) for (j = 0; j < *zoom_factor; ++j) { - putpixel (result, - x * *zoom_factor + j, + putpixel_fast (x * *zoom_factor + j, y * *zoom_factor + i, color); } } @@ -579,19 +667,20 @@ lw_map_create_bicolor (int num, int fg, int bg, log_println_str ("Error: unplayable map!"); } - destroy_bitmap (temp); + al_destroy_bitmap (temp); } return result; } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_map_create_textured (int num, int fg, int bg, int network, int random, int min_w, int min_h) { - int x, y, w, h, color; - BITMAP *result = NULL, *bg_tex, *fg_tex; + int x, y, w, h; + ALLEGRO_COLOR color; + ALLEGRO_BITMAP *result = NULL, *bg_tex, *fg_tex; int fg_w, fg_h; int bg_w, bg_h; int zoom_factor, zoom_factor_fg, zoom_factor_bg; @@ -601,31 +690,32 @@ lw_map_create_textured (int num, int fg, int bg, if (bg_tex && fg_tex) { - bg_w = bg_tex->w; - bg_h = bg_tex->h; - fg_w = fg_tex->w; - fg_h = fg_tex->h; + bg_w = al_get_bitmap_width (bg_tex); + bg_h = al_get_bitmap_height (bg_tex); + fg_w = al_get_bitmap_width (fg_tex); + fg_h = al_get_bitmap_height (fg_tex); result = lw_map_create_bicolor (num, 1, 0, network, random, min_w, min_h, &zoom_factor); if (result) { - w = result->w; - h = result->h; + w = al_get_bitmap_width (result); + h = al_get_bitmap_height (result); zoom_factor_fg = zoom_factor_bg = zoom_factor; - if (w != zoom_factor * fg_tex->w || h != zoom_factor * fg_tex->h) + if (w != zoom_factor * al_get_bitmap_width (fg_tex) || h != zoom_factor * al_get_bitmap_height (fg_tex)) { zoom_factor_fg = 1; } - if (w != zoom_factor * bg_tex->w || h != zoom_factor * bg_tex->h) + if (w != zoom_factor * al_get_bitmap_width (bg_tex) || h != zoom_factor * al_get_bitmap_height (bg_tex)) { zoom_factor_bg = 1; } + al_set_target_bitmap (result); for (y = 0; y < h; ++y) for (x = 0; x < w; ++x) { - if (getpixel (result, x, y)) + if (is_color_light(getpixel (result, x, y))) { color = getpixel (fg_tex, (x / zoom_factor_fg) % fg_w, @@ -637,16 +727,16 @@ lw_map_create_textured (int num, int fg, int bg, getpixel (bg_tex, (x / zoom_factor_bg) % bg_w, (y / zoom_factor_bg) % bg_h); } - putpixel (result, x, y, color); + putpixel_fast (x, y, color); } } } if (bg_tex) - destroy_bitmap (bg_tex); + al_destroy_bitmap (bg_tex); if (fg_tex) - destroy_bitmap (fg_tex); + al_destroy_bitmap (fg_tex); return result; } diff --git a/src/map.h b/src/map.h index 470e3ded..c9aa6da0 100644 --- a/src/map.h +++ b/src/map.h @@ -55,7 +55,8 @@ /* includes */ /*==================================================================*/ -#include +#include + /*==================================================================*/ /* constants */ @@ -69,14 +70,12 @@ /*==================================================================*/ void *lw_map_archive_raw (const char *filename); -void *lw_map_archive_raw_bmp (BITMAP * bmp, PALETTE pal, - const char *filename); -BITMAP *lw_map_create_bicolor (int num, int fg, int bg, - int network, int random, int min_w, int min_h, - int *zoom_factor); -BITMAP *lw_map_create_textured (int num, int fg, int bg, - int network, int random, int min_w, - int min_h); +void *lw_map_archive_raw_bmp (ALLEGRO_BITMAP * bmp, const char *filename); +ALLEGRO_BITMAP *lw_map_create_bicolor (int num, int fg, int bg, + int network, int random, int min_w, + int min_h, int *zoom_factor); +ALLEGRO_BITMAP *lw_map_create_textured (int num, int fg, int bg, int network, + int random, int min_w, int min_h); char *lw_map_get_system_name (int num, int network, int random); char *lw_map_get_readable_name (int num, int network, int random); void lw_map_get_res (int num, int *w, int *h, diff --git a/src/palette.h b/src/mapgen_stubs.c similarity index 72% rename from src/palette.h rename to src/mapgen_stubs.c index 72cada07..cfe441fa 100644 --- a/src/palette.h +++ b/src/mapgen_stubs.c @@ -38,56 +38,66 @@ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ +/* Liquid War homepage : http://www.ufoot.org/liquidwar/v5 */ /* Contact author : ufoot@ufoot.org */ /*****************************************************************************/ /********************************************************************/ -/* nom : palette.h */ -/* contenu : gestion des palettes de couleur */ -/* date de modif : 3 mai 98 */ +/* nom : mapgen_stubs.c */ +/* content : stub implementations for mapgen dependencies */ +/* last update : Dec 28th 2024 */ /********************************************************************/ -#ifndef LIQUID_WAR_INCLUDE_PALETTE -#define LIQUID_WAR_INCLUDE_PALETTE - /*==================================================================*/ /* includes */ /*==================================================================*/ -#include +#include "backport.h" +#include /*==================================================================*/ /* variables globales */ /*==================================================================*/ -#define CHOOSE_COLOR_NUMBER 128 -#define CHOOSE_COLOR_WHITE 120 -#define CHOOSE_COLOR_BLACK 127 +/* Global palette for backport compatibility */ +PALETTE GLOBAL_PALETTE; -#define TEAM_FIRST_COLOR 128 +/*==================================================================*/ +/* stub functions */ +/*==================================================================*/ -#define FG_TEXTURE_FIRST_COLOR 64 -#define BG_TEXTURE_FIRST_COLOR 96 +/* Minimal logging stubs */ +void log_print_str(char *str) { + printf("%s", str); +} -#define TEXTURE_COLOR_NUMBER 32 +void log_println_str(char *str) { + printf("%s\n", str); +} -#define MENU_BG 16 -#define MENU_FG 17 +/* Minimal mutex stubs (mapgen doesn't need real threading) */ +void lw_mutex_init(void *mutex) { + (void)mutex; /* suppress unused parameter warning */ + /* stub - mapgen runs single-threaded */ +} -extern PALETTE GLOBAL_PALETTE; -extern int COLORS_PER_TEAM; +void lw_mutex_lock(void *mutex) { + (void)mutex; /* suppress unused parameter warning */ + /* stub - mapgen runs single-threaded */ +} -/*==================================================================*/ -/* fonctions globales */ -/*==================================================================*/ +void lw_mutex_unlock(void *mutex) { + (void)mutex; /* suppress unused parameter warning */ + /* stub - mapgen runs single-threaded */ +} -void my_set_palette (void); -void set_bg_texture_palette (int num); -void set_fg_texture_palette (int num); -void set_palette_for_choose_color (void); -void set_playing_teams_palette (void); -void my_fade_out (void); -void my_fade_in (void); +/* Minimal thread stubs (mapgen doesn't need real threading) */ +void lw_thread_start(void *thread_func) { + (void)thread_func; /* suppress unused parameter warning */ + /* stub - mapgen runs single-threaded */ +} -#endif +/* Mouse function stub (mapgen doesn't use mouse) */ +void lw_mouse_update_show_hide(void) { + /* stub - mapgen doesn't use mouse */ +} \ No newline at end of file diff --git a/src/maptex.c b/src/maptex.c index 84a66102..0c42d359 100644 --- a/src/maptex.c +++ b/src/maptex.c @@ -53,10 +53,10 @@ #include +#include "backport.h" #include "maptex.h" #include "map.h" #include "texture.h" -#include "palette.h" #include "disk.h" /*==================================================================*/ @@ -123,12 +123,12 @@ lw_maptex_is_custom_texture_used (int num, } /*-----------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_maptex_create_map (int num, int fg, int bg, int network, int random, int min_w, int min_h, int use_default_texture) { - BITMAP *result; + ALLEGRO_BITMAP *result; int found; result = lw_map_create_textured (num, @@ -146,11 +146,11 @@ lw_maptex_create_map (int num, int fg, int bg, } /*-----------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_maptex_create_fg (int num, int fg, int network, int random, int use_default_texture) { - BITMAP *result; + ALLEGRO_BITMAP *result; int found; result = @@ -162,11 +162,11 @@ lw_maptex_create_fg (int num, int fg, int network, int random, } /*-----------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_maptex_create_bg (int num, int bg, int network, int random, int use_default_texture) { - BITMAP *result; + ALLEGRO_BITMAP *result; int found; result = @@ -185,9 +185,8 @@ lw_maptex_set_fg_palette (int num, { int found; - set_fg_texture_palette (calc_real_texture_number - (num, fg, network, random, use_default_texture, - &found)); + // set_fg_texture_palette - No longer needed in true color mode + calc_real_texture_number(num, fg, network, random, use_default_texture, &found); } /*-----------------------------------------------------------------*/ @@ -198,7 +197,6 @@ lw_maptex_set_bg_palette (int num, { int found; - set_bg_texture_palette (calc_real_texture_number - (num, bg, network, random, use_default_texture, - &found)); + // set_bg_texture_palette - No longer needed in true color mode + calc_real_texture_number(num, bg, network, random, use_default_texture, &found); } diff --git a/src/maptex.h b/src/maptex.h index 77b61f49..0c5f2273 100644 --- a/src/maptex.h +++ b/src/maptex.h @@ -54,7 +54,7 @@ /* includes */ /*==================================================================*/ -#include +#include #include "maptex.h" /*==================================================================*/ @@ -69,13 +69,13 @@ int lw_maptex_is_custom_texture_used (int num, int texture, int network, int random, int use_default_texture); -BITMAP *lw_maptex_create_map (int num, int fg, int bg, int network, - int random, int min_w, int min_h, - int use_default_texture); -BITMAP *lw_maptex_create_fg (int num, int fg, int network, int random, - int use_default_texture); -BITMAP *lw_maptex_create_bg (int num, int bg, int network, int random, - int use_default_texture); +ALLEGRO_BITMAP *lw_maptex_create_map (int num, int fg, int bg, int network, + int random, int min_w, int min_h, + int use_default_texture); +ALLEGRO_BITMAP *lw_maptex_create_fg (int num, int fg, int network, int random, + int use_default_texture); +ALLEGRO_BITMAP *lw_maptex_create_bg (int num, int bg, int network, int random, + int use_default_texture); void lw_maptex_set_fg_palette (int num, int fg, int network, int random, int use_default_texture); void lw_maptex_set_bg_palette (int num, int bg, int network, int random, diff --git a/src/menu.c b/src/menu.c index 1af0ad54..80f464b0 100644 --- a/src/menu.c +++ b/src/menu.c @@ -87,9 +87,6 @@ confirm_quit (void) standard_button (d, 0, 0, 2, 1); standard_button (d + 1, 1, 0, 2, 1); d[0].dp = lw_lang_string (LW_LANG_STRING_MENU_EXIT); -#ifdef DOS - d[0].dp = lw_lang_string (LW_LANG_STRING_MENU_EXITDOS); -#endif #ifdef WIN32 d[0].dp = lw_lang_string (LW_LANG_STRING_MENU_EXITWINDOWS); #endif @@ -120,7 +117,7 @@ main_menu (int fade_in) if (fade_in) { - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode } while (retour != MENU_EXIT) @@ -155,11 +152,7 @@ main_menu (int fade_in) retour = play_sequence (); break; case 5: -#ifndef DOS retour = network_game (); -#else - retour = error_no_network_support (); -#endif break; case 6: retour = choose_map (); @@ -181,11 +174,7 @@ main_menu (int fade_in) { if (LW_NETWORK_ON) { -#ifndef DOS retour = netplay_sequence (); -#else - retour = play_sequence (); -#endif } else { diff --git a/src/mesh.c b/src/mesh.c index 2218b8fa..be9b844c 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -52,6 +52,7 @@ /* includes */ /*==================================================================*/ +#include "backport.h" #include "bigdata.h" #include "config.h" #include "map.h" @@ -87,8 +88,8 @@ MESH *CURRENT_MESH = NULL; int CURRENT_MESH_SIZE = 0; int CURRENT_AREA_W = 0; int CURRENT_AREA_H = 0; -BITMAP *CURRENT_AREA_DISP = NULL; -BITMAP *CURRENT_AREA_BACK = NULL; +ALLEGRO_BITMAP *CURRENT_AREA_DISP = NULL; +ALLEGRO_BITMAP *CURRENT_AREA_BACK = NULL; /*==================================================================*/ /* fonctions */ @@ -100,13 +101,13 @@ BITMAP *CURRENT_AREA_BACK = NULL; /*------------------------------------------------------------------*/ static MESHER * -create_first_mesher (BITMAP * map) +create_first_mesher (ALLEGRO_BITMAP * map) { MESHER *result; int x, y, h, w, size, i, j; - w = map->w; - h = map->h; + w = al_get_bitmap_width (map); + h = al_get_bitmap_height (map); size = h * w; result = malloc_in_big_data_top (size * sizeof (MESHER)); if (result != NULL) @@ -121,7 +122,7 @@ create_first_mesher (BITMAP * map) for (y = 0; y < h; ++y) for (x = 0; x < w; ++x) - result[y * w + x].used = (getpixel (map, x, y) == MESH_FG) ? 0 : 1; + result[y * w + x].used = is_color_light(getpixel (map, x, y)) ? 0 : 1; for (y = 1; y < h - 1; ++y) for (x = 1; x < w - 1; ++x) @@ -163,14 +164,14 @@ create_first_mesher (BITMAP * map) /*------------------------------------------------------------------*/ static int -group_mesher (MESHER * mesher, BITMAP * map, int step) +group_mesher (MESHER * mesher, ALLEGRO_BITMAP * map, int step) { int found = 0; int x, y, w, h, i, j, k; MESHER *ne, *se, *sw, *nw, *test; - w = map->w; - h = map->h; + w = al_get_bitmap_width (map); + h = al_get_bitmap_height (map); for (y = 0; y < h - step; y += step * 2) for (x = 0; x < w - step; x += step * 2) @@ -236,14 +237,15 @@ group_mesher (MESHER * mesher, BITMAP * map, int step) /*------------------------------------------------------------------*/ static MESH * -mesher_to_mesh (MESHER * mesher, BITMAP * map, int *size, int *w, int *h) +mesher_to_mesh (MESHER * mesher, ALLEGRO_BITMAP * map, int *size, int *w, + int *h) { MESH *result; MESHER *temp; int mesher_size, i, j, k; - (*w) = map->w; - (*h) = map->h; + (*w) = al_get_bitmap_width (map); + (*h) = al_get_bitmap_height (map); mesher_size = (*h) * (*w); *size = 0; @@ -344,7 +346,7 @@ int create_mesh (void) { int retour = 0, i; - BITMAP *map; + ALLEGRO_BITMAP *map; MESHER *mesher; int zoom_factor = 1; @@ -374,7 +376,7 @@ create_mesh (void) &CURRENT_AREA_W, &CURRENT_AREA_H); free_last_big_data_top (); } - destroy_bitmap (map); + al_destroy_bitmap (map); } if (CURRENT_MESH == NULL) retour = -1; /* pas assez de memoire */ @@ -387,10 +389,10 @@ create_mesh (void) /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * create_mesh_bitmap (int mode) { - BITMAP *result; + ALLEGRO_BITMAP *result; int i, j, color; result = lw_maptex_create_map @@ -421,12 +423,18 @@ create_mesh_bitmap (int mode) color = i; } - rectfill (result, CURRENT_MESH[i].x, - CURRENT_MESH[i].y, - CURRENT_MESH[i].x + - CURRENT_MESH[i].side.size - 1, - CURRENT_MESH[i].y + - CURRENT_MESH[i].side.size - 1, 96 + color % 32); + // Create a color based on mesh index for visualization + // Map the old palette index (96 + color % 32) to a grayscale or color + { + int intensity = 96 + (color % 32) * 5; // Scale to 0-255 range + ALLEGRO_COLOR mesh_color = al_map_rgb(intensity, intensity, intensity); + rectfill (result, CURRENT_MESH[i].x, + CURRENT_MESH[i].y, + CURRENT_MESH[i].x + + CURRENT_MESH[i].side.size - 1, + CURRENT_MESH[i].y + + CURRENT_MESH[i].side.size - 1, mesh_color); + } } } diff --git a/src/mesh.h b/src/mesh.h index 3c6d57c7..869eba1e 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include #include "base.h" @@ -122,8 +122,8 @@ extern MESH *CURRENT_MESH; extern int CURRENT_MESH_SIZE; extern int CURRENT_AREA_W; extern int CURRENT_AREA_H; -extern BITMAP *CURRENT_AREA_DISP; -extern BITMAP *CURRENT_AREA_BACK; +extern ALLEGRO_BITMAP *CURRENT_AREA_DISP; +extern ALLEGRO_BITMAP *CURRENT_AREA_BACK; /*==================================================================*/ /* fonctions globales */ @@ -132,6 +132,6 @@ extern BITMAP *CURRENT_AREA_BACK; void reset_mesh (void); void test_mesh (void); int create_mesh (void); -BITMAP *create_mesh_bitmap (int mode); +ALLEGRO_BITMAP *create_mesh_bitmap (int mode); #endif diff --git a/src/message.c b/src/message.c index 979cd97a..8ceb59a2 100644 --- a/src/message.c +++ b/src/message.c @@ -52,7 +52,7 @@ /* includes */ /*==================================================================*/ -#include +#include "backport.h" #include #include @@ -115,8 +115,8 @@ display_message (void) //text_mode (-1); deprecated for (i = 0; i < MESSAGE_NB; ++i) textout_ex (NEXT_SCREEN, font, MESSAGE[i], - NEXT_SCREEN->w - text_length (font, MESSAGE[i]), - NEXT_SCREEN->h - (MESSAGE_NB - i) * h, -1, -1); + al_get_bitmap_width (NEXT_SCREEN) - text_length (font, MESSAGE[i]), + al_get_bitmap_height (NEXT_SCREEN) - (MESSAGE_NB - i) * h, NO_COLOR, NO_COLOR); } /*------------------------------------------------------------------*/ diff --git a/src/monster.h b/src/monster.h deleted file mode 100644 index afc9f797..00000000 --- a/src/monster.h +++ /dev/null @@ -1,92 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : monster.h */ -/* contenu : deplacement des streums accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -#ifndef LIQUID_WAR_INCLUDE_MONSTER -#define LIQUID_WAR_INCLUDE_MONSTER - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include "area.h" -#include "mesh.h" -#include "asm.h" - -/*==================================================================*/ -/* types */ -/*==================================================================*/ - -extern void LW_ASM_FUNC boost_move_fighters (FIGHTER * current_army, - int current_army_size, - PLACE * current_area, - int current_area_w, - int *active_fighters, - int *attack, - int *defense, - int *new_health, - int max_fighter_health_1, - int sens, - int start, - int neg_global_clock, - int *fighter_move_xy, - int *fighter_move_offset, - char *current_area_back_data, - char *current_area_disp_data, - int *color_first_entry, - int colors_per_team, - int *local_dir, - int temp1, - int temp2, - int temp3, - int temp4, - int temp5, - int temp6, int temp7, int temp8); - -#endif diff --git a/src/monster.s b/src/monster.s deleted file mode 100644 index 5f9e689a..00000000 --- a/src/monster.s +++ /dev/null @@ -1,974 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : monster.s */ -/* contenu : deplacement des streums accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - - -/*typedef union */ -/* { */ -/* int time; */ -/* struct */ -/* { */ -/* short x; */ -/* short y; */ -/* } cursor; */ -/* } MESH_UPDATE; */ - -/* typedef struct */ -/* { */ -/* int dir :8; */ -/* int grad:24; */ -/* } MESH_STATE; */ - -/*typedef struct */ -/* { */ -/* MESH_UPDATE update;*/ -/* MESH_STATE state; */ -/* } MESH_INFO; */ - -.equ SIZE_OF_INFO,8 - -.equ INFO_UPDATE,0 -.equ INFO_STATE,4 - - -/*typedef struct */ -/* { */ -/* char decal_for_dir :8; */ -/* int size :24; */ -/* } MESH_SIDE; */ - -/*typedef struct */ -/* { */ -/* short x; */ -/* short y; */ -/* MESH_SIDE side; */ -/* MESH_INFO info[NB_TEAMS]; */ -/* void *link[NB_DIRS]; */ -/* } MESH; */ - -.equ SIZE_OF_MESH,104 - -.equ MESH_INFO,8 -.equ MESH_LINK,56 - - - -/*typedef struct */ -/* { */ -/* short x; */ -/* short y; */ -/* short health; */ -/* char team; */ -/* char last_dir; */ -/* } FIGHTER; */ - - -.equ SIZE_OF_FIGHTER,8 -.equ FIGHTER_XY,0 -.equ FIGHTER_X,0 -.equ FIGHTER_Y,2 -.equ FIGHTER_HEALTH,4 -.equ FIGHTER_TEAM,6 -.equ FIGHTER_LAST_DIR,7 - - -/*typedef struct */ -/* { */ -/* MESH *mesh; */ -/* FIGHTER *fighter; */ -/* } PLACE; */ - - -.equ SIZE_OF_PLACE,8 -.equ PLACE_MESH,0 -.equ PLACE_FIGHTER,4 - -.equ MOVE_BLOCK_NUMBER,5 - -.equ ARG_CURRENT_ARMY, 8 -.equ ARG_CURRENT_ARMY_SIZE, 12 -.equ ARG_CURRENT_AREA, 16 -.equ ARG_CURRENT_AREA_W, 20 -.equ ARG_ACTIVE_FIGHTERS, 24 -.equ ARG_ATTACK, 28 -.equ ARG_DEFENSE, 32 -.equ ARG_NEW_HEALTH, 36 -.equ ARG_MAX_FIGHTER_HEALTH_1, 40 -.equ ARG_SENS, 44 -.equ ARG_START, 48 -.equ ARG_NEG_GLOBAL_CLOCK, 52 -.equ ARG_FIGHTER_MOVE_XY, 56 -.equ ARG_FIGHTER_MOVE_OFFSET, 60 -.equ ARG_CURRENT_AREA_BACK, 64 -.equ ARG_CURRENT_AREA_DISP, 68 -.equ ARG_COLOR_FIRST_ENTRY, 72 -.equ ARG_COLORS_PER_TEAM, 76 -.equ ARG_LOCAL_DIR, 80 -.equ ARG_TEMP1, 84 -.equ ARG_TEMP2, 88 -.equ ARG_TEMP3, 92 -.equ ARG_TEMP4, 96 -.equ ARG_TEMP5, 100 -.equ ARG_TEMP6, 104 -.equ ARG_TEMP7, 108 -.equ ARG_TEMP8, 112 - -.equ OFFSET_P0,0 -.equ OFFSET_P1,4 -.equ OFFSET_P2,8 -.equ OFFSET_P3,12 -.equ OFFSET_P4,16 - -.equ SIDE_ATTACK_FACTOR,4 #on divise attaque par 2^4=16 qd - #l attaque se fait sur le cote - -/*#define AREA_START_GRADIENT 2000000*/ -.equ AREA_START_GRADIENT,2000000*256 - -.text - - - -/*==================================================================*/ -/* grosse fonction enorme, on fait ce qu on pneu */ -/*==================================================================*/ - -/*--------------------------------------------------------------------*/ -/* void boost_move_fighters (FIGHTER *current_army, */ -/* int current_army_size, */ -/* PLACE *current_area, */ -/* int current_area_w, */ -/* int *active_fighters, */ -/* int *attack, */ -/* int *defense, */ -/* int *new_health, */ -/* int max_fighter_health_1, */ -/* int sens, */ -/* int start, */ -/* int neg_global_clock, */ -/* int *fighter_move_xy, */ -/* int *fighter_move_offset, */ -/* char *current_area_back_data, */ -/* char *current_area_disp_data, */ -/* int *color_first_entry, */ -/* int colors_per_team, */ -/* int *local_dir, */ -/* int temp1, */ -/* int temp2, */ -/* int temp3, */ -/* int temp4, */ -/* int temp5, */ -/* int temp6, */ -/* int temp7, */ -/* int temp8); */ -/*--------------------------------------------------------------------*/ -.globl _boost_move_fighters -.globl boost_move_fighters - .align 4 -_boost_move_fighters: -boost_move_fighters: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - pushw %fs - pushw %gs - - movw %ds,%ax - movw %ax,%es - movw %ax,%fs - movw %ax,%gs - - movl ARG_CURRENT_ARMY_SIZE(%ebp),%ecx # ecx=nombre de streums - movl ARG_CURRENT_ARMY(%ebp),%esi # esi=adresse du streum courant - -main_loop: - push %ecx - -/*------------------------------------------------------------------*/ -/* indice de l equipe */ -/*------------------------------------------------------------------*/ - xor %ecx,%ecx # ecx a zero - movb FIGHTER_TEAM(%esi),%cl # equipe dans le champ ecx - movl %ecx,%ds:ARG_TEMP1(%ebp) # temp1 prend team - shl $2,%ecx # ecx contient maintenant team*4 - -/*------------------------------------------------------------------*/ -/* mise a jour du nombre de combattants de l equipe */ -/*------------------------------------------------------------------*/ - mov ARG_ACTIVE_FIGHTERS(%ebp),%edi # recuperation de pointeur - add %ecx,%edi # ajout de l offset pour l equipe - incl %ds:(%edi) # mise a jour du fighter number - -/*------------------------------------------------------------------*/ -/* localisation du streum courant */ -/*------------------------------------------------------------------*/ - movl FIGHTER_XY(%esi),%eax # eax contient fighter->xy - xor %ebx,%ebx # ebx a 0 - movw %ax,%bx # ebx contient fighter->x - shr $16,%eax # eax contient fighter->y - cdq # je crois que ca sert pour imul - mull %ds:ARG_CURRENT_AREA_W(%ebp) # eax prend fighter->y*CURRENT_AREA_W - add %ebx,%eax # eax contient un joli offset - mov %eax,%ds:ARG_TEMP2(%ebp) # temp2 prend y*CURRENT_AREA_W+1 - shl $3,%eax # eax*=8 (taille de PLACE) - add ARG_CURRENT_AREA(%ebp),%eax - mov %eax,%edi # edi=adresse dans CURRENT_AREA - # situant la place du streum courant -/*------------------------------------------------------------------*/ -/* on recupere le parametre update du streum courant */ -/*------------------------------------------------------------------*/ - shl $1,%ecx # ecx contient maintenant team*8 - add $MESH_INFO,%ecx # ecx=offset pour info%team - mov PLACE_MESH(%edi),%ebx # ebx prend l adresse du maillage - add %ecx,%ebx # sur l instant de mise a jour - mov INFO_UPDATE(%ebx),%eax # eax=instant mise a jour - -/*------------------------------------------------------------------*/ -/* on calcule la direction principale de deplacement */ -/*------------------------------------------------------------------*/ - cmp $0,%eax - jge fdl_start - -/*------------------------------------------------------------------*/ -/* calcul base sur les gradients */ -/*------------------------------------------------------------------*/ - mov ARG_NEG_GLOBAL_CLOCK(%ebp),%edx # edx=-GLOBAL_CLOCK - cmp %edx,%eax # direction a jour??? - je fdg_dir_ok # oui... - # non, on la met, en - mov %edx,INFO_UPDATE(%ebx) # commencant par l heure - - mov ARG_START(%ebp),%al # al=direction de depart - mov %al,%ah # ah=direction courante - ror $8,%eax - mov %al,%ah # direction trouvee sur - rol $8,%eax # la partie haute de eax - - mov $AREA_START_GRADIENT,%edx # plus proche distance - # trouvee - - movb ARG_SENS(%ebp),%bl # bl=sens - - cmp $0,%bl - jne fdg_sens_1 - -/*------------------------------------------------------------------*/ -/* dans le sens 0 */ -/*------------------------------------------------------------------*/ -fdg_sens_0: -loop_fdg_sens_0: - - xor %ebx,%ebx - mov %ah,%bl - sal $2,%ebx - add PLACE_MESH(%edi),%ebx # ebx prend l adresse du maillage - mov MESH_LINK(%ebx),%ebx - cmp $0,%ebx # le mesh existe-t-il ??? - je not_better_fdg_sens_0 - add %ecx,%ebx # sur l instant de mise a jour - mov INFO_STATE(%ebx),%ebx # ebx= distance - cmp %edx,%ebx # on compare - jge not_better_fdg_sens_0 # pas mieux - mov %ebx,%edx # mieux!, on met a jour - ror $8,%eax - mov %al,%ah # direction trouve ds eax haut - rol $8,%eax - -not_better_fdg_sens_0: - inc %ah # direction suivante - cmp $12,%ah - jne skip_fdg_sens_0 - xor %ah,%ah -skip_fdg_sens_0: - cmp %ah,%al - jne loop_fdg_sens_0 - - movb $1,ARG_SENS(%ebp) # la prochaine fois on - # changera de direction - jmp fdg_end_of_calc - -/*------------------------------------------------------------------*/ -/* dans le sens 1 */ -/*------------------------------------------------------------------*/ -fdg_sens_1: -loop_fdg_sens_1: - - xor %ebx,%ebx - mov %ah,%bl - sal $2,%ebx - add PLACE_MESH(%edi),%ebx # ebx prend l adresse du maillage - mov MESH_LINK(%ebx),%ebx - cmp $0,%ebx # le mesh existe-t-il ??? - je not_better_fdg_sens_1 - add %ecx,%ebx # sur l instant de mise a jour - mov INFO_STATE(%ebx),%ebx # ebx= distance - cmp %edx,%ebx # on compare - jge not_better_fdg_sens_1 # pas mieux - mov %ebx,%edx # mieux!, on met a jour - ror $8,%eax - mov %al,%ah # direction trouve ds eax haut - rol $8,%eax - -not_better_fdg_sens_1: - dec %ah # direction suivante - jge skip_fdg_sens_1 - mov $11,%ah -skip_fdg_sens_1: - cmp %ah,%al - jne loop_fdg_sens_1 - - movb $0,ARG_SENS(%ebp) # la prochaine fois on - # changera de direction -# jmp fdg_end_of_calc - -/*------------------------------------------------------------------*/ -/* fin du calcul, partie commune du calcul de direction principal */ -/*------------------------------------------------------------------*/ -fdg_end_of_calc: - mov PLACE_MESH(%edi),%ebx # ebx prend l adresse du maillage - add %ecx,%ebx # sur le param update - ror $8,%eax # ah=dir choisie - movb %ah,INFO_STATE(%ebx) # mise a jour en memoire - -/*------------------------------------------------------------------*/ -/* la direction a ete calculee pour tout le mesh */ -/*------------------------------------------------------------------*/ -fdg_dir_ok: - xor %eax,%eax # eax a 0 - movb INFO_STATE(%ebx),%al # - -# movb $0,%al - - jmp dir_calculated -skip_1: - -/*------------------------------------------------------------------*/ -/* calcul "local" */ -/*------------------------------------------------------------------*/ - -fdl_start: - xor %ecx,%ecx # ecx= resultat des tests - movl FIGHTER_XY(%esi),%edx # eax contient fighter->xy - - cmp %ax,%dx - je fdl_skip_x1 - jg fdl_skip_x2 - or $2,%cl - jmp fdl_skip_x1 -fdl_skip_x2: - or $8,%cl -fdl_skip_x1: - - ror $16,%eax - ror $16,%edx - - cmp %ax,%dx - je fdl_skip_x3 - jg fdl_skip_x4 - or $4,%cl - jmp fdl_skip_x3 -fdl_skip_x4: - or $1,%cl -fdl_skip_x3: - - or %cl,%cl - je on_the_spot - mov ARG_LOCAL_DIR(%ebp),%ebx - dec %cl - shl $1,%cl - add ARG_SENS(%ebp),%ecx - shl $2,%cl - add %ecx,%ebx - mov (%ebx),%eax - jmp end_of_fdl -on_the_spot: - mov ARG_START(%ebp),%eax -end_of_fdl: - -#movb $6,%al - - # a l issue de ces calculs, eax contient la direction en question - -/*------------------------------------------------------------------*/ -/* on dispose ici dans eax de la direction principale de deplacement*/ -/*------------------------------------------------------------------*/ - -dir_calculated: - - shl $2,%eax - mov %eax,%ecx - shl $2,%eax - add %eax,%ecx #ecx=eax*20... - -/*------------------------------------------------------------------*/ -/* test si deplacement possible dans direction associee a p0 */ -/*------------------------------------------------------------------*/ - - mov %ecx,%ebx #on recupere la dir - add ARG_FIGHTER_MOVE_OFFSET(%ebp),%ebx #ebx=pointeur a garder!!! - mov OFFSET_P0(%ebx),%eax #eax=offs ds cur_area - - mov %eax,ARG_TEMP5(%ebp) #offset dir p0 memorise - - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_3 #oui - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #la place est-elle libre? - jne skip_3 #non - -/*------------------------------------------------------------------*/ -/* deplacement dans direction associee a p0 */ -/*------------------------------------------------------------------*/ - - movl $0,%ds:PLACE_FIGHTER(%edi) #on vide dans cur_area - mov %esi,%ds:PLACE_FIGHTER(%eax) #nouvelle place - - add ARG_FIGHTER_MOVE_XY(%ebp),%ecx #offset ds move_xy - mov OFFSET_P0(%ecx),%edx #on charge l increm - addl %edx,%ds:FIGHTER_XY(%esi) #addition des coord - - mov ARG_TEMP2(%ebp),%ecx #y*cur_area_w+x - mov ARG_CURRENT_AREA_BACK(%ebp),%eax #eax=cur_area_back->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dl #pixel memorise - mov ARG_CURRENT_AREA_DISP(%ebp),%eax #eax=cur_area_disp->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dh #couleur du monstre - movb %dl,%ds:(%eax) #effacement - add OFFSET_P0(%ebx),%eax #deplacement - movb %dh,%ds:(%eax) #affichage - - jmp next_monster #fini avec ce monstre... - -skip_3: - -/*------------------------------------------------------------------*/ -/* test si deplacement possible dans direction associee a p1 */ -/*------------------------------------------------------------------*/ - - mov %ecx,%ebx #on recupere la dir - add ARG_FIGHTER_MOVE_OFFSET(%ebp),%ebx #ebx=pointeur a garder!!! - mov OFFSET_P1(%ebx),%eax #eax=offs ds cur_area - - mov %eax,ARG_TEMP6(%ebp) #offset dir p1 memorise - - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_4 #oui - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #la place est-elle libre? - jne skip_4 #non - -/*------------------------------------------------------------------*/ -/* deplacement dans direction associee a p1 */ -/*------------------------------------------------------------------*/ - - movl $0,%ds:PLACE_FIGHTER(%edi) #on vide dans cur_area - mov %esi,%ds:PLACE_FIGHTER(%eax) #nouvelle place - - add ARG_FIGHTER_MOVE_XY(%ebp),%ecx #offset ds move_xy - mov OFFSET_P1(%ecx),%edx #on charge l increm - addl %edx,%ds:FIGHTER_XY(%esi) #addition des coord - - mov ARG_TEMP2(%ebp),%ecx #y*cur_area_w+x - mov ARG_CURRENT_AREA_BACK(%ebp),%eax #eax=cur_area_back->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dl #pixel memorise - mov ARG_CURRENT_AREA_DISP(%ebp),%eax #eax=cur_area_disp->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dh #couleur du monstre - movb %dl,%ds:(%eax) #effacement - add OFFSET_P1(%ebx),%eax #deplacement - movb %dh,%ds:(%eax) #affichage - - jmp next_monster #fini avec ce monstre... - -skip_4: - -/*------------------------------------------------------------------*/ -/* test si deplacement possible dans direction associee a p2 */ -/*------------------------------------------------------------------*/ - - mov %ecx,%ebx #on recupere la dir - add ARG_FIGHTER_MOVE_OFFSET(%ebp),%ebx #ebx=pointeur a garder!!! - mov OFFSET_P2(%ebx),%eax #eax=offs ds cur_area - - mov %eax,ARG_TEMP7(%ebp) #offset dir p2 memorise - - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_5 #oui - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #la place est-elle libre? - jne skip_5 #non - -/*------------------------------------------------------------------*/ -/* deplacement dans direction associee a p2 */ -/*------------------------------------------------------------------*/ - - movl $0,%ds:PLACE_FIGHTER(%edi) #on vide dans cur_area - mov %esi,%ds:PLACE_FIGHTER(%eax) #nouvelle place - - add ARG_FIGHTER_MOVE_XY(%ebp),%ecx #offset ds move_xy - mov OFFSET_P2(%ecx),%edx #on charge l increm - addl %edx,%ds:FIGHTER_XY(%esi) #addition des coord - - mov ARG_TEMP2(%ebp),%ecx #y*cur_area_w+x - mov ARG_CURRENT_AREA_BACK(%ebp),%eax #eax=cur_area_back->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dl #pixel memorise - mov ARG_CURRENT_AREA_DISP(%ebp),%eax #eax=cur_area_disp->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dh #couleur du monstre - movb %dl,%ds:(%eax) #effacement - add OFFSET_P2(%ebx),%eax #deplacement - movb %dh,%ds:(%eax) #affichage - - jmp next_monster #fini avec ce monstre... - -skip_5: - -/*------------------------------------------------------------------*/ -/* test si deplacement possible dans direction associee a p3 */ -/*------------------------------------------------------------------*/ - - mov %ecx,%ebx #on recupere la dir - add ARG_FIGHTER_MOVE_OFFSET(%ebp),%ebx #ebx=pointeur a garder!!! - mov OFFSET_P3(%ebx),%eax #eax=offs ds cur_area - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_6 #oui - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #la place est-elle libre? - jne skip_6 #non - -/*------------------------------------------------------------------*/ -/* deplacement dans direction associee a p3 */ -/*------------------------------------------------------------------*/ - - movl $0,%ds:PLACE_FIGHTER(%edi) #on vide dans cur_area - mov %esi,%ds:PLACE_FIGHTER(%eax) #nouvelle place - - add ARG_FIGHTER_MOVE_XY(%ebp),%ecx #offset ds move_xy - mov OFFSET_P3(%ecx),%edx #on charge l increm - addl %edx,%ds:FIGHTER_XY(%esi) #addition des coord - - mov ARG_TEMP2(%ebp),%ecx #y*cur_area_w+x - mov ARG_CURRENT_AREA_BACK(%ebp),%eax #eax=cur_area_back->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dl #pixel memorise - mov ARG_CURRENT_AREA_DISP(%ebp),%eax #eax=cur_area_disp->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dh #couleur du monstre - movb %dl,%ds:(%eax) #effacement - add OFFSET_P3(%ebx),%eax #deplacement - movb %dh,%ds:(%eax) #affichage - - jmp next_monster #fini avec ce monstre... - -skip_6: - -/*------------------------------------------------------------------*/ -/* test si deplacement possible dans direction associee a p4 */ -/*------------------------------------------------------------------*/ - - mov %ecx,%ebx #on recupere la dir - add ARG_FIGHTER_MOVE_OFFSET(%ebp),%ebx #ebx=pointeur a garder!!! - mov OFFSET_P4(%ebx),%eax #eax=offs ds cur_area - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_7 #oui - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #la place est-elle libre? - jne skip_7 #non - -/*------------------------------------------------------------------*/ -/* deplacement dans direction associee a p4 */ -/*------------------------------------------------------------------*/ - - movl $0,%ds:PLACE_FIGHTER(%edi) #on vide dans cur_area - mov %esi,%ds:PLACE_FIGHTER(%eax) #nouvelle place - - add ARG_FIGHTER_MOVE_XY(%ebp),%ecx #offset ds move_xy - mov OFFSET_P4(%ecx),%edx #on charge l increm - addl %edx,%ds:FIGHTER_XY(%esi) #addition des coord - - mov ARG_TEMP2(%ebp),%ecx #y*cur_area_w+x - mov ARG_CURRENT_AREA_BACK(%ebp),%eax #eax=cur_area_back->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dl #pixel memorise - mov ARG_CURRENT_AREA_DISP(%ebp),%eax #eax=cur_area_disp->dat - add %ecx,%eax #pointe sur pixel - movb %ds:(%eax),%dh #couleur du monstre - movb %dl,%ds:(%eax) #effacement - add OFFSET_P4(%ebx),%eax #deplacement - movb %dh,%ds:(%eax) #affichage - - jmp next_monster #fini avec ce monstre... - -skip_7: - -/*------------------------------------------------------------------*/ -/* test si attaque dans direction associee a p0 */ -/*------------------------------------------------------------------*/ - - mov ARG_TEMP5(%ebp),%eax #mega astuce!!! - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_8 #oui, fini - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #y-a-t-il un streum? - je skip_8 #non, fini - movb ARG_TEMP1(%ebp),%al #recupere team - cmpb FIGHTER_TEAM(%edx),%al #compare - je skip_8 #les memes... - -/*------------------------------------------------------------------*/ -/* attaque ds dir associee a p0 */ -/*------------------------------------------------------------------*/ - - xor %ecx,%ecx # ecx a 0 - mov %al,%cl # ecx=al - shl $2,%cl # ecx=team*4 - mov ARG_ATTACK(%ebp),%ebx # ebx=attack - add %ecx,%ebx # ebx=attack[team] - movw FIGHTER_HEALTH(%edx),%ax # ax=health du voisin - subw (%ebx),%ax # attaque!!! - jg no_change_team_0 # change de camp??? - mov ARG_NEW_HEALTH(%ebp),%ebx # ebx=new_health - add %ecx,%ebx # ebx=new_health[team] - movw (%ebx),%bx # bx=valeur de n_h[team] -new_health_loop_0: - add %bx,%ax # health+=new_health - jl new_health_loop_0 # tant que health<0 - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%bx - cmpw %bx,%ax # health>max_health-1? - jle not_to_much_new_health_0 - mov %bx,%ax # health=max_health-1 -not_to_much_new_health_0: - shr $2,%cl - movb %cl,FIGHTER_TEAM(%edx) # changement de team - shl $2,%cl # en memoire - jmp display_attacked_fighter_0 - -no_change_team_0: - xor %ecx,%ecx # ecx=0 - movb FIGHTER_TEAM(%edx),%cl # cl=team - shl $2,%cl # ecx=team*4 - -display_attacked_fighter_0: - - movw %ax,FIGHTER_HEALTH(%edx) # health en mem - - cwde # eax=ax - mov ARG_COLORS_PER_TEAM(%ebp),%ebx # bx=colors - cdq - mull %ebx # eax*=colors - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%ebx # bx=max_health - inc %ebx - cdq - divl %ebx # eax/=max_health - mov ARG_COLOR_FIRST_ENTRY(%ebp),%ebx # ebx=cfe - add %ecx,%ebx # ebx=cfe+team - addb (%ebx),%al # eax=color - - mov ARG_CURRENT_AREA_DISP(%ebp),%ebx # ecx=cur_area_disp>dat - add ARG_TEMP2(%ebp),%ebx # y*cur_area_w+x - add ARG_TEMP5(%ebp),%ebx #on recupere la dir - - movb %al,(%ebx) - - jmp next_monster -skip_8: - -/*------------------------------------------------------------------*/ -/* test si attaque dans direction associee a p1 */ -/*------------------------------------------------------------------*/ - - mov ARG_TEMP6(%ebp),%eax #mega astuce!!! - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_9 #oui, fini - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #y-a-t-il un streum? - je skip_9 #non, fini - movb ARG_TEMP1(%ebp),%al #recupere team - cmpb FIGHTER_TEAM(%edx),%al #compare - je skip_9 #les memes... - -/*------------------------------------------------------------------*/ -/* attaque ds dir associee a p1 */ -/*------------------------------------------------------------------*/ - - xor %ecx,%ecx # ecx a 0 - mov %al,%cl # ecx=al - shl $2,%cl # ecx=team*4 - mov ARG_ATTACK(%ebp),%ebx # ebx=attack - add %ecx,%ebx # ebx=attack[team] - movw FIGHTER_HEALTH(%edx),%ax # ax=health du voisin - mov (%ebx),%bx # bx=force d attaque - shr $SIDE_ATTACK_FACTOR,%bx # force/ car - # attaque sur le cote - subw %bx,%ax # attaque!!! - jg no_change_team_1 # change de camp??? - mov ARG_NEW_HEALTH(%ebp),%ebx # ebx=new_health - add %ecx,%ebx # ebx=new_health[team] - movw (%ebx),%bx # bx=valeur de n_h[team] -new_health_loop_1: - add %bx,%ax # health+=new_health - jl new_health_loop_1 # tant que health<0 - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%bx - cmpw %bx,%ax # health>max_health-1? - jle not_to_much_new_health_1 - mov %bx,%ax # health=max_health-1 -not_to_much_new_health_1: - shr $2,%cl - movb %cl,FIGHTER_TEAM(%edx) # changement de team - shl $2,%cl # en memoire - jmp display_attacked_fighter_1 - -no_change_team_1: - xor %ecx,%ecx # ecx=0 - movb FIGHTER_TEAM(%edx),%cl # cl=team - shl $2,%cl # ecx=team*4 - -display_attacked_fighter_1: - - movw %ax,FIGHTER_HEALTH(%edx) # health en mem - - cwde # eax=ax - mov ARG_COLORS_PER_TEAM(%ebp),%ebx # bx=colors - cdq - mull %ebx # eax*=colors - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%ebx # bx=max_health - inc %ebx - cdq - divl %ebx # eax/=max_health - mov ARG_COLOR_FIRST_ENTRY(%ebp),%ebx # ebx=cfe - add %ecx,%ebx # ebx=cfe+team - addb (%ebx),%al # eax=color - - mov ARG_CURRENT_AREA_DISP(%ebp),%ebx # ecx=cur_area_disp>dat - add ARG_TEMP2(%ebp),%ebx # y*cur_area_w+x - add ARG_TEMP6(%ebp),%ebx #on recupere la dir - - movb %al,(%ebx) - - jmp next_monster -skip_9: - -/*------------------------------------------------------------------*/ -/* test si attaque dans direction associee a p2 */ -/*------------------------------------------------------------------*/ - - mov ARG_TEMP6(%ebp),%eax #mega astuce!!! - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_10 #oui, fini - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #y-a-t-il un streum? - je skip_10 #non, fini - movb ARG_TEMP1(%ebp),%al #recupere team - cmpb FIGHTER_TEAM(%edx),%al #compare - je skip_10 #les memes... - -/*------------------------------------------------------------------*/ -/* attaque ds dir associee a p2 */ -/*------------------------------------------------------------------*/ - - xor %ecx,%ecx # ecx a 0 - mov %al,%cl # ecx=al - shl $2,%cl # ecx=team*4 - mov ARG_ATTACK(%ebp),%ebx # ebx=attack - add %ecx,%ebx # ebx=attack[team] - movw FIGHTER_HEALTH(%edx),%ax # ax=health du voisin - mov (%ebx),%bx # bx=force d attaque - shr $SIDE_ATTACK_FACTOR,%bx # force/ car - # attaque sur le cote - subw %bx,%ax # attaque!!! - jg no_change_team_2 # change de camp??? - mov ARG_NEW_HEALTH(%ebp),%ebx # ebx=new_health - add %ecx,%ebx # ebx=new_health[team] - movw (%ebx),%bx # bx=valeur de n_h[team] -new_health_loop_2: - add %bx,%ax # health+=new_health - jl new_health_loop_2 # tant que health<0 - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%bx - cmpw %bx,%ax # health>max_health-1? - jle not_to_much_new_health_2 - mov %bx,%ax # health=max_health-1 -not_to_much_new_health_2: - shr $2,%cl - movb %cl,FIGHTER_TEAM(%edx) # changement de team - shl $2,%cl # en memoire - jmp display_attacked_fighter_2 - -no_change_team_2: - xor %ecx,%ecx # ecx=0 - movb FIGHTER_TEAM(%edx),%cl # cl=team - shl $2,%cl # ecx=team*4 - -display_attacked_fighter_2: - - movw %ax,FIGHTER_HEALTH(%edx) # health en mem - - cwde # eax=ax - mov ARG_COLORS_PER_TEAM(%ebp),%ebx # bx=colors - cdq - mull %ebx # eax*=colors - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%ebx # bx=max_health - inc %ebx - cdq - divl %ebx # eax/=max_health - mov ARG_COLOR_FIRST_ENTRY(%ebp),%ebx # ebx=cfe - add %ecx,%ebx # ebx=cfe+team - addb (%ebx),%al # eax=color - - mov ARG_CURRENT_AREA_DISP(%ebp),%ebx # ecx=cur_area_disp>dat - add ARG_TEMP2(%ebp),%ebx # y*cur_area_w+x - add ARG_TEMP6(%ebp),%ebx #on recupere la dir - - movb %al,(%ebx) - - jmp next_monster -skip_10: - -/*------------------------------------------------------------------*/ -/* test si regeneration dans direction associee a p0 */ -/*------------------------------------------------------------------*/ - mov ARG_TEMP5(%ebp),%eax #mega astuce!!! - shl $3,%eax - add %edi,%eax #eax=pointeur sur place - - mov PLACE_MESH(%eax),%edx #edx=pointeur sur mesh - cmp $0,%edx #la place est-elle un mur? - je skip_11 #oui, fini - mov PLACE_FIGHTER(%eax),%edx #edx=pointeur sur fighter - cmp $0,%edx #y-a-t-il un streum? - je skip_11 #non, fini - movb ARG_TEMP1(%ebp),%al #recupere team - cmpb FIGHTER_TEAM(%edx),%al #compare - jne skip_11 #les memes... - -/*------------------------------------------------------------------*/ -/* regeneration ds dir associee a p0 */ -/*------------------------------------------------------------------*/ - xor %ecx,%ecx # ecx a 0 - mov %al,%cl # ecx=al - shl $2,%cl # ecx=team*4 - mov ARG_DEFENSE(%ebp),%ebx # ebx=defense - add %ecx,%ebx # ebx=defense[team] - movw FIGHTER_HEALTH(%edx),%ax # ax=health du voisin - addw (%ebx),%ax # regeneration!!! - mov ARG_MAX_FIGHTER_HEALTH_1(%ebp),%bx - cmpw %bx,%ax # health>max_health? - jle not_to_much_defense - mov %bx,%ax -not_to_much_defense: - jmp display_attacked_fighter_0 -skip_11: - -/*------------------------------------------------------------------*/ -/* fin de la boucle, on passe a la suite */ -/*------------------------------------------------------------------*/ -next_monster: - add $SIZE_OF_FIGHTER,%esi # on passe au streumon suivant - - pop %ecx - dec %ecx - je the_end - jmp main_loop - -the_end: - - popw %gs - popw %fs - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret # retour au c - - diff --git a/src/mouse.c b/src/mouse.c index 7af61ba5..734763c4 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -52,8 +52,7 @@ /* includes */ /*==================================================================*/ -#include - +#include "backport.h" #include "config.h" #include "mouse.h" #include "disk.h" diff --git a/src/move.c b/src/move.c index e040c776..1758895b 100644 --- a/src/move.c +++ b/src/move.c @@ -52,7 +52,7 @@ /* includes */ /*==================================================================*/ -#include +#include #include "area.h" #include "autoplay.h" diff --git a/src/music.c b/src/music.c index 6b5932cd..2bc3c389 100644 --- a/src/music.c +++ b/src/music.c @@ -53,6 +53,7 @@ #include +#include "backport.h" #include "config.h" #include "disk.h" #include "startup.h" diff --git a/src/mutxdos.c b/src/mutxdos.c deleted file mode 100644 index e372f308..00000000 --- a/src/mutxdos.c +++ /dev/null @@ -1,106 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* name : thrddos.c */ -/* content : provides fake mutex support under DOS */ -/********************************************************************/ - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include "mutxgen.h" - -/*==================================================================*/ -/* defines */ -/*==================================================================*/ - -/*==================================================================*/ -/* macros */ -/*==================================================================*/ - -/*==================================================================*/ -/* globals */ -/*==================================================================*/ - -/*==================================================================*/ -/* fonctions */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -int -lw_mutex_init (LW_MUTEX_DATA * mutex) -{ - int result = 1; - - return result; -} - -/*------------------------------------------------------------------*/ -int -lw_mutex_lock (LW_MUTEX_DATA * mutex) -{ - int result = 1; - - return result; -} - -/*------------------------------------------------------------------*/ -int -lw_mutex_trylock (LW_MUTEX_DATA * mutex) -{ - int result = 1; - - return result; -} - -/*------------------------------------------------------------------*/ -int -lw_mutex_unlock (LW_MUTEX_DATA * mutex) -{ - int result = 1; - - return result; -} diff --git a/src/netconf.c b/src/netconf.c index 2c94633e..7c62096c 100644 --- a/src/netconf.c +++ b/src/netconf.c @@ -56,6 +56,7 @@ #include #include +#include "backport.h" #include "netconf.h" #include "sock2gen.h" #include "log.h" @@ -145,15 +146,10 @@ lw_netconf_send (int *sock, LW_NETCONF * config) if (lw_sock_send_str (sock, buffer)) { LW_MACRO_SPRINTF1 (buffer, "%d", - config->asm_algorithm); + config->min_map_res); if (lw_sock_send_str (sock, buffer)) { - LW_MACRO_SPRINTF1 (buffer, "%d", - config->min_map_res); - if (lw_sock_send_str (sock, buffer)) - { - result = 1; - } + result = 1; } } } @@ -209,8 +205,6 @@ lw_netconf_recv (int *sock, LW_NETCONF * config) config->cpu_vs_human = atoi (buffer); if (lw_sock_recv_str (sock, buffer)) { - config->asm_algorithm = - atoi (buffer); if (lw_sock_recv_str (sock, buffer)) { config->min_map_res = @@ -250,7 +244,6 @@ lw_netconf_check (LW_NETCONF * config) LW_NETCONF_CHECK_RANGE (game_time, 16); LW_NETCONF_CHECK_RANGE (cpu_advantage, 4); LW_NETCONF_CHECK_RANGE (cpu_vs_human, 2); - LW_NETCONF_CHECK_RANGE (asm_algorithm, 1); LW_NETCONF_CHECK_RANGE (min_map_res, 8); return result; @@ -272,6 +265,5 @@ lw_netconf_print (LW_NETCONF * config) LW_NETCONF_PRINT_VALUE (game_time); LW_NETCONF_PRINT_VALUE (cpu_advantage); LW_NETCONF_PRINT_VALUE (cpu_vs_human); - LW_NETCONF_PRINT_VALUE (asm_algorithm); LW_NETCONF_PRINT_VALUE (min_map_res); } diff --git a/src/netconf.h b/src/netconf.h index 34865354..e4854e60 100644 --- a/src/netconf.h +++ b/src/netconf.h @@ -72,7 +72,6 @@ typedef struct int game_time; int cpu_advantage; int cpu_vs_human; - int asm_algorithm; int min_map_res; } LW_NETCONF; diff --git a/src/netplay.c b/src/netplay.c index 17c55050..b5b0e510 100644 --- a/src/netplay.c +++ b/src/netplay.c @@ -54,6 +54,7 @@ #include #include +#include "backport.h" #include "back.h" #include "base.h" #include "config.h" @@ -222,7 +223,7 @@ connect_on_server_start (int *sock, char *address, int port) */ while (connect_data->running && !esc_pressed) { - if (key[KEY_ESC]) + if (key[ALLEGRO_KEY_ESCAPE]) { esc_pressed = 1; } diff --git a/src/network.c b/src/network.c index 3ffb8297..d07b49f5 100644 --- a/src/network.c +++ b/src/network.c @@ -54,7 +54,7 @@ #include -#include +#include #include "network.h" #include "config.h" diff --git a/src/options.c b/src/options.c index 8bab199c..3416519e 100644 --- a/src/options.c +++ b/src/options.c @@ -54,6 +54,7 @@ #include +#include "backport.h" #include "back.h" #include "base.h" #include "config.h" @@ -72,6 +73,7 @@ #include "controls.h" #include "lang.h" #include "gfxmode.h" +#include "mouse.h" /*==================================================================*/ /* variables globales */ @@ -119,14 +121,14 @@ options (void) gfxmode_change = 0; display_back_image (); dp = my_init_dialog (d, choix); - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode } else { dp = my_init_dialog (d, choix); } - show_mouse (screen); + lw_mouse_show (); while (my_update_dialog (dp)) ; choix = shutdown_dialog (dp); diff --git a/src/palette.c b/src/palette.c deleted file mode 100644 index 9e0b7c24..00000000 --- a/src/palette.c +++ /dev/null @@ -1,421 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : palette.c */ -/* contenu : gestion de la palette de couleurs */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include "config.h" -#include "decal.h" -#include "disk.h" -#include "palette.h" -#include "network.h" -#include "mouse.h" -#include "texture.h" - -/*==================================================================*/ -/* constantes */ -/*==================================================================*/ - -#define BG_TEXTURE_DEFAULT_COLOR 120 -#define FG_TEXTURE_DEFAULT_COLOR 127 - -/*==================================================================*/ -/* variables globales */ -/*==================================================================*/ - -int COLORS_PER_TEAM = 0; -PALETTE GLOBAL_PALETTE; - -/*==================================================================*/ -/* fonctions */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -/* mise en place de la palette, si necessaire */ -/*------------------------------------------------------------------*/ - -/*------------------------------------------------------------------*/ -static int -sqrt255 (int i) -{ - int result; - - result = fixsqrt (i * 256) / 256; - if (result > 255) - result = 255; - - return result; -} - -/*------------------------------------------------------------------*/ -static int -sqr255 (int i) -{ - int result; - - result = (i * i) / 256; - if (result > 255) - result = 255; - - return result; -} - -/*------------------------------------------------------------------*/ -static void -change_palette_brightness (PALETTE old_pal, PALETTE new_pal) -{ - int r, g, b; - int i; - int brightness; - RGB *rgb; - - brightness = CONFIG_BRIGHTNESS - 8; - if (brightness != 0) - for (i = 0; i < 256; ++i) - { - rgb = old_pal + i; - r = rgb->r * 4; - g = rgb->g * 4; - b = rgb->b * 4; - - if (brightness > 0) - { - r = (brightness * sqrt255 (r) + (8 - brightness) * r) / 8; - g = (brightness * sqrt255 (g) + (8 - brightness) * g) / 8; - b = (brightness * sqrt255 (b) + (8 - brightness) * b) / 8; - } - if (brightness < 0) - { - r = (-brightness * sqr255 (r) + (8 + brightness) * r) / 8; - g = (-brightness * sqr255 (g) + (8 + brightness) * g) / 8; - b = (-brightness * sqr255 (b) + (8 + brightness) * b) / 8; - } - - rgb = new_pal + i; - rgb->r = r / 4; - rgb->g = g / 4; - rgb->b = b / 4; - } - else - for (i = 0; i < 256; ++i) - new_pal[i] = old_pal[i]; -} - -/*------------------------------------------------------------------*/ -void -my_set_palette (void) -{ - PALETTE old_pal, corrected_pal; - int i, equal = 1; - - change_palette_brightness (GLOBAL_PALETTE, corrected_pal); - - get_palette (old_pal); - for (i = 0; i < 256 && equal; ++i) - { - equal = equal && (corrected_pal[i].r == old_pal[i].r); - equal = equal && (corrected_pal[i].g == old_pal[i].g); - equal = equal && (corrected_pal[i].b == old_pal[i].b); - } - if (!equal) - set_palette (corrected_pal); -} - -/*------------------------------------------------------------------*/ -static void -set_raw_texture_palette (void *ptr, int first) -{ - int i; - char *data; - - data = ptr; - data += 4 + LW_TEXTURE_SYSTEM_NAME_SIZE; - for (i = first; i < first + 32; ++i) - { - GLOBAL_PALETTE[i].r = *(data++); - GLOBAL_PALETTE[i].g = *(data++); - GLOBAL_PALETTE[i].b = *(data++); - } -} - -/*------------------------------------------------------------------*/ -static void -get_mono_texture_color (RGB * rgb, int num) -{ - int h1, s1, v1, r, g, b; - float h2, s2, v2; - float h[] = { 0, 20, 40, 70, 110, 150, 180, 210, 240, 270, 300, 330 }; - float s[] = { 1, 0.7, 0.4, 1, 0.5, 1, 0.5, 1, 0.5, 1 }; - float v[] = { 1, 1, 1, 0.8, 0.8, 0.6, 0.6, 0.3, 0.3, 0.1 }; - - h1 = num / 10; - s1 = num % 10; - v1 = s1; - - if (h1 < 12) - { - h2 = h[h1]; - s2 = s[s1]; - v2 = v[v1]; - } - else - { - h2 = 0; - s2 = 0; - v2 = 127 - num; - v2 /= 7.; - } - - hsv_to_rgb (h2, s2, v2, &r, &g, &b); - - rgb->r = r / 4; - rgb->g = g / 4; - rgb->b = b / 4; - /* *rgb=CHOOSE_PALETTE [32+num]; */ -} - -/*------------------------------------------------------------------*/ -static void -set_mono_texture_palette (int num, int first) -{ - get_mono_texture_color (GLOBAL_PALETTE + first, num); -} - - -/*------------------------------------------------------------------*/ -void -set_bg_texture_palette (int num) -{ - if (num < CHOOSE_COLOR_NUMBER) - { - set_mono_texture_palette (num, BG_TEXTURE_FIRST_COLOR); - } - else - { - if (num >= CHOOSE_COLOR_NUMBER - && num < CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER) - { - if (LOADED_TEXTURE) - { - set_raw_texture_palette (RAW_TEXTURE - [num - CHOOSE_COLOR_NUMBER], - BG_TEXTURE_FIRST_COLOR); - } - else - { - set_mono_texture_palette (BG_TEXTURE_DEFAULT_COLOR, - BG_TEXTURE_FIRST_COLOR); - } - } - - if (num >= CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER - && num < - CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER + RAW_MAPTEX_NUMBER) - { - if (LOADED_MAPTEX) - { - set_raw_texture_palette (RAW_MAPTEX - [num - - (CHOOSE_COLOR_NUMBER + - RAW_TEXTURE_NUMBER)], - BG_TEXTURE_FIRST_COLOR); - } - else - { - set_mono_texture_palette (BG_TEXTURE_DEFAULT_COLOR, - BG_TEXTURE_FIRST_COLOR); - } - } - } -} - -/*------------------------------------------------------------------*/ -void -set_fg_texture_palette (int num) -{ - if (num < CHOOSE_COLOR_NUMBER) - { - set_mono_texture_palette (num, FG_TEXTURE_FIRST_COLOR); - } - else - { - if (num >= CHOOSE_COLOR_NUMBER - && num < CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER) - { - if (LOADED_TEXTURE) - { - set_raw_texture_palette (RAW_TEXTURE - [num - CHOOSE_COLOR_NUMBER], - FG_TEXTURE_FIRST_COLOR); - } - else - { - set_mono_texture_palette (FG_TEXTURE_DEFAULT_COLOR, - FG_TEXTURE_FIRST_COLOR); - } - } - - if (num >= CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER - && num < - CHOOSE_COLOR_NUMBER + RAW_TEXTURE_NUMBER + RAW_MAPTEX_NUMBER) - { - if (LOADED_MAPTEX) - { - set_raw_texture_palette (RAW_MAPTEX - [num - - (CHOOSE_COLOR_NUMBER + - RAW_TEXTURE_NUMBER)], - FG_TEXTURE_FIRST_COLOR); - } - else - { - set_mono_texture_palette (FG_TEXTURE_DEFAULT_COLOR, - FG_TEXTURE_FIRST_COLOR); - } - } - } -} - -/*------------------------------------------------------------------*/ -void -set_palette_for_choose_color (void) -{ - int i; - - for (i = 0; i < 128; ++i) - get_mono_texture_color (GLOBAL_PALETTE + 128 + i, i); -} - -/*------------------------------------------------------------------*/ -static void -set_team_color (int teinte, int first, int num) -{ - int i, col, col_r, col_g, col_b, coeff, tot, last; - - last = first + num - 1; - - get_mono_texture_color (GLOBAL_PALETTE + last, teinte * 10); - - col_r = GLOBAL_PALETTE[last].r; - col_g = GLOBAL_PALETTE[last].g; - col_b = GLOBAL_PALETTE[last].b; - tot = 8 * num - 7; - for (i = 0; i < num - 1; ++i) - { - coeff = num + 7 * i; - col = (col_r * coeff) / tot; - GLOBAL_PALETTE[first + i].r = col; - col = (col_g * coeff) / tot; - GLOBAL_PALETTE[first + i].g = col; - col = (col_b * coeff) / tot; - GLOBAL_PALETTE[first + i].b = col; - } -} - -/*------------------------------------------------------------------*/ -void -set_playing_teams_palette (void) -{ - int i, j, n, color, active; - - COLORS_PER_TEAM = 128 / PLAYING_TEAMS; - for (i = 0, n = 0; i < NB_TEAMS; ++i) - { - color = 0; - active = 0; - if (LW_NETWORK_ON) - { - for (j = 0; j < NB_TEAMS; ++j) - { - if (LW_NETWORK_INFO[j].active && - LW_NETWORK_INFO[j].server_id == i) - { - active = 1; - color = LW_NETWORK_INFO[j].color; - } - } - } - else - { - if (CONFIG_CONTROL_TYPE[i] != CONFIG_CONTROL_TYPE_OFF) - { - active = 1; - color = CONFIG_TEAM_COLOR[i]; - } - } - - if (active) - { - COLOR_FIRST_ENTRY[n] = 128 + n * COLORS_PER_TEAM; - set_team_color (color, COLOR_FIRST_ENTRY[n], COLORS_PER_TEAM); - n++; - } - } -} - -/*------------------------------------------------------------------*/ -void -my_fade_out (void) -{ - fade_out (48); -} - -/*------------------------------------------------------------------*/ -void -my_fade_in (void) -{ - PALETTE pal; - - change_palette_brightness (GLOBAL_PALETTE, pal); - fade_in (pal, 48); - - lw_mouse_update_show_hide (); -} diff --git a/src/path.c b/src/path.c index 0ae7861d..a7c83867 100644 --- a/src/path.c +++ b/src/path.c @@ -51,11 +51,23 @@ /* includes */ /*==================================================================*/ +#include + #include "path.h" #include "startup.h" #include "macro.h" #include "log.h" +/*==================================================================*/ +/* defines */ +/*==================================================================*/ + +#ifdef UNIX +#define _SEP '/' +#else +#define _SEP '\\' +#endif + /*==================================================================*/ /* types */ /*==================================================================*/ @@ -98,17 +110,6 @@ lw_path_get_system_name (const char *filename) LW_MACRO_STRCPY (buf2, start); search = strchr (buf2, '.'); - /* - if (search != NULL) - { - end = search; - } - else - { - end = buf2 + strlen (buf2); - } - */ - if (search == NULL) { search = buf2 + strlen (buf2); @@ -118,3 +119,49 @@ lw_path_get_system_name (const char *filename) return buf2; } + +/*------------------------------------------------------------------*/ +/* + * Fonction used to build complete paths from different parts. + */ +char * +lw_path_join2(const char *begin, const char *end) { + while (*end==_SEP) { + end++; + } + int begin_len = strlen(begin); + int end_len = strlen(end); + int joined_len = begin_len + end_len; + char *joined = malloc(joined_len+2); + memset(joined, 0, joined_len+2); + memcpy(joined, begin, begin_len); + joined[begin_len] = _SEP; + memcpy(joined+begin_len+1, end, end_len); + return joined; +} + +/*------------------------------------------------------------------*/ +/* + * Fonction used to build complete paths from different parts. + */ +char * +lw_path_join3(const char *begin, const char *middle, const char *end) { + while (*middle==_SEP) { + middle++; + } + while (*end==_SEP) { + end++; + } + int begin_len = strlen(begin); + int middle_len = strlen(middle); + int end_len = strlen(end); + int joined_len = begin_len + middle_len + end_len; + char *joined = malloc(joined_len+3); + memset(joined, 0, joined_len+3); + memcpy(joined, begin, begin_len); + joined[begin_len] = _SEP; + memcpy(joined+begin_len+1, middle, middle_len); + joined[begin_len+middle_len+1] = _SEP; + memcpy(joined+begin_len+middle_len+2, end, end_len); + return joined; +} diff --git a/src/path.h b/src/path.h index 2dbcf99d..4d623fcb 100644 --- a/src/path.h +++ b/src/path.h @@ -67,5 +67,7 @@ /*==================================================================*/ char *lw_path_get_system_name (const char *filename); +char *lw_path_join2(const char *begin, const char *end); +char *lw_path_join3(const char *begin, const char *middle, const char *end); #endif diff --git a/src/ping.c b/src/ping.c index 6f9cc598..b8843dc1 100644 --- a/src/ping.c +++ b/src/ping.c @@ -51,8 +51,7 @@ /* includes */ /*==================================================================*/ -#include - +#include "backport.h" #include "ping.h" #include "thrdgen.h" #include "ticker.h" diff --git a/src/pion.c b/src/pion.c index 61fe0ee5..67439b6b 100644 --- a/src/pion.c +++ b/src/pion.c @@ -52,14 +52,14 @@ /* includes */ /*==================================================================*/ -#include +#include +#include "backport.h" #include "area.h" #include "base.h" #include "config.h" #include "cursor.h" #include "decal.h" -#include "palette.h" #include "viewport.h" #include "pion.h" #include "lwtime.h" @@ -132,10 +132,10 @@ static CURSOR_POINT CURSOR_LAYOUT[CURSOR_POINT_NUMBER] = {-1, -4, 31, CL_MIDDLE}, {-1, -5, 31, CL_OUTSIDE} }; -static char CURSOR_GRAPHIC_MEMORY[NB_TEAMS][CURSOR_POINT_NUMBER]; +static ALLEGRO_COLOR CURSOR_GRAPHIC_MEMORY[NB_TEAMS][CURSOR_POINT_NUMBER]; -static char CURSOR_COLOR_MAP[CURSOR_COLOR_NUMBER]; -static char CURSOR_COLOR_BACK[CURSOR_COLOR_NUMBER]; +static int CURSOR_COLOR_MAP[CURSOR_COLOR_NUMBER]; // Intensity values (0-255) +static ALLEGRO_COLOR CURSOR_COLOR_BACK[CURSOR_COLOR_NUMBER]; /*==================================================================*/ /* fonctions */ @@ -145,18 +145,15 @@ static char CURSOR_COLOR_BACK[CURSOR_COLOR_NUMBER]; void init_disp_cursor (void) { - int i, x, y, color_back; + int i, x, y; + ALLEGRO_COLOR color_back; + // In true color mode, just pick random colors from the background texture for (i = 0; i < CURSOR_COLOR_NUMBER; ++i) { - color_back = 0; - while (color_back < FG_TEXTURE_FIRST_COLOR - || color_back >= FG_TEXTURE_FIRST_COLOR + 32) - { - x = random () % CURRENT_AREA_W; - y = random () % CURRENT_AREA_H; - color_back = getpixel (CURRENT_AREA_BACK, x, y); - } + x = random () % CURRENT_AREA_W; + y = random () % CURRENT_AREA_H; + color_back = getpixel (CURRENT_AREA_BACK, x, y); CURSOR_COLOR_BACK[i] = color_back; } } @@ -165,11 +162,11 @@ init_disp_cursor (void) static void disp_cursor (int number) { - int i, x, y, x0, y0, color_offset; + int i, x, y, x0, y0, team; x0 = CURRENT_CURSOR[number].x; y0 = CURRENT_CURSOR[number].y; - color_offset = COLOR_FIRST_ENTRY[CURRENT_CURSOR[number].team]; + team = CURRENT_CURSOR[number].team; for (i = 0; i < CURSOR_POINT_NUMBER; ++i) @@ -183,7 +180,7 @@ disp_cursor (int number) case CL_INSIDE: case CL_MIDDLE: putpixel (CURRENT_AREA_DISP, x, y, - CURSOR_COLOR_MAP[CURSOR_LAYOUT[i].color] + color_offset); + lw_team_color(team, CURSOR_COLOR_MAP[CURSOR_LAYOUT[i].color])); break; case CL_MIDDLE2: putpixel (CURRENT_AREA_DISP, x, y, @@ -216,26 +213,26 @@ disp_all_cursors (void) { int i, degrad_size, fp, ip; + // In true color mode, intensity ranges from 0 to 255 degrad_size = CURSOR_COLOR_NUMBER / (2 * CURSOR_LIGHTS); - ip = ((GLOBAL_TICKER * COLORS_PER_TEAM) / CURSOR_CYCLE) - % (COLORS_PER_TEAM * 2); + ip = ((GLOBAL_TICKER * 256) / CURSOR_CYCLE) % (256 * 2); fp = 0; for (i = 0; i < CURSOR_COLOR_NUMBER; ++i) { - if (ip < COLORS_PER_TEAM) + if (ip < 256) CURSOR_COLOR_MAP[i] = ip; else - CURSOR_COLOR_MAP[i] = 2 * COLORS_PER_TEAM - 1 - ip; + CURSOR_COLOR_MAP[i] = 2 * 256 - 1 - ip; - fp += COLORS_PER_TEAM; + fp += 256; while (fp >= degrad_size) { fp -= degrad_size; ip++; } - while (ip >= 2 * COLORS_PER_TEAM) - ip -= 2 * COLORS_PER_TEAM; + while (ip >= 2 * 256) + ip -= 2 * 256; } for (i = 0; i < NB_TEAMS; ++i) diff --git a/src/play.c b/src/play.c index 62518edc..8c51f034 100644 --- a/src/play.c +++ b/src/play.c @@ -53,7 +53,7 @@ /*==================================================================*/ #include -#include +#include #include "back.h" #include "config.h" @@ -62,7 +62,6 @@ #include "error.h" #include "game.h" #include "gfxmode.h" -#include "palette.h" #include "maptex.h" #include "play.h" #include "score.h" @@ -154,7 +153,7 @@ play_sequence_ex (void) * we set up the Allegro palette and LW's palette parameters so that * an optimized number of colors is used for each team's fighters */ - set_playing_teams_palette (); + // set_playing_teams_palette (); // No longer needed in true color mode /* * if there's only one team selected we stop right away and quit @@ -180,7 +179,7 @@ play_sequence_ex (void) /* * fade out cause we're going to switch video modes */ - my_fade_out (); + // my_fade_out (); // No longer needed in true color mode /* * we change the resolution, but only if the game resolution is @@ -203,7 +202,7 @@ play_sequence_ex (void) /* * fiat lux */ - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode /* * start playing some music @@ -239,7 +238,7 @@ play_sequence_ex (void) /* * fade out before video mode switching */ - my_fade_out (); + // my_fade_out (); // No longer needed in true color mode /* * again, we change the video mode only if it is really required */ diff --git a/src/popupw32.c b/src/popupw32.c index 7296d65c..d1738c73 100644 --- a/src/popupw32.c +++ b/src/popupw32.c @@ -51,7 +51,7 @@ /* includes */ /*==================================================================*/ -#include +#include #ifdef WIN32 #include #endif diff --git a/src/profile.c b/src/profile.c index 2f08e75a..b7ffcce8 100644 --- a/src/profile.c +++ b/src/profile.c @@ -52,7 +52,7 @@ /* includes */ /*==================================================================*/ -#include +#include #include "profile.h" #include "ticker.h" diff --git a/src/random.c b/src/random.c index 811e6985..e2d69b19 100644 --- a/src/random.c +++ b/src/random.c @@ -54,8 +54,9 @@ #include #include -#include +#include +#include "backport.h" #include "random.h" #include "base.h" #include "alleg2.h" @@ -96,39 +97,39 @@ int LW_RANDOM_ON = 0; /* * Generates a black&white palette which is suitable for * the game to handle nicely maps generated by lwmapgen. Basically - * all we need is color 0 == black and color 2555 = white, but - * we do a full grayscale, just to say the palette is not full of - * garbage. + * Palette generation removed - not needed for Allegro 5 */ -static void -generate_bw_palette (PALETTE pal) -{ - int i; - - for (i = 0; i < 256; ++i) - { - pal[i].r = i; - pal[i].g = i; - pal[i].b = i; - } -} /*------------------------------------------------------------------*/ -static BITMAP * +static ALLEGRO_BITMAP * generate_bitmap () { - BITMAP *bmp; - PALETTE pal; + ALLEGRO_BITMAP *bmp; char filename[LW_STARTUP_MAX_PATH_LENGTH]; char command[LW_STARTUP_MAX_PATH_LENGTH + LW_COMMAND_EXTRA_SIZE]; int size; int ok = 0; + int temp_fd; size = random () % 6; - LW_MACRO_SPRINTF1 (filename, "%s.bmp", tmpnam (NULL)); + // Create secure temporary file using mkstemp + // First create template without .bmp extension for mkstemp + char temp_name[] = "/tmp/lwmapgen_XXXXXX"; + temp_fd = mkstemp(temp_name); + if (temp_fd == -1) { + log_println_str("Error: Could not create temporary file"); + return NULL; + } + close(temp_fd); // Close the file descriptor, we just need the name + + // Remove the temporary file created by mkstemp (we just wanted the unique name) + delete_file(temp_name); + + // Add .bmp extension to the filename + LW_MACRO_SPRINTF1(filename, "%s.bmp", temp_name); LW_MACRO_SPRINTF4 (command, "%s --out %s --size %d%s", STARTUP_GEN_PATH, filename, size, LW_RANDOM_COMMAND_END); @@ -157,7 +158,7 @@ generate_bitmap () if (ok) { - bmp = load_bitmap (filename, pal); + bmp = al_load_bitmap_flags(filename, ALLEGRO_MEMORY_BITMAP); } else { @@ -189,17 +190,15 @@ generate_bitmap () int lw_random_generate_map () { - BITMAP *bmp; - PALETTE pal; + ALLEGRO_BITMAP *bmp; void *raw_map = NULL; int result = 0; bmp = generate_bitmap (); - generate_bw_palette (pal); if (bmp) { - raw_map = lw_map_archive_raw_bmp (bmp, pal, "lwmapgen"); + raw_map = lw_map_archive_raw_bmp (bmp, "lwmapgen"); } if (raw_map) diff --git a/src/score.c b/src/score.c index 9a14f234..b4f561d6 100644 --- a/src/score.c +++ b/src/score.c @@ -56,6 +56,7 @@ #include #include +#include "backport.h" #include "army.h" #include "back.h" #include "base.h" @@ -204,17 +205,18 @@ init_tombola () /*------------------------------------------------------------------*/ static int -draw_score_bitmap (BITMAP * bitmap, int cursor, int ellipse_h, int fill_level) +draw_score_bitmap (ALLEGRO_BITMAP * bitmap, int cursor, int ellipse_h, + int fill_level) { int w, h; - int color1 = 0, color2 = 0; + ALLEGRO_COLOR color1, color2; int y_rect1, y_rect2, x_mid; int to_be_filled, to_be_drawn; - w = bitmap->w; + w = al_get_bitmap_width(bitmap); if (!(w & 1)) w -= 1; - h = bitmap->h; + h = al_get_bitmap_height(bitmap); y_rect1 = ellipse_h / 2; y_rect2 = h - y_rect1 - 1; x_mid = w / 2; @@ -222,8 +224,9 @@ draw_score_bitmap (BITMAP * bitmap, int cursor, int ellipse_h, int fill_level) fill_level = 0; else { - color1 = CURRENT_CURSOR[cursor].color_entry + COLORS_PER_TEAM / 2; - color2 = CURRENT_CURSOR[cursor].color_entry + COLORS_PER_TEAM - 1; + int team = CURRENT_CURSOR[cursor].team; + color1 = lw_team_color(team, 128); // Mid intensity + color2 = lw_team_color(team, 255); // Full intensity } if (fill_level < 0) fill_level = 0; @@ -239,7 +242,7 @@ draw_score_bitmap (BITMAP * bitmap, int cursor, int ellipse_h, int fill_level) fill_level /= 1000; fill_level += 2 * y_rect1; - rectfill (bitmap, 0, 0, w, h, 0); + rectfill (bitmap, 0, 0, w, h, al_map_rgb(0, 0, 0)); if (to_be_filled) ellipsefill (bitmap, x_mid, y_rect2, x_mid, ellipse_h / 2, color1); @@ -277,7 +280,7 @@ display_scores (void) int ellipse_h; int i; int cursor[3]; - BITMAP *eprouvette[3]; + ALLEGRO_BITMAP *eprouvette[3]; int time_delay[3] = { 500, 2500, 1500 }; int fill_level; int done[3]; @@ -333,7 +336,7 @@ display_scores (void) done[i] = 0; write_score (cursor[i], buf[i], 0); buf_old[i][0] = '\0'; - eprouvette[i] = my_create_bitmap (w, h[i]); + eprouvette[i] = my_create_memory_bitmap (w, h[i]); } d[MENU_QUICK_QUIT].flags = D_HIDDEN; @@ -344,7 +347,7 @@ display_scores (void) my_update_dialog (dp); shutdown_dialog (dp); - my_fade_in (); + // my_fade_in (); // No longer needed in true color mode play_win (); first_ticker = get_ticker (); @@ -440,7 +443,7 @@ display_scores (void) } for (i = 0; i < 3; ++i) - destroy_bitmap (eprouvette[i]); + al_destroy_bitmap (eprouvette[i]); if (retour > 0) retour--; diff --git a/src/serial.h b/src/serial.h index 795a23ac..ba5f77da 100644 --- a/src/serial.h +++ b/src/serial.h @@ -54,7 +54,7 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* constants */ diff --git a/src/sockdos.c b/src/sockdos.c deleted file mode 100644 index fe70a0f8..00000000 --- a/src/sockdos.c +++ /dev/null @@ -1,141 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* name : sockdos.c */ -/* content : fake DOS network support to avoid link failure */ -/* last update : April 13th 2001 */ -/********************************************************************/ - -/* - * This file contains empty functions even if DOS releases of LW - * have no network support. It permits safe linking. - */ - -/*==================================================================*/ -/* globals */ -/*==================================================================*/ - -int LW_SOCK_LOG = 0; - -/*==================================================================*/ -/* functions */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -int -lw_sock_init () -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_exit () -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_listen (int *sock, char *ip, int port) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_accept (int *new_sock, char *ip, int *port, int listening_sock) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_connect (int *sock, char *ip, int port) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_peek_ex (int sock, int len) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_send_str_ex (int sock, char *str) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_recv_str_ex (int sock, char *str) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_send_buffer_ex (int sock, char *buffer, int len) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_recv_buffer_ex (int sock, char *buffer, int len) -{ - return 0; -} - -/*------------------------------------------------------------------*/ -int -lw_sock_close (int *sock) -{ - return 0; -} diff --git a/src/sound.c b/src/sound.c index c3b05829..66edd440 100644 --- a/src/sound.c +++ b/src/sound.c @@ -51,6 +51,7 @@ /* includes */ /*==================================================================*/ +#include "backport.h" #include "config.h" #include "disk.h" #include "sound.h" @@ -107,7 +108,7 @@ water_handler (void) } } -END_OF_FUNCTION (water_handler); +// END_OF_FUNCTION removed - not needed in Allegro 5 /*------------------------------------------------------------------*/ int @@ -123,17 +124,8 @@ start_water (void) { WATER_VOLUME = CONFIG_WATER_VOLUME_MENU; - LOCK_FUNCTION (water_handler); - LOCK_VARIABLE (HASARD_INDEX); - LOCK_VARIABLE (HASARD_VALUE); - LOCK_VARIABLE (SAMPLE_WATER); - LOCK_VARIABLE (WATER_VOLUME); - LOCK_VARIABLE (SOUND_VOLUME_VALUES); - -#ifdef DOS - _go32_dpmi_lock_data (HASARD_VALUE, HASARD_SIZE * sizeof (int)); - _go32_dpmi_lock_data (SOUND_VOLUME_VALUES, 17 * sizeof (int)); -#endif + // LOCK macros removed - not needed in Allegro 5 + // DOS-specific dpmi code removed - not needed in modern systems result = install_int_ex (water_handler, MSEC_TO_TIMER (WATER_DELAY)); water_handler (); @@ -150,7 +142,7 @@ stop_water (void) /*------------------------------------------------------------------*/ static void -my_play_sample (SAMPLE * s, int vol) +my_play_sample (ALLEGRO_SAMPLE * s, int vol) { if (vol > 0) play_sample (s, SOUND_VOLUME_VALUES[vol - 1], 128, 1000, 0); diff --git a/src/spread.h b/src/spread.h deleted file mode 100644 index ec8ad260..00000000 --- a/src/spread.h +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : spread.h */ -/* contenu : etalement du gradient accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -#ifndef LIQUID_WAR_INCLUDE_SPREAD -#define LIQUID_WAR_INCLUDE_SPREAD - -/*==================================================================*/ -/* includes */ -/*==================================================================*/ - -#include "mesh.h" -#include "asm.h" - -/*==================================================================*/ -/* types */ -/*==================================================================*/ - -extern void LW_ASM_FUNC boost_gradient_down_2 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_down_3 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_down_4 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_down_5 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_down_6 (MESH * first, - int size, int offset); - -extern void LW_ASM_FUNC boost_gradient_up_2 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_up_3 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_up_4 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_up_5 (MESH * first, - int size, int offset); -extern void LW_ASM_FUNC boost_gradient_up_6 (MESH * first, - int size, int offset); - -#endif diff --git a/src/spread.s b/src/spread.s deleted file mode 100644 index 6b4865e8..00000000 --- a/src/spread.s +++ /dev/null @@ -1,959 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : spread.s */ -/* contenu : etalement du gradient accelere */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - - -/*typedef union */ -/* { */ -/* int time; */ -/* struct */ -/* { */ -/* short x; */ -/* short y; */ -/* } cursor; */ -/* } MESH_UPDATE; */ - -/*typedef struct */ -/* { */ -/* int dir :8; */ -/* int grad:24; */ -/* } MESH_STATE; */ - -/*typedef struct */ -/* { */ -/* MESH_UPDATE update; */ -/* MESH_STATE state; */ -/* } MESH_INFO; */ - -/*typedef struct */ -/* { */ -/* char decal_for_dir :8; */ -/* int size :24; */ -/* } MESH_SIDE; */ - -/*typedef struct */ -/* { */ -/* short x; */ -/* short y; */ -/* MESH_SIDE side; */ -/* MESH_INFO info[NB_TEAMS]; */ -/* void *link[NB_DIRS]; */ -/* } MESH; */ - - -.equ SIZE_OF_MESH,104 - -.equ OFFSET_TO_GRAD_0,12 -.equ OFFSET_TO_GRAD_1,20 -.equ OFFSET_TO_GRAD_2,28 -.equ OFFSET_TO_GRAD_3,36 -.equ OFFSET_TO_GRAD_4,44 -.equ OFFSET_TO_GRAD_5,52 - -.equ SQUARE_SIZE_INC,4 - -.equ ARG_FIRST,8 -.equ ARG_SIZE,12 -.equ ARG_OFFSET,16 - -.text - -/* il y a de maniere tres bourrine 5*2 procedures attachees chacune */ -/* a l'etalement de 2,3,4,5 ou 6 gradients, le code est le meme */ -/* dans chacune d'elle a l'exception d'une constante. */ -/* la moitie des fonctions etale les gradients dans un sens, */ -/* l'autre moitie les etale dans l'autre sens */ - - -/*==================================================================*/ -/* premiere serie de fonctions, etalement des gradients vers le bas */ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -/* void boost_gradient_down_2 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_down_2 -.globl boost_gradient_down_2 - .align 4 -_boost_gradient_down_2: -boost_gradient_down_2: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gd_2: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gd_2_1 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax /* GPF sous win ICI */ - jae skip_gd_2_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gd_2_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gd_2_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gd_2_1: - - addl $SIZE_OF_MESH,%esi - - loopl main_loop_gd_2 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_down_3 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_down_3 -.globl boost_gradient_down_3 - .align 4 -_boost_gradient_down_3: -boost_gradient_down_3: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gd_3: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gd_3_2 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gd_3_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gd_3_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gd_3_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gd_3_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gd_3_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gd_3_2: - - addl $SIZE_OF_MESH,%esi - - loopl main_loop_gd_3 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_down_4 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_down_4 -.globl boost_gradient_down_4 - .align 4 -_boost_gradient_down_4: -boost_gradient_down_4: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gd_4: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gd_4_3 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gd_4_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gd_4_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gd_4_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gd_4_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gd_4_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gd_4_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gd_4_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gd_4_3: - - addl $SIZE_OF_MESH,%esi - - loopl main_loop_gd_4 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_down_5 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_down_5 -.globl boost_gradient_down_5 - .align 4 -_boost_gradient_down_5: -boost_gradient_down_5: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gd_5: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gd_5_4 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gd_5_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gd_5_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gd_5_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gd_5_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gd_5_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gd_5_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gd_5_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gd_5_3: - - movl OFFSET_TO_GRAD_4(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_4(%edi),%eax - jae skip_gd_5_4 - movl %eax,%ds:OFFSET_TO_GRAD_4(%edi) - -skip_gd_5_4: - - addl $SIZE_OF_MESH,%esi - - loopl main_loop_gd_5 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - - -/*------------------------------------------------------------------*/ -/* void boost_gradient_down_6 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_down_6 -.globl boost_gradient_down_6 - .align 4 -_boost_gradient_down_6: -boost_gradient_down_6: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gd_6: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gd_6_5 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gd_6_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gd_6_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gd_6_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gd_6_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gd_6_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gd_6_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gd_6_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gd_6_3: - - movl OFFSET_TO_GRAD_4(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_4(%edi),%eax - jae skip_gd_6_4 - movl %eax,%ds:OFFSET_TO_GRAD_4(%edi) - -skip_gd_6_4: - - movl OFFSET_TO_GRAD_5(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_5(%edi),%eax - jae skip_gd_6_5 - movl %eax,%ds:OFFSET_TO_GRAD_5(%edi) - -skip_gd_6_5: - - addl $SIZE_OF_MESH,%esi - - loopl main_loop_gd_6 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - - -/*==================================================================*/ -/* deuxieme serie de fonctions, etalement des gradients vers le haut*/ -/*==================================================================*/ - -/*------------------------------------------------------------------*/ -/* void boost_gradient_up_2 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_up_2 -.globl boost_gradient_up_2 - .align 4 -_boost_gradient_up_2: -boost_gradient_up_2: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gu_2: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gu_2_1 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gu_2_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gu_2_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gu_2_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gu_2_1: - - subl $SIZE_OF_MESH,%esi - - loopl main_loop_gu_2 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_up_3 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_up_3 -.globl boost_gradient_up_3 - .align 4 -_boost_gradient_up_3: -boost_gradient_up_3: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gu_3: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gu_3_2 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gu_3_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gu_3_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gu_3_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gu_3_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gu_3_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gu_3_2: - - subl $SIZE_OF_MESH,%esi - - loopl main_loop_gu_3 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_up_4 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_up_4 -.globl boost_gradient_up_4 - .align 4 -_boost_gradient_up_4: -boost_gradient_up_4: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gu_4: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gu_4_3 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gu_4_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gu_4_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gu_4_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gu_4_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gu_4_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gu_4_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gu_4_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gu_4_3: - - subl $SIZE_OF_MESH,%esi - - loopl main_loop_gu_4 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - -/*------------------------------------------------------------------*/ -/* void boost_gradient_up_5 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_up_5 -.globl boost_gradient_up_5 - .align 4 -_boost_gradient_up_5: -boost_gradient_up_5: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gu_5: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gu_5_4 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gu_5_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gu_5_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gu_5_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gu_5_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gu_5_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gu_5_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gu_5_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gu_5_3: - - movl OFFSET_TO_GRAD_4(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_4(%edi),%eax - jae skip_gu_5_4 - movl %eax,%ds:OFFSET_TO_GRAD_4(%edi) - -skip_gu_5_4: - - subl $SIZE_OF_MESH,%esi - - loopl main_loop_gu_5 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - - -/*------------------------------------------------------------------*/ -/* void boost_gradient_up_6 (MESH *first, int size, int offset); */ -/*------------------------------------------------------------------*/ - -.globl _boost_gradient_up_6 -.globl boost_gradient_up_6 - .align 4 -_boost_gradient_up_6: -boost_gradient_up_6: - pushl %ebp - movl %esp, %ebp - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushw %es - - movl ARG_FIRST(%ebp),%esi /* esi pointeur sur mesh courant*/ - movl ARG_SIZE(%ebp),%ecx /* ecx prend la taille de la boucle */ - movl ARG_OFFSET(%ebp),%ebx /* ebx prend l'offset de direction */ - -main_loop_gu_6: - - add %ebx,%esi - movl (%esi),%edi - sub %ebx,%esi - - cmp $0,%edi - je skip_gu_6_5 - - movl OFFSET_TO_GRAD_0(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_0(%edi),%eax - jae skip_gu_6_0 - movl %eax,%ds:OFFSET_TO_GRAD_0(%edi) - -skip_gu_6_0: - - movl OFFSET_TO_GRAD_1(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_1(%edi),%eax - jae skip_gu_6_1 - movl %eax,%ds:OFFSET_TO_GRAD_1(%edi) - -skip_gu_6_1: - - movl OFFSET_TO_GRAD_2(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_2(%edi),%eax - jae skip_gu_6_2 - movl %eax,%ds:OFFSET_TO_GRAD_2(%edi) - -skip_gu_6_2: - - movl OFFSET_TO_GRAD_3(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_3(%edi),%eax - jae skip_gu_6_3 - movl %eax,%ds:OFFSET_TO_GRAD_3(%edi) - -skip_gu_6_3: - - movl OFFSET_TO_GRAD_4(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_4(%edi),%eax - jae skip_gu_6_4 - movl %eax,%ds:OFFSET_TO_GRAD_4(%edi) - -skip_gu_6_4: - - movl OFFSET_TO_GRAD_5(%esi),%edx - movl SQUARE_SIZE_INC(%esi),%eax - add %edx,%eax - cmp OFFSET_TO_GRAD_5(%edi),%eax - jae skip_gu_6_5 - movl %eax,%ds:OFFSET_TO_GRAD_5(%edi) - -skip_gu_6_5: - - subl $SIZE_OF_MESH,%esi - - loopl main_loop_gu_6 - - popw %es - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax -/* movl %ebp, %esp*/ - popl %ebp - ret - - - - - - diff --git a/src/srvchan.c b/src/srvchan.c index 9c4a0b1c..6dadc998 100644 --- a/src/srvchan.c +++ b/src/srvchan.c @@ -75,6 +75,7 @@ static char *ACCEPTED_VERSIONS[] = { "5.6.3", "5.6.4", "5.6.5", + "5.6.6", LW_VERSION, NULL }; @@ -357,7 +358,7 @@ handle_team (LW_SRVCHAN * chan, LW_NETMESS * mess, int *free_teams) /* * OK, there are 3 arguments * - arg 1 is the team index - * - arg 2 is the "control_type" parameter + * - arg 2 is the "control_type" parameter * - arg 3 is the team name */ i = atoi (mess->argv[0]); @@ -991,7 +992,7 @@ lw_srvchan_wait_teams (LW_SRVCHAN * chan, int *free_teams, } /* - * lw_netmess_free must *not* be forgetted + * lw_netmess_free must *not* be forgetted */ lw_netmess_free (mess); @@ -1022,7 +1023,7 @@ lw_srvchan_wait_teams (LW_SRVCHAN * chan, int *free_teams, log_print_int (chan->port); log_println_str ("\" accepted"); - /* + /* * We play a little sound for people who have the server * opened on a console and want it to beep when someone * connects @@ -1144,7 +1145,7 @@ lw_srvchan_keepalive (LW_SRVCHAN * chan, } /* - * lw_netmess_free must *not* be forgetted + * lw_netmess_free must *not* be forgetted */ lw_netmess_free (mess); @@ -1200,7 +1201,7 @@ lw_srvchan_keepalive (LW_SRVCHAN * chan, /*------------------------------------------------------------------*/ /* - * Answers OK to a client, and waits for the "WHO" message + * Answers OK to a client, and waits for the "WHO" message */ int lw_srvchan_tell_who (LW_SRVCHAN * chan, void *map, LW_NETCONF * config) @@ -1268,7 +1269,7 @@ lw_srvchan_tell_who (LW_SRVCHAN * chan, void *map, LW_NETCONF * config) } /* - * lw_netmess_free must *not* be forgetted + * lw_netmess_free must *not* be forgetted */ lw_netmess_free (mess); @@ -1400,7 +1401,7 @@ lw_srvchan_close (LW_SRVCHAN * chan) /* * Receives key presses from a computer. * The keys come in the "computer's order" ie one still has to - * sort them by server id. + * sort them by server id. */ int lw_srvchan_recv_keys (LW_SRVCHAN * chan, LW_NETKEY * netkey) @@ -1433,7 +1434,7 @@ lw_srvchan_recv_keys (LW_SRVCHAN * chan, LW_NETKEY * netkey) /* * Sends key presses to a computer. * The keys must be send in the "computer's order" ie they must - * be sorted first. + * be sorted first. */ int lw_srvchan_send_keys (LW_SRVCHAN * chan, LW_NETKEY * netkey) diff --git a/src/srvcont.c b/src/srvcont.c index c8d3847e..95bf6c5f 100644 --- a/src/srvcont.c +++ b/src/srvcont.c @@ -131,7 +131,6 @@ distribute_teams (LW_SRVCONT * cont) int result = 1; int i, j, k; int i_orig, j_orig; - int asm_algorithm; /* * The first step is to attribute a unique number to each @@ -225,20 +224,6 @@ distribute_teams (LW_SRVCONT * cont) } } - /* - * Last step, we check if the "asm_algorithm" parameter should be - * enabled. Indeed, it must be enabled on _all_ computers or on - * none of them... - */ - asm_algorithm = 1; - for (i = 0; i < cont->nb_chans; ++i) - { - asm_algorithm = (cont->chan[i].config.asm_algorithm && asm_algorithm); - } - for (i = 0; i < cont->nb_chans; ++i) - { - cont->chan[i].config.asm_algorithm = asm_algorithm; - } return result; } diff --git a/src/startup.c b/src/startup.c index 8160143c..f920787a 100644 --- a/src/startup.c +++ b/src/startup.c @@ -52,10 +52,10 @@ /* includes */ /*==================================================================*/ -#include #include #include +#include "backport.h" #include "parser.h" #include "startup.h" #include "server.h" @@ -74,7 +74,6 @@ #define IDENT_NOCUSTOM "nocustom" #define IDENT_NOSOUND "silent" #define IDENT_NOSVGA "vga" -#define IDENT_NOASM "c" #define IDENT_NOJOY "nojoy" #define IDENT_STOP "stop" #define IDENT_SAFE "safe" @@ -108,7 +107,6 @@ int STARTUP_WATER_STATE = 1; int STARTUP_SFX_STATE = 1; int STARTUP_MUSIC_STATE = 1; int STARTUP_CUSTOM_STATE = 1; -int STARTUP_ASM = 1; int STARTUP_SVGA = 1; int STARTUP_STOP = 0; int STARTUP_AUTO = 0; @@ -127,10 +125,10 @@ static char *DEFAULT_CFG_PATH = CONFIG_UNIX_CFG; static char *DEFAULT_LOG_PATH = ""; static char *DEFAULT_SRV_PATH = "./liquidwar-server"; static char *DEFAULT_GEN_PATH = "./liquidwar-mapgen"; -static char *DEFAULT_DAT_PATH = "../Resources/data/liquidwar.dat"; -static char *DEFAULT_MAP_PATH = "../Resources/custom/map/"; -static char *DEFAULT_TEX_PATH = "../Resources/custom/texture/"; -static char *DEFAULT_MID_PATH = "../Resources/custom/music/"; +static char *DEFAULT_DAT_PATH = "./data"; +static char *DEFAULT_MAP_PATH = "./custom/map"; +static char *DEFAULT_TEX_PATH = "./custom/texture"; +static char *DEFAULT_MID_PATH = "./custom/music"; #else static char *DEFAULT_CFG_PATH = CONFIG_UNIX_CFG; static char *DEFAULT_LOG_PATH = ""; @@ -238,14 +236,6 @@ set_graphic_possibilities (void) STARTUP_SVGA = 0; } -/*------------------------------------------------------------------*/ -static void -set_c_or_asm (void) -{ - if (exist_argument (IDENT_NOASM)) - STARTUP_ASM = 0; -} - /*------------------------------------------------------------------*/ static void set_stop (void) @@ -455,14 +445,7 @@ set_misc (void) static void set_various_hacks (void) { -#ifndef ASM - /* - * important to set it to 0, even if assembly code is not compiled - * in, for we want the program to be able to tell others that it - * can't do any assembly, in a network game for instance. - */ - STARTUP_ASM = 0; -#endif + /* Assembly support removed */ } /*------------------------------------------------------------------*/ @@ -472,7 +455,6 @@ set_startup (void) set_joystick (); set_load_states (); set_graphic_possibilities (); - set_c_or_asm (); set_path (); set_stop (); set_safe (); diff --git a/src/startup.h b/src/startup.h index d45871d3..6c9f9f4b 100644 --- a/src/startup.h +++ b/src/startup.h @@ -78,7 +78,6 @@ extern int STARTUP_WATER_STATE; extern int STARTUP_SFX_STATE; extern int STARTUP_MUSIC_STATE; extern int STARTUP_CUSTOM_STATE; -extern int STARTUP_ASM; extern int STARTUP_SVGA; extern int STARTUP_STOP; extern int STARTUP_AUTO; diff --git a/src/team.c b/src/team.c index 5fea2e2b..99eee8de 100644 --- a/src/team.c +++ b/src/team.c @@ -283,7 +283,11 @@ update_team_box (DIALOG * d, int number) } else { - d[0].bg = 128 + (CONFIG_TEAM_COLOR[number]) * 10; + // Map team color (0-5) with some brightness offset + int color_idx = CONFIG_TEAM_COLOR[number]; + int team = color_idx / 2; // Map 12 colors to 6 teams + int intensity = (color_idx % 2) ? 200 : 128; // Alternate between mid and bright + d[0].bg = lw_team_color(team, intensity); } } @@ -344,7 +348,11 @@ team_param (DIALOG * d, int x, int y, int number) d[i].x = x + (i - 2) * w1; d[i].y = y + 2 * h; d[i].w = w1 - 2; - d[i].bg = 128 + (i - 2) * 10; + // Create 12 color buttons (2 shades × 6 teams) + int color_idx = i - 2; + int team = color_idx / 2; // Map 12 colors to 6 teams + int intensity = (color_idx % 2) ? 200 : 128; // Alternate between mid and bright + d[i].bg = lw_team_color(team, intensity); } for (i = 16; i < 20; ++i) @@ -413,8 +421,8 @@ choose_teams (void) d[124].proc = NULL; - set_palette_for_choose_color (); - my_set_palette (); + // set_palette_for_choose_color (); // No longer needed in true color mode + // my_set_palette (); // No longer needed in true color mode display_back_image (); while (retour == 0) diff --git a/src/test_backport_pixel.c b/src/test_backport_pixel.c new file mode 100644 index 00000000..bfc56d1e --- /dev/null +++ b/src/test_backport_pixel.c @@ -0,0 +1,226 @@ +/********************************************************************/ +/* */ +/* L I QQ U U I DD W W A RR 555 */ +/* L I Q Q U U I D D W W A A R R 5 */ +/* L I Q Q U U I D D W W W AAA RR 55 */ +/* L I Q Q U U I D D WW WW A A R R 5 */ +/* LLL I Q Q U I DD W W A A R R 55 */ +/* */ +/* b */ +/* bb y y */ +/* b b yyy */ +/* bb y */ +/* yy */ +/* */ +/* U U FFF O O TTT */ +/* U U F O O O O T */ +/* U U TIRET FF O O O O T */ +/* U U F O O O O T */ +/* U F O O T */ +/* */ +/********************************************************************/ + +/*****************************************************************************/ +/* Liquid War is a multiplayer wargame */ +/* Copyright (C) 1998-2025 Christian Mauduit */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You 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 */ +/* */ +/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ +/* Contact author : ufoot@ufoot.org */ +/*****************************************************************************/ + +/********************************************************************/ +/* name : test_backport_pixel.c */ +/* content : unit tests for putpixel/getpixel functions */ +/********************************************************************/ + +/*==================================================================*/ +/* includes */ +/*==================================================================*/ + +#include +#include +#include + +#include "test_simple.h" +#include "backport.h" + +/*==================================================================*/ +/* functions */ +/*==================================================================*/ + +/*------------------------------------------------------------------*/ +static void +init_test_environment() +{ + // Initialize Allegro + if (!al_init()) { + fprintf(stderr, "Failed to initialize Allegro\n"); + exit(1); + } + + // Initialize a basic palette for testing + // This is a simplified palette initialization + for (int i = 0; i < PALETTE_SIZE; i++) { + unsigned char r = ((i >> 5) & 0x07) * 255 / 7; // 3 bits red + unsigned char g = ((i >> 2) & 0x07) * 255 / 7; // 3 bits green + unsigned char b = (i & 0x03) * 255 / 3; // 2 bits blue + GLOBAL_PALETTE[i].r = r; + GLOBAL_PALETTE[i].g = g; + GLOBAL_PALETTE[i].b = b; + } +} + +/*------------------------------------------------------------------*/ +static void +test_putpixel_getpixel_basic() +{ + // Create a test bitmap + ALLEGRO_BITMAP *test_bitmap = al_create_bitmap(100, 100); + TEST_ASSERT(test_bitmap != NULL, "Test bitmap created"); + + // Test basic putpixel/getpixel round-trip + int test_color = 42; + putpixel(test_bitmap, 50, 50, test_color); + int retrieved_color = getpixel(test_bitmap, 50, 50); + + TEST_ASSERT_EQ(test_color, retrieved_color, "Basic putpixel/getpixel round-trip"); + + al_destroy_bitmap(test_bitmap); +} + +/*------------------------------------------------------------------*/ +static void +test_putpixel_getpixel_multiple_colors() +{ + ALLEGRO_BITMAP *test_bitmap = al_create_bitmap(100, 100); + TEST_ASSERT(test_bitmap != NULL, "Test bitmap created for multiple colors"); + + // Test multiple colors + int test_colors[] = {0, 1, 15, 63, 127, 255}; + int num_colors = sizeof(test_colors) / sizeof(test_colors[0]); + + for (int i = 0; i < num_colors; i++) { + int x = 10 + i * 10; + int y = 10; + int color = test_colors[i]; + + putpixel(test_bitmap, x, y, color); + int retrieved = getpixel(test_bitmap, x, y); + + char msg[100]; + snprintf(msg, sizeof(msg), "Color %d round-trip at (%d,%d)", color, x, y); + TEST_ASSERT_EQ(color, retrieved, msg); + } + + al_destroy_bitmap(test_bitmap); +} + +/*------------------------------------------------------------------*/ +static void +test_putpixel_getpixel_edge_cases() +{ + ALLEGRO_BITMAP *test_bitmap = al_create_bitmap(100, 100); + TEST_ASSERT(test_bitmap != NULL, "Test bitmap created for edge cases"); + + // Test corners and edges + int positions[][2] = {{0, 0}, {99, 0}, {0, 99}, {99, 99}, {50, 0}, {50, 99}}; + int num_positions = sizeof(positions) / sizeof(positions[0]); + + for (int i = 0; i < num_positions; i++) { + int x = positions[i][0]; + int y = positions[i][1]; + int color = 64 + i; // Different color for each position + + putpixel(test_bitmap, x, y, color); + int retrieved = getpixel(test_bitmap, x, y); + + char msg[100]; + snprintf(msg, sizeof(msg), "Edge case color %d at (%d,%d)", color, x, y); + TEST_ASSERT_EQ(color, retrieved, msg); + } + + al_destroy_bitmap(test_bitmap); +} + +/*------------------------------------------------------------------*/ +static void +test_putpixel_getpixel_pattern() +{ + ALLEGRO_BITMAP *test_bitmap = al_create_bitmap(50, 50); + TEST_ASSERT(test_bitmap != NULL, "Test bitmap created for pattern"); + + // Create a checkerboard pattern + for (int y = 0; y < 50; y++) { + for (int x = 0; x < 50; x++) { + int color = ((x + y) % 2) ? 100 : 150; + putpixel(test_bitmap, x, y, color); + } + } + + // Verify the pattern + int correct_pixels = 0; + for (int y = 0; y < 50; y++) { + for (int x = 0; x < 50; x++) { + int expected = ((x + y) % 2) ? 100 : 150; + int actual = getpixel(test_bitmap, x, y); + if (expected == actual) { + correct_pixels++; + } + } + } + + TEST_ASSERT_EQ(2500, correct_pixels, "Checkerboard pattern verification (50x50 = 2500 pixels)"); + + al_destroy_bitmap(test_bitmap); +} + +/*------------------------------------------------------------------*/ +static void +test_palette_boundary_values() +{ + ALLEGRO_BITMAP *test_bitmap = al_create_bitmap(10, 10); + TEST_ASSERT(test_bitmap != NULL, "Test bitmap created for boundary values"); + + // Test first and last valid palette indices + putpixel(test_bitmap, 0, 0, 0); // First palette color + int first_color = getpixel(test_bitmap, 0, 0); + TEST_ASSERT_EQ(0, first_color, "First palette color (0)"); + + putpixel(test_bitmap, 1, 1, PALETTE_SIZE - 1); // Last palette color + int last_color = getpixel(test_bitmap, 1, 1); + TEST_ASSERT_EQ(PALETTE_SIZE - 1, last_color, "Last palette color"); + + al_destroy_bitmap(test_bitmap); +} + +/*------------------------------------------------------------------*/ +int +main() +{ + TEST_START(); + + init_test_environment(); + + printf("\n=== Testing putpixel/getpixel functions ===\n"); + test_putpixel_getpixel_basic(); + test_putpixel_getpixel_multiple_colors(); + test_putpixel_getpixel_edge_cases(); + test_putpixel_getpixel_pattern(); + test_palette_boundary_values(); + + TEST_END(); +} \ No newline at end of file diff --git a/src/test_path.c b/src/test_path.c new file mode 100644 index 00000000..75a57cd3 --- /dev/null +++ b/src/test_path.c @@ -0,0 +1,288 @@ +/********************************************************************/ +/* */ +/* L I QQ U U I DD W W A RR 555 */ +/* L I Q Q U U I D D W W A A R R 5 */ +/* L I Q Q U U I D D W W W AAA RR 55 */ +/* L I Q Q U U I D D WW WW A A R R 5 */ +/* LLL I Q Q U I DD W W A A R R 55 */ +/* */ +/* b */ +/* bb y y */ +/* b b yyy */ +/* bb y */ +/* yy */ +/* */ +/* U U FFF O O TTT */ +/* U U F O O O O T */ +/* U U TIRET FF O O O O T */ +/* U U F O O O O T */ +/* U F O O T */ +/* */ +/********************************************************************/ + +/*****************************************************************************/ +/* Liquid War is a multiplayer wargame */ +/* Copyright (C) 1998-2025 Christian Mauduit */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You 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 */ +/* */ +/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ +/* Contact author : ufoot@ufoot.org */ +/*****************************************************************************/ + +/********************************************************************/ +/* name : test_path.c */ +/* content : unit tests for path manipulation functions */ +/********************************************************************/ + +/*==================================================================*/ +/* includes */ +/*==================================================================*/ + +#include +#include +#include + +#include "test_simple.h" +#include "path.h" + +/*==================================================================*/ +/* functions */ +/*==================================================================*/ + +/*------------------------------------------------------------------*/ +static void +test_lw_path_get_system_name_basic() +{ + char *result; + + result = lw_path_get_system_name("myfile.txt"); + TEST_ASSERT(strcmp(result, "myfile") == 0, "Basic filename without path"); + + result = lw_path_get_system_name("file"); + TEST_ASSERT(strcmp(result, "file") == 0, "Filename without extension"); + + result = lw_path_get_system_name("test.map.txt"); + TEST_ASSERT(strcmp(result, "test") == 0, "Filename with multiple dots"); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_get_system_name_with_paths() +{ + char *result; + + result = lw_path_get_system_name("/home/user/test.txt"); + TEST_ASSERT(strcmp(result, "test") == 0, "Unix path with extension"); + + result = lw_path_get_system_name("C:\\Users\\test\\file.map"); + TEST_ASSERT(strcmp(result, "file") == 0, "Windows path with extension"); + + result = lw_path_get_system_name("/very/long/path/to/myfile.pcx"); + TEST_ASSERT(strcmp(result, "myfile") == 0, "Long Unix path"); + + result = lw_path_get_system_name("relative/path/file.bmp"); + TEST_ASSERT(strcmp(result, "file") == 0, "Relative path"); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_get_system_name_edge_cases() +{ + char *result; + + result = lw_path_get_system_name("/path/to/"); + TEST_ASSERT(strcmp(result, "") == 0, "Path ending with separator"); + + result = lw_path_get_system_name("."); + TEST_ASSERT(strcmp(result, "") == 0, "Single dot"); + + result = lw_path_get_system_name(".hidden"); + TEST_ASSERT(strcmp(result, "") == 0, "Hidden file starting with dot"); + + result = lw_path_get_system_name("/path/.hidden.txt"); + TEST_ASSERT(strcmp(result, "") == 0, "Hidden file with extension"); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_join2_basic() +{ + char *result; + + result = lw_path_join2("home", "user"); + TEST_ASSERT(result != NULL, "join2 returns non-null"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "home/user") == 0, "Basic join2 Unix"); +#else + TEST_ASSERT(strcmp(result, "home\\user") == 0, "Basic join2 Windows"); +#endif + free(result); + + result = lw_path_join2("", "file.txt"); + TEST_ASSERT(result != NULL, "join2 with empty first part"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "/file.txt") == 0, "join2 empty first part Unix"); +#else + TEST_ASSERT(strcmp(result, "\\file.txt") == 0, "join2 empty first part Windows"); +#endif + free(result); + + result = lw_path_join2("dir", ""); + TEST_ASSERT(result != NULL, "join2 with empty second part"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "dir/") == 0, "join2 empty second part Unix"); +#else + TEST_ASSERT(strcmp(result, "dir\\") == 0, "join2 empty second part Windows"); +#endif + free(result); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_join2_various_inputs() +{ + char *result; + + result = lw_path_join2("/usr/local", "bin"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "/usr/local/bin") == 0, "Absolute path join2"); +#else + TEST_ASSERT(strcmp(result, "/usr/local\\bin") == 0, "Absolute path join2 Windows"); +#endif + free(result); + + result = lw_path_join2("data", "maps"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "data/maps") == 0, "Relative path join2"); +#else + TEST_ASSERT(strcmp(result, "data\\maps") == 0, "Relative path join2 Windows"); +#endif + free(result); + + result = lw_path_join2("very_long_directory_name", "very_long_filename.extension"); + TEST_ASSERT(result != NULL, "join2 with long names"); + TEST_ASSERT(strlen(result) > 30, "join2 result has expected length"); + free(result); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_join3_basic() +{ + char *result; + + result = lw_path_join3("home", "user", "documents"); + TEST_ASSERT(result != NULL, "join3 returns non-null"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "home/user/documents") == 0, "Basic join3 Unix"); +#else + TEST_ASSERT(strcmp(result, "home\\user\\documents") == 0, "Basic join3 Windows"); +#endif + free(result); + + result = lw_path_join3("", "middle", "end"); + TEST_ASSERT(result != NULL, "join3 with empty first part"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "/middle/end") == 0, "join3 empty first Unix"); +#else + TEST_ASSERT(strcmp(result, "\\middle\\end") == 0, "join3 empty first Windows"); +#endif + free(result); + + result = lw_path_join3("start", "", "end"); + TEST_ASSERT(result != NULL, "join3 with empty middle part"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "start//end") == 0, "join3 empty middle Unix"); +#else + TEST_ASSERT(strcmp(result, "start\\\\end") == 0, "join3 empty middle Windows"); +#endif + free(result); +} + +/*------------------------------------------------------------------*/ +static void +test_lw_path_join3_various_inputs() +{ + char *result; + + result = lw_path_join3("/usr", "local", "share"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "/usr/local/share") == 0, "Absolute path join3"); +#else + TEST_ASSERT(strcmp(result, "/usr\\local\\share") == 0, "Absolute path join3 Windows"); +#endif + free(result); + + result = lw_path_join3("data", "maps", "level1.map"); +#ifdef UNIX + TEST_ASSERT(strcmp(result, "data/maps/level1.map") == 0, "File path join3"); +#else + TEST_ASSERT(strcmp(result, "data\\maps\\level1.map") == 0, "File path join3 Windows"); +#endif + free(result); + + result = lw_path_join3("a", "b", "c"); + TEST_ASSERT(result != NULL, "join3 with single chars"); + TEST_ASSERT(strlen(result) == 5, "join3 single chars correct length"); + free(result); +} + +/*------------------------------------------------------------------*/ +static void +test_memory_management() +{ + char *result1, *result2, *result3; + + result1 = lw_path_join2("test", "path"); + result2 = lw_path_join2("another", "test"); + result3 = lw_path_join3("three", "part", "path"); + + TEST_ASSERT(result1 != NULL && result2 != NULL && result3 != NULL, "Multiple allocations successful"); + TEST_ASSERT(result1 != result2 && result2 != result3 && result1 != result3, "Different memory addresses"); + + free(result1); + free(result2); + free(result3); + + result1 = lw_path_join2("after", "free"); + TEST_ASSERT(result1 != NULL, "Allocation after free works"); + free(result1); +} + +/*------------------------------------------------------------------*/ +int +main() +{ + TEST_START(); + + printf("\n=== Testing lw_path_get_system_name ===\n"); + test_lw_path_get_system_name_basic(); + test_lw_path_get_system_name_with_paths(); + test_lw_path_get_system_name_edge_cases(); + + printf("\n=== Testing lw_path_join2 ===\n"); + test_lw_path_join2_basic(); + test_lw_path_join2_various_inputs(); + + printf("\n=== Testing lw_path_join3 ===\n"); + test_lw_path_join3_basic(); + test_lw_path_join3_various_inputs(); + + printf("\n=== Testing Memory Management ===\n"); + test_memory_management(); + + TEST_END(); +} diff --git a/src/thrddos.c b/src/test_simple.h similarity index 63% rename from src/thrddos.c rename to src/test_simple.h index 9cb4c9f0..91146e2c 100644 --- a/src/thrddos.c +++ b/src/test_simple.h @@ -43,44 +43,84 @@ /*****************************************************************************/ /********************************************************************/ -/* name : thrddos.c */ -/* content : provides fake thread support under DOS */ +/* name : test_simple.h */ +/* content : simple unit testing framework */ /********************************************************************/ +#ifndef LIQUID_WAR_INCLUDE_TEST_SIMPLE +#define LIQUID_WAR_INCLUDE_TEST_SIMPLE + /*==================================================================*/ /* includes */ /*==================================================================*/ -#include "thrdgen.h" - -/*==================================================================*/ -/* defines */ -/*==================================================================*/ +#include +#include /*==================================================================*/ /* macros */ /*==================================================================*/ -/*==================================================================*/ -/* globals */ -/*==================================================================*/ +static int _test_count = 0; +static int _test_passed = 0; +static int _test_failed = 0; -/*==================================================================*/ -/* fonctions */ -/*==================================================================*/ +#define TEST_START() \ + do { \ + printf("Starting tests...\n"); \ + _test_count = 0; \ + _test_passed = 0; \ + _test_failed = 0; \ + } while(0) + +#define TEST_ASSERT(condition, message) \ + do { \ + _test_count++; \ + if (condition) { \ + printf("PASS: %s\n", message); \ + _test_passed++; \ + } else { \ + printf("FAIL: %s\n", message); \ + _test_failed++; \ + } \ + } while(0) + +#define TEST_ASSERT_EQ(expected, actual, message) \ + do { \ + _test_count++; \ + if ((expected) == (actual)) { \ + printf("PASS: %s (expected=%d, actual=%d)\n", message, (int)(expected), (int)(actual)); \ + _test_passed++; \ + } else { \ + printf("FAIL: %s (expected=%d, actual=%d)\n", message, (int)(expected), (int)(actual)); \ + _test_failed++; \ + } \ + } while(0) -/*------------------------------------------------------------------*/ -/* - * Starts a new thread using the given callback - */ -int -lw_thread_start (void (*func) (void *), void *args) -{ - int result = 0; +#define TEST_ASSERT_NE(not_expected, actual, message) \ + do { \ + _test_count++; \ + if ((not_expected) != (actual)) { \ + printf("PASS: %s (not_expected=%d, actual=%d)\n", message, (int)(not_expected), (int)(actual)); \ + _test_passed++; \ + } else { \ + printf("FAIL: %s (not_expected=%d, actual=%d)\n", message, (int)(not_expected), (int)(actual)); \ + _test_failed++; \ + } \ + } while(0) - /* - * There's no thread support under DOS 8-/ - */ +#define TEST_END() \ + do { \ + printf("\n=== Test Summary ===\n"); \ + printf("Total tests: %d\n", _test_count); \ + printf("Passed: %d\n", _test_passed); \ + printf("Failed: %d\n", _test_failed); \ + if (_test_failed == 0) { \ + printf("ALL TESTS PASSED!\n"); \ + } else { \ + printf("SOME TESTS FAILED!\n"); \ + } \ + return (_test_failed == 0) ? 0 : 1; \ + } while(0) - return result; -} +#endif \ No newline at end of file diff --git a/src/texture.c b/src/texture.c index 69647821..8e66833c 100644 --- a/src/texture.c +++ b/src/texture.c @@ -53,11 +53,10 @@ /*==================================================================*/ #include "base.h" -#include "alleg2.h" +#include "backport.h" #include "bigdata.h" #include "texture.h" #include "disk.h" -#include "palette.h" #include "startup.h" #include "log.h" #include "serial.h" @@ -79,280 +78,29 @@ /* gestion des bitmaps des textures */ /*------------------------------------------------------------------*/ -/*-----------------------------------------------------------------*/ -static int -find_color (PALETTE pal, RGB rgb) -{ - int i, found = -1; - - for (i = 0; i < 256 && found < 0; ++i) - if (pal[i].r == rgb.r && pal[i].g == rgb.g && pal[i].b == rgb.b) - found = i; - - return found; -} - -/*-----------------------------------------------------------------*/ -static int -exist_color (PALETTE pal, RGB rgb) -{ - return (find_color (pal, rgb) >= 0); -} - -/*-----------------------------------------------------------------*/ -static int -recalculate_number_of_colors (int max_number, BITMAP * bmp, PALETTE pal) -{ - int i, x, y, n = 1; - RGB color; - PALETTE pal2; - - color = pal[getpixel (bmp, 0, 0)]; - - for (i = 0; i < 256; ++i) - pal2[i] = color; - - for (y = 0; y < bmp->h && n < max_number; ++y) - for (x = 0; x < bmp->w && n < max_number; ++x) - { - color = pal[getpixel (bmp, x, y)]; - if (!exist_color (pal2, color)) - pal2[n++] = color; - } - return n; -} - -/*-----------------------------------------------------------------*/ -static void -create_new_palette (PALETTE dst, - PALETTE src, - BITMAP * bmp, int first_color, int number_of_colors) -{ - int i, x, y, index; - int nb_retries = 0; - RGB color; - - x = random () % bmp->w; - y = random () % bmp->h; - color = src[getpixel (bmp, x, y)]; - - for (i = 0; i < 256; ++i) - dst[i] = color; - - for (i = 1; i < number_of_colors;) - { - x = random () % bmp->w; - y = random () % bmp->h; - index = getpixel (bmp, x, y); - color = src[index]; - if ((!exist_color (dst, color)) || - (nb_retries > LW_TEXTURE_RANDOM_MAX_RETRIES)) - { - dst[first_color + (i++)] = color; - nb_retries = 0; - } - else - { - nb_retries++; - } - } -} - -/*-----------------------------------------------------------------*/ -static void -correct_palette (PALETTE pal, int first_color, int number_of_colors) -{ - int i; - - for (i = 0; i < first_color; ++i) - { - pal[i].r = 0; - pal[i].g = 0; - pal[i].b = 0; - } - for (i = first_color + number_of_colors; i < 256; ++i) - { - pal[i].r = 63; - pal[i].g = 63; - pal[i].b = 63; - } -} - -/*-----------------------------------------------------------------*/ -static void -create_converted_bitmap (BITMAP * bmp, - PALETTE dst, - PALETTE src, int first_color, int number_of_colors) -{ - char corres[256]; - int i, x, y, index; - - for (i = 0; i < 256; ++i) - corres[i] = bestfit_color (dst, src[i].r, src[i].g, src[i].b); - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - { - index = corres[getpixel (bmp, x, y)]; - index = (index < first_color || - index >= first_color + number_of_colors) ? - first_color : index; - putpixel (bmp, x, y, index); - } -} - -/*------------------------------------------------------------------*/ -static void -red8col (BITMAP * bmp, PALETTE pal, int first_color, int number_of_colors) -{ - PALETTE pal2; - int i; - - for (i = 0; i < 256; ++i) - pal2[i] = pal[i]; - - number_of_colors = recalculate_number_of_colors - (number_of_colors, bmp, pal); - create_new_palette (pal, pal2, bmp, first_color, number_of_colors); - create_converted_bitmap (bmp, pal, pal2, first_color, number_of_colors); - correct_palette (pal, first_color, number_of_colors); -} - -/*------------------------------------------------------------------*/ -static void -texture_8to5 (BITMAP * bmp, PALETTE pal, void *result, - int first_color, int number_of_colors, char *filename) -{ - char *buffer; - int pos = 0, pos8 = 0, x, y, i; - char octet[5], toadd; - int coul; - char system_name_buffer[LW_TEXTURE_SYSTEM_NAME_SIZE + 1]; - - lw_serial_set_texture_header (result, (short) bmp->w, (short) bmp->h); - - buffer = ((char *) result) + 2 * sizeof (short); - - /* - * We store the system name - */ - memset (system_name_buffer, 0, sizeof (system_name_buffer)); - LW_MACRO_STRCPY (system_name_buffer, lw_path_get_system_name (filename)); - memcpy (buffer, system_name_buffer, LW_TEXTURE_SYSTEM_NAME_SIZE); - buffer += LW_TEXTURE_SYSTEM_NAME_SIZE; - - for (i = 0; i < number_of_colors; ++i) - { - buffer[pos++] = pal[first_color + i].r; - buffer[pos++] = pal[first_color + i].g; - buffer[pos++] = pal[first_color + i].b; - } - - for (i = 0; i < 5; ++i) - octet[i] = 0; - - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - { - coul = getpixel (bmp, x, y) - first_color; - toadd = 1 << pos8; - octet[0] |= (coul & 1) ? toadd : 0; - octet[1] |= (coul & 2) ? toadd : 0; - octet[2] |= (coul & 4) ? toadd : 0; - octet[3] |= (coul & 8) ? toadd : 0; - octet[4] |= (coul & 16) ? toadd : 0; - - if (pos8 == 7 || (y == bmp->h - 1 && x == bmp->w - 1)) - { - for (i = 0; i < 5; ++i) - { - buffer[pos++] = octet[i]; - octet[i] = 0; - } - pos8 = 0; - } - else - pos8++; - } -} +/* Palette-based texture functions removed - not needed for Allegro 5 RGB mode */ /*------------------------------------------------------------------*/ void * lw_texture_archive_raw (const char *filename) { - int i, w, h, size = 0; - BITMAP *bmp; - PALETTE pal; - char *result = NULL, *temp = NULL; - char *f = (char *) filename; + /* Simplified for Allegro 5 - just store the bitmap pointer directly + * No palette quantization or 5-bit packing needed with RGB bitmaps */ + ALLEGRO_BITMAP *bmp; - bmp = load_bitmap (filename, pal); - if (bmp) - { - w = bmp->w; - h = bmp->h; - if (w > 0 && h > 0) - { - temp = malloc (size = - 2 * sizeof (short) - + LW_TEXTURE_SYSTEM_NAME_SIZE - + 3 * TEXTURE_COLOR_NUMBER + ((w * h + 7) / 8) * 5); - if (temp) - { - red8col (bmp, pal, 0, TEXTURE_COLOR_NUMBER); - texture_8to5 (bmp, pal, temp, 0, TEXTURE_COLOR_NUMBER, f); - } - } - destroy_bitmap (bmp); - } - if (temp) - { - result = malloc (size); - if (result) - { - for (i = 0; i < size; ++i) - { - result[i] = temp[i]; - } - } - free (temp); - } + bmp = al_load_bitmap_flags(filename, ALLEGRO_MEMORY_BITMAP); - return result; + /* Return the bitmap as-is - callers will use it as an ALLEGRO_BITMAP* */ + return (void *)bmp; } /*------------------------------------------------------------------*/ -static BITMAP * -create_raw_texture (void *ptr, int first) +static ALLEGRO_BITMAP * +create_raw_texture (void *ptr) { - int x, y, pos8 = 0, color; - char totest, *data; - BITMAP *result; - short w, h; - - data = ptr; - lw_serial_get_texture_header (data, &w, &h); - data += 2 * sizeof (short) + LW_TEXTURE_SYSTEM_NAME_SIZE + 3 * 32; - - result = my_create_bitmap (w, h); - if (result) - for (y = 0; y < h; ++y) - for (x = 0; x < w; ++x) - { - totest = 1 << pos8; - color = first + ((data[0] & totest) ? 1 : 0) - + ((data[1] & totest) ? 2 : 0) - + ((data[2] & totest) ? 4 : 0) - + ((data[3] & totest) ? 8 : 0) + ((data[4] & totest) ? 16 : 0); - putpixel (result, x, y, color); - if (pos8 == 7) - { - data += 5; - pos8 = 0; - } - else - pos8++; - } - return result; + /* Simplified for Allegro 5 - ptr is already an ALLEGRO_BITMAP* + * Just return it directly */ + return (ALLEGRO_BITMAP *)ptr; } /*------------------------------------------------------------------*/ @@ -381,49 +129,51 @@ get_raw_texture (int num) } /*------------------------------------------------------------------*/ -static BITMAP * -create_mono_texture (int first) +static ALLEGRO_BITMAP * +create_mono_texture (ALLEGRO_COLOR color) { - BITMAP *result; + ALLEGRO_BITMAP *result; - result = my_create_bitmap (1, 1); - putpixel (result, 0, 0, first); + result = my_create_memory_bitmap (1, 1); + putpixel (result, 0, 0, color); return result; } /*------------------------------------------------------------------*/ -static BITMAP * -create_texture (int num, int first) +static ALLEGRO_BITMAP * +create_texture (int num, ALLEGRO_COLOR default_color) { - BITMAP *result; + ALLEGRO_BITMAP *result; void *texture; texture = get_raw_texture (num); if (texture) { - result = create_raw_texture (texture, first); + result = create_raw_texture (texture); } else { - result = create_mono_texture (first); + result = create_mono_texture (default_color); } return result; } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_texture_create_bg (int num) { - return create_texture (num, BG_TEXTURE_FIRST_COLOR); + // In true color mode, use a default gray for background textures + return create_texture (num, al_map_rgb(64, 64, 64)); } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * lw_texture_create_fg (int num) { - return create_texture (num, FG_TEXTURE_FIRST_COLOR); + // In true color mode, use a default white for foreground textures + return create_texture (num, al_map_rgb(192, 192, 192)); } /*------------------------------------------------------------------*/ diff --git a/src/texture.h b/src/texture.h index 7de574c5..3ec0df02 100644 --- a/src/texture.h +++ b/src/texture.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include #include "texture.h" /*==================================================================*/ @@ -69,8 +69,8 @@ /*==================================================================*/ void *lw_texture_archive_raw (const char *filename); -BITMAP *lw_texture_create_bg (int num); -BITMAP *lw_texture_create_fg (int num); +ALLEGRO_BITMAP *lw_texture_create_bg (int num); +ALLEGRO_BITMAP *lw_texture_create_fg (int num); char *lw_texture_get_system_name (int num); #endif diff --git a/src/thrdgen.h b/src/thrdgen.h index 21df2f46..49217bd4 100644 --- a/src/thrdgen.h +++ b/src/thrdgen.h @@ -50,6 +50,22 @@ #ifndef LIQUID_WAR_INCLUDE_THRDGEN #define LIQUID_WAR_INCLUDE_THRDGEN +/*==================================================================*/ +/* types */ +/*==================================================================*/ + +typedef struct +{ + void *data; +} +LW_THREAD_HANDLE, *LW_THREAD_HANDLE_PTR; + +/*==================================================================*/ +/* functions */ +/*==================================================================*/ + int lw_thread_start (void (*func) (void *), void *args); +int lw_thread_create (LW_THREAD_HANDLE * handle, void (*func) (void *), void *args); +int lw_thread_join (LW_THREAD_HANDLE * handle); #endif diff --git a/src/thrdunix.c b/src/thrdunix.c index 13db080a..fb197bfc 100644 --- a/src/thrdunix.c +++ b/src/thrdunix.c @@ -53,6 +53,7 @@ #include #include +#include #include "thrdgen.h" @@ -74,62 +75,137 @@ /*------------------------------------------------------------------*/ /* - * Wrapper structure to pass function and args together + * Internal structure to pass both function and args to pthread wrapper */ -typedef struct -{ - void (*func) (void *); +typedef struct { + void (*func)(void *); void *args; } lw_thread_wrapper_data; +/*------------------------------------------------------------------*/ /* - * Wrapper function to adapt void-returning functions to pthread's signature + * Wrapper function that matches pthread signature and calls the original function */ static void * -lw_thread_wrapper (void *arg) +lw_thread_wrapper (void *data) { - lw_thread_wrapper_data *data = (lw_thread_wrapper_data *) arg; - void (*func) (void *) = data->func; - void *args = data->args; + lw_thread_wrapper_data *wrapper_data = (lw_thread_wrapper_data *) data; + + // Call the original function + wrapper_data->func (wrapper_data->args); + + // Clean up the wrapper data + free (wrapper_data); - free (data); - func (args); return NULL; } +/*------------------------------------------------------------------*/ +/* + * Creates a joinable thread and returns a handle + */ +int +lw_thread_create (LW_THREAD_HANDLE * handle, void (*func) (void *), void *args) +{ + pthread_t *thread; + int result = 0; + lw_thread_wrapper_data *wrapper_data; + + // Allocate thread handle + thread = malloc (sizeof (pthread_t)); + if (thread == NULL) + { + return 0; + } + + // Allocate wrapper data structure + wrapper_data = malloc (sizeof (lw_thread_wrapper_data)); + if (wrapper_data == NULL) + { + free (thread); + return 0; + } + + wrapper_data->func = func; + wrapper_data->args = args; + + // Create joinable thread (default behavior when attr is NULL) + if (pthread_create (thread, NULL, lw_thread_wrapper, wrapper_data) == 0) + { + handle->data = thread; + result = 1; + } + else + { + // Thread creation failed, clean up + free (wrapper_data); + free (thread); + } + + return result; +} + +/*------------------------------------------------------------------*/ +/* + * Waits for a thread to complete + */ +int +lw_thread_join (LW_THREAD_HANDLE * handle) +{ + pthread_t *thread; + int result = 0; + + if (handle && handle->data) + { + thread = (pthread_t *) handle->data; + if (pthread_join (*thread, NULL) == 0) + { + result = 1; + } + free (thread); + handle->data = NULL; + } + + return result; +} + +/*------------------------------------------------------------------*/ /* - * Starts a new thread using the given callback + * Starts a new thread using the given callback (detached) */ int lw_thread_start (void (*func) (void *), void *args) { pthread_t thread; int result = 0; - lw_thread_wrapper_data *data; + lw_thread_wrapper_data *wrapper_data; - data = (lw_thread_wrapper_data *) malloc (sizeof (lw_thread_wrapper_data)); - if (data != NULL) + // Allocate wrapper data structure + wrapper_data = malloc (sizeof (lw_thread_wrapper_data)); + if (wrapper_data == NULL) { - data->func = func; - data->args = args; + return 0; + } + + wrapper_data->func = func; + wrapper_data->args = args; - if (pthread_create (&thread, NULL, lw_thread_wrapper, data) == 0) + if (pthread_create (&thread, NULL, lw_thread_wrapper, wrapper_data) == 0) + { + if (pthread_detach (thread) == 0) { - if (pthread_detach (thread) == 0) - { - result = 1; - } - else - { - /* Detach failed, but thread is running - data will be freed by wrapper */ - } + result = 1; } else { - /* Thread creation failed, free the wrapper data */ - free (data); + /* Detach failed, but thread is running - data will be freed by wrapper */ } } + else + { + // Thread creation failed, clean up wrapper data + free (wrapper_data); + } return result; } diff --git a/src/thrdw32.c b/src/thrdw32.c index 303ef6b3..80efc86b 100644 --- a/src/thrdw32.c +++ b/src/thrdw32.c @@ -53,6 +53,7 @@ #ifdef WIN32 #include +#include #endif #include "thrdgen.h" @@ -75,7 +76,62 @@ /*------------------------------------------------------------------*/ /* - * Starts a new thread using the given callback + * Creates a joinable thread and returns a handle + */ +int +lw_thread_create (LW_THREAD_HANDLE * handle, void (*func) (void *), void *args) +{ +#ifdef WIN32 + uintptr_t thread_handle; + int result = 0; + + // Use _beginthreadex which returns a handle we can wait on + // Unlike _beginthread, this doesn't auto-close the handle + thread_handle = _beginthreadex (NULL, 0, (unsigned (__stdcall *)(void *))func, args, 0, NULL); + + if (thread_handle != 0) + { + handle->data = (void *)thread_handle; + result = 1; + } + + return result; +#else + // Not on Windows, shouldn't happen but return failure + return 0; +#endif +} + +/*------------------------------------------------------------------*/ +/* + * Waits for a thread to complete + */ +int +lw_thread_join (LW_THREAD_HANDLE * handle) +{ +#ifdef WIN32 + int result = 0; + + if (handle && handle->data) + { + // Wait for thread to complete + WaitForSingleObject ((HANDLE)handle->data, INFINITE); + // Close the thread handle + CloseHandle ((HANDLE)handle->data); + handle->data = NULL; + result = 1; + } + + return result; +#else + // Not on Windows, shouldn't happen but return failure + return 0; +#endif +} + +/*------------------------------------------------------------------*/ +/* + * Starts a new thread using the given callback (detached) */ int lw_thread_start (void (*func) (void *), void *args) diff --git a/src/ticker.c b/src/ticker.c index 79422d6a..9b95f226 100644 --- a/src/ticker.c +++ b/src/ticker.c @@ -52,20 +52,14 @@ /* includes */ /*==================================================================*/ -#include - +#include "backport.h" #include "ticker.h" /*==================================================================*/ /* variables globales */ /*==================================================================*/ -#ifdef DOS -#define TICKER_STEP 5 -#else -#define TICKER_STEP 10 -#endif -static int TICKER_VALUE = 0; +static double ticker_start_time = 0.0; /*==================================================================*/ /* fonctions */ @@ -76,45 +70,32 @@ static int TICKER_VALUE = 0; /* mise en place du chrono */ /*------------------------------------------------------------------*/ -/*------------------------------------------------------------------*/ -static void -ticker_handler (void) -{ - TICKER_VALUE += TICKER_STEP; -} - -END_OF_FUNCTION (ticker_handler); - /*------------------------------------------------------------------*/ int start_ticker (void) { - int result = 0; - //#ifdef DOS - LOCK_FUNCTION (ticker_handler); - LOCK_VARIABLE (TICKER_VALUE); - - result = install_int_ex (ticker_handler, MSEC_TO_TIMER (TICKER_STEP)); - //#endif - return result; + // Initialize ticker with current time + ticker_start_time = al_get_time(); + return 0; // Always succeeds with Allegro 5 } /*------------------------------------------------------------------*/ void stop_ticker (void) { - //#ifdef DOS - remove_int (ticker_handler); - //#endif + // No cleanup needed with Allegro 5's al_get_time() + // Just reset the start time + ticker_start_time = 0.0; } /*------------------------------------------------------------------*/ int get_ticker (void) { - //#ifdef DOS - return TICKER_VALUE; - //#else - //return ++TICKER_VALUE; - //#endif + // Return elapsed time in milliseconds since start_ticker() was called + double current_time = al_get_time(); + double elapsed_seconds = current_time - ticker_start_time; + + // Convert to milliseconds and return as integer + return (int)(elapsed_seconds * 1000.0); } diff --git a/src/viewport.c b/src/viewport.c index 518c0c79..d074b9ef 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -52,13 +52,11 @@ /* includes */ /*==================================================================*/ -#include - #include "area.h" -#include "alleg2.h" +#include "backport.h" #include "config.h" +#include "dialog.h" #include "gfxmode.h" -#include "palette.h" #include "viewport.h" #include "info.h" #include "distor.h" @@ -69,7 +67,7 @@ /*==================================================================*/ int PAGE_FLIP_H = 0; -BITMAP *NEXT_SCREEN = NULL; +ALLEGRO_BITMAP *NEXT_SCREEN = NULL; static int VIEWPORT_X = 0; static int VIEWPORT_Y = 0; @@ -149,7 +147,7 @@ init_viewport_size (int x, int y, int w, int h) } /*------------------------------------------------------------------*/ -BITMAP * +ALLEGRO_BITMAP * page_flip (void) { int old_h, new_h; @@ -159,7 +157,7 @@ page_flip (void) { if (NEXT_SCREEN) { - destroy_bitmap (NEXT_SCREEN); + al_destroy_bitmap (NEXT_SCREEN); } lw_info_get_room_for_viewport (&x, &y, &w, &h); @@ -222,7 +220,7 @@ last_flip (void) PAGE_FLIP_H = 0; } - destroy_bitmap (NEXT_SCREEN); + al_destroy_bitmap (NEXT_SCREEN); NEXT_SCREEN = NULL; } } diff --git a/src/viewport.h b/src/viewport.h index 46e301fd..9a29c08b 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -55,7 +55,7 @@ /* includes */ /*==================================================================*/ -#include +#include /*==================================================================*/ /* variables globales */ @@ -66,14 +66,14 @@ extern int PAGE_FLIP_H; extern int MODEX_SCALE; -extern BITMAP *NEXT_SCREEN; +extern ALLEGRO_BITMAP *NEXT_SCREEN; /*==================================================================*/ /* fonctions globales */ /*==================================================================*/ void rect_for_viewport (void); -BITMAP *page_flip (void); +ALLEGRO_BITMAP *page_flip (void); void last_flip (void); void lw_viewport_register_change (int count); diff --git a/src/watchdog.c b/src/watchdog.c index 345578d2..b4978a46 100644 --- a/src/watchdog.c +++ b/src/watchdog.c @@ -52,9 +52,9 @@ /* includes */ /*==================================================================*/ -#include #include +#include "backport.h" #include "watchdog.h" #include "log.h" #include "macro.h" diff --git a/src/x11icon.c b/src/x11icon.c index bf76fbdd..b8bff7b5 100644 --- a/src/x11icon.c +++ b/src/x11icon.c @@ -1,4 +1,6 @@ -#include +#include + +#if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR /* XPM */ static const char *allegico_xpm[] = { /* columns rows colors chars-per-pixel */ @@ -288,8 +290,6 @@ static const char *allegico_xpm[] = { "vXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvX", "vXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvX" }; - -#if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR extern void *allegro_icon; CONSTRUCTOR_FUNCTION (static void _set_allegro_icon (void)); static void diff --git a/utils/Makefile.in b/utils/Makefile.in index 98427b9d..722502cb 100644 --- a/utils/Makefile.in +++ b/utils/Makefile.in @@ -1,28 +1,9 @@ -SNPRINTF = @SNPRINTF@ -ALCFLAGS = @ALCFLAGS@ -ALLIBS = @ALLIBS@ - -ifeq ($(SNPRINTF),yes) - SNPRINTF_FILES = - SNPRINTF_OPTIONS = -else - SNPRINTF_FILES = snprintf/snprintf.o - SNPRINTF_OPTIONS = -DSNPRINTF -endif - -EXE_FILES = liquidwarcol liquidwarmap liquidwartex - -OBJ_NAMES = liquidwarcol liquidwarmap liquidwartex -OBJ_FILES = $(addsuffix .o, $(OBJ_NAMES)) - -CMD_CC = $(CC) $(CFLAGS) $(ALCFLAGS) -c -Wall -W $(SNPRINTF_OPTIONS) - -all: $(EXE_FILES) $(OBJ_FILES) +all: install: -config: print_cmd_cc +config: check: @@ -31,27 +12,5 @@ indent: dep: clean: - @rm -f *.o - @rm -f */*.o - @rm -f $(OBJ_FILES) - @rm -f $(EXE_FILES) distclean: - @rm -f snprintf/test - @rm -f lwmapgen/lwmapgen - @rm -f lwmapgen/liquidwar-mapgen - @rm -f Makefile - -liquidwar%: liquidwar%.o $(SNPRINTF_FILES) - @echo "Building $@" - @$(CC) $(LDFLAGS) -o $@ $< $(SNPRINTF_FILES) $(ALLIBS) - -%.o: %.c - @echo "Compiling" $< - @$(CMD_CC) $< -o $@ - -print_cmd_cc: - @echo "The command line to compile .c files in this directory is:" - @echo -- $(CMD_CC) - @echo "The command line to link .o files in this directory is" - @echo -- $(CC) $(LDFLAGS) $(ALLIBS) diff --git a/utils/liquidwarcol.c b/utils/liquidwarcol.c deleted file mode 100644 index 483feaa6..00000000 --- a/utils/liquidwarcol.c +++ /dev/null @@ -1,451 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : liquidwarcol.c */ -/* contenu : tools to convert files to 8 bits palettes */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -/*=================================================================*/ -/* defines */ -/*=================================================================*/ - -#define ALLEGRO_USE_CONSOLE - -/*=================================================================*/ -/* includes */ -/*=================================================================*/ - -#include -#include -#include -#include -#include - -/*=================================================================*/ -/* constants */ -/*=================================================================*/ - -#define LW_TEXTURE_RANDOM_MAX_RETRIES 10000 - -/*=================================================================*/ -/* variables globales */ -/*=================================================================*/ - -int ARGC; -char **ARGV; -int FLAG_BACKUP = 0; -int FLAG_HELP = 0; -int FLAG_SILENT = 0; -int FIRST_COLOR; -int NUMBER_OF_COLORS; -char *FILENAMES[65536]; -int NUMBER_OF_FILES = 0; -PALETTE PALETTE_SRC; -PALETTE PALETTE_DST; -BITMAP *BITMAP_SRC = NULL; -BITMAP *BITMAP_DST = NULL; - -/*=================================================================*/ -/* fonctions */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -/* affichages d'aide */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -display_common_help (void) -{ - printf ("liquidwarcol by U-Foot (ufoot@ufoot.org).\n"); - printf ("This is a 'palette reducer' for 256 colors bitmaps.\n"); - printf ("It is free software, protected by the GPL.\n"); - printf ("It uses Allegro by Shawn Hargreaves.\n"); - printf ("\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_short_help (void) -{ - display_common_help (); - printf ("Type \"liquidwarcol -?\" for more help.\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_long_help (void) -{ - display_common_help (); - printf ("Syntax:\n"); - printf ("liquidwarcol [options] first_color number_of_colors filenames\n"); - printf ("\n"); - printf ("Options:\n"); - printf ("-? -h -H : displays this help.\n"); - printf ("-s -S : silent mode, nothing written to the console.\n"); - printf ("\n"); - printf ("Warning: the source file will be replaced!\n"); -} - -/*-----------------------------------------------------------------*/ -/* lecture des parametres de la ligne de commande */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -acknowledge_flag (char *str) -{ - int found = 0; - - if (str[0] == '-' || str[0] == '/') - { - found = 1; - switch (str[1]) - { - case '?': - case 'h': - case 'H': - FLAG_HELP = 1; - break; - case 'b': - case 'B': - FLAG_BACKUP = 1; - break; - case 's': - case 'S': - FLAG_SILENT = 1; - break; - default: - found = 0; - } - } - return found; -} - -/*-----------------------------------------------------------------*/ -int -read_command_line (void) -{ - int i, j = 0, success = 1; - - for (i = 1; i < ARGC; ++i) - { - if ((!acknowledge_flag (ARGV[i]))) - { - if (j == 0) - FIRST_COLOR = atoi (ARGV[i]); - if (j == 1) - NUMBER_OF_COLORS = atoi (ARGV[i]); - if (j >= 2) - FILENAMES[j - 2] = ARGV[i]; - j++; - } - } - NUMBER_OF_FILES = j - 2; - if (NUMBER_OF_FILES > 0) - { - if (FIRST_COLOR < 0) - { - success = 0; - printf ("ERROR! First color number must be >= 0.\n"); - } - if (FIRST_COLOR > 255) - { - success = 0; - printf ("ERROR! First color number must be < 255.\n"); - } - if (NUMBER_OF_COLORS < 1) - { - success = 0; - printf ("ERROR! Number of colors must be > 1.\n"); - } - if (NUMBER_OF_COLORS + FIRST_COLOR > 256) - { - success = 0; - printf ("ERROR! Last color number must be < 256.\n"); - } - } - else - { - success = 0; - if (!FLAG_HELP) - printf ("ERROR! Two few arguments.\n"); - } - return success; -} - -/*-----------------------------------------------------------------*/ -/* acces disque */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -load_file (char *filename) -{ - int success; - - if (!FLAG_SILENT) - printf ("Loading '%s'.\n", filename); - - if (BITMAP_SRC != NULL) - destroy_bitmap (BITMAP_SRC); - BITMAP_SRC = load_bitmap (filename, PALETTE_SRC); - success = BITMAP_SRC != NULL; - if (!success) - printf ("ERROR! Unable to read '%s'.\n", filename); - return success; -} - -/*-----------------------------------------------------------------*/ -void -save_backup (char *filename) -{ - char *bak_name = "faut encore le programmer"; - - if (!FLAG_SILENT) - printf ("Saving a copy of '%s' as '%s'.\n", filename, bak_name); -} - -/*-----------------------------------------------------------------*/ -void -save_file (char *filename) -{ - if (!FLAG_SILENT) - printf ("Replacing '%s'.\n", filename); - if (save_bitmap (filename, BITMAP_DST, PALETTE_DST)) - printf ("ERROR! Unable to save '%s'.\n", filename); -} - -/*-----------------------------------------------------------------*/ -/* operations de conversion */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -find_color (PALETTE pal, RGB rgb) -{ - int i, found = -1; - - for (i = 0; i < 256 && found < 0; ++i) - if (pal[i].r == rgb.r && pal[i].g == rgb.g && pal[i].b == rgb.b) - found = i; - - return found; -} - -/*-----------------------------------------------------------------*/ -int -exist_color (PALETTE pal, RGB rgb) -{ - return (find_color (pal, rgb) >= 0); -} - -/*-----------------------------------------------------------------*/ -void -recalculate_number_of_colors () -{ - int i, x, y, n = 1; - RGB color; - PALETTE pal; - - //nb_of_colors=NUMBER_OF_COLORS; - color = PALETTE_SRC[getpixel (BITMAP_SRC, 0, 0)]; - - for (i = 0; i < 256; ++i) - pal[i] = color; - - for (y = 0; y < BITMAP_SRC->h && n < NUMBER_OF_COLORS; ++y) - for (x = 0; x < BITMAP_SRC->w && n < NUMBER_OF_COLORS; ++x) - { - color = PALETTE_SRC[getpixel (BITMAP_SRC, x, y)]; - if (!exist_color (pal, color)) - pal[n++] = color; - } - NUMBER_OF_COLORS = n; -} - -/*-----------------------------------------------------------------*/ -void -create_new_palette (void) -{ - int i, x, y, index; - int nb_retries = 0; - RGB color; - - x = random () % BITMAP_SRC->w; - y = random () % BITMAP_SRC->h; - color = PALETTE_SRC[getpixel (BITMAP_SRC, x, y)]; - - for (i = 0; i < 256; ++i) - PALETTE_DST[i] = color; - - for (i = 1; i < NUMBER_OF_COLORS;) - { - x = random () % BITMAP_SRC->w; - y = random () % BITMAP_SRC->h; - index = getpixel (BITMAP_SRC, x, y); - color = PALETTE_SRC[index]; - if ((!exist_color (PALETTE_DST, color)) || - (nb_retries > LW_TEXTURE_RANDOM_MAX_RETRIES)) - { - PALETTE_DST[FIRST_COLOR + (i++)] = color; - nb_retries = 0; - } - else - { - nb_retries++; - } - } -} - -/*-----------------------------------------------------------------*/ -void -correct_palette (void) -{ - int i; - - for (i = 0; i < FIRST_COLOR; ++i) - { - PALETTE_DST[i].r = 0; - PALETTE_DST[i].g = 0; - PALETTE_DST[i].b = 0; - } - for (i = FIRST_COLOR + NUMBER_OF_COLORS; i < 256; ++i) - { - PALETTE_DST[i].r = 63; - PALETTE_DST[i].g = 63; - PALETTE_DST[i].b = 63; - } -} - -/*-----------------------------------------------------------------*/ -void -create_converted_bitmap (void) -{ - char corres[256]; - int i, x, y, index; - - for (i = 0; i < 256; ++i) - corres[i] = bestfit_color (PALETTE_DST, - PALETTE_SRC[i].r, - PALETTE_SRC[i].g, PALETTE_SRC[i].b); - BITMAP_DST = create_bitmap (BITMAP_SRC->w, BITMAP_SRC->h); - for (y = 0; y < BITMAP_SRC->h; ++y) - for (x = 0; x < BITMAP_SRC->w; ++x) - { - index = corres[getpixel (BITMAP_SRC, x, y)]; - index = (index < FIRST_COLOR || - index >= FIRST_COLOR + NUMBER_OF_COLORS) ? - FIRST_COLOR : index; - putpixel (BITMAP_DST, x, y, index); - } -} - -/*-----------------------------------------------------------------*/ -void -convert_bitmap () -{ - if (BITMAP_DST != NULL) - destroy_bitmap (BITMAP_DST); - - recalculate_number_of_colors (); - create_new_palette (); - create_converted_bitmap (); - correct_palette (); -} - -/*=================================================================*/ -/* fonctions main */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -int -main (int argc, char **argv) -{ - int i; - - ARGC = argc; - ARGV = argv; - -#ifdef ALLEGRO_UNIX - install_allegro (SYSTEM_NONE, &errno, atexit); -#else - allegro_init (); -#endif - - set_color_depth (8); - set_color_conversion (COLORCONV_REDUCE_TO_256); - - srandom (time (NULL)); - // srandom(1); - - if (read_command_line ()) - { - for (i = 0; i < NUMBER_OF_FILES; ++i) - { - if (load_file (FILENAMES[i])) - { - if (FLAG_BACKUP) - save_backup (FILENAMES[i]); - convert_bitmap (); - save_file (FILENAMES[i]); - } - } - } - else - { - if (FLAG_HELP) - display_long_help (); - else - display_short_help (); - } - allegro_exit (); - - return 0; - -} - -END_OF_MAIN (); diff --git a/utils/liquidwarmap.c b/utils/liquidwarmap.c deleted file mode 100644 index 288ee607..00000000 --- a/utils/liquidwarmap.c +++ /dev/null @@ -1,576 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : liquidwarmap.c */ -/* contenu : tools to generate tabs */ -/* date de modif : 3 mai 98 */ -/********************************************************************/ - -/*=================================================================*/ -/* defines */ -/*=================================================================*/ - -#define ALLEGRO_USE_CONSOLE - -/*=================================================================*/ -/* includes */ -/*=================================================================*/ - -#include -#include -#include -#include -#include -#include -#include - -/*=================================================================*/ -/* contantes */ -/*=================================================================*/ - -#define LIGHT_OR_DARK_TRESHOLD 315 -#define CONSIDERED_AS_DARK 0 -#define CONSIDERED_AS_LIGHT 2 -#define PLAYABLE_AREA 1 -#define MINI_SIDE_SIZE 4 -#define MINI_PLAYABLE_AREA 1024 - -/*=================================================================*/ -/* variables globales */ -/*=================================================================*/ - -int ARGC; -char **ARGV; -int FLAG_HELP = 0; -int FLAG_SILENT = 0; -char *FILENAMES[65536]; -int NUMBER_OF_FILES = 0; -PALETTE PALETTE_SRC; -BITMAP *BITMAP_SRC = NULL; -BITMAP *BITMAP_DST = NULL; -signed char BUFFER[1048576]; -int DST_X, DST_Y, DST_W, DST_H, DST_SIZE, BG_SIZE; -char SYSTEM_NAME[16]; -char READABLE_NAME[32]; - -/*=================================================================*/ -/* fonctions */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -/* affichages d'aide */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -display_common_help (void) -{ - printf ("liquidwarmap by U-Foot (ufoot@ufoot.org).\n"); - printf ("This program creates maps for Liquid War.\n"); - printf ("It is free software, protected by the GPL.\n"); - printf ("It uses Allegro by Shawn Hargreaves.\n"); - printf ("\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_short_help (void) -{ - display_common_help (); - printf ("Type \"liquidwarmap -?\" for more help.\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_long_help (void) -{ - display_common_help (); - printf ("The source must be a 256 color bitmap.\n"); - printf ("Walls must be in the same color - same index in fact.\n"); - printf ("The wall index color is given by the top left pixel,\n"); - printf ("and the map must be contained in a closed rectangle.\n"); - printf ("\n"); - printf ("Syntax:\n"); - printf ("liquidwarmap [options] filenames\n"); - printf ("\n"); - printf ("Options:\n"); - printf ("-? -h -H : displays this help.\n"); - printf ("-s -S : silent mode, nothing written to the console.\n"); - printf ("\n"); - printf ("Remark: the created map will have a .map extension.\n"); - printf ("Warning: the source file will be replaced by a smaller file.\n"); -} - -/*-----------------------------------------------------------------*/ -/* lecture des parametres de la ligne de commande */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -acknowledge_flag (char *str) -{ - int found = 0; - - if (str[0] == '-' || str[0] == '/') - { - found = 1; - switch (str[1]) - { - case '?': - case 'h': - case 'H': - FLAG_HELP = 1; - break; - case 's': - case 'S': - FLAG_SILENT = 1; - break; - default: - found = 0; - } - } - return found; -} - -/*-----------------------------------------------------------------*/ -int -read_command_line (void) -{ - int i, j = 0, success = 1; - - for (i = 1; i < ARGC; ++i) - { - if ((!acknowledge_flag (ARGV[i]))) - { - FILENAMES[j] = ARGV[i]; - j++; - } - } - NUMBER_OF_FILES = j; - if (NUMBER_OF_FILES <= 0) - { - success = 0; - if (!FLAG_HELP) - printf ("ERROR! Two few arguments.\n"); - } - return success; -} - -/*-----------------------------------------------------------------*/ -/* acces disque */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -load_file (char *filename) -{ - int success; - - if (!FLAG_SILENT) - printf ("Loading '%s'.\n", filename); - - if (BITMAP_SRC != NULL) - destroy_bitmap (BITMAP_SRC); - BITMAP_SRC = load_bitmap (filename, PALETTE_SRC); - success = BITMAP_SRC != NULL; - if (!success) - printf ("ERROR! Unable to read '%s'.\n", filename); - return success; -} - -/*-----------------------------------------------------------------*/ -/* lecture des parametres du tableau */ -/*-----------------------------------------------------------------*/ - -/*------------------------------------------------------------------*/ -static void -sort_light_and_dark (BITMAP * bmp, PALETTE pal) -{ - char table[256]; - int i, x, y; - - for (i = 0; i < 256; ++i) - { - if (6 * pal[i].r + 3 * pal[i].g + pal[i].b > LIGHT_OR_DARK_TRESHOLD) - table[i] = CONSIDERED_AS_LIGHT; - else - table[i] = CONSIDERED_AS_DARK; - } - - for (y = 0; y < bmp->h; ++y) - for (x = 0; x < bmp->w; ++x) - putpixel (bmp, x, y, table[getpixel (bmp, x, y)]); -} - -/*-----------------------------------------------------------------*/ -void -get_range (void) -{ - /* - useless and buggy code from an old time, when maps where - systematically drawn on 320x200 bitmaps and "getting the - useable part had a sense". Not any more. Now it only - wrecks some maps. Definitely useless. - - int min_x = BITMAP_SRC->w; - int min_y = BITMAP_SRC->h; - int max_x = -1; - int max_y = -1; - int x, y; - - for (y = 0; y < BITMAP_SRC->h; ++y) - for (x = 0; x < BITMAP_SRC->w; ++x) - if (!getpixel (BITMAP_SRC, x, y)) - { - if (min_x > x) - min_x = x; - if (min_y > y) - min_y = y; - if (max_x < x) - max_x = x; - if (max_y < y) - max_y = y; - } - - DST_X = min_x; - DST_Y = min_y; - DST_W = max_x - min_x + 1; - DST_H = max_y - min_y + 1; - */ - - DST_X = 0; - DST_Y = 0; - DST_W = BITMAP_SRC->w; - DST_H = BITMAP_SRC->h; - - if (DST_W < 1 || DST_H < 1) - { - printf ("ERROR! Map is too small.\n"); - DST_W = DST_H = 1; - } - if (BITMAP_DST != NULL) - destroy_bitmap (BITMAP_DST); - BITMAP_DST = create_bitmap (DST_W, DST_H); - blit (BITMAP_SRC, BITMAP_DST, DST_X, DST_Y, 0, 0, DST_W, DST_H); -} - -/*-----------------------------------------------------------------*/ -/* conversion dans le buffer */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -convert_to_buffer (void) -{ - int pos_src, pos_dst, l, wh; - char *data; - int wall_color; - - wh = BITMAP_DST->h * BITMAP_DST->w; - data = BITMAP_DST->dat; - pos_src = pos_dst = 0; - BG_SIZE = 0; - - if (wh > 0) - { - wall_color = CONSIDERED_AS_DARK; - while (pos_src < wh) - { - l = 0; - if (data[pos_src] == wall_color) - { - while (pos_src < wh && (data[pos_src] == wall_color) && l < 127) - { - l++; - pos_src++; - } - BUFFER[pos_dst++] = l; - } - else - { - while (pos_src < wh && data[pos_src] != wall_color && l < 127) - { - l++; - pos_src++; - } - BUFFER[pos_dst++] = -l; - BG_SIZE += l; - } - } - } - BUFFER[pos_dst++] = 0; - - DST_SIZE = pos_dst; -} - -/*-----------------------------------------------------------------*/ -void -change_ext_to_txt (char *str) -{ - char *ext; - - ext = strchr (str, '.'); - ext[1] = 't'; - ext[2] = 'x'; - ext[3] = 't'; -} - -/*-----------------------------------------------------------------*/ -void -update_system_name (char *str) -{ - char *search; - - memset (SYSTEM_NAME, 0, sizeof (SYSTEM_NAME)); - - /* - * No extension we just use the file name - */ - strncpy (SYSTEM_NAME, str, sizeof (SYSTEM_NAME)); - search = strchr (SYSTEM_NAME, '.'); - if (search) - { - (*search) = '\0'; - } -} - -/*-----------------------------------------------------------------*/ -void -update_readable_name (char *str) -{ - FILE *f; - char *search; - - memset (READABLE_NAME, 0, sizeof (READABLE_NAME)); - - f = fopen (str, "r"); - if (f != NULL) - { - /* - * If there's a corresponding .txt file, we open it and interpret - * it as the name of the map - */ - fread (READABLE_NAME, sizeof (READABLE_NAME), 1, f); - fclose (f); - /* - * Now we get rid of all the lines following the first one - */ - search = strchr (READABLE_NAME, 10); - if (search) - { - (*search) = 0; - } - search = strchr (READABLE_NAME, 13); - if (search) - { - (*search) = 0; - } - } - else - { - /* - * No .txt file we just use the file name - */ - strncpy (READABLE_NAME, str, sizeof (READABLE_NAME)); - search = strchr (READABLE_NAME, '.'); - if (search) - { - (*search) = '\0'; - } - } -} - -/*-----------------------------------------------------------------*/ -/* on ecrit sur le disque */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -change_ext_to_map (char *str) -{ - char *ext; - - ext = strchr (str, '.'); - ext[1] = 'm'; - ext[2] = 'a'; - ext[3] = 'p'; -} - -/*-----------------------------------------------------------------*/ -void -write_to_disk (char *str) -{ - FILE *f; - short w, h; - int size; - unsigned char header[8]; - - if (!FLAG_SILENT) - printf ("Writing %s to disk.\n", str); - delete_file (str); - f = fopen (str, "w"); - if (f != NULL) - { - w = DST_W; - h = DST_H; - size = DST_SIZE; - - /* - * Previous versions of LW used to store the size of - * the background here, to sort map afterwards. Now - * we store the size of the map. - */ - - /* - * Here's an ugly serialization of ints and shorts. - * Usefull to make the game work on Mac OS X and possible - * any platform that does not have PC-like endianess - */ - - header[0] = 0xFF & size; - header[1] = 0xFF & size >> 8; - header[2] = 0xFF & size >> 16; - header[3] = size >> 24; - header[4] = 0xFF & w; - header[5] = w >> 8; - header[6] = 0xFF & h; - header[7] = h >> 8; - - /* - Uncomment this to invert endianess of map header. - Used only for testing, do not uncomment it even - when compiling on Mac, it would make the game - unusable in network mode... - */ - /* - header[3] = 0xFF & size; - header[2] = 0xFF & size>>8; - header[1] = 0xFF & size>>16; - header[0] = size>>24; - header[5] = 0xFF & w; - header[4] = w>>8; - header[7] = 0xFF & h; - header[6] = h>>8; - */ - - fwrite (&(header[0]), 8, 1, f); - fwrite (SYSTEM_NAME, sizeof (SYSTEM_NAME), 1, f); - fwrite (READABLE_NAME, sizeof (READABLE_NAME), 1, f); - fwrite (BUFFER, size, 1, f); - fclose (f); - } - else - { - printf ("Unable to write %s.\n", str); - } -} - -/*-----------------------------------------------------------------*/ -void -write_with_new_size (char *str) -{ - if (!FLAG_SILENT) - printf ("Writing %s to disk.\n", str); - delete_file (str); - - save_bitmap (str, BITMAP_DST, PALETTE_SRC); -} - -/*=================================================================*/ -/* fonctions main */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -int -main (int argc, char **argv) -{ - int i; - - ARGC = argc; - ARGV = argv; - -#ifdef ALLEGRO_UNIX - install_allegro (SYSTEM_NONE, &errno, atexit); -#else - allegro_init (); -#endif - - set_color_depth (8); - set_color_conversion (COLORCONV_REDUCE_TO_256); - - if (read_command_line ()) - { - for (i = 0; i < NUMBER_OF_FILES; ++i) - { - if (load_file (FILENAMES[i])) - { - sort_light_and_dark (BITMAP_SRC, PALETTE_SRC); - get_range (); - if (BITMAP_SRC->w != BITMAP_DST->w - || BITMAP_SRC->h != BITMAP_DST->h) - write_with_new_size (FILENAMES[i]); - convert_to_buffer (); - change_ext_to_txt (FILENAMES[i]); - update_system_name (FILENAMES[i]); - update_readable_name (FILENAMES[i]); - change_ext_to_map (FILENAMES[i]); - write_to_disk (FILENAMES[i]); - } - } - } - else - { - if (FLAG_HELP) - display_long_help (); - else - display_short_help (); - } - allegro_exit (); - - return 0; - -} - -END_OF_MAIN () diff --git a/utils/liquidwartex.c b/utils/liquidwartex.c deleted file mode 100644 index e5bf9fe6..00000000 --- a/utils/liquidwartex.c +++ /dev/null @@ -1,447 +0,0 @@ -/********************************************************************/ -/* */ -/* L I QQ U U I DD W W A RR 555 */ -/* L I Q Q U U I D D W W A A R R 5 */ -/* L I Q Q U U I D D W W W AAA RR 55 */ -/* L I Q Q U U I D D WW WW A A R R 5 */ -/* LLL I Q Q U I DD W W A A R R 55 */ -/* */ -/* b */ -/* bb y y */ -/* b b yyy */ -/* bb y */ -/* yy */ -/* */ -/* U U FFF O O TTT */ -/* U U F O O O O T */ -/* U U TIRET FF O O O O T */ -/* U U F O O O O T */ -/* U F O O T */ -/* */ -/********************************************************************/ - -/*****************************************************************************/ -/* Liquid War is a multiplayer wargame */ -/* Copyright (C) 1998-2025 Christian Mauduit */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You 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 */ -/* */ -/* Liquid War homepage : https://ufoot.org/liquidwar/v5 */ -/* Contact author : ufoot@ufoot.org */ -/*****************************************************************************/ - -/********************************************************************/ -/* nom : liquidwartex.c */ -/* contenu : tool to generate textures */ -/* date de modif : March 2000 */ -/********************************************************************/ - -/*=================================================================*/ -/* defines */ -/*=================================================================*/ - -#define ALLEGRO_USE_CONSOLE - -/*=================================================================*/ -/* includes */ -/*=================================================================*/ - -#include -#include -#include -#include -#include -#include -#include - -/*=================================================================*/ -/* variables globales */ -/*=================================================================*/ - -int ARGC; -char **ARGV; -int FLAG_HELP = 0; -int FLAG_SILENT = 0; -char *FILENAMES[65536]; -int NUMBER_OF_FILES = 0; -PALETTE PALETTE_SRC; -BITMAP *BITMAP_SRC = NULL; -int DST_X, DST_Y, DST_W, DST_H, DST_SIZE; -int FIRST_COLOR = 32; -int COLOR_NUMBER = 32; -char BUFFER[1048576]; -char SYSTEM_NAME[16]; - - -/*=================================================================*/ -/* fonctions */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -/* affichages d'aide */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -display_common_help (void) -{ - printf ("liquidwartex by U-Foot (ufoot@ufoot.org).\n"); - printf ("This program creates textures for Liquid War.\n"); - printf ("It is free software, protected by the GPL.\n"); - printf ("It uses Allegro by Shawn Hargreaves.\n"); - printf ("\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_short_help (void) -{ - display_common_help (); - printf ("Type \"liquidwartex -?\" for more help.\n"); -} - -/*-----------------------------------------------------------------*/ -void -display_long_help (void) -{ - display_common_help (); - printf - ("The source must be a 256 color bitmap using color from first_color to first_color+number_of_colors-1.\n"); - printf ("\n"); - printf ("Syntax:\n"); - printf ("liquidwartex [options] first_color number_of_colors filenames\n"); - printf ("\n"); - printf ("Options:\n"); - printf ("-? -h -H : displays this help.\n"); - printf ("-s -S : silent mode, nothing written to the console.\n"); - printf ("\n"); - printf ("Remark: the created texture will have a .tex extension.\n"); -} - -/*-----------------------------------------------------------------*/ -/* lecture des parametres de la ligne de commande */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -acknowledge_flag (char *str) -{ - int found = 0; - - if (str[0] == '-' || str[0] == '/') - { - found = 1; - switch (str[1]) - { - case '?': - case 'h': - case 'H': - FLAG_HELP = 1; - break; - case 's': - case 'S': - FLAG_SILENT = 1; - break; - default: - found = 0; - } - } - return found; -} - -/*-----------------------------------------------------------------*/ -int -read_command_line (void) -{ - int i, j = 0, success = 1; - - if (ARGC <= 2) - { - success = 0; - if (!FLAG_HELP) - printf ("ERROR! Too few arguments.\n"); - } - else - { - for (i = 1; i < ARGC; ++i) - { - if ((!acknowledge_flag (ARGV[i]))) - { - if (j == 0) - FIRST_COLOR = atoi (ARGV[i]); - if (j == 1) - COLOR_NUMBER = atoi (ARGV[i]); - if (j >= 2) - FILENAMES[j - 2] = ARGV[i]; - j++; - } - } - if (COLOR_NUMBER < 8 || COLOR_NUMBER > 32) - { - /* - * COLOR_NUMBER must be <=32 for weird implementation - * reasons. There's no easy way to change this easily. - */ - success = 0; - if (!FLAG_HELP) - printf ("ERROR! Color number must be between 8 and 32"); - } - else - { - NUMBER_OF_FILES = j - 2; - if (NUMBER_OF_FILES <= 0) - { - success = 0; - if (!FLAG_HELP) - printf ("ERROR! Too few arguments.\n"); - } - } - } - return success; -} - -/*-----------------------------------------------------------------*/ -/* acces disque */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -int -load_file (char *filename) -{ - int success; - - if (!FLAG_SILENT) - printf ("Loading '%s'.\n", filename); - - if (BITMAP_SRC != NULL) - destroy_bitmap (BITMAP_SRC); - BITMAP_SRC = load_bitmap (filename, PALETTE_SRC); - success = BITMAP_SRC != NULL; - if (!success) - printf ("ERROR! Unable to read '%s'.\n", filename); - return success; -} - -/*-----------------------------------------------------------------*/ -/* lecture des parametres du tableau */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -get_range (void) -{ - int min_x = BITMAP_SRC->w; - int min_y = BITMAP_SRC->h; - int max_x = -1; - int max_y = -1; - int x, y; - - for (y = 0; y < BITMAP_SRC->h; ++y) - for (x = 0; x < BITMAP_SRC->w; ++x) - if (getpixel (BITMAP_SRC, x, y) >= FIRST_COLOR || - getpixel (BITMAP_SRC, x, y) < FIRST_COLOR + COLOR_NUMBER) - { - if (min_x > x) - min_x = x; - if (min_y > y) - min_y = y; - if (max_x < x) - max_x = x; - if (max_y < y) - max_y = y; - } - DST_X = min_x; - DST_Y = min_y; - DST_W = max_x - min_x + 1; - DST_H = max_y - min_y + 1; - - if (DST_W < 1 || DST_H < 1) - { - printf ("ERROR! Texture is too small.\n"); - DST_W = DST_H = 1; - } - DST_SIZE = 3 * COLOR_NUMBER + ((DST_W * DST_H + 7) / 8) * 5; -} - -/*-----------------------------------------------------------------*/ -void -update_system_name (char *str) -{ - char *search; - - memset (SYSTEM_NAME, 0, sizeof (SYSTEM_NAME)); - - /* - * No extension we just use the file name - */ - strncpy (SYSTEM_NAME, str, sizeof (SYSTEM_NAME)); - search = strchr (SYSTEM_NAME, '.'); - if (search) - { - (*search) = '\0'; - } -} - -/*-----------------------------------------------------------------*/ -/* conversion dans le buffer */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -convert_to_buffer (void) -{ - int pos = 0, pos8 = 0, x, y, i; - char octet[5], toadd; - int coul; - - for (i = 0; i < COLOR_NUMBER; ++i) - { - BUFFER[pos++] = PALETTE_SRC[FIRST_COLOR + i].r; - BUFFER[pos++] = PALETTE_SRC[FIRST_COLOR + i].g; - BUFFER[pos++] = PALETTE_SRC[FIRST_COLOR + i].b; - } - - for (i = 0; i < 5; ++i) - octet[i] = 0; - - for (y = 0; y < DST_H; ++y) - for (x = 0; x < DST_W; ++x) - { - coul = getpixel (BITMAP_SRC, DST_X + x, DST_Y + y) - FIRST_COLOR; - toadd = 1 << pos8; - octet[0] |= (coul & 1) ? toadd : 0; - octet[1] |= (coul & 2) ? toadd : 0; - octet[2] |= (coul & 4) ? toadd : 0; - octet[3] |= (coul & 8) ? toadd : 0; - octet[4] |= (coul & 16) ? toadd : 0; - - if (pos8 == 7 || (y == DST_H - 1 && x == DST_W - 1)) - { - for (i = 0; i < 5; ++i) - { - BUFFER[pos++] = octet[i]; - octet[i] = 0; - } - pos8 = 0; - } - else - pos8++; - } -} - -/*-----------------------------------------------------------------*/ -/* on ecrit sur le disque */ -/*-----------------------------------------------------------------*/ - -/*-----------------------------------------------------------------*/ -void -change_ext (char *str) -{ - char *ext; - - ext = strchr (str, '.'); - ext[1] = 't'; - ext[2] = 'e'; - ext[3] = 'x'; -} - -/*-----------------------------------------------------------------*/ -void -write_to_disk (char *str) -{ - FILE *f; - short w, h; - char header[4]; - - if (!FLAG_SILENT) - printf ("Writing %s to disk.\n", str); - delete_file (str); - f = fopen (str, "w"); - if (f != NULL) - { - w = DST_W; - h = DST_H; - - /* - * This is supposed to match the endianess used in - * the serial.h/serial.c files of the core source. - */ - header[0] = 0xFF & w; - header[1] = w >> 8; - header[2] = 0xFF & h; - header[3] = h >> 8; - - fwrite (header, 4, 1, f); - - fwrite (SYSTEM_NAME, sizeof (SYSTEM_NAME), 1, f); - fwrite (BUFFER, DST_SIZE, 1, f); - fclose (f); - } - else - { - printf ("Unable to write %s.\n", str); - } -} - -/*=================================================================*/ -/* fonctions main */ -/*=================================================================*/ - -/*-----------------------------------------------------------------*/ -int -main (int argc, char **argv) -{ - int i; - - ARGC = argc; - ARGV = argv; - -#ifdef ALLEGRO_UNIX - install_allegro (SYSTEM_NONE, &errno, atexit); -#else - allegro_init (); -#endif - - set_color_depth (8); - set_color_conversion (COLORCONV_REDUCE_TO_256); - - if (read_command_line ()) - { - for (i = 0; i < NUMBER_OF_FILES; ++i) - { - if (load_file (FILENAMES[i])) - { - get_range (); - convert_to_buffer (); - update_system_name (FILENAMES[i]); - change_ext (FILENAMES[i]); - write_to_disk (FILENAMES[i]); - } - } - } - else - { - if (FLAG_HELP) - display_long_help (); - else - display_short_help (); - } - allegro_exit (); - - return 0; - -} - -END_OF_MAIN () diff --git a/utils/lwmapgen/big_quad.c b/utils/lwmapgen/big_quad.c index 29478a07..36f987bc 100644 --- a/utils/lwmapgen/big_quad.c +++ b/utils/lwmapgen/big_quad.c @@ -36,7 +36,7 @@ big_quad () vert[6] = rand_num (map.sec_width + 1, map.width - map.sec_width - 1); vert[7] = rand_num (map.height - map.sec_height, map.height - 3); - polygon (map.map, 4, vert, 0); + polygon (map.map, 4, vert, al_map_rgb(0, 0, 0)); return; } diff --git a/utils/lwmapgen/boxes.c b/utils/lwmapgen/boxes.c index f9d154f2..9914dd90 100644 --- a/utils/lwmapgen/boxes.c +++ b/utils/lwmapgen/boxes.c @@ -50,7 +50,7 @@ boxes () else endy = map.sec_height * (r + 1) - pad; - rectfill (map.map, startx, starty, endx, endy, 0); + rectfill (map.map, startx, starty, endx, endy, al_map_rgb(0, 0, 0)); } } } diff --git a/utils/lwmapgen/bubbles.c b/utils/lwmapgen/bubbles.c index c750d1b3..20b157c3 100644 --- a/utils/lwmapgen/bubbles.c +++ b/utils/lwmapgen/bubbles.c @@ -58,8 +58,8 @@ bubbles () *centery *= (centery / bubblesy); */ - circlefill (map.map, centerx, centery, outradius, 255); - circlefill (map.map, centerx, centery, inradius, 0); + circlefill (map.map, centerx, centery, outradius, al_map_rgb(255, 255, 255)); + circlefill (map.map, centerx, centery, inradius, al_map_rgb(0, 0, 0)); } } /* for(c..) */ } /* for(r..) */ diff --git a/utils/lwmapgen/circles.c b/utils/lwmapgen/circles.c index 426e2d68..31f4db35 100644 --- a/utils/lwmapgen/circles.c +++ b/utils/lwmapgen/circles.c @@ -28,7 +28,7 @@ circles () { rand_point_section_offset (¢erx, ¢ery, r, c, 0); radius = rand () % size + 1; - circlefill (map.map, centerx, centery, radius, 0); + circlefill (map.map, centerx, centery, radius, al_map_rgb(0, 0, 0)); } } diff --git a/utils/lwmapgen/circuit.c b/utils/lwmapgen/circuit.c index 1b346a5f..bd10bb85 100644 --- a/utils/lwmapgen/circuit.c +++ b/utils/lwmapgen/circuit.c @@ -39,12 +39,12 @@ draw_pipe (int fromr, int fromc, int tor, int toc, int flip) /* go up/down to reach target */ section_center (&fromx, &fromy, fromr, fromc); section_center (&tox, &toy, tor, fromc); - rectfill (map.map, fromx - size, fromy, tox + size, toy, 255); + rectfill (map.map, fromx - size, fromy, tox + size, toy, al_map_rgb(255, 255, 255)); /* across some num of sections */ section_center (&fromx, &fromy, tor, fromc); section_center (&tox, &toy, tor, toc); - rectfill (map.map, fromx, fromy - size, tox, toy + size, 255); + rectfill (map.map, fromx, fromy - size, tox, toy + size, al_map_rgb(255, 255, 255)); } /* across then up/down */ else @@ -52,12 +52,12 @@ draw_pipe (int fromr, int fromc, int tor, int toc, int flip) /* across some num of sections */ section_center (&fromx, &fromy, fromr, fromc); section_center (&tox, &toy, fromr, toc); - rectfill (map.map, fromx, fromy - size, tox, toy + size, 255); + rectfill (map.map, fromx, fromy - size, tox, toy + size, al_map_rgb(255, 255, 255)); /* go up/down to reach target */ section_center (&fromx, &fromy, fromr, toc); section_center (&tox, &toy, tor, toc); - rectfill (map.map, fromx - size, fromy, tox + size, toy, 255); + rectfill (map.map, fromx - size, fromy, tox + size, toy, al_map_rgb(255, 255, 255)); } } else if (fromc > toc) @@ -68,12 +68,12 @@ draw_pipe (int fromr, int fromc, int tor, int toc, int flip) /* across some num of sections */ section_center (&fromx, &fromy, fromr, fromc); section_center (&tox, &toy, fromr, toc); - rectfill (map.map, fromx, fromy - size, tox, toy + size, 255); + rectfill (map.map, fromx, fromy - size, tox, toy + size, al_map_rgb(255, 255, 255)); /* go up/down to reach target */ section_center (&fromx, &fromy, fromr, toc); section_center (&tox, &toy, tor, toc); - rectfill (map.map, fromx - size, fromy, tox + size, toy, 255); + rectfill (map.map, fromx - size, fromy, tox + size, toy, al_map_rgb(255, 255, 255)); } /* up/down then across */ else @@ -81,12 +81,12 @@ draw_pipe (int fromr, int fromc, int tor, int toc, int flip) /* go up/down to reach target */ section_center (&fromx, &fromy, fromr, fromc); section_center (&tox, &toy, tor, fromc); - rectfill (map.map, fromx - size, fromy, tox + size, toy, 255); + rectfill (map.map, fromx - size, fromy, tox + size, toy, al_map_rgb(255, 255, 255)); /* across some num of sections */ section_center (&fromx, &fromy, tor, fromc); section_center (&tox, &toy, tor, toc); - rectfill (map.map, fromx, fromy - size, tox, toy + size, 255); + rectfill (map.map, fromx, fromy - size, tox, toy + size, al_map_rgb(255, 255, 255)); } } else @@ -94,7 +94,7 @@ draw_pipe (int fromr, int fromc, int tor, int toc, int flip) /* go up/down to reach target */ section_center (&fromx, &fromy, fromr, fromc); section_center (&tox, &toy, tor, toc); - rectfill (map.map, fromx - size, fromy, tox + size, toy, 255); + rectfill (map.map, fromx - size, fromy, tox + size, toy, al_map_rgb(255, 255, 255)); } return; @@ -403,7 +403,7 @@ circuit () } section_center (¢erx, ¢ery, r, c); - circlefill (map.map, centerx, centery, radius, 255); + circlefill (map.map, centerx, centery, radius, al_map_rgb(255, 255, 255)); grid[r][c] = 1; count[r]++; @@ -421,7 +421,7 @@ circuit () /* redraw outline */ /* TODO: once in a while if cuts off the edge.. */ - rect (map.map, 0, 0, map.width - 1, map.height - 1, 0); + rect (map.map, 0, 0, map.width - 1, map.height - 1, al_map_rgb(0, 0, 0)); return; } diff --git a/utils/lwmapgen/cut.c b/utils/lwmapgen/cut.c index 81183139..25f73f58 100644 --- a/utils/lwmapgen/cut.c +++ b/utils/lwmapgen/cut.c @@ -42,7 +42,7 @@ cut () vert[6] = endx - size; vert[7] = map.height - 1; - polygon (map.map, 4, vert, 255); + polygon (map.map, 4, vert, al_map_rgb(255, 255, 255)); } /* horizontial */ @@ -66,7 +66,7 @@ cut () vert[6] = map.width - 2; vert[7] = endy + size; - polygon (map.map, 4, vert, 255); + polygon (map.map, 4, vert, al_map_rgb(255, 255, 255)); } return; diff --git a/utils/lwmapgen/main.c b/utils/lwmapgen/main.c index f24a3de2..dfcfd266 100644 --- a/utils/lwmapgen/main.c +++ b/utils/lwmapgen/main.c @@ -23,27 +23,6 @@ void do_args (int argc, char **argv); void print_help (); void print_version (); -#ifdef DOS -/* - * These macros reduce the size of the DOS executable - */ -BEGIN_GFX_DRIVER_LIST - END_GFX_DRIVER_LIST - BEGIN_COLOR_DEPTH_LIST - COLOR_DEPTH_8 - END_COLOR_DEPTH_LIST - BEGIN_DIGI_DRIVER_LIST - END_DIGI_DRIVER_LIST - BEGIN_MIDI_DRIVER_LIST - END_MIDI_DRIVER_LIST BEGIN_JOYSTICK_DRIVER_LIST END_JOYSTICK_DRIVER_LIST -#endif -#ifdef WIN32 -/* - * Under Win32 we want a console executable so we don't use - * the "END_OF_MAIN" stuff, and this implies to undef "main". - */ -#undef main -#endif int main (int argc, char **argv) { @@ -51,13 +30,13 @@ main (int argc, char **argv) int i; /* init allegro and init palette */ - install_allegro (SYSTEM_NONE, &errno, atexit); + allegro_init (); set_color_depth (8); set_color_conversion (COLORCONV_REDUCE_TO_256); for (i = 0; i < 256; i++) { - /* divided by 4 because the colour value ranges from 0-63 */ - pal[i].r = pal[i].g = pal[i].b = i / 4; + /* Use 8-bit color values (0-255) instead of VGA (0-63) */ + pal[i].r = pal[i].g = pal[i].b = i; } srand (time (NULL)); @@ -69,16 +48,12 @@ main (int argc, char **argv) map_generator (filename, size, grid_size, func_id); printf ("map-- %s\n", map.filename); - save_bitmap (map.filename, map.map, pal); + save_bitmap (map.filename, map.map); // Palette parameter removed in Allegro 5 printf ("map-- %s\n", map.filename); return EXIT_SUCCESS; } -#ifndef WIN32 -END_OF_MAIN (); -#endif - /*****************************************************************************/ void diff --git a/utils/lwmapgen/map.c b/utils/lwmapgen/map.c index 42d01a60..06aef641 100644 --- a/utils/lwmapgen/map.c +++ b/utils/lwmapgen/map.c @@ -48,9 +48,9 @@ map_t map; void clear_map () { - clear_to_color (map.map, 255); + clear_to_color (map.map, al_map_rgb(255, 255, 255)); /* draw outline */ - rect (map.map, 0, 0, map.width - 1, map.height - 1, 0); + rect (map.map, 0, 0, map.width - 1, map.height - 1, al_map_rgb(0, 0, 0)); } /*****************************************************************************/ @@ -58,7 +58,7 @@ clear_map () void clear_invert_map () { - clear_to_color (map.map, 0); + clear_to_color (map.map, al_map_rgb(0, 0, 0)); } /*****************************************************************************/ diff --git a/utils/lwmapgen/map.h b/utils/lwmapgen/map.h index 45798528..7bae4d1b 100644 --- a/utils/lwmapgen/map.h +++ b/utils/lwmapgen/map.h @@ -9,7 +9,7 @@ #define LWMAPGEN_MAP_H -#include +#include "../../src/backport.h" #include "func.h" #include "misc.h" diff --git a/utils/lwmapgen/old/rand_poly_cut.c b/utils/lwmapgen/old/rand_poly_cut.c index 249a4f3f..f1611ae5 100644 --- a/utils/lwmapgen/old/rand_poly_cut.c +++ b/utils/lwmapgen/old/rand_poly_cut.c @@ -41,7 +41,7 @@ void rand_poly_cut() if( rand()%3 != 0 ) continue; - offset(&xoffset, &yoffset, r, 0); + offset(&xoffset, &yoffset, r, al_map_rgb(0, 0, 0)); cutsize = rand()%(section_height/2-map.max_pad)+1; cuty = section_height/2 + yoffset; diff --git a/utils/lwmapgen/old/rand_poly_diag_cut.c b/utils/lwmapgen/old/rand_poly_diag_cut.c index 403b5cba..7b070d3c 100644 --- a/utils/lwmapgen/old/rand_poly_diag_cut.c +++ b/utils/lwmapgen/old/rand_poly_diag_cut.c @@ -51,7 +51,7 @@ void rand_poly_diag_cut() for( r = start; r < map.num_row; r += 2 ) { - offset(&xoffset, &yoffset, r, 0); + offset(&xoffset, &yoffset, r, al_map_rgb(0, 0, 0)); cutsize = rand()%(section_height/2-map.max_pad)+1; diff --git a/utils/lwmapgen/rand_box.c b/utils/lwmapgen/rand_box.c index 551fd14b..59f6d1de 100644 --- a/utils/lwmapgen/rand_box.c +++ b/utils/lwmapgen/rand_box.c @@ -43,7 +43,7 @@ rand_box () bheight -= (starty + bheight) - (map.sec_height - 1); rectfill (map.map, startx + xoffset, starty + yoffset, - startx + bwidth + xoffset, starty + bheight + yoffset, 0); + startx + bwidth + xoffset, starty + bheight + yoffset, al_map_rgb(0, 0, 0)); } } diff --git a/utils/lwmapgen/rand_poly.c b/utils/lwmapgen/rand_poly.c index ce2407bb..e1113a9a 100644 --- a/utils/lwmapgen/rand_poly.c +++ b/utils/lwmapgen/rand_poly.c @@ -62,7 +62,7 @@ rand_poly () /* draw poly */ - polygon (map.map, num_vert, vert, map.color); + polygon (map.map, num_vert, vert, map.color == 0 ? al_map_rgb(0, 0, 0) : al_map_rgb(255, 255, 255)); delete_array (vert); diff --git a/utils/lwmapgen/street.c b/utils/lwmapgen/street.c index 4ca0f1d5..2edeebed 100644 --- a/utils/lwmapgen/street.c +++ b/utils/lwmapgen/street.c @@ -59,7 +59,7 @@ street () /* draw main row */ section_center (&startx, &starty, r, 0); section_center (&endx, &endy, r, map.num_col - 1); - rectfill (map.map, startx, starty - size, endx, endy + size, 255); + rectfill (map.map, startx, starty - size, endx, endy + size, al_map_rgb(255, 255, 255)); /* do the branches */ @@ -76,7 +76,7 @@ street () tor = rand () % r; section_center (&endx, &endy, tor, c); rectfill (map.map, startx - size, starty, endx + size, endy, - 255); + al_map_rgb(255, 255, 255)); } /* draw down */ @@ -87,7 +87,7 @@ street () /* tor = rand()%(map.num_row-r-1)+r+1; */ section_center (&endx, &endy, tor, c); rectfill (map.map, startx - size, starty, endx + size, endy, - 255); + al_map_rgb(255, 255, 255)); } } } @@ -101,7 +101,7 @@ street () /* draw main col */ section_center (&startx, &starty, 0, c); section_center (&endx, &endy, map.num_row - 1, c); - rectfill (map.map, startx - size, starty, endx + size, endy, 255); + rectfill (map.map, startx - size, starty, endx + size, endy, al_map_rgb(255, 255, 255)); /* do the branches */ @@ -118,7 +118,7 @@ street () toc = rand () % c; section_center (&endx, &endy, r, toc); rectfill (map.map, startx, starty - size, endx, endy + size, - 255); + al_map_rgb(255, 255, 255)); } /* draw right */ @@ -128,7 +128,7 @@ street () /* toc = rand()%(map.num_col-c-1)+c+1; */ section_center (&endx, &endy, r, toc); rectfill (map.map, startx - size, starty - size, endx, - endy + size, 255); + endy + size, al_map_rgb(255, 255, 255)); } } } diff --git a/utils/lwmapgen/worms.c b/utils/lwmapgen/worms.c index ec88bbe7..ae27316b 100644 --- a/utils/lwmapgen/worms.c +++ b/utils/lwmapgen/worms.c @@ -18,7 +18,7 @@ int -filled (int centerx, int centery, int rad, int startdeg, int col, int seg) +filled (int centerx, int centery, int rad, int startdeg, ALLEGRO_COLOR col, int seg) { int deg; int result = 0; @@ -38,10 +38,9 @@ filled (int centerx, int centery, int rad, int startdeg, int col, int seg) for (deg = startdeg - check_degrees; deg < startdeg + check_degrees; deg += 5) { - - if (getpixel - (map.map, centerx + (rad * cos (M_PI * deg / 180)), - centery + (rad * sin (M_PI * deg / 180))) == col) + ALLEGRO_COLOR pixel = getpixel (map.map, centerx + (rad * cos (M_PI * deg / 180)), + centery + (rad * sin (M_PI * deg / 180))); + if (pixel.r == col.r && pixel.g == col.g && pixel.b == col.b) { result = 1; break; @@ -82,9 +81,9 @@ worms () centerx += radius * cos (M_PI * degree / 180); centery += radius * sin (M_PI * degree / 180); - if (filled (centerx, centery, radius + 1, degree, 0, segs) == 0) + if (filled (centerx, centery, radius + 1, degree, al_map_rgb(0, 0, 0), segs) == 0) { - circlefill (map.map, centerx, centery, radius, 0); + circlefill (map.map, centerx, centery, radius, al_map_rgb(0, 0, 0)); } else {