mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-25 11:52:32 +01:00
Merge branch 'develop-SoapyMan' into develop-Fireboyd78
This commit is contained in:
commit
593cb7e580
@ -1,21 +1,22 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
# Creating flatpak directories
|
# Configure
|
||||||
mkdir -p "${APPVEYOR_BUILD_FOLDER}/.flatpak/lib" "${APPVEYOR_BUILD_FOLDER}/.flatpak/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/bin"
|
|
||||||
|
|
||||||
cd "$APPVEYOR_BUILD_FOLDER/src_rebuild"
|
cd "$APPVEYOR_BUILD_FOLDER/src_rebuild"
|
||||||
|
|
||||||
./premake5 gmake2
|
./premake5 gmake2
|
||||||
|
|
||||||
cd project_gmake2_linux
|
cd project_gmake2_linux
|
||||||
|
|
||||||
|
# Build
|
||||||
for config in debug_x86 release_x86 release_dev_x86
|
for config in debug_x86 release_x86 release_dev_x86
|
||||||
do
|
do
|
||||||
make config=$config -j$(nproc)
|
make config=$config -j$(nproc)
|
||||||
done
|
done
|
||||||
|
|
||||||
find ${APPVEYOR_BUILD_FOLDER}/src_rebuild/bin -name 'REDRIVER2*' -exec cp -t ${APPVEYOR_BUILD_FOLDER}/.flatpak/bin {} +
|
cd ${APPVEYOR_BUILD_FOLDER}
|
||||||
|
|
||||||
|
# Creating flatpak directories
|
||||||
|
mkdir -p "${APPVEYOR_BUILD_FOLDER}/.flatpak/lib" "${APPVEYOR_BUILD_FOLDER}/.flatpak/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/bin"
|
||||||
|
find ${APPVEYOR_BUILD_FOLDER}/src_rebuild/bin/Release -name 'REDRIVER2*' -exec cp -t ${APPVEYOR_BUILD_FOLDER}/.flatpak/bin {} +
|
||||||
|
|
||||||
# Copy missing libraries in the runtime
|
# Copy missing libraries in the runtime
|
||||||
for lib in libjpeg libopenal libsndio libbsd
|
for lib in libjpeg libopenal libsndio libbsd
|
||||||
@ -24,7 +25,6 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
cp -r "${APPVEYOR_BUILD_FOLDER}/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/"
|
cp -r "${APPVEYOR_BUILD_FOLDER}/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/"
|
||||||
cd ${APPVEYOR_BUILD_FOLDER}
|
|
||||||
|
|
||||||
# Editing metadatas with the current version
|
# Editing metadatas with the current version
|
||||||
export APPVEYOR_BUILD_DATE=$(date "+%Y-%m-%d")
|
export APPVEYOR_BUILD_DATE=$(date "+%Y-%m-%d")
|
||||||
|
@ -26,7 +26,7 @@ export XDG_DATA_DIRS="/var/lib/flatpak/exports/share:${HOME}/.local/share/flatpa
|
|||||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||||
|
|
||||||
# Adding Platform/SDK for the Linux flatpak release
|
# Adding Platform/SDK for the Linux flatpak release
|
||||||
flatpak --user install flathub org.freedesktop.Platform/x86_64/20.08 -y
|
flatpak --user install flathub org.freedesktop.Platform/x86_64/22.08 -y
|
||||||
flatpak --user install flathub org.freedesktop.Sdk/x86_64/20.08 -y
|
flatpak --user install flathub org.freedesktop.Sdk/x86_64/22.08 -y
|
||||||
flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/20.08 -y
|
flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/22.08 -y
|
||||||
flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/20.08 -y
|
flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/22.08 -y
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
<metadata_license>MIT</metadata_license>
|
<metadata_license>MIT</metadata_license>
|
||||||
<project_license>MIT</project_license>
|
<project_license>MIT</project_license>
|
||||||
<name>REDRIVER2</name>
|
<name>REDRIVER2</name>
|
||||||
<summary>Driver 2 Playstation game reverse engineering effort</summary>
|
<summary>Driver 2 - Back On The Streets / The Wheelman Is Back</summary>
|
||||||
<description>
|
<description>
|
||||||
<p>Driver 2 Playstation game reverse engineering effort </p>
|
<p>Reverse-Engineered version of Driver 2. https://opendriver2.github.io</p>
|
||||||
</description>
|
</description>
|
||||||
<categories>
|
<categories>
|
||||||
<category>Game</category>
|
<category>Game</category>
|
||||||
|
5
.flatpak/ld.so.conf
Normal file
5
.flatpak/ld.so.conf
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# We just make any GL32 extension have higher priority
|
||||||
|
include /run/flatpak/ld.so.conf.d/app-*-org.freedesktop.Platform.GL32.*.conf
|
||||||
|
/app/lib32
|
||||||
|
/app/lib/i386-linux-gnu
|
||||||
|
/lib64
|
@ -13,7 +13,7 @@ function importDefaultData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [ ! -d /var/data/DRIVER2 ]; then
|
if [ ! -d /var/data/DRIVER2 ]; then
|
||||||
zenity --error --no-wrap --text="`printf "DRIVER2 files are missing! Add the folder in:\n ${HOME}/.var/io.github.opendriver2.Redriver2/data"`"
|
zenity --error --no-wrap --text="`printf "DRIVER2 files are missing! Please provide DRIVER2 folder in:\n ${HOME}/.var/app/io.github.opendriver2.Redriver2/data"`"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
39
Dockerfile
Normal file
39
Dockerfile
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
FROM fedora:37
|
||||||
|
LABEL Description="Build environment"
|
||||||
|
|
||||||
|
ENV HOME /root
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
|
RUN dnf update -y && \
|
||||||
|
dnf groupinstall -y 'Development Tools' && \
|
||||||
|
dnf install -y make gcc gcc-c++ \
|
||||||
|
libjpeg-turbo-devel.i686 \
|
||||||
|
glibc-devel.i686 \
|
||||||
|
SDL2-devel.i686 \
|
||||||
|
openal-soft-devel.i686 \
|
||||||
|
flatpak flatpak-builder
|
||||||
|
|
||||||
|
ENV APPVEYOR_BUILD_FOLDER=/src
|
||||||
|
|
||||||
|
# Setting XDG_DATA_DIRS environement variable for flatpak
|
||||||
|
ENV XDG_DATA_DIRS="/var/lib/flatpak/exports/share:${HOME}/.local/share/flatpak/exports/share:$XDG_DATA_DIRS"
|
||||||
|
|
||||||
|
# Adding the flathub repo
|
||||||
|
RUN flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||||
|
|
||||||
|
# Adding Platform/SDK for the Linux flatpak release
|
||||||
|
RUN flatpak --user install flathub org.freedesktop.Platform/x86_64/22.08 -y
|
||||||
|
RUN flatpak --user install flathub org.freedesktop.Sdk/x86_64/22.08 -y
|
||||||
|
RUN flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/22.08 -y
|
||||||
|
RUN flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/22.08 -y
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
|
|
||||||
|
# Building example:
|
||||||
|
# docker build -t builder/multiarch_build:1.0 -f Dockerfile .
|
||||||
|
|
||||||
|
# Running example:
|
||||||
|
# docker run -it --privileged=true --rm --name=builder --mount type=bind,source=${PWD},target=/src builder/multiarch_build:1.0 bash
|
@ -1,4 +1,4 @@
|
|||||||
version: 7.6.{build}
|
version: 7.8.{build}
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
Binary file not shown.
BIN
data/DRIVER2/GFX/HQ/fefont.fn2
Normal file
BIN
data/DRIVER2/GFX/HQ/fefont.fn2
Normal file
Binary file not shown.
BIN
data/DRIVER2/GFX/HQ/fefont.tga
Normal file
BIN
data/DRIVER2/GFX/HQ/fefont.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
BIN
data/DRIVER2/GFX/HQ/font2.fn2
Normal file
BIN
data/DRIVER2/GFX/HQ/font2.fn2
Normal file
Binary file not shown.
BIN
data/DRIVER2/GFX/HQ/font2.tga
Normal file
BIN
data/DRIVER2/GFX/HQ/font2.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
5
dockerbuild.sh
Executable file
5
dockerbuild.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
docker build -t builder/multiarch_build:1.0 -f Dockerfile .
|
||||||
|
docker run -it --privileged=true --rm --name=builder --mount type=bind,source=${PWD},target=/src builder/multiarch_build:1.0 ./.appveyor/Build.sh
|
@ -1,9 +1,11 @@
|
|||||||
---
|
|
||||||
app-id: io.github.opendriver2.Redriver2
|
app-id: io.github.opendriver2.Redriver2
|
||||||
runtime: org.freedesktop.Platform
|
runtime: org.freedesktop.Platform
|
||||||
runtime-version: '20.08'
|
runtime-version: &runtime-version '22.08'
|
||||||
rename-icon: 'icon'
|
x-gl-version: &gl-version '1.4'
|
||||||
|
x-gl-versions: &gl-versions 22.08;22.08-extra;1.4
|
||||||
sdk: org.freedesktop.Sdk
|
sdk: org.freedesktop.Sdk
|
||||||
|
separate-locales: false
|
||||||
|
rename-icon: 'icon'
|
||||||
command: start.sh
|
command: start.sh
|
||||||
finish-args:
|
finish-args:
|
||||||
- "--socket=x11"
|
- "--socket=x11"
|
||||||
@ -14,47 +16,66 @@ finish-args:
|
|||||||
- "--persist=."
|
- "--persist=."
|
||||||
- "--allow=multiarch"
|
- "--allow=multiarch"
|
||||||
- "--env=SDL_DYNAMIC_API=/app/lib/i386-linux-gnu/libSDL2-2.0.so.0"
|
- "--env=SDL_DYNAMIC_API=/app/lib/i386-linux-gnu/libSDL2-2.0.so.0"
|
||||||
|
|
||||||
add-extensions:
|
add-extensions:
|
||||||
org.freedesktop.Platform.Compat.i386:
|
org.freedesktop.Platform.Compat.i386:
|
||||||
directory: lib/i386-linux-gnu
|
directory: lib/i386-linux-gnu
|
||||||
version: '20.08'
|
version: *runtime-version
|
||||||
|
|
||||||
org.freedesktop.Platform.Compat.i386.Debug:
|
org.freedesktop.Platform.Compat.i386.Debug:
|
||||||
directory: lib/debug/lib/i386-linux-gnu
|
directory: lib/debug/lib/i386-linux-gnu
|
||||||
version: '20.08'
|
version: *runtime-version
|
||||||
no-autodownload: true
|
no-autodownload: true
|
||||||
|
|
||||||
org.freedesktop.Platform.GL32:
|
org.freedesktop.Platform.GL32:
|
||||||
directory: lib/i386-linux-gnu/GL
|
directory: lib/i386-linux-gnu/GL
|
||||||
version: '20.08'
|
version: *gl-version
|
||||||
|
versions: *gl-versions
|
||||||
subdirectories: true
|
subdirectories: true
|
||||||
no-autodownload: true
|
no-autodownload: true
|
||||||
autodelete: false
|
autodelete: false
|
||||||
add-ld-path: lib
|
add-ld-path: lib
|
||||||
merge-dirs: vulkan/icd.d;glvnd/egl_vendor.d
|
merge-dirs: vulkan/icd.d;glvnd/egl_vendor.d;OpenCL/vendors;lib/dri;lib/d3d;vulkan/explicit_layer.d;vulkan/implicit_layer.d
|
||||||
download-if: active-gl-driver
|
download-if: active-gl-driver
|
||||||
enable-if: active-gl-driver
|
enable-if: active-gl-driver
|
||||||
|
|
||||||
sdk-extensions:
|
sdk-extensions:
|
||||||
- org.freedesktop.Sdk.Compat.i386
|
- org.freedesktop.Sdk.Compat.i386
|
||||||
- org.freedesktop.Sdk.Extension.toolchain-i386
|
- org.freedesktop.Sdk.Extension.toolchain-i386
|
||||||
|
|
||||||
build-options:
|
build-options:
|
||||||
prepend-pkg-config-path: "/app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig"
|
prepend-pkg-config-path: /app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig
|
||||||
ldflags: "-L/app/lib32"
|
ldflags: -L/app/lib32
|
||||||
append-path: "/usr/lib/sdk/toolchain-i386/bin"
|
prepend-path: /usr/lib/sdk/toolchain-i386/bin
|
||||||
env:
|
env:
|
||||||
CC: i686-unknown-linux-gnu-gcc
|
CC: i686-unknown-linux-gnu-gcc
|
||||||
CXX: i686-unknown-linux-gnu-g++
|
CXX: i686-unknown-linux-gnu-g++
|
||||||
libdir: "/app/lib32"
|
libdir: /app/lib32
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
- "/include"
|
- "/include"
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
- name: ld-i386
|
|
||||||
|
- name: platform-bootstrap
|
||||||
buildsystem: simple
|
buildsystem: simple
|
||||||
build-commands:
|
build-commands:
|
||||||
- mkdir -p /app/lib/i386-linux-gnu /app/lib/debug/lib/i386-linux-gnu
|
- |
|
||||||
- install -Dm644 -t /app/etc ld.so.conf
|
set -e
|
||||||
|
mkdir -p /app/bin
|
||||||
|
mkdir -p /app/lib/i386-linux-gnu
|
||||||
|
mkdir -p /app/lib/debug/lib/i386-linux-gnu
|
||||||
|
mkdir -p /app/lib/i386-linux-gnu/GL
|
||||||
|
cp /usr/bin/addr2line /app/bin/
|
||||||
|
cp /usr/lib/x86_64-linux-gnu/libbfd-*.so /app/lib/
|
||||||
|
install -Dm644 -t /app/etc ld.so.conf
|
||||||
|
mkdir -p /app/links/lib
|
||||||
|
ln -srv /app/lib /app/links/lib/x86_64-linux-gnu
|
||||||
|
ln -srv /app/lib32 /app/links/lib/i386-linux-gnu
|
||||||
sources:
|
sources:
|
||||||
- type: shell
|
- type: dir
|
||||||
commands:
|
path: .flatpak
|
||||||
- echo "/app/lib32" > ld.so.conf
|
|
||||||
- name: game
|
- name: game
|
||||||
buildsystem: simple
|
buildsystem: simple
|
||||||
build-commands:
|
build-commands:
|
||||||
|
@ -253,7 +253,7 @@ void plotCarPolyGT3(int numTris, CAR_POLY *src, SVECTOR *vlist, SVECTOR *nlist,
|
|||||||
|
|
||||||
ofse = pg->damageLevel[src->originalindex];
|
ofse = pg->damageLevel[src->originalindex];
|
||||||
|
|
||||||
*(u_int*)&prim->u0 = (src->clut_uv0 & 0xffffU | pg->pciv_clut[palette + (src->clut_uv0 >> 0x10)] << 0x10) + ofse;
|
*(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse;
|
||||||
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
||||||
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ void plotCarPolyGT3Lit(int numTris, CAR_POLY* src, SVECTOR* vlist, SVECTOR* nlis
|
|||||||
|
|
||||||
ofse = pg->damageLevel[src->originalindex];
|
ofse = pg->damageLevel[src->originalindex];
|
||||||
|
|
||||||
*(u_int*)&prim->u0 = (src->clut_uv0 & 0xffffU | pg->pciv_clut[palette + (src->clut_uv0 >> 0x10)] << 0x10) + ofse;
|
*(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse;
|
||||||
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
||||||
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
||||||
|
|
||||||
@ -407,7 +407,7 @@ void plotCarPolyGT3nolight(int numTris, CAR_POLY *src, SVECTOR *vlist, plotCarGl
|
|||||||
|
|
||||||
ofse = pg->damageLevel[src->originalindex];
|
ofse = pg->damageLevel[src->originalindex];
|
||||||
|
|
||||||
*(u_int*)&prim->u0 = (src->clut_uv0 & 0xffffU | pg->pciv_clut[palette + (src->clut_uv0 >> 0x10)] << 0x10) + ofse;
|
*(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse;
|
||||||
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
*(u_int*)&prim->u1 = src->tpage_uv1 + ofse;
|
||||||
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
*(u_int*)&prim->u2 = src->uv3_uv2 + ofse;
|
||||||
|
|
||||||
@ -965,7 +965,8 @@ void buildNewCars(void)
|
|||||||
// [D] [T]
|
// [D] [T]
|
||||||
void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first)
|
void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first)
|
||||||
{
|
{
|
||||||
u_char ptype, clut;
|
ushort clut;
|
||||||
|
u_char ptype, carid;
|
||||||
u_char *polyList;
|
u_char *polyList;
|
||||||
CAR_POLY *cp;
|
CAR_POLY *cp;
|
||||||
|
|
||||||
@ -1074,12 +1075,14 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first)
|
|||||||
{
|
{
|
||||||
POLYGT3* pgt3 = (POLYGT3*)polyList;
|
POLYGT3* pgt3 = (POLYGT3*)polyList;
|
||||||
|
|
||||||
clut = GetCarPalIndex(pgt3->texture_set);
|
carid = GetCarPalIndex(pgt3->texture_set);
|
||||||
civ_clut[clut][pgt3->texture_id][0] = texture_cluts[pgt3->texture_set][pgt3->texture_id];
|
clut = (carid - 1) * 6 * 32 + pgt3->texture_id * 6;
|
||||||
|
|
||||||
|
civ_clut[carid][pgt3->texture_id][0] = texture_cluts[pgt3->texture_set][pgt3->texture_id];
|
||||||
|
|
||||||
cp->vindices = M_INT_4R(pgt3->v0, pgt3->v1, pgt3->v2, 0);
|
cp->vindices = M_INT_4R(pgt3->v0, pgt3->v1, pgt3->v2, 0);
|
||||||
cp->nindices = M_INT_4R(pgt3->n0, pgt3->n1, pgt3->n2, 0);
|
cp->nindices = M_INT_4R(pgt3->n0, pgt3->n1, pgt3->n2, 0);
|
||||||
cp->clut_uv0 = M_INT_2((clut * 384 + pgt3->texture_id * 12 - 384) >> 1, * (ushort*)&pgt3->uv0);
|
cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt3->uv0);
|
||||||
cp->tpage_uv1 = M_INT_2(texture_pages[pgt3->texture_set], *(ushort *)&pgt3->uv1);
|
cp->tpage_uv1 = M_INT_2(texture_pages[pgt3->texture_set], *(ushort *)&pgt3->uv1);
|
||||||
cp->uv3_uv2 = *(ushort *)&pgt3->uv2;
|
cp->uv3_uv2 = *(ushort *)&pgt3->uv2;
|
||||||
cp->originalindex = i;
|
cp->originalindex = i;
|
||||||
@ -1092,12 +1095,14 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first)
|
|||||||
{
|
{
|
||||||
POLYGT4* pgt4 = (POLYGT4*)polyList;
|
POLYGT4* pgt4 = (POLYGT4*)polyList;
|
||||||
|
|
||||||
clut = GetCarPalIndex(pgt4->texture_set);
|
carid = GetCarPalIndex(pgt4->texture_set);
|
||||||
civ_clut[clut][pgt4->texture_id][0] = texture_cluts[pgt4->texture_set][pgt4->texture_id];
|
clut = (carid - 1) * 6 * 32 + pgt4->texture_id * 6;
|
||||||
|
|
||||||
|
civ_clut[carid][pgt4->texture_id][0] = texture_cluts[pgt4->texture_set][pgt4->texture_id];
|
||||||
|
|
||||||
cp->vindices = M_INT_4R(pgt4->v0, pgt4->v1, pgt4->v2, 0);
|
cp->vindices = M_INT_4R(pgt4->v0, pgt4->v1, pgt4->v2, 0);
|
||||||
cp->nindices = M_INT_4R(pgt4->n0, pgt4->n1, pgt4->n2, 0);
|
cp->nindices = M_INT_4R(pgt4->n0, pgt4->n1, pgt4->n2, 0);
|
||||||
cp->clut_uv0 = M_INT_2((clut * 384 + pgt4->texture_id * 12 - 384) >> 1, *(ushort*)&pgt4->uv0);
|
cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt4->uv0);
|
||||||
cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort*)&pgt4->uv1);
|
cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort*)&pgt4->uv1);
|
||||||
cp->uv3_uv2 = *(ushort*)&pgt4->uv2;
|
cp->uv3_uv2 = *(ushort*)&pgt4->uv2;
|
||||||
cp->originalindex = i;
|
cp->originalindex = i;
|
||||||
@ -1106,7 +1111,7 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first)
|
|||||||
|
|
||||||
cp->vindices = M_INT_4R(pgt4->v0, pgt4->v2, pgt4->v3, 0);
|
cp->vindices = M_INT_4R(pgt4->v0, pgt4->v2, pgt4->v3, 0);
|
||||||
cp->nindices = M_INT_4R(pgt4->n0, pgt4->n2, pgt4->n3, 0);
|
cp->nindices = M_INT_4R(pgt4->n0, pgt4->n2, pgt4->n3, 0);
|
||||||
cp->clut_uv0 = M_INT_2((clut * 384 + pgt4->texture_id * 12 - 384) >> 1, *(ushort*)&pgt4->uv0);
|
cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt4->uv0);
|
||||||
cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort *)&pgt4->uv2);
|
cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort *)&pgt4->uv2);
|
||||||
cp->uv3_uv2 = *(ushort *)&pgt4->uv3;
|
cp->uv3_uv2 = *(ushort *)&pgt4->uv3;
|
||||||
cp->originalindex = i;
|
cp->originalindex = i;
|
||||||
@ -1231,7 +1236,7 @@ void MangleWheelModels(void)
|
|||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (++i < 3);
|
}
|
||||||
|
|
||||||
// HACK: Show clean model only in Rio.
|
// HACK: Show clean model only in Rio.
|
||||||
//if (GameLevel == 3)
|
//if (GameLevel == 3)
|
||||||
@ -1265,24 +1270,23 @@ void ProcessPalletLump(char *lump_ptr, int lump_size)
|
|||||||
texnum = buffPtr[1];
|
texnum = buffPtr[1];
|
||||||
tpageindex = buffPtr[2];
|
tpageindex = buffPtr[2];
|
||||||
clut_number = buffPtr[3];
|
clut_number = buffPtr[3];
|
||||||
|
buffPtr += 4;
|
||||||
|
|
||||||
if (clut_number == -1)
|
if (clut_number == -1)
|
||||||
{
|
{
|
||||||
// store clut
|
// store clut
|
||||||
LoadImage(&clutpos, (u_long*)(buffPtr + 4));
|
LoadImage(&clutpos, (u_long*)buffPtr);
|
||||||
|
buffPtr += 8;
|
||||||
|
|
||||||
clutValue = GetClut(clutpos.x, clutpos.y);
|
clutValue = GetClut(clutpos.x, clutpos.y);
|
||||||
*clutTablePtr++ = clutValue;
|
|
||||||
|
|
||||||
IncrementClutNum(&clutpos);
|
IncrementClutNum(&clutpos);
|
||||||
|
|
||||||
buffPtr += 12;
|
*clutTablePtr++ = clutValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// use stored clut
|
// use stored clut
|
||||||
clutValue = clutTable[clut_number];
|
clutValue = clutTable[clut_number];
|
||||||
buffPtr += 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
civ_clut[GetCarPalIndex(tpageindex)][texnum][palette + 1] = clutValue;
|
civ_clut[GetCarPalIndex(tpageindex)][texnum][palette + 1] = clutValue;
|
||||||
|
@ -68,6 +68,8 @@ void ProcessCosmeticsLump(char *lump_ptr, int lump_size)
|
|||||||
car_cosmetics[i] = *(CAR_COSMETICS*)((u_char*)lump_ptr + offset);
|
car_cosmetics[i] = *(CAR_COSMETICS*)((u_char*)lump_ptr + offset);
|
||||||
|
|
||||||
#ifndef PSX
|
#ifndef PSX
|
||||||
|
extern int gContentOverride;
|
||||||
|
if(gContentOverride)
|
||||||
LoadCustomCarCosmetics(&car_cosmetics[i], model);
|
LoadCustomCarCosmetics(&car_cosmetics[i], model);
|
||||||
#endif
|
#endif
|
||||||
FixCarCos(&car_cosmetics[i], model);
|
FixCarCos(&car_cosmetics[i], model);
|
||||||
|
@ -28,7 +28,7 @@ char* DentingFiles[] =
|
|||||||
|
|
||||||
u_char gCarDamageZoneVerts[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_VERTS];
|
u_char gCarDamageZoneVerts[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_VERTS];
|
||||||
u_char gHDCarDamageZonePolys[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_POLYS];
|
u_char gHDCarDamageZonePolys[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_POLYS];
|
||||||
u_char gHDCarDamageLevels[MAX_CAR_MODELS][MAX_DAMAGE_LEVELS];
|
u_char gHDCarDamageLevels[MAX_CAR_MODELS][MAX_DAMAGE_LEVELS]; // the damage level (texture) count for polygons
|
||||||
|
|
||||||
// [D] [T]
|
// [D] [T]
|
||||||
void InitialiseDenting(void)
|
void InitialiseDenting(void)
|
||||||
@ -66,12 +66,11 @@ void DentCar(CAR_DATA *cp)
|
|||||||
// collect vertices from zones
|
// collect vertices from zones
|
||||||
if (pCleanModel != NULL)
|
if (pCleanModel != NULL)
|
||||||
{
|
{
|
||||||
VertNo = 0;
|
for (VertNo = 0; VertNo < pCleanModel->num_vertices; VertNo++)
|
||||||
while (VertNo < pCleanModel->num_vertices)
|
tempDamage[VertNo] = 0;
|
||||||
tempDamage[VertNo++] = 0;
|
|
||||||
|
|
||||||
Zone = 0;
|
for (Zone = 0; Zone < NUM_DAMAGE_ZONES; Zone++)
|
||||||
do {
|
{
|
||||||
Damage = cp->ap.damage[Zone];
|
Damage = cp->ap.damage[Zone];
|
||||||
|
|
||||||
if (Damage > MaxDamage)
|
if (Damage > MaxDamage)
|
||||||
@ -79,21 +78,14 @@ void DentCar(CAR_DATA *cp)
|
|||||||
|
|
||||||
DamPtr = gCarDamageZoneVerts[cp->ap.model][Zone];
|
DamPtr = gCarDamageZoneVerts[cp->ap.model][Zone];
|
||||||
|
|
||||||
VertNo = 0;
|
for (VertNo = 0; VertNo < MAX_DAMAGE_ZONE_VERTS && *DamPtr != 0xFF; VertNo++, DamPtr++)
|
||||||
while (VertNo < MAX_DAMAGE_ZONE_VERTS && *DamPtr != 0xFF)
|
|
||||||
{
|
{
|
||||||
if (tempDamage[*DamPtr] == 0)
|
if (tempDamage[*DamPtr] == 0)
|
||||||
tempDamage[*DamPtr] += Damage;
|
tempDamage[*DamPtr] += Damage;
|
||||||
else
|
else
|
||||||
tempDamage[*DamPtr] += Damage / 2;
|
tempDamage[*DamPtr] += Damage / 2;
|
||||||
|
|
||||||
DamPtr++;
|
|
||||||
|
|
||||||
VertNo++;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Zone++;
|
|
||||||
} while (Zone < NUM_DAMAGE_ZONES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update vertices positon
|
// update vertices positon
|
||||||
@ -102,17 +94,11 @@ void DentCar(CAR_DATA *cp)
|
|||||||
DamVertPtr = (SVECTOR *)gCarDamModelPtr[model]->vertices;
|
DamVertPtr = (SVECTOR *)gCarDamModelPtr[model]->vertices;
|
||||||
CleanVertPtr = (SVECTOR *)gCarCleanModelPtr[model]->vertices;
|
CleanVertPtr = (SVECTOR *)gCarCleanModelPtr[model]->vertices;
|
||||||
|
|
||||||
VertNo = 0;
|
for (VertNo = 0; VertNo < pCleanModel->num_vertices; VertNo++, DamVertPtr++, CleanVertPtr++)
|
||||||
while (VertNo < pCleanModel->num_vertices)
|
|
||||||
{
|
{
|
||||||
gTempCarVertDump[cp->id][VertNo].vx = CleanVertPtr->vx + FIXEDH((DamVertPtr->vx - CleanVertPtr->vx) * tempDamage[VertNo] / 2);
|
gTempCarVertDump[cp->id][VertNo].vx = CleanVertPtr->vx + FIXEDH((DamVertPtr->vx - CleanVertPtr->vx) * tempDamage[VertNo] / 2);
|
||||||
gTempCarVertDump[cp->id][VertNo].vy = CleanVertPtr->vy + FIXEDH((DamVertPtr->vy - CleanVertPtr->vy) * tempDamage[VertNo] / 2);
|
gTempCarVertDump[cp->id][VertNo].vy = CleanVertPtr->vy + FIXEDH((DamVertPtr->vy - CleanVertPtr->vy) * tempDamage[VertNo] / 2);
|
||||||
gTempCarVertDump[cp->id][VertNo].vz = CleanVertPtr->vz + FIXEDH((DamVertPtr->vz - CleanVertPtr->vz) * tempDamage[VertNo] / 2);
|
gTempCarVertDump[cp->id][VertNo].vz = CleanVertPtr->vz + FIXEDH((DamVertPtr->vz - CleanVertPtr->vz) * tempDamage[VertNo] / 2);
|
||||||
|
|
||||||
DamVertPtr++;
|
|
||||||
CleanVertPtr++;
|
|
||||||
|
|
||||||
VertNo++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,21 +108,22 @@ void DentCar(CAR_DATA *cp)
|
|||||||
dentptr = gTempHDCarUVDump[cp->id];
|
dentptr = gTempHDCarUVDump[cp->id];
|
||||||
|
|
||||||
// reset UV coordinates
|
// reset UV coordinates
|
||||||
Poly = 0;
|
|
||||||
while (Poly < pCleanModel->num_polys)
|
for (Poly = 0; Poly < pCleanModel->num_polys; Poly++)
|
||||||
{
|
{
|
||||||
dentptr->u3 = 0;
|
dentptr->u3 = 0;
|
||||||
Poly++;
|
|
||||||
dentptr++;
|
dentptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zone = 0;
|
for(Zone = 0; Zone < NUM_DAMAGE_ZONES; Zone++)
|
||||||
do {
|
{
|
||||||
Damage = cp->ap.damage[Zone];
|
Damage = cp->ap.damage[Zone];
|
||||||
|
|
||||||
Poly = 0;
|
for (Poly = 0; Poly < MAX_DAMAGE_ZONE_POLYS; Poly++)
|
||||||
while (Poly < MAX_DAMAGE_ZONE_POLYS && gHDCarDamageZonePolys[cp->ap.model][Zone][Poly] != 0xFF)
|
|
||||||
{
|
{
|
||||||
|
if (gHDCarDamageZonePolys[cp->ap.model][Zone][Poly] == 0xFF)
|
||||||
|
break;
|
||||||
|
|
||||||
dentptr = gTempHDCarUVDump[cp->id] + gHDCarDamageZonePolys[cp->ap.model][Zone][Poly];
|
dentptr = gTempHDCarUVDump[cp->id] + gHDCarDamageZonePolys[cp->ap.model][Zone][Poly];
|
||||||
|
|
||||||
// add a damage level
|
// add a damage level
|
||||||
@ -145,28 +132,17 @@ void DentCar(CAR_DATA *cp)
|
|||||||
// clamp level
|
// clamp level
|
||||||
if (dentptr->u3 > 2)
|
if (dentptr->u3 > 2)
|
||||||
dentptr->u3 = 2;
|
dentptr->u3 = 2;
|
||||||
|
|
||||||
Poly++;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Zone++;
|
|
||||||
} while (Zone < NUM_DAMAGE_ZONES);
|
|
||||||
|
|
||||||
Poly = 0;
|
|
||||||
|
|
||||||
DamPtr = gHDCarDamageLevels[model];
|
DamPtr = gHDCarDamageLevels[model];
|
||||||
dentptr = gTempHDCarUVDump[cp->id];
|
dentptr = gTempHDCarUVDump[cp->id];
|
||||||
|
|
||||||
while (Poly < pCleanModel->num_polys)
|
for (Poly = 0; Poly < pCleanModel->num_polys; Poly++, DamPtr++, dentptr++)
|
||||||
{
|
{
|
||||||
// calculate the UV offset with strange XORs
|
// calculate the UV offset with strange XORs
|
||||||
if(dentptr->u3 > 0)
|
if(dentptr->u3 > 0)
|
||||||
dentptr->u3 = (*DamPtr ^ 1 ^ (*DamPtr ^ 1 | dentptr->u3)) * 64;
|
dentptr->u3 = (*DamPtr ^ 1 ^ (*DamPtr ^ 1 | dentptr->u3)) * 64;
|
||||||
|
|
||||||
dentptr++;
|
|
||||||
|
|
||||||
DamPtr++;
|
|
||||||
Poly++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,11 +170,9 @@ void CreateDentableCar(CAR_DATA *cp)
|
|||||||
while (vcount-- != -1)
|
while (vcount-- != -1)
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
|
|
||||||
count = 0;
|
for (count = 0; count < srcModel->num_polys; count++)
|
||||||
while (count < srcModel->num_polys)
|
|
||||||
{
|
{
|
||||||
gTempHDCarUVDump[cp->id][count].u3 = 0;
|
gTempHDCarUVDump[cp->id][count].u3 = 0;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -209,11 +183,9 @@ void CreateDentableCar(CAR_DATA *cp)
|
|||||||
srcModel = gCarLowModelPtr[model];
|
srcModel = gCarLowModelPtr[model];
|
||||||
if (srcModel != NULL)
|
if (srcModel != NULL)
|
||||||
{
|
{
|
||||||
count = 0;
|
for (count = 0; count < srcModel->num_polys; count++)
|
||||||
while (count < srcModel->num_polys)
|
|
||||||
{
|
{
|
||||||
gTempLDCarUVDump[cp->id][count].u3 = 0;
|
gTempLDCarUVDump[cp->id][count].u3 = 0;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -223,11 +195,9 @@ void CreateDentableCar(CAR_DATA *cp)
|
|||||||
|
|
||||||
if (gDontResetCarDamage == 0)
|
if (gDontResetCarDamage == 0)
|
||||||
{
|
{
|
||||||
count = 0;
|
for (count = 0; count < NUM_DAMAGE_ZONES; count++)
|
||||||
while (count < NUM_DAMAGE_ZONES)
|
|
||||||
{
|
{
|
||||||
cp->ap.damage[count] = 0;
|
cp->ap.damage[count] = 0;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cp->totalDamage = 0;
|
cp->totalDamage = 0;
|
||||||
@ -436,9 +406,7 @@ void ProcessDentLump(char *lump_ptr, int lump_size)
|
|||||||
int offset;
|
int offset;
|
||||||
u_char* mem;
|
u_char* mem;
|
||||||
|
|
||||||
i = 0;
|
for (i = 0; i < MAX_CAR_MODELS; i++)
|
||||||
|
|
||||||
while (i < MAX_CAR_MODELS)
|
|
||||||
{
|
{
|
||||||
model = MissionHeader->residentModels[i];
|
model = MissionHeader->residentModels[i];
|
||||||
|
|
||||||
@ -457,12 +425,16 @@ void ProcessDentLump(char *lump_ptr, int lump_size)
|
|||||||
offset = *(int *)(lump_ptr + model * 4);
|
offset = *(int *)(lump_ptr + model * 4);
|
||||||
mem = (u_char*)lump_ptr;
|
mem = (u_char*)lump_ptr;
|
||||||
#ifndef PSX
|
#ifndef PSX
|
||||||
|
extern int gContentOverride;
|
||||||
|
if (gContentOverride)
|
||||||
|
{
|
||||||
char* newDenting = LoadCarDentingFromFile(NULL, model);
|
char* newDenting = LoadCarDentingFromFile(NULL, model);
|
||||||
if(newDenting)
|
if (newDenting)
|
||||||
{
|
{
|
||||||
mem = (u_char*)newDenting;
|
mem = (u_char*)newDenting;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memcpy((u_char*)gCarDamageZoneVerts[i], mem + offset, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS);
|
memcpy((u_char*)gCarDamageZoneVerts[i], mem + offset, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS);
|
||||||
@ -473,8 +445,6 @@ void ProcessDentLump(char *lump_ptr, int lump_size)
|
|||||||
|
|
||||||
memcpy((u_char*)gHDCarDamageLevels[i], mem + offset, MAX_FILE_DAMAGE_LEVELS);
|
memcpy((u_char*)gHDCarDamageLevels[i], mem + offset, MAX_FILE_DAMAGE_LEVELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2816,8 +2816,9 @@ u_int hypot(int x, int y)
|
|||||||
|
|
||||||
if (x < y)
|
if (x < y)
|
||||||
{
|
{
|
||||||
|
t = y;
|
||||||
y = x;
|
y = x;
|
||||||
x = y;
|
x = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x < 0x8000)
|
if (x < 0x8000)
|
||||||
|
@ -292,7 +292,7 @@ char* LoadCarModelFromFile(char* dest, int modelNumber, int type)
|
|||||||
char* mem;
|
char* mem;
|
||||||
char filename[64];
|
char filename[64];
|
||||||
|
|
||||||
sprintf(filename, "LEVELS\\%s\\CARMODEL_%d_%s.DMODEL", LevelNames[GameLevel], modelNumber, CarModelTypeNames[type-1]);
|
sprintf(filename, "LEVELS\\%s\\CARMODEL_%d_%s.MDL", LevelNames[GameLevel], modelNumber, CarModelTypeNames[type-1]);
|
||||||
if(FileExists(filename))
|
if(FileExists(filename))
|
||||||
{
|
{
|
||||||
mem = (char*)(dest ? dest : (_other_buffer + modelNumber * 0x10000 + (type-1) * 0x4000));
|
mem = (char*)(dest ? dest : (_other_buffer + modelNumber * 0x10000 + (type-1) * 0x4000));
|
||||||
@ -314,10 +314,18 @@ MODEL* GetCarModel(char *src, char **dest, int KeepNormals, int modelNumber, int
|
|||||||
char* mem;
|
char* mem;
|
||||||
|
|
||||||
#ifndef PSX
|
#ifndef PSX
|
||||||
|
extern int gContentOverride;
|
||||||
|
if (gContentOverride)
|
||||||
|
{
|
||||||
mem = LoadCarModelFromFile(NULL, modelNumber, type);
|
mem = LoadCarModelFromFile(NULL, modelNumber, type);
|
||||||
|
|
||||||
if (!mem) // fallback to lump
|
if (!mem) // fallback to lump
|
||||||
mem = src;
|
mem = src;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mem = src;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
mem = src;
|
mem = src;
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "cars.h"
|
#include "cars.h"
|
||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -611,7 +611,7 @@ void DrawBodySprite(LPPEDESTRIAN pDrawingPed, int boneId, VERTTYPE v1[2], VERTTY
|
|||||||
prims->x3 = v2[0] - FIXEDH(cs) - dx1;
|
prims->x3 = v2[0] - FIXEDH(cs) - dx1;
|
||||||
prims->y3 = v2[1] - FIXEDH(sn) - dy1;
|
prims->y3 = v2[1] - FIXEDH(sn) - dy1;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
if (!bDoingShadow) // [A] Psy-X is currently incorrectly offsets the offscreen PGXP geometry. We don't need it anyway.
|
if (!bDoingShadow) // [A] Psy-X is currently incorrectly offsets the offscreen PGXP geometry. We don't need it anyway.
|
||||||
{
|
{
|
||||||
ushort pgxpIdx = PGXP_GetIndex(0) - 64;
|
ushort pgxpIdx = PGXP_GetIndex(0) - 64;
|
||||||
|
@ -287,7 +287,6 @@ MENU_ITEM DebugOptionsItems[] =
|
|||||||
{
|
{
|
||||||
{ "Spawn position", PAUSE_TYPE_SUBMENU, 2, NULL, MENU_QUIT_NONE, &DebugSpawnPositionHeader },
|
{ "Spawn position", PAUSE_TYPE_SUBMENU, 2, NULL, MENU_QUIT_NONE, &DebugSpawnPositionHeader },
|
||||||
#ifdef CUTSCENE_RECORDER
|
#ifdef CUTSCENE_RECORDER
|
||||||
//{ gCutsceneRecorderPauseText, 5u, 2u, (pauseFunc)&NextCutsceneRecorderPlayer, MENU_QUIT_NONE, NULL },
|
|
||||||
{ gCurrentChasePauseText, 5u, 2u, (pauseFunc)&CutRec_NextChase, MENU_QUIT_NONE, NULL },
|
{ gCurrentChasePauseText, 5u, 2u, (pauseFunc)&CutRec_NextChase, MENU_QUIT_NONE, NULL },
|
||||||
#endif
|
#endif
|
||||||
{ "Display position", PAUSE_TYPE_FUNC, 2, SetDisplayPosition, MENU_QUIT_NONE, NULL},
|
{ "Display position", PAUSE_TYPE_FUNC, 2, SetDisplayPosition, MENU_QUIT_NONE, NULL},
|
||||||
|
@ -7,19 +7,24 @@ extern int gShowMap;
|
|||||||
|
|
||||||
#ifndef PSX
|
#ifndef PSX
|
||||||
|
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
|
||||||
#include "../utils/stb_truetype.h"
|
|
||||||
#include "../utils/targa.h"
|
|
||||||
|
|
||||||
#include "PsyX/PsyX_render.h"
|
#include "PsyX/PsyX_render.h"
|
||||||
|
#include "../utils/targa.h"
|
||||||
|
#include "../utils/hqfont.h"
|
||||||
|
|
||||||
#define HIRES_FONTS
|
#define HIRES_FONTS
|
||||||
#define HIRES_FONT_SIZE_W 768
|
|
||||||
#define HIRES_FONT_SIZE_H 512
|
struct FONT_QUAD
|
||||||
|
{
|
||||||
|
float x0, y0, s0, t0; // top-left
|
||||||
|
float x1, y1, s1, t1; // bottom-right
|
||||||
|
};
|
||||||
|
|
||||||
TextureID gHiresFontTexture = 0;
|
TextureID gHiresFontTexture = 0;
|
||||||
TextureID gHiresDigitsTexture = 0;
|
TextureID gHiresDigitsTexture = 0;
|
||||||
|
|
||||||
stbtt_packedchar gSTBCharData[224]; // ASCII 32..126 is 95 glyphs
|
OUT_FN2RANGE gHiresFontRanges[4];
|
||||||
|
OUT_FN2INFO gHiresFontCharData[4][224];
|
||||||
|
int gHiresFontRangeCount = 0;
|
||||||
|
|
||||||
int gFontScale = 4096;
|
int gFontScale = 4096;
|
||||||
int gLastFontScale = 4096;
|
int gLastFontScale = 4096;
|
||||||
@ -34,7 +39,7 @@ void InitHiresFonts()
|
|||||||
{
|
{
|
||||||
int width, height, bpp;
|
int width, height, bpp;
|
||||||
|
|
||||||
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\DIGITS.TGA");
|
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\digits.tga");
|
||||||
FS_FixPathSlashes(namebuffer);
|
FS_FixPathSlashes(namebuffer);
|
||||||
|
|
||||||
if (LoadTGAImage(namebuffer, &data, width, height, bpp))
|
if (LoadTGAImage(namebuffer, &data, width, height, bpp))
|
||||||
@ -44,50 +49,51 @@ void InitHiresFonts()
|
|||||||
gHiresDigitsTexture = GR_CreateRGBATexture(width, height, data);
|
gHiresDigitsTexture = GR_CreateRGBATexture(width, height, data);
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init font2
|
// init font2
|
||||||
if(!gHiresFontTexture)
|
if(!gHiresFontTexture)
|
||||||
{
|
{
|
||||||
|
gHiresFontRangeCount = 0;
|
||||||
|
|
||||||
|
int width, height, bpp;
|
||||||
int x, y;
|
int x, y;
|
||||||
int size;
|
int size;
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\ariblk.ttf");
|
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\font2.fn2");
|
||||||
|
FS_FixPathSlashes(namebuffer);
|
||||||
|
|
||||||
fp = fopen(namebuffer, "rb");
|
fp = fopen(namebuffer, "rb");
|
||||||
if (fp)
|
if (fp)
|
||||||
{
|
{
|
||||||
// read whole file
|
int i;
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
size = ftell(fp);
|
// read fn2 step by step
|
||||||
fseek(fp, 0, SEEK_SET);
|
OUT_FN2HEADER fn2hdr;
|
||||||
data = (u_char*)malloc(size);
|
fread(&fn2hdr, sizeof(fn2hdr), 1, fp);
|
||||||
fread(data, 1, size, fp);
|
|
||||||
|
gHiresFontRangeCount = fn2hdr.range_count;
|
||||||
|
for (i = 0; i < fn2hdr.range_count; ++i)
|
||||||
|
{
|
||||||
|
fread(&gHiresFontRanges[i], sizeof(gHiresFontRanges[i]), 1, fp);
|
||||||
|
fread(gHiresFontCharData[i], sizeof(OUT_FN2INFO), gHiresFontRanges[i].count, fp);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
// gen font
|
|
||||||
u_char* tmpBitmap = (u_char*)malloc(HIRES_FONT_SIZE_W * HIRES_FONT_SIZE_H);
|
|
||||||
u_int* bitmapRGBA = (u_int*)malloc(HIRES_FONT_SIZE_W * HIRES_FONT_SIZE_H * 4);
|
|
||||||
|
|
||||||
stbtt_pack_context pc;
|
|
||||||
|
|
||||||
stbtt_PackBegin(&pc, tmpBitmap, HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, 0, 1, NULL);
|
|
||||||
stbtt_PackSetOversampling(&pc, 2, 2);
|
|
||||||
stbtt_PackFontRange(&pc, data, 0, 40.0f, 32, 224, gSTBCharData);
|
|
||||||
stbtt_PackEnd(&pc);
|
|
||||||
|
|
||||||
for (x = 0; x < HIRES_FONT_SIZE_W; ++x)
|
|
||||||
{
|
|
||||||
for (y = 0; y < HIRES_FONT_SIZE_H; ++y)
|
|
||||||
{
|
|
||||||
bitmapRGBA[x + y * HIRES_FONT_SIZE_W] = tmpBitmap[x + y * HIRES_FONT_SIZE_W] << 24 | 0xffffff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gHiresFontTexture = GR_CreateRGBATexture(HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, (u_char*)bitmapRGBA);
|
// load TGA file
|
||||||
free(bitmapRGBA);
|
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\font2.tga");
|
||||||
free(tmpBitmap);
|
FS_FixPathSlashes(namebuffer);
|
||||||
|
|
||||||
|
if (LoadTGAImage(namebuffer, &data, width, height, bpp))
|
||||||
|
{
|
||||||
|
if (bpp == 32)
|
||||||
|
{
|
||||||
|
gHiresFontTexture = GR_CreateRGBATexture(HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, data);
|
||||||
|
}
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,15 +140,14 @@ void SetHiresDigitsTexture(int enabled)
|
|||||||
current->primptr += sizeof(DR_PSYX_TEX);
|
current->primptr += sizeof(DR_PSYX_TEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetHiresBakedQuad(int char_index, float* xpos, float* ypos, stbtt_aligned_quad* q)
|
void GetHiresBakedQuad(int char_index, float* xpos, float* ypos, FONT_QUAD* q)
|
||||||
{
|
{
|
||||||
float ipw = 1.0f / (float)HIRES_FONT_SIZE_W;
|
float ipw = 1.0f / (float)HIRES_FONT_SIZE_W;
|
||||||
float iph = 1.0f / (float)HIRES_FONT_SIZE_H;
|
float iph = 1.0f / (float)HIRES_FONT_SIZE_H;
|
||||||
const stbtt_packedchar* b = gSTBCharData + char_index;
|
|
||||||
|
|
||||||
|
const OUT_FN2INFO* b = gHiresFontCharData[0] + char_index - gHiresFontRanges[0].start;
|
||||||
float scaling = gFontScale / 4096.f;
|
float scaling = gFontScale / 4096.f;
|
||||||
|
float scale = 0.275f;
|
||||||
float scale = 0.45f * scaling;
|
|
||||||
|
|
||||||
float s_x = b->x1 - b->x0;
|
float s_x = b->x1 - b->x0;
|
||||||
float s_y = b->y1 - b->y0;
|
float s_y = b->y1 - b->y0;
|
||||||
@ -183,8 +188,8 @@ int StrighWidthHires(char* string)
|
|||||||
float fx, fy;
|
float fx, fy;
|
||||||
fx = 0.0f;
|
fx = 0.0f;
|
||||||
fy = 0.0f;
|
fy = 0.0f;
|
||||||
stbtt_aligned_quad q;
|
FONT_QUAD q;
|
||||||
GetHiresBakedQuad(chr - 32, &fx, &fy, &q);
|
GetHiresBakedQuad(chr, &fx, &fy, &q);
|
||||||
width += fx;
|
width += fx;
|
||||||
}
|
}
|
||||||
return width;
|
return width;
|
||||||
@ -232,8 +237,8 @@ int PrintStringHires(char* string, int x, int y)
|
|||||||
float fx, fy;
|
float fx, fy;
|
||||||
fx = width;
|
fx = width;
|
||||||
fy = y;
|
fy = y;
|
||||||
stbtt_aligned_quad q;
|
FONT_QUAD q;
|
||||||
GetHiresBakedQuad(chr - 32, &fx, &fy, &q);
|
GetHiresBakedQuad(chr, &fx, &fy, &q);
|
||||||
|
|
||||||
fontFT4 = (POLY_FT4*)current->primptr;
|
fontFT4 = (POLY_FT4*)current->primptr;
|
||||||
|
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
|
|
||||||
struct OUT_FONTINFO
|
struct OUT_FONTINFO
|
||||||
{
|
{
|
||||||
u_char x;
|
u_char x, y;
|
||||||
u_char y;
|
char offx, offy;
|
||||||
char offx;
|
u_char width, height;
|
||||||
char offy;
|
|
||||||
u_char width;
|
|
||||||
u_char height;
|
|
||||||
u_short pad;
|
u_short pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ void LoadSky(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// [D] [T]
|
// [D] [T]
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
void DisplaySun(DVECTORF* pos, CVECTOR* col, int flare_col)
|
void DisplaySun(DVECTORF* pos, CVECTOR* col, int flare_col)
|
||||||
#else
|
#else
|
||||||
void DisplaySun(DVECTOR* pos, CVECTOR* col, int flare_col)
|
void DisplaySun(DVECTOR* pos, CVECTOR* col, int flare_col)
|
||||||
@ -393,7 +393,7 @@ void DisplaySun(DVECTOR* pos, CVECTOR* col, int flare_col)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// [D] [T]
|
// [D] [T]
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
void DisplayMoon(DVECTORF* pos, CVECTOR* col, int flip)
|
void DisplayMoon(DVECTORF* pos, CVECTOR* col, int flip)
|
||||||
#else
|
#else
|
||||||
void DisplayMoon(DVECTOR* pos, CVECTOR* col, int flip)
|
void DisplayMoon(DVECTOR* pos, CVECTOR* col, int flip)
|
||||||
@ -492,7 +492,7 @@ void DrawLensFlare(void)
|
|||||||
|
|
||||||
int haze_col;
|
int haze_col;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
DVECTORF sun_pers_conv_position;
|
DVECTORF sun_pers_conv_position;
|
||||||
#else
|
#else
|
||||||
DVECTOR sun_pers_conv_position;
|
DVECTOR sun_pers_conv_position;
|
||||||
@ -649,7 +649,7 @@ void DrawLensFlare(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
// remap
|
// remap
|
||||||
PsyX_GetPSXWidescreenMappedViewport(&viewp);
|
PsyX_GetPSXWidescreenMappedViewport(&viewp);
|
||||||
sun_pers_conv_position.vx = RemapVal(sun_pers_conv_position.vx, float(viewp.x), float(viewp.w), 0.0f, 320.0f);
|
sun_pers_conv_position.vx = RemapVal(sun_pers_conv_position.vx, float(viewp.x), float(viewp.w), 0.0f, 320.0f);
|
||||||
@ -818,7 +818,7 @@ void calc_sky_brightness(RGB16* skycolor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
DVECTORF scratchPad_skyVertices[35]; // 1f800044
|
DVECTORF scratchPad_skyVertices[35]; // 1f800044
|
||||||
#else
|
#else
|
||||||
#define scratchPad_skyVertices ((DVECTOR*)getScratchAddr(0x11)) // 1f800044
|
#define scratchPad_skyVertices ((DVECTOR*)getScratchAddr(0x11)) // 1f800044
|
||||||
@ -834,7 +834,7 @@ void PlotSkyPoly(POLYFT4* polys, int skytexnum, unsigned char r, unsigned char g
|
|||||||
src = polys;
|
src = polys;
|
||||||
poly = (POLY_FT4*)current->primptr;
|
poly = (POLY_FT4*)current->primptr;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
DVECTORF* outpoints = scratchPad_skyVertices;
|
DVECTORF* outpoints = scratchPad_skyVertices;
|
||||||
#else
|
#else
|
||||||
DVECTOR* outpoints = scratchPad_skyVertices;
|
DVECTOR* outpoints = scratchPad_skyVertices;
|
||||||
@ -867,7 +867,7 @@ void PlotSkyPoly(POLYFT4* polys, int skytexnum, unsigned char r, unsigned char g
|
|||||||
|
|
||||||
addPrim(current->ot + OTSIZE - 1, poly);
|
addPrim(current->ot + OTSIZE - 1, poly);
|
||||||
|
|
||||||
#if defined(USE_PGXP) && defined(USE_EXTENDED_PRIM_POINTERS)
|
#if USE_PGXP && USE_EXTENDED_PRIM_POINTERS
|
||||||
poly->pgxp_index = outpoints[src->v0].pgxp_index;
|
poly->pgxp_index = outpoints[src->v0].pgxp_index;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -880,7 +880,7 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset, RGB16* skycolor)
|
|||||||
{
|
{
|
||||||
SVECTOR* verts;
|
SVECTOR* verts;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
DVECTORF* dv;
|
DVECTORF* dv;
|
||||||
#else
|
#else
|
||||||
DVECTOR* dv;
|
DVECTOR* dv;
|
||||||
@ -896,7 +896,7 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset, RGB16* skycolor)
|
|||||||
dv = scratchPad_skyVertices;
|
dv = scratchPad_skyVertices;
|
||||||
count = model->num_vertices;
|
count = model->num_vertices;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, 256.0f);
|
PGXP_SetZOffsetScale(0.0f, 256.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -909,7 +909,7 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset, RGB16* skycolor)
|
|||||||
if(count == 15)
|
if(count == 15)
|
||||||
gte_stszotz(&z);
|
gte_stszotz(&z);
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
// store PGXP index
|
// store PGXP index
|
||||||
// HACK: -1 is needed here for some reason
|
// HACK: -1 is needed here for some reason
|
||||||
dv[0].pgxp_index = dv[1].pgxp_index = dv[2].pgxp_index = PGXP_GetIndex(0) - 1;
|
dv[0].pgxp_index = dv[1].pgxp_index = dv[2].pgxp_index = PGXP_GetIndex(0) - 1;
|
||||||
@ -919,7 +919,7 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset, RGB16* skycolor)
|
|||||||
count -= 3;
|
count -= 3;
|
||||||
} while (count);
|
} while (count);
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -473,10 +473,9 @@ int CompleteSoundSetup(int channel, int bank, int sample, int pitch, int proximi
|
|||||||
|
|
||||||
if (bpf == 0)
|
if (bpf == 0)
|
||||||
{
|
{
|
||||||
channel = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
chan = &channels[channel];
|
chan = &channels[channel];
|
||||||
|
|
||||||
if (gSoundMode == 1 && proximity != -1)
|
if (gSoundMode == 1 && proximity != -1)
|
||||||
@ -506,7 +505,6 @@ int CompleteSoundSetup(int channel, int bank, int sample, int pitch, int proximi
|
|||||||
SpuSetKey(1, chan->attr.voice);
|
SpuSetKey(1, chan->attr.voice);
|
||||||
|
|
||||||
stop_sound_handler = 0;
|
stop_sound_handler = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
@ -591,6 +589,9 @@ int Start3DTrackingSound(int channel, int bank, int sample, VECTOR *position, LO
|
|||||||
|
|
||||||
channel = CompleteSoundSetup(channel, bank, sample, 4096, 0);
|
channel = CompleteSoundSetup(channel, bank, sample, 4096, 0);
|
||||||
|
|
||||||
|
if (channel < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
ComputeDoppler(&channels[channel]);
|
ComputeDoppler(&channels[channel]);
|
||||||
SetChannelPitch(channel, 4096);
|
SetChannelPitch(channel, 4096);
|
||||||
|
|
||||||
@ -619,6 +620,9 @@ int Start3DSoundVolPitch(int channel, int bank, int sample, int x, int y, int z,
|
|||||||
|
|
||||||
channel = CompleteSoundSetup(channel, bank, sample, pitch, 0);
|
channel = CompleteSoundSetup(channel, bank, sample, pitch, 0);
|
||||||
|
|
||||||
|
if (channel < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
ComputeDoppler(&channels[channel]);
|
ComputeDoppler(&channels[channel]);
|
||||||
SetChannelPitch(channel, pitch);
|
SetChannelPitch(channel, pitch);
|
||||||
|
|
||||||
|
@ -715,6 +715,7 @@ void CheckValidSpoolData(void)
|
|||||||
if (models_ready)
|
if (models_ready)
|
||||||
init_spooled_models();
|
init_spooled_models();
|
||||||
|
|
||||||
|
#ifdef PSX
|
||||||
if (spoolactive && check_regions_present())
|
if (spoolactive && check_regions_present())
|
||||||
{
|
{
|
||||||
stopgame();
|
stopgame();
|
||||||
@ -727,6 +728,7 @@ void CheckValidSpoolData(void)
|
|||||||
|
|
||||||
startgame();
|
startgame();
|
||||||
}
|
}
|
||||||
|
#endif // PSX
|
||||||
}
|
}
|
||||||
|
|
||||||
// [D] [T]
|
// [D] [T]
|
||||||
@ -759,14 +761,6 @@ void CheckLoadAreaData(int cellx, int cellz)
|
|||||||
|
|
||||||
spoolptr = (Spool *)(RegionSpoolInfo + spoolinfo_offsets[current_region]);
|
spoolptr = (Spool *)(RegionSpoolInfo + spoolinfo_offsets[current_region]);
|
||||||
|
|
||||||
#ifndef PSX
|
|
||||||
// [A] this fixes spooling not activated bug (reversing bug?)
|
|
||||||
if (LoadedArea != spoolptr->super_region && spoolptr->super_region != 0xFF && old_region != -1)
|
|
||||||
{
|
|
||||||
LoadedArea = spoolptr->super_region;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (old_region == -1 && spoolptr->super_region != 0xFF)
|
if (old_region == -1 && spoolptr->super_region != 0xFF)
|
||||||
{
|
{
|
||||||
// just load the area if no
|
// just load the area if no
|
||||||
@ -778,7 +772,7 @@ void CheckLoadAreaData(int cellx, int cellz)
|
|||||||
|
|
||||||
if (old_region == -1)
|
if (old_region == -1)
|
||||||
LoadedArea = -1;
|
LoadedArea = -1;
|
||||||
else if (/*spoolptr->super_region == 0xFF ||*/ nAreas == 0)
|
else if (spoolptr->super_region == 0xFF && nAreas == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#define BOUNDARY_MIN 15
|
#define BOUNDARY_MIN 15
|
||||||
|
@ -850,7 +850,7 @@ void InitaliseDrawEnv(DB* pBuff, int x, int y, int w, int h)
|
|||||||
pBuff[1].id = 1;
|
pBuff[1].id = 1;
|
||||||
pBuff[1].draw.dfe = 1;
|
pBuff[1].draw.dfe = 1;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
if(NumPlayers == 2)
|
if(NumPlayers == 2)
|
||||||
{
|
{
|
||||||
pBuff[0].draw.clip.x -= 256;
|
pBuff[0].draw.clip.x -= 256;
|
||||||
|
@ -38,7 +38,7 @@ void Tile1x1Lit(MODEL* model)
|
|||||||
else
|
else
|
||||||
ofse = 133;
|
ofse = 133;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f);
|
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ void Tile1x1Lit(MODEL* model)
|
|||||||
polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]);
|
polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ void Tile1x1(MODEL *model)
|
|||||||
else
|
else
|
||||||
ofse = 133;
|
ofse = 133;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f);
|
PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ void Tile1x1(MODEL *model)
|
|||||||
polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]);
|
polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -664,7 +664,7 @@ void TileNxN(MODEL *model, int levels, int Dofse)
|
|||||||
ttype = 0;
|
ttype = 0;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
switch (ttype)
|
switch (ttype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -688,7 +688,7 @@ void TileNxN(MODEL *model, int levels, int Dofse)
|
|||||||
polys += plotContext.polySizes[*polys];
|
polys += plotContext.polySizes[*polys];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
PGXP_SetZOffsetScale(0.0f, 1.0f);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "driver2.h"
|
#include "driver2.h"
|
||||||
|
|
||||||
#include "FEmain.h"
|
#include "FEmain.h"
|
||||||
|
#include "FEtypes.h"
|
||||||
|
|
||||||
#include "C/cd_icon.h"
|
#include "C/cd_icon.h"
|
||||||
|
|
||||||
@ -22,7 +23,259 @@
|
|||||||
#include "C/spool.h"
|
#include "C/spool.h"
|
||||||
#include "C/state.h"
|
#include "C/state.h"
|
||||||
|
|
||||||
#include "FEtypes.h"
|
#ifndef PSX
|
||||||
|
|
||||||
|
#include "PsyX/PsyX_render.h"
|
||||||
|
#include "../utils/targa.h"
|
||||||
|
#include "../utils/hqfont.h"
|
||||||
|
|
||||||
|
#define HIRES_FONTS
|
||||||
|
|
||||||
|
struct FEFONT_QUAD
|
||||||
|
{
|
||||||
|
float x0, y0, s0, t0; // top-left
|
||||||
|
float x1, y1, s1, t1; // bottom-right
|
||||||
|
};
|
||||||
|
|
||||||
|
TextureID gHiresFEFontTexture = 0;
|
||||||
|
OUT_FN2RANGE gHiresFEFontRanges[4];
|
||||||
|
OUT_FN2INFO gHiresFEFontCharData[4][224];
|
||||||
|
int gHiresFEFontRangeCount = 0;
|
||||||
|
|
||||||
|
void InitHiresFEFont()
|
||||||
|
{
|
||||||
|
char namebuffer[64];
|
||||||
|
u_char* data;
|
||||||
|
|
||||||
|
// init font2
|
||||||
|
if (!gHiresFEFontTexture)
|
||||||
|
{
|
||||||
|
gHiresFEFontRangeCount = 0;
|
||||||
|
|
||||||
|
int width, height, bpp;
|
||||||
|
int x, y;
|
||||||
|
int size;
|
||||||
|
FILE* fp;
|
||||||
|
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\fefont.fn2");
|
||||||
|
FS_FixPathSlashes(namebuffer);
|
||||||
|
|
||||||
|
fp = fopen(namebuffer, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// read fn2 step by step
|
||||||
|
OUT_FN2HEADER fn2hdr;
|
||||||
|
fread(&fn2hdr, sizeof(fn2hdr), 1, fp);
|
||||||
|
|
||||||
|
gHiresFEFontRangeCount = fn2hdr.range_count;
|
||||||
|
for (i = 0; i < fn2hdr.range_count; ++i)
|
||||||
|
{
|
||||||
|
fread(&gHiresFEFontRanges[i], sizeof(gHiresFEFontRanges[i]), 1, fp);
|
||||||
|
fread(gHiresFEFontCharData[i], sizeof(OUT_FN2INFO), gHiresFEFontRanges[i].count, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load TGA file
|
||||||
|
sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\fefont.tga");
|
||||||
|
FS_FixPathSlashes(namebuffer);
|
||||||
|
|
||||||
|
if (LoadTGAImage(namebuffer, &data, width, height, bpp))
|
||||||
|
{
|
||||||
|
if (bpp == 32)
|
||||||
|
{
|
||||||
|
gHiresFEFontTexture = GR_CreateRGBATexture(HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, data);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FEGetHiresBakedQuad(int char_index, float scale, float* xpos, float* ypos, FEFONT_QUAD* q)
|
||||||
|
{
|
||||||
|
float ipw = 1.0f / (float)HIRES_FONT_SIZE_W;
|
||||||
|
float iph = 1.0f / (float)HIRES_FONT_SIZE_H;
|
||||||
|
|
||||||
|
const OUT_FN2INFO* b = gHiresFEFontCharData[0] + char_index - gHiresFEFontRanges[0].start;
|
||||||
|
|
||||||
|
float fscale = 0.5f * scale;
|
||||||
|
|
||||||
|
float s_x = b->x1 - b->x0;
|
||||||
|
float s_y = b->y1 - b->y0;
|
||||||
|
|
||||||
|
q->x0 = *xpos + b->xoff * fscale;
|
||||||
|
q->y0 = *ypos + b->yoff * fscale;
|
||||||
|
q->x1 = (b->xoff2 - b->xoff) * fscale;
|
||||||
|
q->y1 = (b->yoff2 - b->yoff) * fscale;
|
||||||
|
|
||||||
|
q->s0 = b->x0 * 255.0f * ipw;
|
||||||
|
q->t0 = b->y0 * 255.0f * iph;
|
||||||
|
q->s1 = s_x * 255.0f * ipw;
|
||||||
|
q->t1 = s_y * 255.0f * iph;
|
||||||
|
|
||||||
|
q->y0 += 32.0f;
|
||||||
|
|
||||||
|
*xpos += b->xadvance * fscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHiresFEFontTexture(int enabled)
|
||||||
|
{
|
||||||
|
if (gHiresFEFontTexture == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DR_PSYX_TEX* tex = (DR_PSYX_TEX*)current->primptr;
|
||||||
|
if (enabled)
|
||||||
|
SetPsyXTexture(tex, gHiresFEFontTexture, 255, 255);
|
||||||
|
else
|
||||||
|
SetPsyXTexture(tex, 0, 0, 0);
|
||||||
|
|
||||||
|
addPrim(current->ot + 1, tex);
|
||||||
|
current->primptr += sizeof(DR_PSYX_TEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FEStringWidthHires(char* string)
|
||||||
|
{
|
||||||
|
char* pString = string;
|
||||||
|
u_char c = 0;
|
||||||
|
|
||||||
|
int w = 0;
|
||||||
|
|
||||||
|
while ((c = *pString++) != 0)
|
||||||
|
{
|
||||||
|
float fx, fy;
|
||||||
|
fx = 0;
|
||||||
|
fy = 0;
|
||||||
|
FEFONT_QUAD q;
|
||||||
|
FEGetHiresBakedQuad(c, 1.0f, &fx, &fy, &q);
|
||||||
|
|
||||||
|
w += fx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FEPrintStringSizedHires(char* string, int x, int y, int scale, int transparent, int r, int g, int b)
|
||||||
|
{
|
||||||
|
if (current == NULL || string == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
POLY_FT4* shadow;
|
||||||
|
POLY_FT4* font;
|
||||||
|
u_char let;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
|
||||||
|
SetHiresFEFontTexture(0);
|
||||||
|
font = (POLY_FT4*)current->primptr;
|
||||||
|
|
||||||
|
while ((let = *string++) != 0)
|
||||||
|
{
|
||||||
|
if (let == '\n')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float fx, fy;
|
||||||
|
fx = x;
|
||||||
|
fy = y;
|
||||||
|
FEFONT_QUAD q;
|
||||||
|
FEGetHiresBakedQuad(let, scale / 4096.0f, &fx, &fy, &q);
|
||||||
|
|
||||||
|
setPolyFT4(font);
|
||||||
|
setSemiTrans(font, 1);
|
||||||
|
|
||||||
|
setRGB0(font, r, g, b);
|
||||||
|
setUVWH(font, q.s0, q.t0, q.s1, q.t1);
|
||||||
|
setXYWH(font, q.x0, q.y0, q.x1, q.y1);
|
||||||
|
|
||||||
|
font->clut = 0;
|
||||||
|
font->tpage = 0;
|
||||||
|
|
||||||
|
addPrim(current->ot + 1, font);
|
||||||
|
shadow = font + 1;
|
||||||
|
|
||||||
|
// add shadow poly
|
||||||
|
memcpy(shadow, font, sizeof(POLY_FT4));
|
||||||
|
setRGB0(shadow, 10, 10, 10);
|
||||||
|
setXYWH(shadow, q.x0 + 1.0f, q.y0 + 1.0f, q.x1, q.y1);
|
||||||
|
|
||||||
|
addPrim(current->ot + 1, shadow);
|
||||||
|
font += 2;
|
||||||
|
|
||||||
|
// make room for next character
|
||||||
|
x += fx - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set tail
|
||||||
|
current->primptr = (char*)font;
|
||||||
|
SetHiresFEFontTexture(1);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FEPrintStringHires(char* string, float x, float y, int justification, int r, int g, int b)
|
||||||
|
{
|
||||||
|
POLY_FT4* shadow;
|
||||||
|
POLY_FT4* font;
|
||||||
|
u_char let;
|
||||||
|
|
||||||
|
if (justification & 4)
|
||||||
|
{
|
||||||
|
x -= FEStringWidthHires(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHiresFEFontTexture(0);
|
||||||
|
font = (POLY_FT4*)current->primptr;
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
while ((let = *string++) != 0)
|
||||||
|
{
|
||||||
|
float fx, fy;
|
||||||
|
fx = x;
|
||||||
|
fy = y;
|
||||||
|
FEFONT_QUAD q;
|
||||||
|
FEGetHiresBakedQuad(let, 1.0f, &fx, &fy, &q);
|
||||||
|
|
||||||
|
setPolyFT4(font);
|
||||||
|
setSemiTrans(font, 1);
|
||||||
|
|
||||||
|
setRGB0(font, r, g, b);
|
||||||
|
setUVWH(font, q.s0, q.t0, q.s1, q.t1);
|
||||||
|
setXYWH(font, q.x0, q.y0, q.x1, q.y1);
|
||||||
|
|
||||||
|
font->clut = 0;
|
||||||
|
font->tpage = 0;
|
||||||
|
|
||||||
|
addPrim(current->ot + 1, font);
|
||||||
|
shadow = font + 1;
|
||||||
|
|
||||||
|
// add shadow poly
|
||||||
|
memcpy(shadow, font, sizeof(POLY_FT4));
|
||||||
|
setRGB0(shadow, 10, 10, 10);
|
||||||
|
setXYWH(shadow, q.x0 + 1.0f, q.y0 + 1.0f, q.x1, q.y1);
|
||||||
|
|
||||||
|
addPrim(current->ot + 1, shadow);
|
||||||
|
font += 2;
|
||||||
|
|
||||||
|
// add space for next character
|
||||||
|
x += fx - x;
|
||||||
|
|
||||||
|
if (++counter >= 32)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set tail
|
||||||
|
current->primptr = (char *)font;
|
||||||
|
|
||||||
|
SetHiresFEFontTexture(1);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PSX
|
||||||
|
|
||||||
#define FE_OTSIZE 16
|
#define FE_OTSIZE 16
|
||||||
|
|
||||||
@ -1005,7 +1258,7 @@ void DisplayOnScreenText(void)
|
|||||||
text = "Incompatible controller in Port 1";
|
text = "Incompatible controller in Port 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
FEPrintStringSized(text, 40, 400, 0xc00, transparent, 64, 64, 64);
|
FEPrintStringSized(text, 40, 400, 3072, transparent, 64, 64, 64);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1019,14 +1272,14 @@ void DisplayOnScreenText(void)
|
|||||||
strcat(ScreenTitle, ScreenNames[i]);
|
strcat(ScreenTitle, ScreenNames[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FEPrintStringSized(ScreenTitle, 40, 400, 0xc00, 1, 64, 64, 64);
|
FEPrintStringSized(ScreenTitle, 40, 400, 3072, 1, 64, 64, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iScreenSelect == SCREEN_CUTSCENE)
|
if (iScreenSelect == SCREEN_CUTSCENE)
|
||||||
{
|
{
|
||||||
text = GET_MISSION_TXT(CutSceneNames[cutSelection + CutAmountsTotal[currCity]]);
|
text = GET_MISSION_TXT(CutSceneNames[cutSelection + CutAmountsTotal[currCity]]);
|
||||||
|
|
||||||
FEPrintStringSized(text, 100, 226, 0xc00, 1, 64, 64, 64);
|
FEPrintStringSized(text, 100, 226, 3072, 1, 64, 64, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iScreenSelect == SCREEN_TIMEOFDAY)
|
if (iScreenSelect == SCREEN_TIMEOFDAY)
|
||||||
@ -2170,6 +2423,9 @@ void SetFEDrawMode(void)
|
|||||||
void InitFrontend(void)
|
void InitFrontend(void)
|
||||||
{
|
{
|
||||||
InitCdIcon();
|
InitCdIcon();
|
||||||
|
#ifdef HIRES_FONTS
|
||||||
|
InitHiresFEFont();
|
||||||
|
#endif
|
||||||
|
|
||||||
ResetGraph(1);
|
ResetGraph(1);
|
||||||
SetDispMask(0);
|
SetDispMask(0);
|
||||||
@ -2322,9 +2578,15 @@ int FEStringWidth(char* string)
|
|||||||
{
|
{
|
||||||
char* pString = string;
|
char* pString = string;
|
||||||
u_char c = 0;
|
u_char c = 0;
|
||||||
|
|
||||||
int w = 0;
|
int w = 0;
|
||||||
|
|
||||||
|
#ifdef HIRES_FONTS
|
||||||
|
if (gHiresFEFontTexture)
|
||||||
|
{
|
||||||
|
return FEStringWidthHires(string);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
while ((c = *pString++) != 0)
|
while ((c = *pString++) != 0)
|
||||||
{
|
{
|
||||||
if (c == ' ')
|
if (c == ' ')
|
||||||
@ -2342,29 +2604,23 @@ int FEPrintString(char *string, int x, int y, int justification, int r, int g, i
|
|||||||
if (current == NULL || string == NULL)
|
if (current == NULL || string == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#ifdef HIRES_FONTS
|
||||||
|
if (gHiresFEFontTexture)
|
||||||
|
{
|
||||||
|
return FEPrintStringHires(string, x, y, justification, r, g, b);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
FE_CHARDATA *pFontInfo;
|
FE_CHARDATA *pFontInfo;
|
||||||
SPRT *font;
|
SPRT *font;
|
||||||
u_char let;
|
u_char let;
|
||||||
|
|
||||||
font = (SPRT *)current->primptr;
|
|
||||||
|
|
||||||
if (justification & 4)
|
if (justification & 4)
|
||||||
{
|
{
|
||||||
char *pString = string;
|
x -= FEStringWidth(string);
|
||||||
u_char c = 0;
|
|
||||||
|
|
||||||
int w = 0;
|
|
||||||
|
|
||||||
while ((c = *pString++) != 0)
|
|
||||||
{
|
|
||||||
if (c == ' ')
|
|
||||||
w += 4;
|
|
||||||
else
|
|
||||||
w += feFont.CharInfo[c].w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x -= w;
|
font = (SPRT*)current->primptr;
|
||||||
}
|
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
@ -2423,6 +2679,13 @@ int FEPrintStringSized(char *string, int x, int y, int scale, int transparent, i
|
|||||||
if (current == NULL || string == NULL)
|
if (current == NULL || string == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#ifdef HIRES_FONTS
|
||||||
|
if (gHiresFEFontTexture)
|
||||||
|
{
|
||||||
|
return FEPrintStringSizedHires(string, x, y, scale, transparent, r, g, b);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
POLY_FT4 *font;
|
POLY_FT4 *font;
|
||||||
FE_CHARDATA *pFontInfo;
|
FE_CHARDATA *pFontInfo;
|
||||||
u_char let;
|
u_char let;
|
||||||
@ -2491,10 +2754,10 @@ int CentreScreen(int bSetup)
|
|||||||
char text[32];
|
char text[32];
|
||||||
|
|
||||||
sprintf(text, "X1: %d, Y1: %d", current->disp.screen.x, current->disp.screen.y);
|
sprintf(text, "X1: %d, Y1: %d", current->disp.screen.x, current->disp.screen.y);
|
||||||
FEPrintStringSized(text, 25, 50, 0xC00, 0, 128, 0, 0);
|
FEPrintStringSized(text, 25, 50, 3072, 0, 128, 0, 0);
|
||||||
|
|
||||||
sprintf(text, "X2: %d, Y2: %d", last->disp.screen.x, last->disp.screen.y);
|
sprintf(text, "X2: %d, Y2: %d", last->disp.screen.x, last->disp.screen.y);
|
||||||
FEPrintStringSized(text, 25, 75, 0xC00, 0, 128, 0, 0);
|
FEPrintStringSized(text, 25, 75, 3072, 0, 128, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (feNewPad & MPAD_CROSS)
|
if (feNewPad & MPAD_CROSS)
|
||||||
|
@ -160,26 +160,6 @@ struct MODEL
|
|||||||
int normals;
|
int normals;
|
||||||
int point_normals;
|
int point_normals;
|
||||||
int collision_block;
|
int collision_block;
|
||||||
|
|
||||||
SVECTOR* pVertex(int i) const
|
|
||||||
{
|
|
||||||
return (SVECTOR *)(((u_char *)this) + vertices) + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
SVECTOR* pNormal(int i) const
|
|
||||||
{
|
|
||||||
return (SVECTOR *)(((u_char *)this) + point_normals) + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
COLLISION_PACKET* pCollisionPacket(int i) const
|
|
||||||
{
|
|
||||||
return (COLLISION_PACKET *)(((u_char *)this) + collision_block) + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* pPolyAt(int ofs) const
|
|
||||||
{
|
|
||||||
return (char *)(((u_char *)this) + poly_block + ofs);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef GAME_VERSION_N
|
#ifndef GAME_VERSION_N
|
||||||
#define GAME_VERSION_N "7.6"
|
#define GAME_VERSION_N "7.8"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GAME_VERSION_RES
|
#ifndef GAME_VERSION_RES
|
||||||
#define GAME_VERSION_RES 7,6
|
#define GAME_VERSION_RES 7,8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GAME_TITLE "REDRIVER2"
|
#define GAME_TITLE "REDRIVER2"
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
require "premake_modules/usage"
|
require "premake_modules/usage"
|
||||||
require "premake_modules/emscripten"
|
require "premake_modules/emscripten"
|
||||||
|
|
||||||
|
IS_ANDROID = (_ACTION == "androidndk")
|
||||||
|
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
newoption {
|
newoption {
|
||||||
@ -58,6 +60,7 @@ workspace "REDRIVER2"
|
|||||||
"-Wno-parentheses",
|
"-Wno-parentheses",
|
||||||
"-Wno-format",
|
"-Wno-format",
|
||||||
}
|
}
|
||||||
|
|
||||||
linkoptions {
|
linkoptions {
|
||||||
"-s TOTAL_MEMORY=1073741824",
|
"-s TOTAL_MEMORY=1073741824",
|
||||||
"-s USE_SDL=2",
|
"-s USE_SDL=2",
|
||||||
@ -80,6 +83,51 @@ workspace "REDRIVER2"
|
|||||||
"{COPY} " .. WEBSHELL_PATH .. "/lsfs.js %{cfg.buildtarget.directory}"
|
"{COPY} " .. WEBSHELL_PATH .. "/lsfs.js %{cfg.buildtarget.directory}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elseif IS_ANDROID then
|
||||||
|
system "android"
|
||||||
|
shortcommands "On"
|
||||||
|
|
||||||
|
platforms {
|
||||||
|
"android-arm", "android-arm64"
|
||||||
|
}
|
||||||
|
|
||||||
|
disablewarnings {
|
||||||
|
"c++11-narrowing",
|
||||||
|
"constant-conversion",
|
||||||
|
"writable-strings",
|
||||||
|
"unused-value",
|
||||||
|
"switch",
|
||||||
|
"shift-op-parentheses",
|
||||||
|
"parentheses",
|
||||||
|
"format",
|
||||||
|
}
|
||||||
|
|
||||||
|
buildoptions {
|
||||||
|
"-fpermissive",
|
||||||
|
"-fexceptions",
|
||||||
|
"-pthread",
|
||||||
|
}
|
||||||
|
|
||||||
|
linkoptions {
|
||||||
|
"--no-undefined",
|
||||||
|
"-fexceptions",
|
||||||
|
"-pthread",
|
||||||
|
|
||||||
|
"-mfloat-abi=softfp", -- force NEON to be used
|
||||||
|
"-mfpu=neon"
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "platforms:*-x86"
|
||||||
|
architecture "x86"
|
||||||
|
|
||||||
|
filter "platforms:*-x86_64"
|
||||||
|
architecture "x86_64"
|
||||||
|
|
||||||
|
filter "platforms:*-arm"
|
||||||
|
architecture "arm"
|
||||||
|
|
||||||
|
filter "platforms:*-arm64"
|
||||||
|
architecture "arm64"
|
||||||
else
|
else
|
||||||
platforms { "x86" } --, "x86_64" }
|
platforms { "x86" } --, "x86_64" }
|
||||||
end
|
end
|
||||||
@ -137,6 +185,9 @@ end
|
|||||||
-- Psy-Cross layer
|
-- Psy-Cross layer
|
||||||
include "premake5_psycross.lua"
|
include "premake5_psycross.lua"
|
||||||
|
|
||||||
|
-- font tool
|
||||||
|
include "premake5_font_tool.lua"
|
||||||
|
|
||||||
-- game iteslf
|
-- game iteslf
|
||||||
project "REDRIVER2"
|
project "REDRIVER2"
|
||||||
kind "WindowedApp"
|
kind "WindowedApp"
|
||||||
@ -175,7 +226,6 @@ project "REDRIVER2"
|
|||||||
"utils/**.cpp",
|
"utils/**.cpp",
|
||||||
"utils/**.c",
|
"utils/**.c",
|
||||||
"redriver2_psxpc.cpp",
|
"redriver2_psxpc.cpp",
|
||||||
"DebugOverlay.cpp",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filter "platforms:emscripten"
|
filter "platforms:emscripten"
|
||||||
|
33
src_rebuild/premake5_font_tool.lua
Normal file
33
src_rebuild/premake5_font_tool.lua
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
-- Font generator tool
|
||||||
|
project "FontTool"
|
||||||
|
kind "ConsoleApp"
|
||||||
|
language "C++"
|
||||||
|
targetdir "bin/%{cfg.buildcfg}"
|
||||||
|
|
||||||
|
files {
|
||||||
|
"tools/font_tool/**.h",
|
||||||
|
"tools/font_tool/**.H",
|
||||||
|
"tools/font_tool/**.c",
|
||||||
|
"tools/font_tool/**.C",
|
||||||
|
"tools/font_tool/**.cpp",
|
||||||
|
"tools/font_tool/**.CPP",
|
||||||
|
"utils/stb_truetype.*",
|
||||||
|
"utils/targa.*",
|
||||||
|
}
|
||||||
|
|
||||||
|
defines { }
|
||||||
|
|
||||||
|
includedirs {
|
||||||
|
"utils",
|
||||||
|
"PsyCross/include/psx"
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "system:Windows"
|
||||||
|
defines { "_WINDOWS" }
|
||||||
|
|
||||||
|
filter "configurations:Release"
|
||||||
|
optimize "Speed"
|
||||||
|
|
||||||
|
filter "configurations:Release_dev"
|
||||||
|
optimize "Speed"
|
||||||
|
|
27
src_rebuild/premake_modules/androidndk/LICENSE.txt
Normal file
27
src_rebuild/premake_modules/androidndk/LICENSE.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2021 Vitaliy Triang3l Kuzmin.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of premake-androidndk nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
541
src_rebuild/premake_modules/androidndk/README.md
Normal file
541
src_rebuild/premake_modules/androidndk/README.md
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
# premake-androidndk
|
||||||
|
|
||||||
|
A module for generation of ndk-build Android.mk files for [Premake 5](https://premake.github.io/).
|
||||||
|
|
||||||
|
* Providing the same level of **multi-ABI building capabilities** as hand-written Android.mk files, allowing for building for multiple ABIs from one ndk-build invocation and supporting ABI filtering for most of the project settings.
|
||||||
|
* Supporting all languages accepted by ndk-build — C, C++, the GNU Assembler, Yasm, RenderScript, as well as prebuilt libraries and external Android.mk files.
|
||||||
|
* Focused on supporting as many Premake project settings as possible, with attention to coverage of edge cases such as allowed characters.
|
||||||
|
* Preferring exposing Android.mk settings through existing Premake project settings over adding new ones where semantically appropriate to allow porting of projects from other targets with minimal changes.
|
||||||
|
|
||||||
|
Available under the [Unlicense](UNLICENSE.txt), or, similar to Premake, the [BSD 3-Clause “New” or “Revised” License](LICENSE.txt).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Generating Android.mk files
|
||||||
|
|
||||||
|
Clone or download the module, and `require("path/to/premake-androidndk/androidndk")` in your workspace's Premake script. Use the `androidndk` action to perform generation.
|
||||||
|
|
||||||
|
All projects — which represent ndk-build modules — in the application must be located in a single workspace, as a workspace corresponds to an Application.mk file and the root Android.mk.
|
||||||
|
|
||||||
|
Add Android platform definitions to the `platforms` of your workspace or the projects in it. This is especially important in two cases — if your workspace targets other operating systems alongside Android, and if you want to specify ABI-specific settings. Using `configurations` for this purpose also works, but generally it's recommended to use the configuration axis for build flavors such as debug/release, while doing all platform and architecture filtering via the platform axis — and due to the nature of specifying platforms and configurations to be built by ndk-build for Android.mk files generated by this module, mixing the two may result in complicated setup and unnecessary duplication of arguments you'll need to pass to ndk-build.
|
||||||
|
|
||||||
|
**Specify the `system` as `"android"`** in your Android platforms and configurations. While this module doesn't check the value of `system` anywhere internally, if it's not specified, Premake will assume that the host OS is the target, which may be undesirable — for instance, build libraries may not have the `"lib"` prefix if the `system` is selected as `"windows"`.
|
||||||
|
|
||||||
|
If you need to specify settings that apply only to certain ABIs, you can specify separate `platforms` (or `configurations`) with different `architecture` values. The supported architectures are `"ARM"` (corresponds to the `armeabi-v7a` ABI), `"ARM64"` (`arm64-v8a` ABI), `"x86"` (`x86` ABI) and `"x86_64"` (`x86_64` ABI).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
configurations({"Debug", "Release")
|
||||||
|
platforms({"Windows-x86_64", "Android-ARM64", "Android-x86_64"})
|
||||||
|
filter({"platforms:Windows-*"})
|
||||||
|
system("windows")
|
||||||
|
systemversion("10.0")
|
||||||
|
filter({"platforms:Android-*"})
|
||||||
|
system("android")
|
||||||
|
systemversion("24")
|
||||||
|
cppstl("c++")
|
||||||
|
filter({"platforms:*-x86_64"})
|
||||||
|
architecture("x86_64")
|
||||||
|
filter({"platforms:*-ARM64"})
|
||||||
|
architecture("ARM64")
|
||||||
|
filter({})
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also possible to specify both architecture-specific and architecture-agnostic (with a nil or `"universal"` architecture) platforms in the same project. In this case, the architecture specialization will be chosen when ndk-build is building for an ABI for which one available, and the architecture-independent settings will be used as a fallback if one is not:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
platforms({"AndroidOther", "AndroidARMv7", "AndroidARMv8"})
|
||||||
|
filter({"platforms:AndroidARMv7"})
|
||||||
|
architecture("ARM")
|
||||||
|
filter({"platforms:AndroidARMv8"})
|
||||||
|
architecture("ARM64")
|
||||||
|
filter({"architecture:ARM or ARM64"})
|
||||||
|
files({"neonmath.cpp"})
|
||||||
|
filter({})
|
||||||
|
-- `armeabi-v7a` ABI will use the AndroidARMv7 platform with neonmath.cpp.
|
||||||
|
-- `arm64-v8a` ABI will use the AndroidARMv8 platform with neonmath.cpp.
|
||||||
|
-- `x86` and `x86_64` ABIs will use the AndroidOther platform without neonmath.cpp.
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that deprecated ABIs such as `armeabi`, `armeabi-v7a-hard`, `mips`, `mips64` are not supported. `armeabi-v7a` builds by default will have NEON enabled and will use the Thumb instruction set for release configurations, this can be changed via settings listed in the section below.
|
||||||
|
|
||||||
|
It is important to consider that **Premake settings such as `architecture` are assigned to configuration–platform pairs**. So, if you want to use `filter({"architecture:"})`, you **must create a platform or a configuration for that architecture**, otherwise it will not work.
|
||||||
|
|
||||||
|
To exclude a project from building for certain ABIs, you can set its `kind` to `None` with the required filter.
|
||||||
|
|
||||||
|
Most settings allow GNU make variable expansion and function call passthrough, so you can use environment variables, or variables and functions provided by ndk-build like `$(TARGET_ARCH_ABI)`, in your projects, and they will be expanded at build time. You need to be careful not to reference variables or functions that may result in disallowed characters in the specific context, such as whitespaces in settings that end up being written to a list variable, however — it's not possible for the module to validate the value in this case. To use the dollar sign as a character, specify `$$` instead. Paths starting with a dollar sign (even if it's `$$` denoting an escaped raw `$` character) are treated as absolute by Premake, allowing for the usage of paths relative to directories such as `$(NDK_ROOT)`. If you want to override this behavior, explicitly prefix the path with `./`.
|
||||||
|
|
||||||
|
#### Usage of prebuilt libraries and external Android.mk files
|
||||||
|
|
||||||
|
Normally, this module provides functionality for building of projects from source code.
|
||||||
|
|
||||||
|
However, it also exposes the prebuilt library functionality of ndk-build. This is the recommended way of including non-system library binaries in the workspace and linking projects against them, as it lets ndk-build properly ensure that the library is copied into the destination directory properly and that it's loaded from the correct path. ndk-build will generate warnings if the project is linked against non-system libraries via system `links` or via `linkoptions`.
|
||||||
|
|
||||||
|
In addition, it's also possible to create a project that will use an external Android.mk file instead of its own settings (certain settings still must be correctly specified for linkage purposes, however).
|
||||||
|
|
||||||
|
To create a project using a prebuilt library or an external Android.mk file, specify **just one `.a`, `.so` or `.mk` file** and **no other source files** in the `files` setting for the desired configurations/platforms. Also, you **must specify the correct `kind`** of the project — `"SharedLib"` for `.so`, `"StaticLib"` for `.a`, or the kind that matches the actual build script included in the external Android.mk.
|
||||||
|
|
||||||
|
Projects using an external Android.mk files have special rules regarding their usage, specifically:
|
||||||
|
|
||||||
|
- The external Android.mk must contain settings for only at most one project (module).
|
||||||
|
- The `kind` of the project must match the build script used in the external Android.mk — `"SharedLib"` for `BUILD_SHARED_LIBRARY` or `PREBUILT_SHARED_LIBRARY`, `"StaticLib"` for `BUILD_STATIC_LIBRARY` or `PREBUILT_STATIC_LIBRARY`, `"ConsoleApp"` for `BUILD_EXECUTABLE`. **Do not use the `"Makefile"` kind** — it has a completely different purpose, and is not supported by this module. The module must know the actual `kind` for linkage.
|
||||||
|
- The name of the project must be the same as `LOCAL_MODULE` in the external Android.mk.
|
||||||
|
|
||||||
|
The following settings have effect when used in a prebuilt library project or an external Android.mk project:
|
||||||
|
|
||||||
|
- `configurations`
|
||||||
|
- `flags`
|
||||||
|
- `"ExcludeFromBuild"`
|
||||||
|
- `"LinkTimeOptimization"` (for static libraries, if any object files in it are built with `-flto`)
|
||||||
|
- `linkoptions` (the only supported options are `-u` or `-Wl,--undefined` exported from static libraries)
|
||||||
|
- `links` (must match `LOCAL_SHARED_LIBRARIES` and `LOCAL_STATIC_LIBRARIES`/`LOCAL_WHOLE_STATIC_LIBRARIES` for external Android.mk projects referencing other Premake projects, external or not; also, for static libraries, must include the system libraries from `LOCAL_EXPORT_LDLIBS`)
|
||||||
|
- `location` (or `basedir` if not provided)
|
||||||
|
- `kind`
|
||||||
|
- `platforms`
|
||||||
|
- `project` (must match `LOCAL_MODULE` in the external Android.mk)
|
||||||
|
- `wholelib`
|
||||||
|
|
||||||
|
For example, to add the Android Native App Glue to your workspace, you can create a project with the following settings:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
project("android_native_app_glue")
|
||||||
|
kind("StaticLib")
|
||||||
|
files({"$(NDK_ROOT)/sources/android/native_app_glue/Android.mk"})
|
||||||
|
links({"log", "android"})
|
||||||
|
linkoptions({"-u ANativeActivity_onCreate"})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### RenderScript library linkage
|
||||||
|
|
||||||
|
To link projects with RenderScript sources, you may need to add some of these prebuilt library projects to your workspace (most importantly `"RScpp_static"`) and to specify them in `links` of the projects that use RenderScript:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
project("RSSupport")
|
||||||
|
kind("SharedLib")
|
||||||
|
files({"$(RENDERSCRIPT_TOOLCHAIN_PREBUILT_ROOT)/platform/$(TARGET_ARCH)/libRSSupport.so"})
|
||||||
|
project("RSSupportIO")
|
||||||
|
kind("SharedLib")
|
||||||
|
files({"$(RENDERSCRIPT_TOOLCHAIN_PREBUILT_ROOT)/platform/$(TARGET_ARCH)/libRSSupportIO.so"})
|
||||||
|
project("blasV8")
|
||||||
|
kind("SharedLib")
|
||||||
|
files({"$(RENDERSCRIPT_TOOLCHAIN_PREBUILT_ROOT)/platform/$(TARGET_ARCH)/libblasV8.so"})
|
||||||
|
project("RScpp_static")
|
||||||
|
kind("StaticLib")
|
||||||
|
files({"$(RENDERSCRIPT_TOOLCHAIN_PREBUILT_ROOT)/platform/$(TARGET_ARCH)/libRScpp_static.a"})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Invoking ndk-build
|
||||||
|
|
||||||
|
#### Setting up applicaton settings
|
||||||
|
|
||||||
|
The basic setup is different depending on whether you're using the `externalNativeBuild` functionality of Gradle to build the application.
|
||||||
|
|
||||||
|
The module generates an Application.mk file containing basic settings for the entire application, with some support for Premake configuration and platform filtering that may be useful, for instance, for choosing `APP_DEBUG` and `APP_OPTIM` based on the selected configuration. However, as ABI filtering is not available in Application.mk, it will be more coarse than for settings that go to Android.mk — it is assumed that all Application.mk-level settings should not depend on the target ABI, you can see the exact list of the settings that go to Application.mk in the list of supported project settings.
|
||||||
|
|
||||||
|
If you're launching ndk-build as a custom task, or not using Gradle at all, you need to specify the path to the Application.mk in the ndk-build command arguments, as `NDK_APPLICATION_MK:=path/to/WORKSPACE_NAME.Application.mk`, where `WORKSPACE_NAME` is the name of the Premake workspace for the application. The Application.mk file is written to the `location` directory of the workspace.
|
||||||
|
|
||||||
|
**Gradle's `externalNativeBuild`, however, causes most Application.mk settings to be ignored and overridden by the settings specified in the Gradle script itself.** Because of this, using the Application.mk file generated by this module may not be absolutely necessary, but for correctness, you should still set the `NDK_APPLICATION_MK` variable in ndk-build arguments, otherwise it will try to use the Application.mk from the default path — it's better to express the intentions explicitly than to rely on the file not currently existing. However, you'll need to specify the correct settings in the Gradle script manually anyway. Because Gradle scripts contain settings not only for NDK, but also for all aspects of the application, and since the layout of configurations — build types and product flavors — may vary greatly between applications, Gradle setup is out of the scope of this module.
|
||||||
|
|
||||||
|
Here is an example of configuring the application settings relevant to the usage of files generated by this module:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
android {
|
||||||
|
// The Android NDK version to build the application with.
|
||||||
|
// If omitted, the latest installed version will be used.
|
||||||
|
ndkVersion '23.0.7599858'
|
||||||
|
|
||||||
|
// Per-configuration Gradle settings.
|
||||||
|
// May be specified for defaultConfig, as well as for buildTypes and productFlavors.
|
||||||
|
defaultConfig {
|
||||||
|
// Minimum Android SDK version supported by the application.
|
||||||
|
// Corresponds to APP_PLATFORM := android- in Application.mk (Premake `systemversion`).
|
||||||
|
minSdkVersion 14
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
// See com.android.build.api.dsl.ExternalNativeNdkBuildOptions documentation.
|
||||||
|
|
||||||
|
// Application.mk path - specifying the correct one is recommended.
|
||||||
|
arguments 'NDK_APPLICATION_MK:=path/to/WORKSPACE_NAME.Application.mk',
|
||||||
|
// Premake platforms to build for - see the section about configuration and platform selection below.
|
||||||
|
'PREMAKE_ANDROIDNDK_PLATFORMS:=Android-ARM',
|
||||||
|
'PREMAKE_ANDROIDNDK_PLATFORMS+=Android-ARM64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk {
|
||||||
|
// See com.android.build.api.dsl.Ndk documentation for more useful options such as `jobs`.
|
||||||
|
|
||||||
|
// The list of the ABIs to build this application for.
|
||||||
|
// Corresponds to APP_ABI in Application.mk.
|
||||||
|
// Should match the actual list of ABIs supported by at least some of the projects in the workspace.
|
||||||
|
// If omitted, ndk-build will try to build for all ABIs supported by the used NDK version.
|
||||||
|
// In this case, you should provide an architecture-agnostic platform/configuration for the projects.
|
||||||
|
// It may be fine not to specify this if you target only a subset of APIs, but ndk-build will be emitting warnings.
|
||||||
|
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
||||||
|
|
||||||
|
// The C++ STL to use.
|
||||||
|
// Corresponds to APP_STL in Application.mk.
|
||||||
|
// If omitted, APP_STL (Premake `cppstl` and `staticruntime`) from the Application.mk will be used.
|
||||||
|
// If that's not specified too, the default STL for the current API version will be selected.
|
||||||
|
stl 'c++_static'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
debuggable false
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
// Premake configurations to build for - see the section about configuration and platform selection below.
|
||||||
|
arguments 'PREMAKE_ANDROIDNDK_CONFIGURATIONS:=Release'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug {
|
||||||
|
debuggable true
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
// Premake configurations to build for - see the section about configuration and platform selection below.
|
||||||
|
arguments 'PREMAKE_ANDROIDNDK_CONFIGURATIONS:=Debug'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
// See com.android.build.api.dsl.NdkBuild documentation.
|
||||||
|
// This is required to initiate native code building at all.
|
||||||
|
|
||||||
|
// The Android.mk file to use - the generated workspace Android.mk in the `location` of the workspace.
|
||||||
|
// Corresponds to APP_BUILD_SCRIPT in Application.mk.
|
||||||
|
path file('path/to/WORKSPACE_NAME.wks.Android.mk')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Specifying Premake configurations and platforms to build
|
||||||
|
|
||||||
|
Because a single ndk-build invocation builds for multiple ABIs, the usage of the generated files is slightly unusual compared to most build systems targeted by Premake where only a single configuration and platform pair is selected for building.
|
||||||
|
|
||||||
|
Instead of letting you select just one configuration and platform, this module allows you to execute ndk-build for **multiple platforms and configurations**.
|
||||||
|
|
||||||
|
For this purpose, the module provides two variables that you need to set in the arguments of the ndk-build invocation (`externalNativeBuild.ndkBuild.arguments` for a Gradle build configuration):
|
||||||
|
|
||||||
|
* `PREMAKE_ANDROIDNDK_CONFIGURATIONS` — Premake configurations to build, **at least one must be specified**.
|
||||||
|
* `PREMAKE_ANDROIDNDK_PLATFORMS` — Premake platforms to build for. Optional, if none are specified, will be building for all platforms specified in any project.
|
||||||
|
|
||||||
|
To set a variable to just one value, you can use the `VARIABLE:=value` syntax of the ndk-build argument. For multiple values, you need to provide each in a separate argument as `VARIABLE+=value` (preferably the first with `:=` still to ensure it's overwritten if there's an environment variable with the same name). The Gradle example above shows how you can enable building for multiple platforms representing different ABIs, and for a configuration depending on the Gradle build type.
|
||||||
|
|
||||||
|
This, however, does not mean that you can create debug and release builds at once — rather, this architecture is designed specifically to provide a way for building for multiple ABIs as usual while being able to use an `architecture` filter in Premake. Because of this, **you must ensure** that **for every ABI, only at most one configuration–platform pair will be selected** for every project. An ambiguous selection of platforms and configurations will result in an undefined behavior.
|
||||||
|
|
||||||
|
Platform-agnostic projects — those that have no `platforms` inherited from the workspace or defined — will be built regardless of the value of `PREMAKE_ANDROIDNDK_PLATFORMS` (only configuration selection will be used for them).
|
||||||
|
|
||||||
|
## Supported settings
|
||||||
|
|
||||||
|
Please carefully verify that the settings you're using in your projects are handled in a way that's supported by this module and by ndk-build itself. Most importantly, please **check the settings that are listed as per-file or per-extension here**, especially if you have source files of different languages in your projects.
|
||||||
|
|
||||||
|
### Per-file or per-configuration/per-platform for a project, ABI-filtered
|
||||||
|
|
||||||
|
There is a small number of settings for which it's possible to specify the value for individual source files using the `files` filter.
|
||||||
|
|
||||||
|
- **`armisa`** (new) = `"A32"` / `"T32"` (default)
|
||||||
|
- ARMv7 instruction set to use. By default, Thumb (`"T32"`) will be used for release builds. Debug builds, however, always use A32.
|
||||||
|
- At the project configuration scope, it controls `LOCAL_ARM_MODE`.
|
||||||
|
- At the file scope, it can be used to build the specified files for A32 in a Thumb project, **but not vice versa**, by adding the `.arm` suffix to the file in `LOCAL_SRC_FILES`. Alternatively, you can use the `.arm` suffix (if needed, as a part of `.arm.neon`, but not `.neon.arm`) directly in the `files` setting, which will take precedence.
|
||||||
|
- **`flags`**
|
||||||
|
- `ExcludeFromBuild`
|
||||||
|
- Also supported for excluding entire projects on specified configurations/platforms.
|
||||||
|
- **`vectorextensions`** (for the `"ARM"` architecture) = `"ARMv7"` (new) / `"NEON"` (default, new)
|
||||||
|
- Whether to allow the compiler to generate instructions from the NEON SIMD instruction set as part of its optimizations. Specifying `"ARMv7"` (analogous to `"IA32"` on x86) disables NEON, specifying `"NEON"` enables it. By default, for consistency with NDK versions starting with r21, NEON will be enabled, even if the project doesn't explicitly specify `vectorextensions` (so on pre-r21, NEON will be used for Premake projects too).
|
||||||
|
- At the project configuration scope, it controls `LOCAL_ARM_NEON`.
|
||||||
|
- At the file scope, it can be used to build the specified files with NEON code generation in a project with NEON disabled, **but not vice versa**, by adding the `.neon` suffix to the file in `LOCAL_SRC_FILES`. Alternatively, you can use the `.neon` suffix (if needed, as a part of `.arm.neon`, but not `.neon.arm`) directly in the `files` setting, which will take precedence.
|
||||||
|
- For the allowed values on other architectures, see the per-configuration/per-platform settings section.
|
||||||
|
|
||||||
|
### Per-language or per-configuration/per-platform for a project, ABI-filtered
|
||||||
|
|
||||||
|
While ndk-build doesn't provide a way to specify compiler flags and most other settings for individual source files, it supports multiple source languages with different compilers, which accept different build options. Premake, however, exposes most build settings under language-agnostic names.
|
||||||
|
|
||||||
|
To specify which compiler should receive the needed value, you can use file extension filters.
|
||||||
|
|
||||||
|
Because the module supports `.arm`, `.neon` and `.arm.neon` suffixes, as well as many C++ extensions, it's not recommended to list file extensions manually. Instead, built-in filter constants provided by the module should be preferred, as they include the ARM suffixes and all the supported extensions.
|
||||||
|
|
||||||
|
For including a specific language, the following variables are available (note that they must be used directly, and if needed, via `..` concatenation — **`%{}` string interpolation will not locate them**):
|
||||||
|
|
||||||
|
- `premake.modules.androidndk.filefilters.as` for the GNU Assembler (GAS)
|
||||||
|
- `premake.modules.androidndk.filefilters.asm` for Yasm
|
||||||
|
- `premake.modules.androidndk.filefilters.c` for C
|
||||||
|
- `premake.modules.androidndk.filefilters.cpp` for C++
|
||||||
|
- `premake.modules.androidndk.filefilters.rs` for RenderScript
|
||||||
|
|
||||||
|
Each of those filters is a single string which already has the `"files:"` prefix (for instance, `premake.modules.androidndk.filefilters.c` is `"files:**.c or files:**.c.arm or files:**.c.neon or files:**.c.arm.neon"`).
|
||||||
|
|
||||||
|
To exclude a language from a file filter, `filefilters` also includes filters prefixed with `not`, such as `premake.modules.androidndk.filefilters.notc`. Unlike the inclusive filters, the exclusive are tables, because Premake exposes the logical `and` as separate table elements. `premake.modules.androidndk.filefilters.notc` is `{ "files:not **.c", "files:not **.c.arm", "files:not **.c.neon", "files:not **.c.arm.neon" }`, for example. Premake filter tables can be nested, you don't need to perform flattening manually if you want to combine the language filters with additional terms.
|
||||||
|
|
||||||
|
In addition, raw combinations of extensions and ARM suffixes are available in `filefilters` with the `extensions` suffix, such as `premake.modules.androidndk.filefilters.cextensions`, which is `{ ".c", ".c.arm", ".c.neon", ".c.arm.neon" }` (without the `**` recursive wildcard). You can do your own processing of them using functions like `table.translate` and `table.concat`, for instance, to attach all the possible extensions to a specific file name.
|
||||||
|
|
||||||
|
Note that ndk-build treats the uppercase `.C` extension as C++. To avoid imposing additional constraints, this module allows using the `.C` extension for C++, even though other Premake actions may treat it as C, especially considering that `path.hasextension` in Premake is case-insensitive. However, **Premake filters are case-insensitive, and `"files:**.c"` or `"files:**.C"` will match *both* C `.c` and C++ `.C` sources**, leading to the specified settings being used for both C and C++. Therefore, **it's recommended to completely avoid using the uppercase `.C` extension**. The `.C` extension is also not included in the `premake.modules.androidndk.filefilters` constants for this reason.
|
||||||
|
|
||||||
|
It is important that **you must not try to derive a `language` filter from an extension filter** because the `language` setting has a `"project"` scope in Premake rather than `"config"`, and thus it doesn't support file-specific or even configuration- or platform-specific overrides, in addition to not having allowed values for GAS, Yasm and RenderScript, so **the following will not work**:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
filter(premake.modules.androidndk.cfilefilter)
|
||||||
|
language("C") -- This WILL NOT WORK!
|
||||||
|
filter(premake.modules.androidndk.cppfilefilter)
|
||||||
|
language("C++") -- This WILL NOT WORK!
|
||||||
|
filter("language:C")
|
||||||
|
defines({"MY_NULL=((void *)0)"})
|
||||||
|
filter("language:C++")
|
||||||
|
defines({"MY_NULL=0"})
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition, if the `NoPCH` flag is not enabled in the project for the configuration–platform pair, and the file specified in `pchheader` is also listed in `files`, any file-filtered settings for it will be treated as C++ settings.
|
||||||
|
|
||||||
|
With some exceptions, most language-specific settings can be set independently for each language supported by this module.
|
||||||
|
|
||||||
|
- **`buildoptions`** (C, C++, GAS, Yasm, RenderScript)
|
||||||
|
- One build option may contain one or multiple compiler arguments separated with whitespaces.
|
||||||
|
- Double quotation marks (`"`) may be used to specify a single compiler argument containing whitespaces.
|
||||||
|
- If double quotation marks need to be escaped, they need to be prefixed with `\`, as `"\\\""` according to Lua string literal escaping rules.
|
||||||
|
- The backslash character (`\`) itself also needs to be escaped with another `\`, as `"\\\\"`, so the module can distinguish between a backslash used for escaping the double quote character and an actual backslash character.
|
||||||
|
- All other characters after GNU make `$` variable or function reference expansion are allowed, and other shell-interpreted characters will be escaped automatically at build time.
|
||||||
|
- Because of the way the values are gathered from the used filters, duplicate `buildoptions` are eliminated. For this reason, always specify multiple-argument options as `{ "-prefix value1", "-prefix value2" }`, not `{ "-prefix", "value1", "-prefix", "value2" }` (as the latter will become `"-prefix value1 value2"`).
|
||||||
|
- See the documentation for the `"LinkTimeOptimization"` flag here for details about the handling of `"-flto=…"`.
|
||||||
|
- **`cdialect`** (C)
|
||||||
|
- **`cppdialect`** (C++)
|
||||||
|
- **`flags`**
|
||||||
|
- `"FatalCompileWarnings"` (C, C++, Yasm)
|
||||||
|
- `"NoBufferSecurityCheck"` (C, C++)
|
||||||
|
- `"ShadowedVariables"` (C, C++)
|
||||||
|
- `"UndefinedIdentifiers"` (C, C++)
|
||||||
|
- **`defines`** (C, C++, Yasm)
|
||||||
|
- All `defines` are passed to the compiler before `undefines` even if they're specified both within and without an extension filter.
|
||||||
|
- **`disablewarnings`** (C, C++, Yasm)
|
||||||
|
- **`enablewarnings`** (C, C++, Yasm)
|
||||||
|
- **`fatalwarnings`** (C, C++, Yasm)
|
||||||
|
- For Yasm, this is treated as `enablewarnings`.
|
||||||
|
- **`floatingpoint`** (C, C++)
|
||||||
|
- `"Strict"` is treated as `"Default"`.
|
||||||
|
- **`floatingpointexceptions`** (C, C++)
|
||||||
|
- **`forceincludes`** (C, C++, Yasm)
|
||||||
|
- For C and C++, double quotation mark characters (`"`) are disallowed, as they would terminate the `#include "path"` statement inserted by the compiler.
|
||||||
|
- For Yasm, `"`, `'`, `;` characters are disallowed.
|
||||||
|
- **`includedirs`** (**C, C++, GAS and Yasm *combined***, RenderScript separately)
|
||||||
|
- C, C++, GAS and Yasm use **the same** list of include directories (that is written to `LOCAL_C_INCLUDES`).
|
||||||
|
- All `includedirs` are passed to the compiler before `sysincludedirs`.
|
||||||
|
- Whitespaces and `#`, `$` (after GNU make reference expansion) characters are disallowed.
|
||||||
|
- **`inlinesvisibility`** (C, C++)
|
||||||
|
- Unlike in other Premake actions using `premake.clang` or `premake.gcc`, this is also supported for C, not only C++.
|
||||||
|
- **`omitframepointer`** (C, C++)
|
||||||
|
- To use the Address Sanitizer, this needs to be set to `Off` — see the [Address Sanitizer](https://developer.android.com/ndk/guides/asan) guide on Android Developers.
|
||||||
|
- **`strictaliasing`** (C, C++)
|
||||||
|
- **`sysincludedirs`** (**C, C++, GAS and Yasm *combined***, RenderScript separately)
|
||||||
|
- See `includedirs`.
|
||||||
|
- **`undefines`** (C, C++, Yasm)
|
||||||
|
- All `defines` are passed to the compiler before `undefines` even if they're specified both within and without an extension filter.
|
||||||
|
- **`unsignedchar`** (C, C++)
|
||||||
|
- **`visibility`** (C, C++)
|
||||||
|
- Unlike in other Premake actions using `premake.clang` or `premake.gcc`, this is also supported for C, not only C++.
|
||||||
|
- **`warnings`** (C, C++, Yasm)
|
||||||
|
- For Yasm, only `"Off"` has effect — other values are treated as warnings enabled as normal.
|
||||||
|
|
||||||
|
### Per-configuration/per-platform for a project, ABI-filtered
|
||||||
|
|
||||||
|
- **`architecture`**
|
||||||
|
- If an architecture is specified, the settings for this configuration–platform pair will be used will be used while building for the respective ABI if the configuration and the platform are selected for building via `PREMAKE_ANDROIDNDK_CONFIGURATIONS` and `PREMAKE_ANDROIDNDK_PLATFORMS`. In this case, the `architecture` filter may be used to provide ABI-specific settings.
|
||||||
|
- `"ARM"` for the `armeabi-v7a` ABI.
|
||||||
|
- `"ARM64"` for the `arm64-v8a` ABI.
|
||||||
|
- `"x86"` for the `x86` ABI.
|
||||||
|
- `"x86_64"` for the `x86_64` ABI.
|
||||||
|
- Leave unspecified or set to `"universal"` to provide fallback settings that will be used for the project for ABIs without a specialization.
|
||||||
|
- Generally `architecture` should be specified under a `platforms` filter, or, depending on your configuration structure, under a `configurations` one. See the “Usage” section for more information ABI filtering of settings.
|
||||||
|
- **`exceptionhandling`** = `"Off"` / `"On"` (default)
|
||||||
|
- **`files`**
|
||||||
|
- For a built Premake project:
|
||||||
|
- The following languages are supported:
|
||||||
|
- C (`.c`)
|
||||||
|
- C++ (`.cc`, `.cp`, `.cxx`, `.cpp`, `.CPP`, `.c++`, `.C`)
|
||||||
|
- The list of allowed extensions is broader than the default for Premake v5.0.0-alpha16, but matches the default for the NDK r23).
|
||||||
|
- Note that while ndk-build (and therefore this setting) is case-sensitive, Premake filters are not. Therefore, a `files:**.c` or a `files:**.C` filter will cause both C `.c` and C++ `.C` to pass, and extension-filtered language-specific settings such as `buildoptions` intended only for C++ will be used for C as well if both are present in the project, for example — see the section about per-language settings. It's better to avoid using the `.C` extension completely.
|
||||||
|
- GNU Assembler (`.s`, `.S`)
|
||||||
|
- Yasm (`.asm`)
|
||||||
|
- `"x86"` and `"x86_64"` architectures only — will be ignored automatically while building for other ABIs, including in architecture-agnostic projects.
|
||||||
|
- RenderScript (`.rs`, `.fs`)
|
||||||
|
- `.arm`, `.neon` and `.arm.neon` (but not `.neon.arm`) suffixes are allowed — see the documentation for per-file `armisa` and `vectorextensions` settings, which can be used as an alternative (using file-filtered `armisa` and `vectorextensions` is recommended instead so filters like `"files:**.c"` can still be used rather than `"files:**.c or **.c.arm or **.c.neon or **.c.arm.neon"`, however — though for extension filtering, constants like `premake.modules.androidndk.filefilters.c` are recommended, which include the `.arm` and `.neon` suffixes).
|
||||||
|
- Whitespaces, backtick, and `"`, `#`, `$` (after GNU make reference expansion), `&`, `'`, `(`, `)`, `,`, `;`, `<`, `>`, `|` characters are disallowed. The backslash is allowed as a path separator on Windows, but disallowed on Linux.
|
||||||
|
- To create a prebuilt library project or to use an external Android.mk file, specify **only one** `.so` (for the `"SharedLib"` kind), `.a` (for the `"StaticLib"` kind) or `.mk` file, and **no other source files**. See the “Usage” section for more information about the required and supported settings for prebuilt and external projects.
|
||||||
|
- In prebuilt library paths, whitespaces, and `"`, `#`, `$` (after GNU make reference expansion), `%`, `&`, `*`, `;`, `<`, `>`, `?`, `|` characters are disallowed on Windows. On other operating systems, backtick, `'`, `(`, `)`, `\` characters are not supported.
|
||||||
|
- In external Android.mk paths, whitespaces are not disallowed.
|
||||||
|
- All irrelevant file types (such as headers) will be ignored automatically.
|
||||||
|
- **`flags`**
|
||||||
|
- `"ExcludeFromBuild"`
|
||||||
|
- Also supported for excluding individual source files from building.
|
||||||
|
- `"FatalLinkWarnings"`
|
||||||
|
- For shared libraries and executables only.
|
||||||
|
- Unlike in ndk-build itself, fatal link warnings are disabled by default (`LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true`).
|
||||||
|
- `"LinkTimeOptimization"`
|
||||||
|
- If used in a static library, shared libraries and executables linked against it will also be linked with link-time optimization (the transitivity ensured for this options, however, doesn't apply to building of source files).
|
||||||
|
- It's possible to override the default link-time optimization type by specifying the desired link-time optimizations type, such as `-flto=thin`, in **both** `buildoptions` and `linkoptions`. The specific `-flto=` type will also be propagated from `linkoptions` of static library dependencies (though in this case, all linked static libraries must have the same LTO type, and static library dependency analysis only checks `linkoptions`, not `buildoptions`).
|
||||||
|
- `"NoPCH"`
|
||||||
|
- Causes `pchheader` to be ignored — see `pchheader` for more information.
|
||||||
|
- **`formatstringchecks`** (new) = `"Off"` / `"On"` (default)
|
||||||
|
- Corresponds to `LOCAL_DISABLE_FORMAT_STRING_CHECKS` (but enabling instead of disabling), whether to check `printf` format strings in the sources.
|
||||||
|
- **`isaextensions`**
|
||||||
|
- This should be used only in libraries with code used conditionally based on the information provided by `cpuid`, or for emulation purposes, otherwise it may prevent the app from working on physical devices.
|
||||||
|
- All `"x86"` and `"x86_64"` architecture `isaextensions` normally supported by Premake actions targeting Clang are supported.
|
||||||
|
- **`libdirs`**
|
||||||
|
- Search paths for library binaries specific directly via `links`.
|
||||||
|
- Not recommended as using library binaries directly via linker arguments is discouraged by ndk-build — prefer using prebuilt library projects, and see `links` for more information.
|
||||||
|
- All `libdirs` gathered from the project and its static library dependencies are passed to the linker before `syslibdirs`.
|
||||||
|
- **`linkoptions`**
|
||||||
|
- Most options are supported only in shared libraries and executables, but there are some exceptions which are exported from static libraries as well.
|
||||||
|
- See `buildoptions` for information about passing multiple arguments, characters that need to be escaped manually, deduplication, disallowed characters.
|
||||||
|
- Going to Clang++ rather than directly to LLD — `-Wl` may be needed for many options.
|
||||||
|
- Unlike in other Premake actions, some parsing is done:
|
||||||
|
- Options prefixed with `-l`, `-L` (with or without `-Wl`), `-Wl,--library`, `-Wl,--library-path` will go to `LOCAL_LDLIBS` instead of `LOCAL_LDFLAGS`, and will be exported from static libraries to dependent shared libraries, similarly to `links`. This may be useful if you have a project named the same as a system library, but you want to link against that system library (for instance, `-llog` if there is a project named `"log"`). See `links` and `libdirs` for more information.
|
||||||
|
- Options prefixed with `-u` (with or without `-Wl`) or `-Wl,--undefined` will also be exported from static libraries transitively to allow preserving “unused” symbols imported from static libraries in the dependent shared libraries, primarily JNI native function implementations in static libraries — similar to `wholelib`, but more granular, for individual symbols.
|
||||||
|
- See the documentation for the `"LinkTimeOptimization"` flag here for details about the handling of `"-flto=…"`.
|
||||||
|
- **`links`**
|
||||||
|
- Premake projects and system libraries to link against — usable in all kinds of projects (in shared libraries and executables, as well as in static libraries for transitive linkage).
|
||||||
|
- If a shared library or an executable is linked against a static library project, it will automatically be linked against all system libraries referenced by its static library dependencies, even if static library dependencies are chained via `links`. Transitivity across shared libraries is not provided, however, as it's not necessary and may be undesirable — instead of using `LOCAL_EXPORT_LDLIBS`, the module traverses the dependency tree by itself. This is done for consistency with other Premake actions such as Visual Studio.
|
||||||
|
- See `wholelib` and `wholelibs` for information about importing static libraries as whole archives.
|
||||||
|
- If you have a project named the same as a system library, but you still want to link against the system library, you can use a `buildoptions` entry with the `-l` prefix (for instance, `-llog` if there is a project named `"log"`).
|
||||||
|
- Generally shouldn't be used for anything but linking to other projects and to the NDK system libraries — ndk-build will generate warnings for non-system libraries. Prebuilt library projects (see the “Usage” section) should be preferred for linking against non-system library binaries directly. However, the module still provides the functionality for linking against arbitrary library files:
|
||||||
|
- Full paths, `libdirs` and `syslibdirs` can be used for specifying search paths (however, there's no way to link against two libraries with the same name under different paths).
|
||||||
|
- Both short library names and full file names are allowed. If the file name ends with `.a` or `.so`, it's treated as a full name — the `"lib"` prefix must be explicitly specified if needed.
|
||||||
|
- The `":"` prefix can be added to the file name explicitly to force handling of it as a full file name.
|
||||||
|
- **`kind`**
|
||||||
|
- `"SharedLib"` or `"StaticLib"` for a built or a prebuilt shared or static library.
|
||||||
|
- `"ConsoleApp"` for an executable.
|
||||||
|
- `"None"` to exclude the project from building for the current configuration/platform.
|
||||||
|
- Note that `"Makefile"` is not a supported option — an external Android.mk file must be used through `files`, and the project for it must have the `kind` that matches the actual ndk-build script included by it.
|
||||||
|
- For more information about the usage of prebuilt libraries and external Android.mk files, see the section about them in “Usage”.
|
||||||
|
- **`renderscriptcompatibility`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- Corresponds to `LOCAL_RENDERSCRIPT_COMPATIBILITY`.
|
||||||
|
- **`renderscriptincludedirsoverride`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- Corresponds to the usage of `LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE` instead of `LOCAL_RENDERSCRIPT_INCLUDES`, whether to ignore the NDK built-in platform and toolchain RenderScript include search paths.
|
||||||
|
- **`pchheader`**
|
||||||
|
- Suffixes such as `.arm` and `.neon` are not supported — handling of ARMv7 ISA overrides is performed internally in ndk-build.
|
||||||
|
- Whitespaces, backtick, and `"`, `#`, `$` (after GNU make reference expansion), `&`, `'`, `(`, `)`, `,`, `;`, `<`, `=`, `>`, `|` characters are disallowed (same as in `files` for sources, but additionally `=`). The backslash is allowed as a path separator on Windows, but disallowed on Linux.
|
||||||
|
- ndk-build treats the precompiled header as C++ code. The module will configure variables necessary for building C++ code (such as `LOCAL_CPPFLAGS`) if the precompiled header is present, however, if you have any C++-specific settings with a file extension filter, you need to provide at least one source file with the respective extension, otherwise this module will not be able to access those settings. If the file specified in `pchheader` is listed among `files`, any file-filtered settings applied to it will also be treated as C++ settings.
|
||||||
|
- Ignored if the `"NoPCH"` flag is enabled for the project configuration/platform.
|
||||||
|
- **`rtti`** = `"Off"` / `"On"` (default)
|
||||||
|
- **`targetprefix`**, **`targetname`**, **`targetsuffix`**
|
||||||
|
- Combined into `LOCAL_MODULE_FILENAME`.
|
||||||
|
- Overriding the binary path or extension is not supported.
|
||||||
|
- Whitespaces and `#`, `$` (after GNU make reference expansion), `%`, `/`, `;`, `|` characters are disallowed.
|
||||||
|
- Only removing the `lib` prefix works when invoking ndk-build from Gradle as of Gradle 7.0.2 because it gathers the names of the targets to build from `LOCAL_MODULE_FILENAME` instead of `LOCAL_MODULE`. If executing ndk-build manually without a list of targets, or with a correctly specified list of them, other values are supported.
|
||||||
|
- **`undefinedsymbols`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- For shared libraries and executables only.
|
||||||
|
- Corresponds to `LOCAL_ALLOW_UNDEFINED_SYMBOLS`, if enabled, errors will not be thrown for undefined symbols, instead, the symbols will be resolved at runtime.
|
||||||
|
- **`shortcommands`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- Corresponds to `LOCAL_SHORT_COMMANDS`, whether to execute build commands from a file rather than directly via the shell, as if the command line is too long, it may not fit in the 8191 character limit on Windows.
|
||||||
|
- **`syslibdirs`**
|
||||||
|
- See `libdirs`.
|
||||||
|
- **`system`**
|
||||||
|
- Must be `"android"` for the correct library name prefix (`"lib"`).
|
||||||
|
- **`thinarchive`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- For static libraries only.
|
||||||
|
- Corresponds to `LOCAL_THIN_ARCHIVE`, whether to store only object file paths instead of the object themselves in the static library being built.
|
||||||
|
- **`vectorextensions`** (for the `"x86"` and `"x86_64"` architectures)
|
||||||
|
- This should be used only in libraries with code used conditionally based on the information provided by `cpuid`, or for emulation purposes, otherwise it may prevent the app from working on physical devices.
|
||||||
|
- Allowed values on the `"x86"` architecture: `"SSE4.1"`, `"SSE4.2"` (new), `"AVX"`, `"AVX2"` (SSSE3 and below are required by Android and are always supported).
|
||||||
|
- Allowed values on the `"x86_64"` architecture: `"AVX"`, `"AVX2"` (SSE4.2 and below are required by Android and are always supported).
|
||||||
|
- For the allowed values on the `"ARM"` architecture, see the per-file settings section.
|
||||||
|
- **`wholelib`** (new) = `"Off"` (default) / `"On"`
|
||||||
|
- For static libraries only.
|
||||||
|
- Whether all object files from this static library should be included in the shared libraries (but not executables) referencing it (and this library will be added to `LOCAL_WHOLE_STATIC_LIBRARIES` instead of `LOCAL_STATIC_LIBRARIES`). This is useful, for instance, when exporting JNI native function implementations from a static library.
|
||||||
|
- This setting is for **exporting** the requirement that the static library must be linked as a whole archive — for the equivalent for importing, see `wholelibs` (a static library will be linked via `LOCAL_WHOLE_STATIC_LIBRARIES` rather than `LOCAL_STATIC_LIBRARIES` if it enables `wholelib` for itself, or if it's specified in `wholelibs` of the project importing it — you only need either to specify `wholelib` in the dependency or to add it to `wholelibs` of the dependent projects; though specifying both the same time is fine, that's redundant).
|
||||||
|
- **`wholelibs`** (new)
|
||||||
|
- List of static library project names among the `links` of the project to link as whole archives.
|
||||||
|
- For more information about whole static libraries, see `wholelib` — this setting provides the same functionality, but for **importing** static library dependencies as whole archives (only one of `wholelib` or `wholelibs` is enough).
|
||||||
|
- If a project is listed in `wholelibs`, it still needs to be added to `links` to be linked — this setting is merely a modifier, and therefore it's fine to just list all static library projects that need to be linked as whole archives once for the entire workspace (though `wholelib` is more suited for this purpose).
|
||||||
|
|
||||||
|
### Per-configuration/per-platform for a workspace, not ABI-filtered
|
||||||
|
|
||||||
|
These settings have effect on `APP` variables in the Application.mk rather than `LOCAL` variables in projects Android.mk files.
|
||||||
|
|
||||||
|
There is a single Application.mk file for the entire workspace, and the same values of the `APP` variables are used regardless of the current target ABI. Thus, **for all configurations and platforms selected in `PREMAKE_ANDROIDNDK_CONFIGURATIONS` and `PREMAKE_ANDROIDNDK_PLATFORMS`, the values of these settings must be the same for**:
|
||||||
|
|
||||||
|
- All projects in the workspace;
|
||||||
|
- All target ABIs (`architecture`s).
|
||||||
|
|
||||||
|
For all selected configurations (which are visited in an undefined order), the module tries to locate the value in:
|
||||||
|
|
||||||
|
1. The workspace itself.
|
||||||
|
2. The `startproject`.
|
||||||
|
3. For all selected platforms, visited in an undefined order, platform-specific projects, also in an undefined order.
|
||||||
|
4. Platform-agnostic projects, in an undefined order.
|
||||||
|
|
||||||
|
You can use, for instance, `optimize("Off")` in the `"Debug"` configuration, and `optimize("On")` in the `"Release"` one, as long as you build the workspace with **either** `PREMAKE_ANDROIDNDK_CONFIGURATIONS:=Debug` or `PREMAKE_ANDROIDNDK_CONFIGURATIONS:=Release`, but not both at once. However, you can't disable optimizations for specific projects in the `"Release"` configuration in this case.
|
||||||
|
|
||||||
|
- **`cppstl`** (new) = `"Default"` / `"c++"` / `"none"` / `"system"`
|
||||||
|
- The C++ standard library to use.
|
||||||
|
- NDK versions before r18 also support `"gabi++"`, `"gnustl"`, `"stlport"`.
|
||||||
|
- Use `staticruntime` to specify whether to link against the static standard library or against the shared one.
|
||||||
|
- **`optimize`**
|
||||||
|
- Handled in a way that approximates the behavior of other Premake actions.
|
||||||
|
- Unspecified, `"Off"`, `"Debug"` result in `APP_OPTIM := debug`.
|
||||||
|
- Anything else (`"Size"`, `"Speed"`, `"Full"`) results in `APP_OPTIM := release`, and also force-disables `APP_DEBUG`.
|
||||||
|
- **`symbols`**
|
||||||
|
- Handled in a way that approximates the behavior of other Premake actions.
|
||||||
|
- Ignored if `optimize` is set to a value that results in optimization enabled.
|
||||||
|
- Unspecified, `"Off"`, `"Default"` result in `APP_DEBUG := true`.
|
||||||
|
- Anything else (`"On"`, `"FastLink"`, `"Full"`) results in `APP_DEBUG := false`.
|
||||||
|
- **`staticruntime`** = `"Default"` / `"Off"` / `"On"` (default)
|
||||||
|
- Whether to use the static C++ standard library (`cppstl`) as opposed to a shared one.
|
||||||
|
- Static by default, consistent with the default CMake behavior (where `c++_static` is the default standard library).
|
||||||
|
- Ignored for `"none"` and `"system"` standard libraries.
|
||||||
|
- **`systemversion`**
|
||||||
|
- Minimum Android SDK version required by the application, as a string representation of a number (corresponds to `APP_PLATFORM := android-systemversion`).
|
||||||
|
|
||||||
|
### Per-project or per-workspace
|
||||||
|
|
||||||
|
- **`basedir`**
|
||||||
|
- **`configurations`**
|
||||||
|
- Whitespaces and `%`, `(`, `)`, `,` characters are disallowed (configuration and platform names are used in GNU make list function calls).
|
||||||
|
- **`location`**
|
||||||
|
- The directory where the Android.mk file for the project or the Application.mk and the root Android.mk for the workspace will be placed (if provided — otherwise `basedir` will be used).
|
||||||
|
- For projects, it is heavily recommended to set this to a folder that doesn't contain header files. This is the path that will be used as `LOCAL_PATH`, and ndk-build internally adds `LOCAL_PATH` as the last include directory, causing `LOCAL_PATH` to be treated as a more “system” include search path than the system paths themselves. This causes issues when the `LOCAL_PATH` directory contains header files named the same as C and C++ standard library headers — the LLVM libc++ uses `#include_next` in a few files (such as `math.h`), causing project's files to included from system headers; this is especially dangerous if the local `"math.h"` itself `#include`s `<math.h>`.
|
||||||
|
- **`platforms`**
|
||||||
|
- See `configurations`.
|
||||||
|
- **`project`**
|
||||||
|
- Whitespaces and `#`, `$`, `%`, `/`, `:`, `;`, `=`, `|` characters are disallowed.
|
||||||
|
- GNU make variable or function references (`$`) are disallowed.
|
||||||
|
- **`startproject`**
|
||||||
|
- The start project will have a higher priority when locating setting values for Application.mk variables.
|
||||||
|
- **`workspace`**
|
||||||
|
- Whitespaces and `#`, `$` characters are disallowed.
|
||||||
|
- GNU make variable or function references (`$`) are disallowed.
|
||||||
|
|
||||||
|
## Future work, contributing and omissions
|
||||||
|
|
||||||
|
Several features were left temporarily or intentionally unimplemented in the current version of the module, however, they may be useful in certain cases.
|
||||||
|
|
||||||
|
If your project depends on something missing from the module, feel free to open an issue, and we'll discuss how the needed functionality can be added to the module in a convenient and flexible way — or submit a pull request with the implementation!
|
||||||
|
|
||||||
|
Note that the general preference is to use existing Premake settings wherever possible — potentially twisting them and adding the necessary constraints while still trying to keep the original semantic concepts — instead of adding new ones. Don't hesitate to exploit filters, to interpret a variable in different ways depending on the target ABI and overall context, to use any opportunity to make the module more compatible with existing projects for other targets. However, if new settings need to be added, prefer using `kind = "boolean"` settings rather than flags as the former have three states, making it easier to provide default behavior, especially if the new settings are promoted to the Premake core or used in other modules in the future, potentially on platforms with different defaults.
|
||||||
|
|
||||||
|
If you're adding functionality that involves strings in a new place in the generated Android.mk and Application.mk files, make sure to check which non-letter ASCII characters, including different types of whitespaces, are supported by ndk-build in the specific context, especially if it's a file name or a path, on both Linux (which allows any characters in paths) and Windows (including UNC paths), with attention to backslash-escaping of shell-interpreted characters (see `androidndk.shellEscapedCharactersPostQuotes`), but not only them. All user input must be passed through `p.esc`, preferably early (and functions expecting output of `p.esc` as arguments must be named with the `PostEsc` suffix), to ensure the integrity of GNU make variable or function references (also make sure that paths including `$` references are handled correctly as absolute or as relative depending on the context, especially when joining — usually paths beginning with `$` should be considered absolute, and that's how Premake itself treats them, while a relative path needs to start with `./$` in this case) and of escaping of the comment character `#`. After `p.esc`, the invalid character check may be done for the non-reference part of the string if needed — see the usage `androidndk.staticallyHasPatternPostEsc` (build-time validation would be an overkill if there are references in the string, but to catch potential errors when porting projects from other platforms, generation-time checks are useful). In many places, strings are used in shell commands invoked by ndk-build — see how checkers and escapers starting with `androidndk.shellEscape` are used in the module; also shell character escaping needs to be done at build time, not at Premake invocation time, since it must be performed after expanding GNU make references. Also, if you're passing user input to a GNU make function, use an intermediate variable (see `androidndk.getTemporaryVariableReference`), as the user-provided string may contain brackets or commas, which would break the parsing of the function call.
|
||||||
|
|
||||||
|
The following functionality has been omitted currently, but may be nice to have for reasons like compatibility:
|
||||||
|
|
||||||
|
- Unit tests. This is a large module with complex input handling with a large number of edge cases for many settings that, in some cases, depend on the kind of the project, the target ABIs, source languages used in the project — written in a dynamically-typed language. Many errors and typos may occur. Tests verifying both supported and disallowed input need to be added — covering platform-dependent and platform-agnostic projects, ABI-dependent and ABI-agnostic projects, different kinds of binaries, prebuilt libraries, external Android.mk projects, source files written in various languages with extension filters and `.arm` and `.neon` suffixes, link settings and transitivity of them across chains of static libraries where needed, GNU make variable and function references, disallowed characters, shell-interpreted character escaping, and other cases handled by this module.
|
||||||
|
- Building for deprecated ABIs removed from the NDK — `armeabi`, `armeabi-v7a-hard`, `mips`, `mips64`. While simply adding a new `architecture` is trivial (though for choosing `armeabi-v7a-hard`, a special setting for the floating-point argument convention may be more suitable), that wouldn't imply complete support for the details of them — such as instruction set extensions (like the MXU vector extensions for MIPS), hardware floating-point unit support. MIPS-powered Android devices are extremely rare, and ARMv5 deprecation began in Android 4.0, having been completed in Android 4.4.
|
||||||
|
- Support for obsolete toolchains removed from the NDK, such as GCC, as well as toolchain version selection (as of r23, the NDK only offers one version of the Clang toolchain).
|
||||||
|
- Clang-Tidy — needs to be integrated into the architecture of Premake itself.
|
||||||
|
- Post-processing of the generated machine code and assembly source files via `LOCAL_FILTER_ASM` — needs to be added in a way friendly to the Premake architecture.
|
||||||
|
- Compatibility with the Visual Studio actions for Android (the built-in `android` module). It defines many settings in ways that aren't consistent with the Premake core itself, as well as adding redundant options:
|
||||||
|
- Values are generally lowercase, while the Premake core uses PascalCase internally.
|
||||||
|
- The additions to the list of the allowed `architecture` values are chaotic. For `armeabi`, it allows both `"arm"` and `"armv5"` (which are registered as separate options rather than aliases of each other), while for `armeabi-v7a`, it uses `"armv7"`. Premake itself provides an `"ARM"` option, which, given the removal of ARMv5 support from the NDK, is more likely to be expected to correspond to ARMv7 as opposed to ARMv5. `arm64-v8a` is exposed as `"aarch64"` instead of `"ARM64"` used in the Premake core.
|
||||||
|
- ARMv5 and ARMv7 instruction sets are presented as two options: a `"Thumb"` flag, and a `"thumbmode"` setting, with one of the allowed values being `"disabled"` rather than `"Default"` commonly used in Premake.
|
||||||
|
- `stl` is a new setting in it, but it uses misleading names. The `"gnustl"` and `"c++"` standard libraries provided by ndk-build are called `"gnu"` and `"libc++"` instead, which is likely not what users expect. For `"system"`, the value `"none"` is used — however, the NDK has both `"system"` (which is deprecated) and `"none"`, the difference between the two being `new` and `delete` being supported in `"system"`, while `"none"` providing no C++ standard library functionality at all. The name `stl` also doesn't imply C++ directly, which may cause issues if Premake gets support for a different language that also has the standard library referred to by the same acronym — unlike settings like `buildoptions`, this may be even workspace-level (and in ndk-build, it is), and thus the value is not file- or extension-filterable.
|
||||||
|
- `androidapilevel` is redundant due to the existence of `systemversion`.
|
||||||
|
- The `"posix"` system tag is not added for Android.
|
||||||
|
- The “call array” architecture is not used in the code as certain settings are handled in multiple places in different ways, and various kinds of preprocessing are done. Replacing parts of the generation code in project scripts is unlikely to be useful or convenient for this reason.
|
24
src_rebuild/premake_modules/androidndk/UNLICENSE.txt
Normal file
24
src_rebuild/premake_modules/androidndk/UNLICENSE.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
11
src_rebuild/premake_modules/androidndk/_manifest.lua
Normal file
11
src_rebuild/premake_modules/androidndk/_manifest.lua
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- premake-androidndk - a multi-ABI, multi-language ndk-build Android.mk generator for Premake.
|
||||||
|
-- Originally written by Vitaliy <Triang3l> Kuzmin.
|
||||||
|
-- See README.md for detailed usage and design information.
|
||||||
|
-- Available under the Unlicense (see UNLICENSE.txt) or the BSD 3-Clause "New" or "Revised" License (see LICENSE.txt).
|
||||||
|
|
||||||
|
return {
|
||||||
|
"_preload.lua",
|
||||||
|
"androidndk.lua",
|
||||||
|
"androidndk_project.lua",
|
||||||
|
"androidndk_workspace.lua",
|
||||||
|
};
|
110
src_rebuild/premake_modules/androidndk/_preload.lua
Normal file
110
src_rebuild/premake_modules/androidndk/_preload.lua
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
-- premake-androidndk - a multi-ABI, multi-language ndk-build Android.mk generator for Premake.
|
||||||
|
-- Originally written by Vitaliy <Triang3l> Kuzmin.
|
||||||
|
-- See README.md for detailed usage and design information.
|
||||||
|
-- Available under the Unlicense (see UNLICENSE.txt) or the BSD 3-Clause "New" or "Revised" License (see LICENSE.txt).
|
||||||
|
|
||||||
|
local p = premake;
|
||||||
|
|
||||||
|
p.api.addAllowed("system", p.ANDROID);
|
||||||
|
-- NEON is enabled by default, like in NDK r21.
|
||||||
|
-- Similar to how Premake defines "IA32" for x86, use "ARMv7" to disable NEON (and use the .neon suffix where needed).
|
||||||
|
p.api.addAllowed("vectorextensions", { "ARMv7", "NEON", "SSE4.2" });
|
||||||
|
if os.systemTags[p.ANDROID] == nil then
|
||||||
|
os.systemTags[p.ANDROID] = { "android", "posix", "mobile" };
|
||||||
|
end
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "armisa",
|
||||||
|
scope = "config",
|
||||||
|
kind = "string",
|
||||||
|
allowed = {
|
||||||
|
p.DEFAULT,
|
||||||
|
"A32",
|
||||||
|
"T32",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "cppstl",
|
||||||
|
scope = "config",
|
||||||
|
kind = "string",
|
||||||
|
allowed = {
|
||||||
|
p.DEFAULT,
|
||||||
|
-- As of NDK r18, only none, c++ and system are available, with the latter being deprecated.
|
||||||
|
-- Supporting the older STLs is trivial, however.
|
||||||
|
"c++",
|
||||||
|
"gabi++",
|
||||||
|
"gnustl",
|
||||||
|
"none",
|
||||||
|
"stlport",
|
||||||
|
"system",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "formatstringchecks",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "renderscriptcompatibility",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "renderscriptincludedirsoverride",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "shortcommands",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "thinarchive",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
p.api.register({
|
||||||
|
name = "undefinedsymbols",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
-- Whether this static library project should be linked as a whole, even if not specified in `wholelibs` of dependent projects.
|
||||||
|
p.api.register({
|
||||||
|
name = "wholelib",
|
||||||
|
scope = "config",
|
||||||
|
kind = "boolean",
|
||||||
|
});
|
||||||
|
|
||||||
|
-- Subset of `links` which need to be linked as a whole regardless of their `wholelib` setting.
|
||||||
|
p.api.register({
|
||||||
|
name = "wholelibs",
|
||||||
|
scope = "config",
|
||||||
|
kind = "list:mixed",
|
||||||
|
tokens = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
newaction({
|
||||||
|
trigger = "androidndk",
|
||||||
|
shortname = "Android ndk-build",
|
||||||
|
description = "Generate Android ndk-build makefiles",
|
||||||
|
targetos = p.ANDROID,
|
||||||
|
valid_kinds = { p.CONSOLEAPP, p.SHAREDLIB, p.STATICLIB },
|
||||||
|
valid_languages = { p.C, p.CPP },
|
||||||
|
-- Premake workspace and project names can include periods, so using suffixes for both.
|
||||||
|
onWorkspace = p.modules.androidndk.onWorkspace,
|
||||||
|
onProject = p.modules.androidndk.onProject,
|
||||||
|
});
|
||||||
|
|
||||||
|
-- Decide when the full module should be loaded.
|
||||||
|
return function(config)
|
||||||
|
return _ACTION == "androidndk";
|
||||||
|
end;
|
465
src_rebuild/premake_modules/androidndk/androidndk.lua
Normal file
465
src_rebuild/premake_modules/androidndk/androidndk.lua
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
-- premake-androidndk - a multi-ABI, multi-language ndk-build Android.mk generator for Premake.
|
||||||
|
-- Originally written by Vitaliy <Triang3l> Kuzmin.
|
||||||
|
-- See README.md for detailed usage and design information.
|
||||||
|
-- Available under the Unlicense (see UNLICENSE.txt) or the BSD 3-Clause "New" or "Revised" License (see LICENSE.txt).
|
||||||
|
|
||||||
|
local p = premake;
|
||||||
|
p.modules.androidndk = {};
|
||||||
|
local androidndk = p.modules.androidndk;
|
||||||
|
androidndk._VERSION = "1.0.0";
|
||||||
|
|
||||||
|
include("androidndk_project.lua");
|
||||||
|
include("androidndk_workspace.lua");
|
||||||
|
|
||||||
|
include("_preload.lua");
|
||||||
|
|
||||||
|
-- Inserts one or multiple values into a table.
|
||||||
|
-- Useful for inserting compiler flags from built-in Premake toolsets.
|
||||||
|
function androidndk.insertKeyedFlat(tbl, value)
|
||||||
|
-- Skip if the value is nil, for instance, to quickly ignore irrelevant flags or values of settings without a mapping.
|
||||||
|
if value == nil then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
if type(value) == "table" then
|
||||||
|
for i, element in ipairs(value) do
|
||||||
|
androidndk.insertKeyedFlat(tbl, element);
|
||||||
|
end
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
if tbl[value] ~= nil then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
table.insert(tbl, value);
|
||||||
|
tbl[value] = value;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Rules regarding special characters in the input and how they're handled in this module (as of NDK r23, checked with `$(warning "$(VARIABLE)")`):
|
||||||
|
-- * Whitespaces (tab, vertical tab, form feed, space) - defining the word "whitespace" as all of these, unlike just "space":
|
||||||
|
-- * Horizontal tab being the first on a line defines a recipe.
|
||||||
|
-- * Otherwise, all whitespace characters behave like whitespaces, at least in the syntax of GNU make itself.
|
||||||
|
-- * Trimming behavior in various contexts relevant to Android.mk:
|
||||||
|
-- * All sides of a variable assignment - left-hand, the operator itself, right-hand - have leading whitespaces trimmed.
|
||||||
|
-- * In the right-hand side of a variable assignment, each line (separated with a \-escaped newline) is treated as a list element, like a complete token.
|
||||||
|
-- Any amount (including zero) of whitespaces or escaped newlines between two non-empty elements is collapsed into a single " " space.
|
||||||
|
-- However, if the last non-whitespace character in an element is $ (not $$, but $ alone), no space is inserted, they're just removed (including the $).
|
||||||
|
-- This rule, however, is directly applicable only to inner newline separators, not the beginning or the end of the whole right-hand side.
|
||||||
|
-- Whitespaces and newlines before the first non-empty element are trimmed (as leading whitespaces in general).
|
||||||
|
-- Behavior for the last element is less consistent.
|
||||||
|
-- If the last non-empty element is followed only by whitespaces, all those trailing whitespaces are preserved as their original encoding.
|
||||||
|
-- If there's a \-escaped newline after the last non-empty element, however, all trailing whitespaces and newlines are collapsed into one " " space.
|
||||||
|
-- Within the boundaries of one list element, however, all original whitespaces are preserved.
|
||||||
|
-- * Function call argument lists (as a whole, not individual arguments) have leading whitespaces trimmed.
|
||||||
|
-- * $() can be prepended or appended to include leading or trailing whitespaces in an element or the first function argument.
|
||||||
|
-- * Resolution:
|
||||||
|
-- * Pass through directly.
|
||||||
|
-- * Single-line variable generation:
|
||||||
|
-- * Preserve project-provided leading whitespaces for the whole value (or the first table element) using $().
|
||||||
|
-- * Multiline list variable generation:
|
||||||
|
-- * Preserve project-provided leading and trailing whitespaces for each table element using $(), though not necessary for the last.
|
||||||
|
-- * Both "\" and " \" are fine for separating table elements.
|
||||||
|
-- However, using " \" is consistent with the general recipe line splitting rules of GNU make for joining with a space.
|
||||||
|
-- * Newline characters (carriage return, line feed):
|
||||||
|
-- * Start a new statement.
|
||||||
|
-- * Can be escaped with a backslash, but then the newline itself may be trimmed according to the whitespace trimming rules.
|
||||||
|
-- * True newlines can be kept in variable declarations using define/endef.
|
||||||
|
-- * Resolution:
|
||||||
|
-- * Replace unconditionally with spaces.
|
||||||
|
-- * Escaping handled separately.
|
||||||
|
-- * Not using define/endef until a real use in ndk-build scripts is found.
|
||||||
|
-- * Backslash:
|
||||||
|
-- * If the last character before a newline, behaves as a line split, trimmed according to the whitespace trimming rules.
|
||||||
|
-- * Escapes the number sign which starts a comment.
|
||||||
|
-- * In other cases, passed as a raw character.
|
||||||
|
-- * Resolution:
|
||||||
|
-- * Pass through directly.
|
||||||
|
-- * If the last character on a line and provided by the project, append $().
|
||||||
|
-- * Dollar sign:
|
||||||
|
-- * A single dollar sign is a prefix for a variable or a function reference.
|
||||||
|
-- * $(name arguments) and ${name arguments} are the regular syntax.
|
||||||
|
-- * If neither () nor {} are used, one character immediately following the $ is used as the variable name.
|
||||||
|
-- * $ alone directly in the end of a variable assignment is treated as a raw $ character.
|
||||||
|
-- * The effect of a trailing $ on variable assignments split into multiple lines is described in the section about whitespaces.
|
||||||
|
-- * $$ results in a raw $ character.
|
||||||
|
-- * Resolution:
|
||||||
|
-- * Pass through directly to allow using environment variables and built-in variables like TARGET_ARCH_ABI in scripts, as well as functions.
|
||||||
|
-- * Prevent unclosed variable and function references with an undefined, but safe result.
|
||||||
|
-- The easiest way is to close them - doesn't require insertion into the middle - with a special case for the trailing $ (convert to $$).
|
||||||
|
-- * Number sign:
|
||||||
|
-- * Starts a comment.
|
||||||
|
-- * Escaped with a backslash for passing as raw data, but the backslash itself may be escaped as well.
|
||||||
|
-- * Backslashes preceding a # are treated as n/2 backslashes ((n-1)/2 if there is an odd number of them) in other cases.
|
||||||
|
-- * An even number of backslashes before the # in the original file causes the comment not to be escaped.
|
||||||
|
-- * Resolution:
|
||||||
|
-- * Escape with a single backslash and a terminator to prevent dependence on the number of backslashes, as $()\#.
|
||||||
|
-- * This makes concatenation of a string ending with \ and one starting with an escaped # safe.
|
||||||
|
|
||||||
|
androidndk.commentEscapeString = "$()\\#";
|
||||||
|
androidndk.commentUnescapePattern = string.escapepattern(androidndk.commentEscapeString);
|
||||||
|
|
||||||
|
androidndk.whitespacesNonNewline = {
|
||||||
|
["\t"] = "\t",
|
||||||
|
["\v"] = "\v",
|
||||||
|
["\f"] = "\f",
|
||||||
|
[" "] = " ",
|
||||||
|
};
|
||||||
|
|
||||||
|
-- Due to escaping of #, this function can't be called again on its result.
|
||||||
|
function androidndk.esc(value)
|
||||||
|
value = string.gsub(value, "#", androidndk.commentEscapeString);
|
||||||
|
-- Replace newlines with safer spaces.
|
||||||
|
value = string.gsub(value, "\r\n", " ");
|
||||||
|
value = string.gsub(value, "\n", " ");
|
||||||
|
value = string.gsub(value, "\r", " ");
|
||||||
|
-- Make sure there are no unclosed variable and function references.
|
||||||
|
-- Close $() and ${} with a bracket, and escape the final $.
|
||||||
|
-- As a result, all references will be closed and balanced.
|
||||||
|
local unclosedReferenceTerminators = {};
|
||||||
|
local afterReferenceCharacter = false;
|
||||||
|
-- Need a while loop as the for loop counter can't be modified from the body.
|
||||||
|
local i = 1;
|
||||||
|
while i <= string.len(value) do
|
||||||
|
local character = string.sub(value, i, i);
|
||||||
|
if character == "\\" and string.sub(value, i + 1, i + 1) == "#" then
|
||||||
|
-- Escaped comment character.
|
||||||
|
i = i + 1;
|
||||||
|
character = "#";
|
||||||
|
end
|
||||||
|
if afterReferenceCharacter then
|
||||||
|
-- The character after the $.
|
||||||
|
-- Options: $ (escaped raw $), an opening bracket (opening a reference), any other character (single-character reference).
|
||||||
|
if character == "(" then
|
||||||
|
table.insert(unclosedReferenceTerminators, ")");
|
||||||
|
elseif character == "{" then
|
||||||
|
table.insert(unclosedReferenceTerminators, "}");
|
||||||
|
end
|
||||||
|
afterReferenceCharacter = false;
|
||||||
|
else
|
||||||
|
-- Not the character after the $.
|
||||||
|
-- Options: $, a reference-closing bracket, any other raw character.
|
||||||
|
if character == "$" then
|
||||||
|
afterReferenceCharacter = true;
|
||||||
|
elseif #unclosedReferenceTerminators > 0 and character == unclosedReferenceTerminators[#unclosedReferenceTerminators] then
|
||||||
|
unclosedReferenceTerminators[#unclosedReferenceTerminators] = nil;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
i = i + 1;
|
||||||
|
end
|
||||||
|
local referencesClosed = { value };
|
||||||
|
-- Escape the incomplete single-character reference as a raw $.
|
||||||
|
if afterReferenceCharacter then
|
||||||
|
table.insert(referencesClosed, "$");
|
||||||
|
end
|
||||||
|
-- Close the unclosed references.
|
||||||
|
for i2 = 1, #unclosedReferenceTerminators do
|
||||||
|
table.insert(referencesClosed, unclosedReferenceTerminators[#unclosedReferenceTerminators - i + 1]);
|
||||||
|
end
|
||||||
|
return table.concat(referencesClosed);
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.setupGeneration()
|
||||||
|
-- The tab character is the recipe line prefix in makefiles.
|
||||||
|
p.indent(" ");
|
||||||
|
p.escaper(androidndk.esc);
|
||||||
|
p.eol("\n");
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Whether the string contains GNU make variable or function references.
|
||||||
|
-- p.esc should be done prior to this.
|
||||||
|
-- Empty references, that are $() or ${}, are not treated as references, merely as delimiters.
|
||||||
|
-- $() is used in comment sign escaping, for example.
|
||||||
|
function androidndk.hasNonEmptyMakeReferencesPostEsc(value)
|
||||||
|
-- For strictness and simplicity, the lone trailing $ is treated as a reference too (can't be a result of p.esc anyway).
|
||||||
|
local i = 0;
|
||||||
|
while true do
|
||||||
|
i = string.find(value, "%$", i + 1);
|
||||||
|
if i == nil then
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
if string.sub(value, i, i + 1) == "$$" then
|
||||||
|
i = i + 1;
|
||||||
|
else
|
||||||
|
local potentiallyEmptyReference = string.sub(value, i, i + 2);
|
||||||
|
if potentiallyEmptyReference == "$()" or potentiallyEmptyReference == "${}" then
|
||||||
|
i = i + 2;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Removes variable and function references and reverts p.esc's escaping of # and $ from a GNU make variable value (but not multiline).
|
||||||
|
-- Useful for coarse validation of string contents, whether there are unsupported characters.
|
||||||
|
-- What the references expand to isn't known at Premake time, but static value validation may be good to catch common issues.
|
||||||
|
-- To get a value that can be passed back to GNU make, do string.gsub of the "%$" pattern to "$$", and then p.esc.
|
||||||
|
-- For strictness and simplicity, the lone trailing $ is treated as a reference too (can't be a result of p.esc anyway).
|
||||||
|
function androidndk.unescapeAndRemoveMakeReferencesPostEsc(value)
|
||||||
|
-- Unescape p.esc's escaping of the comment character.
|
||||||
|
value = string.gsub(value, androidndk.commentUnescapePattern, "#");
|
||||||
|
local newValue = {};
|
||||||
|
local unclosedReferenceTerminators = {};
|
||||||
|
local afterReferenceCharacter = false;
|
||||||
|
for i = 1, string.len(value) do
|
||||||
|
local character = string.sub(value, i, i);
|
||||||
|
if afterReferenceCharacter then
|
||||||
|
-- The character after the $.
|
||||||
|
-- Options: $ (escaped raw $), an opening bracket (opening a reference), any other character (single-character reference).
|
||||||
|
if character == "$" then
|
||||||
|
if not (#unclosedReferenceTerminators > 0) then
|
||||||
|
-- Escaped $.
|
||||||
|
table.insert(newValue, "$");
|
||||||
|
end
|
||||||
|
elseif character == "(" then
|
||||||
|
table.insert(unclosedReferenceTerminators, ")");
|
||||||
|
elseif character == "{" then
|
||||||
|
table.insert(unclosedReferenceTerminators, "}");
|
||||||
|
end
|
||||||
|
afterReferenceCharacter = false;
|
||||||
|
else
|
||||||
|
-- Not the character after the $.
|
||||||
|
-- Options: $, a reference-closing bracket, any other raw character.
|
||||||
|
if character == "$" then
|
||||||
|
afterReferenceCharacter = true;
|
||||||
|
else
|
||||||
|
if #unclosedReferenceTerminators > 0 then
|
||||||
|
if character == unclosedReferenceTerminators[#unclosedReferenceTerminators] then
|
||||||
|
unclosedReferenceTerminators[#unclosedReferenceTerminators] = nil;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- A raw character outside references.
|
||||||
|
table.insert(newValue, character);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(newValue);
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.staticallyHasPatternPostEsc(value, pattern)
|
||||||
|
return string.find(androidndk.unescapeAndRemoveMakeReferencesPostEsc(value, true), pattern) ~= nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Characters that can be escaped with a backslash in Windows shell commands, except for \ itself and ".
|
||||||
|
-- \ and " should be escaped before these inside individual arguments as they may be wrapped in " by the module itself to include whitespaces.
|
||||||
|
-- On Windows, before other characters (except for \ and "), a \ is kept and treated as a directory separator instead.
|
||||||
|
-- Extracted by using all characters 33-126 (with special rules for #) prefixed with \ in a -Define and seeing the Clang error for its usage.
|
||||||
|
-- Matches Windows sh_chars_sh in GNU make, with the addition of a single quote.
|
||||||
|
-- On Linux, where \ is not a path separator, prefixing any character with \ results in it being escaped in the shell.
|
||||||
|
androidndk.shellEscapedCharactersPostQuotes = {
|
||||||
|
"#", "$", "&", "'", "(", ")", "*", ";", "<", ">", "?", "[", "]", "^", "`", "{", "|", "}"
|
||||||
|
};
|
||||||
|
|
||||||
|
-- Checkers are meant to be used in assignToVariablePostEsc calls, and assume the input is pre-escaped and doesn't contain non-empty references.
|
||||||
|
|
||||||
|
function androidndk.shellEscapePostQuotesChecker(value)
|
||||||
|
-- Comments are escaped as $()\# - contains an empty reference.
|
||||||
|
-- However, this still includes the # itself, which needs to be escaped with a backslash in a shell command.
|
||||||
|
-- Raw dollar signs ($$ representing $) need to be escaped in a shell command too.
|
||||||
|
if string.find(value, "#") ~= nil or string.find(value, "%$%$") ~= nil then
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
-- Remove empty references to check if the value contains (){}.
|
||||||
|
-- It's assumed that these are the only kind of references that may be passed to checkers.
|
||||||
|
value = string.gsub(string.gsub(value, "%$%(%)", ""), "%${}", "");
|
||||||
|
return string.find(value, "[&'%(%)%*;<>%?%[%]%^`{|}]") ~= nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.shellEscapeChecker(value)
|
||||||
|
-- The only two usages of a backslash after androidndk.esc are a raw backslash and a # escape sequence.
|
||||||
|
-- Both \ and # need to be escaped with \ in the shell.
|
||||||
|
-- So, it's okay to return true if there is any \ at all.
|
||||||
|
if string.find(value, "[\\\"]") ~= nil then
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
return androidndk.shellEscapePostQuotesChecker(value);
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.shellEscapeModuleFileNameChecker(value)
|
||||||
|
-- : must be \-escaped on Linux.
|
||||||
|
-- It's a drive letter separator on Windows, however, so it's disallowed in LOCAL_MODULE_FILENAME there (it's a name, not a path).
|
||||||
|
if string.find(value, "[:]") ~= nil then
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
return androidndk.shellEscapeChecker(value);
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.shellEscapeSrcFilesChecker(value)
|
||||||
|
-- : must be \-escaped on Linux, but cannot be escaped on non-Cygwin Windows, and is a drive letter separator there supported directly.
|
||||||
|
-- The differences are handled at build time according to $(HOST_OS).
|
||||||
|
if string.find(value, "[:]") ~= nil then
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
return androidndk.shellEscapeChecker(value);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Using UPPER_CASE names because ndk-build reserves all lower-case names.
|
||||||
|
androidndk.shellEscapePreQuotesMakeCall = "PREMAKE_ANDROIDNDK_SHELL_ESCAPE_PRE_QUOTES";
|
||||||
|
androidndk.shellEscapePostQuotesMakeCall = "PREMAKE_ANDROIDNDK_SHELL_ESCAPE_POST_QUOTES";
|
||||||
|
androidndk.shellEscapeMakeCall = "PREMAKE_ANDROIDNDK_SHELL_ESCAPE";
|
||||||
|
androidndk.shellEscapeModuleFileNameMakeCall = "PREMAKE_ANDROIDNDK_SHELL_ESCAPE_MODULE_FILENAME";
|
||||||
|
androidndk.shellEscapeSrcFilesMakeCall = "PREMAKE_ANDROIDNDK_SHELL_ESCAPE_SRC_FILES";
|
||||||
|
|
||||||
|
androidndk.temporaryVariablePrefix = "PREMAKE_ANDROIDNDK_TEMPORARY_";
|
||||||
|
|
||||||
|
-- Gets or adds a temporary intermediate GNU make variable.
|
||||||
|
-- Useful for wrapping strings in GNU make function calls, for safety if they contain the closing bracket.
|
||||||
|
function androidndk.getTemporaryVariableReference(temporaryVariables, value)
|
||||||
|
local index = temporaryVariables[value];
|
||||||
|
if index == nil then
|
||||||
|
index = #temporaryVariables + 1;
|
||||||
|
temporaryVariables[index] = value;
|
||||||
|
temporaryVariables[value] = index;
|
||||||
|
end
|
||||||
|
return "$(" .. androidndk.temporaryVariablePrefix .. index .. ")";
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.getCaseElse(anyCasesWritten)
|
||||||
|
if anyCasesWritten then
|
||||||
|
return "else ";
|
||||||
|
end
|
||||||
|
return "";
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ABIs that be set by a combination of settings that can be expressed in a project.
|
||||||
|
-- With the architecture set to "universal" or nil, projects can be built for ABIs not in this list though.
|
||||||
|
-- If new ABIs are added to the NDK, they can be supported without updating this module at least in ABI-agnostic projects.
|
||||||
|
-- Sorted alphabetically.
|
||||||
|
androidndk.knownAbis = {
|
||||||
|
"arm64-v8a",
|
||||||
|
-- "armeabi" (ARMv5) was removed in NDK r17.
|
||||||
|
"armeabi-v7a",
|
||||||
|
-- "armeabi-v7a-hard" was removed in NDK r12.
|
||||||
|
-- Building for both calling conventions at once (if passing this table to APP_ABI) would be pointless anyway.
|
||||||
|
-- "mips" and "mips64" were removed in NDK r17.
|
||||||
|
-- Premake has no built-in architecture values for MIPS.
|
||||||
|
"x86",
|
||||||
|
"x86_64",
|
||||||
|
};
|
||||||
|
|
||||||
|
androidndk.ABI_ALL = "all";
|
||||||
|
|
||||||
|
androidndk.architectureAbis = {
|
||||||
|
[p.ARM] = "armeabi-v7a",
|
||||||
|
[p.ARM64] = "arm64-v8a",
|
||||||
|
[p.X86] = "x86",
|
||||||
|
[p.X86_64] = "x86_64",
|
||||||
|
};
|
||||||
|
|
||||||
|
-- Returns:
|
||||||
|
-- * The ABI name for supported configurations.
|
||||||
|
-- * "all" (like the "all" that can be passed to APP_ABI) if the configuration doesn't have an ABI filter.
|
||||||
|
-- * nil for unsupported configurations.
|
||||||
|
function androidndk.getConfigAbi(config)
|
||||||
|
-- While armeabi (ARMv5) and armeabi-v7a (ARMv7) may be both considered "ARM", ARMv5 is different enough to have its own `architecture` option.
|
||||||
|
-- Support for ARMv5, however, was removed in NDK r17.
|
||||||
|
-- If needed, it can be exposed via a separate configuration variable.
|
||||||
|
-- MIPS support was also removed in r17.
|
||||||
|
if config.architecture == nil or config.architecture == p.UNIVERSAL then
|
||||||
|
return androidndk.ABI_ALL;
|
||||||
|
end
|
||||||
|
return androidndk.architectureAbis[config.architecture];
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.preventWhitespaceTrimming(value)
|
||||||
|
if androidndk.whitespacesNonNewline[string.sub(value, 1, 1)] ~= nil then
|
||||||
|
-- Prevent trimming of the leading whitespaces.
|
||||||
|
value = "$()" .. value;
|
||||||
|
end
|
||||||
|
local trailingCharacter = string.sub(value, -1, -1);
|
||||||
|
if trailingCharacter == "\\" or androidndk.whitespacesNonNewline[trailingCharacter] ~= nil then
|
||||||
|
-- Don't treat the final backslash (like in a directory path) as line splitting.
|
||||||
|
-- Also prevent trimming of the trailing whitespaces.
|
||||||
|
value = value .. "$()";
|
||||||
|
end
|
||||||
|
return value;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns whether the post-processing call is needed for any element.
|
||||||
|
function androidndk.assignToVariablePostEsc(name, value, multiline, postProcessChecker, operator)
|
||||||
|
if operator == nil then
|
||||||
|
operator = ":=";
|
||||||
|
end
|
||||||
|
if type(value) == "string" then
|
||||||
|
value = { value };
|
||||||
|
end
|
||||||
|
value = table.filterempty(value);
|
||||||
|
if not (#value > 0) then
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
local postProcessNeeded = false;
|
||||||
|
if multiline then
|
||||||
|
p.push("%s %s \\", name, operator);
|
||||||
|
for i, element in ipairs(value) do
|
||||||
|
local boundedLine = androidndk.preventWhitespaceTrimming(element);
|
||||||
|
if i >= #value then
|
||||||
|
p.w(boundedLine);
|
||||||
|
else
|
||||||
|
p.w("%s \\", boundedLine);
|
||||||
|
end
|
||||||
|
-- Post-processing is always needed if there are references because they are expanded to anything at runtime.
|
||||||
|
-- However, if not needed, don't waste build time doing unnecessary substitutions.
|
||||||
|
if postProcessChecker ~= nil and not postProcessNeeded and (androidndk.hasNonEmptyMakeReferencesPostEsc(element) or postProcessChecker(element)) then
|
||||||
|
postProcessNeeded = true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
p.pop();
|
||||||
|
else
|
||||||
|
-- Inner whitespaces are preserved within the right-hand side of an assignment, safe to concatenate.
|
||||||
|
p.w("%s %s %s", name, operator, androidndk.preventWhitespaceTrimming(table.concat(value, " ")));
|
||||||
|
end
|
||||||
|
return postProcessNeeded;
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.writePostProcessCall(variableName, makeCall)
|
||||||
|
p.w("%s := $(call %s,$(%s))", variableName, makeCall, variableName);
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.isConfigSupported(config, reportWarnings)
|
||||||
|
if config.flags.ExcludeFromBuild then
|
||||||
|
-- Intentionally excluded.
|
||||||
|
-- Warnings specific to this module shouldn't be reported either as the configuration may not be targeting this module at all.
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
if config.project ~= nil then
|
||||||
|
assert(androidndk.isProjectSupported(config.project, false), "Usage of configurations for unsupported projects must not be attempted at all");
|
||||||
|
end
|
||||||
|
-- Wrong kind or ABI are a normal situation when the project has both Android and non-Android configs.
|
||||||
|
-- Not reporting warnings for them (or any warnings as for non-Android targets these issues may be non-existent).
|
||||||
|
if androidndk.kindScripts[config.kind] == nil or androidndk.getConfigAbi(config) == nil then
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
local warningLocation;
|
||||||
|
if reportWarnings then
|
||||||
|
if config.project ~= nil then
|
||||||
|
warningLocation = string.format("workspace '%s' project '%s' configuration '%s'", config.workspace.name, config.project.name, config.name);
|
||||||
|
else
|
||||||
|
warningLocation = string.format("workspace '%s' configuration '%s'", config.workspace.name, config.name);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local configSupported = true;
|
||||||
|
-- Whitespaces because configurations are placed in a whitespace-separated list.
|
||||||
|
-- % because configurations and platforms are used in filter and filter-out, where % is a wildcard.
|
||||||
|
-- It can be escaped with \, but then the case when the % is preceded by other backslashes is complicated to handle.
|
||||||
|
-- The rest are disallowed due to usage of the names in GNU make function calls.
|
||||||
|
local disallowedCharacters = "%(),";
|
||||||
|
local disallowedPattern = "[%s%%%(%),]";
|
||||||
|
if androidndk.staticallyHasPatternPostEsc(p.esc(config.buildcfg), disallowedPattern) then
|
||||||
|
configSupported = false;
|
||||||
|
if reportWarnings then
|
||||||
|
p.warn(
|
||||||
|
"Skipping %s with configuration name containing whitespaces or disallowed characters %s",
|
||||||
|
warningLocation, disallowedCharacters);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if config.platform ~= nil and androidndk.staticallyHasPatternPostEsc(p.esc(config.platform), disallowedPattern) then
|
||||||
|
configSupported = false;
|
||||||
|
if reportWarnings then
|
||||||
|
p.warn(
|
||||||
|
"Skipping %s with platform name containing whitespaces or disallowed characters %s",
|
||||||
|
warningLocation, disallowedCharacters);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return configSupported;
|
||||||
|
end
|
||||||
|
|
||||||
|
return androidndk;
|
1743
src_rebuild/premake_modules/androidndk/androidndk_project.lua
Normal file
1743
src_rebuild/premake_modules/androidndk/androidndk_project.lua
Normal file
File diff suppressed because it is too large
Load Diff
513
src_rebuild/premake_modules/androidndk/androidndk_workspace.lua
Normal file
513
src_rebuild/premake_modules/androidndk/androidndk_workspace.lua
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
-- premake-androidndk - a multi-ABI, multi-language ndk-build Android.mk generator for Premake.
|
||||||
|
-- Originally written by Vitaliy <Triang3l> Kuzmin.
|
||||||
|
-- See README.md for detailed usage and design information.
|
||||||
|
-- Available under the Unlicense (see UNLICENSE.txt) or the BSD 3-Clause "New" or "Revised" License (see LICENSE.txt).
|
||||||
|
|
||||||
|
local p = premake;
|
||||||
|
local androidndk = p.modules.androidndk;
|
||||||
|
|
||||||
|
-- Projects can add their own configurations and platforms.
|
||||||
|
-- So, the use of workspace.configurations, workspace.projects, and their product workspace.configs, should be avoided.
|
||||||
|
-- Instead, configs should be gathered from all projects.
|
||||||
|
|
||||||
|
-- Writes the setup of the variables used in configuration conditionals.
|
||||||
|
-- Required in both Application.mk and the workspace Android.mk because with Gradle, the Application.mk is optional.
|
||||||
|
function androidndk.setupConfigConditionalMakeVariables(usedBuildcfgs, usedPlatforms)
|
||||||
|
-- Display generated workspace usage information.
|
||||||
|
-- Using warning/error directly, not the __ndk_* counterparts.
|
||||||
|
-- __ndk_* functions are internal, and it's more important to show this to the user than to respect NDK_NO_*.
|
||||||
|
-- $(info) is not displayed in the build output in Android Studio, using $(warning) for everything.
|
||||||
|
p.push("ifeq ($(filter %s,$(PREMAKE_ANDROIDNDK_CONFIGURATIONS)),)", table.concat(p.esc(usedBuildcfgs), " "));
|
||||||
|
p.w("$(warning No configurations to build are specified in PREMAKE_ANDROIDNDK_CONFIGURATIONS.)");
|
||||||
|
p.w("$(warning Specify one or multiple \"PREMAKE_ANDROIDNDK_CONFIGURATIONS+=configuration\" in the ndk-build arguments to build those configurations.)");
|
||||||
|
p.w("$(warning For workspaces with multiple target platforms, you can also provide the list of the platforms to build via PREMAKE_ANDROIDNDK_PLATFORMS.)");
|
||||||
|
p.w("$(warning If PREMAKE_ANDROIDNDK_PLATFORMS is not specified, the projects in this workspace will be built for all platforms they're targeting.)");
|
||||||
|
p.w("$(warning Note that configuration and platform names are case-sensitive in this script.)");
|
||||||
|
p.w("$(warning )");
|
||||||
|
p.w("$(warning It's heavily recommended that only at most one configuration and platform specified corresponds to each targeted ABI.)");
|
||||||
|
p.w("$(warning Otherwise, which set of project settings will actually be chosen for building for each ABI will be undefined.)");
|
||||||
|
p.w("$(warning )");
|
||||||
|
p.w("$(warning The recommended approach is to use configurations for the optimization mode, and, if needed, platforms for ABI filtering.)");
|
||||||
|
p.w("$(warning This can be done by specifying different values of the Premake architecture setting for each platform using a platform filter.)");
|
||||||
|
p.w("$(warning In this case, each ABI will unambiguously correspond to only one configuration and platform pair.)");
|
||||||
|
p.w("$(warning )");
|
||||||
|
p.w("$(warning Configurations for this workspace:)");
|
||||||
|
for i, buildcfg in ipairs(usedBuildcfgs) do
|
||||||
|
p.x("$(warning $() %s)", buildcfg);
|
||||||
|
end
|
||||||
|
p.w("$(warning )");
|
||||||
|
if #usedPlatforms > 0 then
|
||||||
|
p.w("$(warning Platforms for this workspace:)");
|
||||||
|
for i, platform in ipairs(usedPlatforms) do
|
||||||
|
p.x("$(warning $() %s)", platform);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
p.w("$(warning This workspace is platform-agnostic.)");
|
||||||
|
end
|
||||||
|
p.w("$(error Aborting.)");
|
||||||
|
p.pop("endif");
|
||||||
|
|
||||||
|
-- Generate variables used for configuration selection.
|
||||||
|
-- As Application.mk variables are preserved in Android.mk, += may result in duplication.
|
||||||
|
-- Only using := for this reason, and also not modifying the original PREMAKE_ANDROIDNDK_CONFIGURATIONS/PLATFORMS.
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_CONFIGURATIONS_PREFIXED := $(addprefix CONFIGURATION=,$(PREMAKE_ANDROIDNDK_CONFIGURATIONS))");
|
||||||
|
if #usedPlatforms > 0 then
|
||||||
|
p.push("ifneq ($(PREMAKE_ANDROIDNDK_PLATFORMS),)");
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_PLATFORMS_PREFIXED := $(addprefix PLATFORM=,$(PREMAKE_ANDROIDNDK_PLATFORMS))");
|
||||||
|
p.pop();
|
||||||
|
p.push("else");
|
||||||
|
local usedPlatformsPrefixed = {};
|
||||||
|
for i, platform in ipairs(usedPlatforms) do
|
||||||
|
table.insert(usedPlatformsPrefixed, "PLATFORM=" .. p.esc(platform));
|
||||||
|
end
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_PLATFORMS_PREFIXED := %s", table.concat(usedPlatformsPrefixed, " "));
|
||||||
|
p.pop("endif");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.findConfigForAppSetting(workspace, buildcfg, platform, predicate)
|
||||||
|
-- In none of these checks should completely unrequested build configurations or platforms pass.
|
||||||
|
-- This may lead, for instance, to systemversion for a totally different OS to be selected as a fallback.
|
||||||
|
|
||||||
|
-- Considering the workspace (and, if it doesn't provide the needed value, the start project) highest-priority.
|
||||||
|
-- Even when requesting platform-specific settings, but the start project is platform-agnostic (nil .platform), still prefer the start project.
|
||||||
|
-- This makes settings more controllable than when some project can override the setting just because it has a platform specialization.
|
||||||
|
|
||||||
|
-- Try to find in the workspace itself.
|
||||||
|
for config in p.workspace.eachconfig(workspace) do
|
||||||
|
if androidndk.isConfigSupported(config, false) then
|
||||||
|
if config.buildcfg == buildcfg and (config.platform == nil or config.platform == platform) and predicate(config) then
|
||||||
|
return config;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If didn't find in the workspace itself, try the main project in the workspace - the start project.
|
||||||
|
if workspace.startproject ~= nil then
|
||||||
|
local startProject = p.workspace.findproject(workspace, workspace.startproject);
|
||||||
|
if startProject ~= nil and androidndk.isProjectSupported(startProject, false) then
|
||||||
|
for config in p.project.eachconfig(startProject) do
|
||||||
|
if androidndk.isConfigSupported(config, false) then
|
||||||
|
if config.buildcfg == buildcfg and (config.platform == nil or config.platform == platform) and predicate(config) then
|
||||||
|
return config;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This configuration may be used by just a subset of the projects.
|
||||||
|
-- Platform-specific specializations and platform-agnostic fallbacks are obtained via separate findConfigForAppSetting calls in this case.
|
||||||
|
-- ?= for platform-agnostic variables is done even if platform conditions pass - no need to look for them here for non-nil platforms.
|
||||||
|
for project in p.workspace.eachproject(workspace) do
|
||||||
|
if androidndk.isProjectSupported(project, false) then
|
||||||
|
for config in p.project.eachconfig(project) do
|
||||||
|
if androidndk.isConfigSupported(config, false) then
|
||||||
|
if config.buildcfg == buildcfg and config.platform == platform and predicate(config) then
|
||||||
|
return config;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Found nothing - don't add the setting.
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a table of { variable = "APP_...", value = ... }, with the variable values escaped.
|
||||||
|
-- Expecting the outer code to set APP_DEBUG to false if APP_OPTIM is release in the end to match Premake optimize/symbols logic.
|
||||||
|
function androidndk.gatherEscapedAppVariables(workspace, buildcfg, platform)
|
||||||
|
-- If the value for a Premake setting is not specified by the projects for this configuration, the default must not be added to the table.
|
||||||
|
-- This would make it impossible for another configuration, where the setting is explicitly defined, to override the value using ?=.
|
||||||
|
-- Only returning variables corresponding to settings explicitly defined for this configuration.
|
||||||
|
|
||||||
|
-- ndk-build defaults to non-debug (potentially no symbols) and optimized.
|
||||||
|
-- Premake doesn't define a default for symbols, but unoptimized by default.
|
||||||
|
-- Replicating the p.config.isDebugBuild and p.config.isOptimizedBuild logic.
|
||||||
|
-- An optimized build is not considered a debug one at all, regardless of whether symbols are needed.
|
||||||
|
local optimizeConfig = androidndk.findConfigForAppSetting(workspace, buildcfg, platform, function(config)
|
||||||
|
return config.optimize ~= nil;
|
||||||
|
end);
|
||||||
|
-- optimizeConfig.optimize ~= nil checked previously.
|
||||||
|
local isOptimized = optimizeConfig ~= nil and optimizeConfig.optimize ~= p.OFF and optimizeConfig.optimize ~= "Debug";
|
||||||
|
local appOptim = nil;
|
||||||
|
if optimizeConfig ~= nil then
|
||||||
|
-- The configuration explicitly wants to enable or to disable optimizations.
|
||||||
|
appOptim = iif(isOptimized, "release", "debug");
|
||||||
|
end
|
||||||
|
-- Expecting the outer code to set APP_DEBUG to false if APP_OPTIM is release.
|
||||||
|
-- Thus, not explicitly returning APP_DEBUG ?= false for release APP_OPTIM.
|
||||||
|
local appDebug = nil;
|
||||||
|
if not isOptimized then
|
||||||
|
local symbolsConfig = androidndk.findConfigForAppSetting(workspace, buildcfg, platform, function(config)
|
||||||
|
return config.symbols ~= nil;
|
||||||
|
end);
|
||||||
|
if symbolsConfig ~= nil then
|
||||||
|
-- p.config.isOptimizedBuild checked previously.
|
||||||
|
appDebug = iif(symbolsConfig.symbols ~= p.OFF and symbolsConfig.symbols ~= p.DEFAULT, "true", "false");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local appVariables = {};
|
||||||
|
|
||||||
|
-- APP_DEBUG
|
||||||
|
if appDebug ~= nil then
|
||||||
|
table.insert(appVariables, { variable = "APP_DEBUG", value = appDebug });
|
||||||
|
end
|
||||||
|
|
||||||
|
-- APP_OPTIM
|
||||||
|
if appOptim ~= nil then
|
||||||
|
table.insert(appVariables, { variable = "APP_OPTIM", value = appOptim });
|
||||||
|
end
|
||||||
|
|
||||||
|
-- APP_PLATFORM
|
||||||
|
local systemVersionConfig = androidndk.findConfigForAppSetting(workspace, buildcfg, platform, function(config)
|
||||||
|
return p.project.systemversion(config) ~= nil;
|
||||||
|
end);
|
||||||
|
if systemVersionConfig ~= nil then
|
||||||
|
table.insert(appVariables, { variable = "APP_PLATFORM", value = "android-" .. p.esc(p.project.systemversion(systemVersionConfig)) });
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PREMAKE_ANDROIDNDK_APP_STL_RUNTIME (part of APP_STL)
|
||||||
|
local stlConfig = androidndk.findConfigForAppSetting(workspace, buildcfg, platform, function(config)
|
||||||
|
return config.cppstl ~= nil;
|
||||||
|
end);
|
||||||
|
if stlConfig ~= nil then
|
||||||
|
-- The default, which in ndk-build is "none", is explicitly requested for this configuration.
|
||||||
|
local stl = iif(stlConfig.cppstl == p.DEFAULT, "none", stlConfig.cppstl);
|
||||||
|
table.insert(appVariables, { variable = "PREMAKE_ANDROIDNDK_APP_STL_RUNTIME", value = p.esc(stl) });
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PREMAKE_ANDROIDNDK_APP_STL_LINKAGE (part of APP_STL)
|
||||||
|
-- While for ndk-build, the default STL is "none", which doesn't have a linkage suffix, for CMake it's "c++_static".
|
||||||
|
-- Therefore, considering static the default (treating explicitly specified "Default" as "On").
|
||||||
|
local staticRuntimeConfig = androidndk.findConfigForAppSetting(workspace, buildcfg, platform, function(config)
|
||||||
|
return config.staticruntime ~= nil;
|
||||||
|
end);
|
||||||
|
if staticRuntimeConfig ~= nil then
|
||||||
|
local stlLinkage = iif(staticRuntimeConfig.staticruntime ~= p.OFF, "_static", "_shared");
|
||||||
|
table.insert(appVariables, { variable = "PREMAKE_ANDROIDNDK_APP_STL_LINKAGE", value = stlLinkage });
|
||||||
|
end
|
||||||
|
|
||||||
|
return appVariables;
|
||||||
|
end
|
||||||
|
|
||||||
|
function androidndk.onWorkspace(workspace)
|
||||||
|
-- Not allowing references or escaped $ in workspace names as they complicate path building as well as specifying APP_BUILD_SCRIPT.
|
||||||
|
-- Premake treats any path beginning with $ as absolute.
|
||||||
|
-- APP_BUILD_SCRIPT also doesn't allow #$ and whitespaces.
|
||||||
|
if string.find(workspace.name, "%$") ~= nil or androidndk.staticallyHasPatternPostEsc(p.esc(workspace.name), "[%s#%$]") then
|
||||||
|
p.warn("Skipping workspace '%s' with name containing GNU make references, whitespaces or disallowed characters #$", workspace.name);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
androidndk.setupGeneration();
|
||||||
|
|
||||||
|
-- Gather build configurations and platforms used by all projects for generating conditionals for application settings.
|
||||||
|
-- Projects may add their configurations not present in the workspace itself, and they won't appear in workspace.configs.
|
||||||
|
-- Some projects may have no platforms specified.
|
||||||
|
-- In this case, they're built regardless of the platform, and also if some completely different platform is specified.
|
||||||
|
-- At least one build configuration is required in a project, however.
|
||||||
|
local usedBuildcfgs = {};
|
||||||
|
local usedPlatforms = {};
|
||||||
|
for project in p.workspace.eachproject(workspace) do
|
||||||
|
if androidndk.isProjectSupported(project, false) then
|
||||||
|
for config in p.project.eachconfig(project) do
|
||||||
|
if androidndk.isConfigSupported(config, false) then
|
||||||
|
table.insertkeyed(usedBuildcfgs, config.buildcfg);
|
||||||
|
if config.platform ~= nil then
|
||||||
|
table.insertkeyed(usedPlatforms, config.platform);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Application.mk.
|
||||||
|
p.generate(workspace, ".Application.mk", function(workspace)
|
||||||
|
-- Verify the correctness of the arguments, and set up the variables used for filtering in Application.mk.
|
||||||
|
androidndk.setupConfigConditionalMakeVariables(usedBuildcfgs, usedPlatforms);
|
||||||
|
|
||||||
|
-- Gather Application.mk variable values for selected configurations and platforms.
|
||||||
|
-- As this is Application.mk, ABI filtering is not possible.
|
||||||
|
-- Therefore, selection of the required build configurations and platforms will work differently than in projects.
|
||||||
|
-- All selected build configurations and platforms must have the same values of settings written here.
|
||||||
|
-- For example, APP_OPTIM may be wrong with `PREMAKE_ANDROIDNDK_CONFIGURATIONS := Debug Release` if they have different `optimize`.
|
||||||
|
-- If one selected configuration-platform defines a value, while another doesn't care, pick from the one where it's explicitly set.
|
||||||
|
-- So, using if/if and ?= instead of if/elseif and :=, unlike in projects (where only configuration-platform pair is supposed to be chosen).
|
||||||
|
-- Most APP variables accept only one value - using ?= for them.
|
||||||
|
-- APP_ABI, however, accumulates the needed ABIs (in this case, for selected configurations and platforms), so using += for it.
|
||||||
|
|
||||||
|
-- First, clear values that will be set - they might have been set externally while invoking ndk-build, override them.
|
||||||
|
-- Setting them to an empty value is not sufficient - `undefine` is required for ?= to work.
|
||||||
|
-- clear-vars is called for known APP variables before including Application.mk, which, as of NDK r23, defines the values as empty, however.
|
||||||
|
-- For this reason, if no value is provided, defining each of these variables as something (at least as empty).
|
||||||
|
p.w("undefine APP_ABI");
|
||||||
|
p.w("undefine APP_DEBUG");
|
||||||
|
p.w("undefine APP_OPTIM");
|
||||||
|
p.w("undefine APP_PLATFORM");
|
||||||
|
p.w("undefine PREMAKE_ANDROIDNDK_APP_STL_RUNTIME");
|
||||||
|
p.w("undefine PREMAKE_ANDROIDNDK_APP_STL_LINKAGE");
|
||||||
|
|
||||||
|
-- Gather ABIs the projects are built for, for each configuration and platform for it.
|
||||||
|
-- Can't just collect all ABIs used by all platforms into a single APP_ABI assignment.
|
||||||
|
-- The reason is that some configurations may not even be targeting Android.
|
||||||
|
-- For instance, may only want ARM builds for Android, but x86 builds only for Windows.
|
||||||
|
-- If "all" is present in any platform-specific or platform-agnostic table, the whole platform must be treated as using "all".
|
||||||
|
local buildcfgsAbis = {
|
||||||
|
-- [1...] = [buildcfg] = {
|
||||||
|
-- platformSpecific = {
|
||||||
|
-- [1...] = [platform] = {
|
||||||
|
-- [1...] = [abi] = abi,
|
||||||
|
-- }
|
||||||
|
-- },
|
||||||
|
-- platformAgnostic = {
|
||||||
|
-- [1...] = [abi] = abi,
|
||||||
|
-- },
|
||||||
|
-- }
|
||||||
|
};
|
||||||
|
local abiAgnosticConfigsUsed = false;
|
||||||
|
for project in p.workspace.eachproject(workspace) do
|
||||||
|
if androidndk.isProjectSupported(project, false) then
|
||||||
|
for config in p.project.eachconfig(project) do
|
||||||
|
if androidndk.isConfigSupported(config, false) then
|
||||||
|
local buildcfgAbis = buildcfgsAbis[config.buildcfg];
|
||||||
|
if buildcfgAbis == nil then
|
||||||
|
buildcfgAbis = { platformSpecific = {}, platformAgnostic = {} };
|
||||||
|
buildcfgsAbis[config.buildcfg] = buildcfgAbis;
|
||||||
|
end
|
||||||
|
local platformAbis;
|
||||||
|
if config.platform ~= nil then
|
||||||
|
platformAbis = buildcfgAbis.platformSpecific[config.platform];
|
||||||
|
if platformAbis == nil then
|
||||||
|
platformAbis = {};
|
||||||
|
buildcfgAbis.platformSpecific[config.platform] = platformAbis;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
platformAbis = buildcfgAbis.platformAgnostic;
|
||||||
|
end
|
||||||
|
local abi = androidndk.getConfigAbi(config);
|
||||||
|
table.insertkeyed(platformAbis, abi);
|
||||||
|
if abi == androidndk.ABI_ALL then
|
||||||
|
abiAgnosticConfigsUsed = true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Gather the variables, and write the ABIs and variables.
|
||||||
|
for i, buildcfg in ipairs(usedBuildcfgs) do
|
||||||
|
local buildcfgConditionalOpen = false;
|
||||||
|
|
||||||
|
local buildcfgAbis = buildcfgsAbis[buildcfg];
|
||||||
|
-- Skip ABIs needed by platform-agnostic projects with this configuration from platform specializations.
|
||||||
|
-- ABIs needed by platform-agnostic projects will be added regardless of the platform.
|
||||||
|
local platformAgnosticAbis = nil;
|
||||||
|
local platformAgnosticAbisAll = false;
|
||||||
|
if buildcfgAbis ~= nil then
|
||||||
|
platformAgnosticAbis = buildcfgAbis.platformAgnostic;
|
||||||
|
platformAgnosticAbisAll = platformAgnosticAbis[androidndk.ABI_ALL] ~= nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Gather and write platform-specific ABIs and platform specializations of APP variables.
|
||||||
|
for i2, platform in ipairs(usedPlatforms) do
|
||||||
|
-- Gather ABIs that any projects, for this buildcfg-platform pair, need to be built for.
|
||||||
|
-- Skip ABIs needed by platform-agnostic projects with this configuration from platform specializations.
|
||||||
|
-- ABIs needed by platform-agnostic projects will be added regardless of the platform.
|
||||||
|
local platformNewAbis = {};
|
||||||
|
if buildcfgAbis ~= nil and not platformAgnosticAbisAll then
|
||||||
|
if buildcfgAbis ~= nil then
|
||||||
|
local platformAbisUnfiltered = buildcfgAbis.platformSpecific[platform];
|
||||||
|
if platformAbisUnfiltered ~= nil then
|
||||||
|
for i3, abi in ipairs(platformAbisUnfiltered) do
|
||||||
|
if abi == androidndk.ABI_ALL then
|
||||||
|
platformNewAbis = { androidndk.ABI_ALL };
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
if platformAgnosticAbis == nil or platformAgnosticAbis[abi] == nil then
|
||||||
|
table.insert(platformNewAbis, abi);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Sort alphabetically for stable output.
|
||||||
|
table.sort(platformNewAbis);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Gather specializations of the APP variables for this platform.
|
||||||
|
local platformAppVariables = androidndk.gatherEscapedAppVariables(workspace, buildcfg, platform);
|
||||||
|
-- Write ABI additions and variable specializations for this platform.
|
||||||
|
if #platformNewAbis > 0 or #platformAppVariables > 0 then
|
||||||
|
if not buildcfgConditionalOpen then
|
||||||
|
buildcfgConditionalOpen = true;
|
||||||
|
p.push("ifneq ($(filter CONFIGURATION=%s,$(PREMAKE_ANDROIDNDK_CONFIGURATIONS_PREFIXED)),)", p.esc(buildcfg));
|
||||||
|
end
|
||||||
|
p.push("ifneq ($(filter PLATFORM=%s,$(PREMAKE_ANDROIDNDK_PLATFORMS_PREFIXED)),)", p.esc(platform));
|
||||||
|
androidndk.assignToVariablePostEsc("APP_ABI", platformNewAbis, false, nil, "+=");
|
||||||
|
for i3, variable in ipairs(platformAppVariables) do
|
||||||
|
androidndk.assignToVariablePostEsc(variable.variable, variable.value, false, nil, "?=");
|
||||||
|
end
|
||||||
|
-- Close the platform conditional.
|
||||||
|
p.pop("endif");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Write ABIs for platform-agnostic projects and APP variable values used when no platform specialization has been chosen.
|
||||||
|
local platformAgnosticAbisSorted = nil;
|
||||||
|
if platformAgnosticAbis ~= nil then
|
||||||
|
if platformAgnosticAbisAll then
|
||||||
|
platformAgnosticAbisSorted = { androidndk.ABI_ALL };
|
||||||
|
else
|
||||||
|
platformAgnosticAbisSorted = table.arraycopy(platformAgnosticAbis);
|
||||||
|
-- Sort alphabetically for stable output.
|
||||||
|
table.sort(platformAgnosticAbisSorted);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local platformAgnosticAppVariables = androidndk.gatherEscapedAppVariables(workspace, buildcfg, nil);
|
||||||
|
if (platformAgnosticAbisSorted ~= nil and #platformAgnosticAbisSorted > 0) or #platformAgnosticAppVariables > 0 then
|
||||||
|
if not buildcfgConditionalOpen then
|
||||||
|
buildcfgConditionalOpen = true;
|
||||||
|
p.push("ifneq ($(filter CONFIGURATION=%s,$(PREMAKE_ANDROIDNDK_CONFIGURATIONS_PREFIXED)),)", p.esc(buildcfg));
|
||||||
|
end
|
||||||
|
if platformAgnosticAbisSorted ~= nil then
|
||||||
|
androidndk.assignToVariablePostEsc("APP_ABI", platformAgnosticAbisSorted, false, nil, "+=");
|
||||||
|
end
|
||||||
|
for i2, variable in ipairs(platformAgnosticAppVariables) do
|
||||||
|
androidndk.assignToVariablePostEsc(variable.variable, variable.value, false, nil, "?=");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if buildcfgConditionalOpen then
|
||||||
|
p.pop("endif");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply defaults if no configuration-specific overrides have been chosen, and normalize variables.
|
||||||
|
-- Also set variables that don't depend on the configuration.
|
||||||
|
|
||||||
|
-- APP_ABI
|
||||||
|
-- Setting to "all" by default is not needed - empty already means `all`.
|
||||||
|
-- Also, it can happen only when no configuration with projects to build is selected.
|
||||||
|
-- Remove duplicates (sorting does that implicitly).
|
||||||
|
p.w("APP_ABI := $(sort $(APP_ABI))");
|
||||||
|
-- If "all" was set for any configuration, and += of any other ABIs happened, make APP_ABI just "all".
|
||||||
|
if abiAgnosticConfigsUsed then
|
||||||
|
p.push("ifneq ($(filter " .. androidndk.ABI_ALL .. ",$(APP_ABI)),)");
|
||||||
|
p.w("APP_ABI := " .. androidndk.ABI_ALL);
|
||||||
|
p.pop("endif");
|
||||||
|
end
|
||||||
|
|
||||||
|
-- APP_BUILD_SCRIPT
|
||||||
|
-- In the same directory, no need for p.filename followed by making it relative.
|
||||||
|
-- Also for this reason, no need for path.join, which may treat the name as an absolute path (for instance, if it begins with a $()\#-escaped #).
|
||||||
|
p.w("APP_BUILD_SCRIPT := %s", "$(call my-dir)/" .. p.esc(workspace.name .. ".wks.Android.mk"));
|
||||||
|
|
||||||
|
-- APP_DEBUG and APP_OPTIM
|
||||||
|
-- Handling according to p.config.isDebugBuild and p.config.isOptimizedBuild logic (unoptimized by default, no symbols by default).
|
||||||
|
-- p.config.isDebugBuild always returns false (no symbols) for optimized builds.
|
||||||
|
-- For more information, see APP_DEBUG and APP_OPTIM gathering.
|
||||||
|
p.w("APP_OPTIM ?= debug");
|
||||||
|
p.push("ifeq ($(APP_OPTIM),release)");
|
||||||
|
p.w("APP_DEBUG := false");
|
||||||
|
p.pop();
|
||||||
|
p.push("else");
|
||||||
|
p.w("APP_DEBUG ?= false");
|
||||||
|
p.pop("endif");
|
||||||
|
|
||||||
|
-- APP_PLATFORM
|
||||||
|
-- Reverting the `undefine` because as of NDK r23, ndk-build sets all APP variables to empty values.
|
||||||
|
p.w("APP_PLATFORM ?=");
|
||||||
|
|
||||||
|
-- APP_STL
|
||||||
|
-- The default for ndk-build is "none". Also, since the default for CMake is "c++_static", assuming static linkage by default.
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_APP_STL_RUNTIME ?= none");
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_APP_STL_LINKAGE ?= _static");
|
||||||
|
-- "none" and "system" don't have linkage suffixes.
|
||||||
|
p.push("ifneq ($(filter none system,$(PREMAKE_ANDROIDNDK_APP_STL_RUNTIME)),)");
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_APP_STL_LINKAGE :=");
|
||||||
|
p.pop("endif");
|
||||||
|
p.w("APP_STL := $(PREMAKE_ANDROIDNDK_APP_STL_RUNTIME)$(PREMAKE_ANDROIDNDK_APP_STL_LINKAGE)");
|
||||||
|
end);
|
||||||
|
|
||||||
|
-- Android.mk.
|
||||||
|
p.generate(workspace, ".wks.Android.mk", function(workspace)
|
||||||
|
-- my-dir returns the directory containing the latest included file, not the directory with the current file.
|
||||||
|
-- Therefore, if project makefiles are written to other directories, calling it every time will result in incorrect paths.
|
||||||
|
p.w("PREMAKE_ANDROIDNDK_WORKSPACE_DIR := $(call my-dir)");
|
||||||
|
|
||||||
|
-- Verify the correctness of the arguments, and set up the variables used for filtering in Android.mk.
|
||||||
|
-- This needs to be in Android.mk even though it inherits Application.mk variables because with Gradle, Application.mk is optional.
|
||||||
|
androidndk.setupConfigConditionalMakeVariables(usedBuildcfgs, usedPlatforms);
|
||||||
|
|
||||||
|
-- Setup post-expansion escaping in text passed to command execution via the shell.
|
||||||
|
-- In some variables - LOCAL_CFLAGS/LOCAL_LDFLAGS, LOCAL_C_INCLUDES, LOCAL_MODULE_FILENAME - path requirements are pretty relaxed.
|
||||||
|
-- On Linux, file names may contain " or \, but they need to be escaped with \ prefix as otherwise they're interpreted by the shell.
|
||||||
|
-- On Windows, " is not allowed in file names, but a single \ is treated as a path separator - no escaping required.
|
||||||
|
-- Function for calling inside quoted arguments (to be followed by the function for a list of arguments).
|
||||||
|
p.w("%s = $(subst \",\\\",$(subst \\,\\\\,$(1)))", androidndk.shellEscapePreQuotesMakeCall);
|
||||||
|
-- Function for calling for lists of quoted arguments.
|
||||||
|
local escapeFunction = { androidndk.shellEscapePostQuotesMakeCall, "_NO_BRACKETS = " };
|
||||||
|
local bracketsEncountered = 0;
|
||||||
|
for i = #androidndk.shellEscapedCharactersPostQuotes, 1, -1 do
|
||||||
|
local character = androidndk.shellEscapedCharactersPostQuotes[i];
|
||||||
|
if character == "(" or character == ")" then
|
||||||
|
-- Brackets must be used in a ${} call, not $().
|
||||||
|
bracketsEncountered = bracketsEncountered + 1;
|
||||||
|
else
|
||||||
|
if character == "#" then
|
||||||
|
-- Escape the comment character similar to the way androidndk.esc does that, breaking the dependency on the number of backslashes.
|
||||||
|
character = androidndk.commentEscapeString;
|
||||||
|
elseif character == "$" then
|
||||||
|
character = "$$";
|
||||||
|
end
|
||||||
|
table.insert(escapeFunction, "$(subst ");
|
||||||
|
table.insert(escapeFunction, character);
|
||||||
|
table.insert(escapeFunction, ",\\");
|
||||||
|
table.insert(escapeFunction, character);
|
||||||
|
table.insert(escapeFunction, ",");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(escapeFunction, "$(1)");
|
||||||
|
table.insert(escapeFunction, string.rep(")", #androidndk.shellEscapedCharactersPostQuotes - bracketsEncountered));
|
||||||
|
p.w(table.concat(escapeFunction));
|
||||||
|
-- Escape the brackets as well.
|
||||||
|
p.w(
|
||||||
|
"%s = ${subst ),\\),${subst (,\\(,${call %s_NO_BRACKETS,${1}}}}",
|
||||||
|
androidndk.shellEscapePostQuotesMakeCall,
|
||||||
|
androidndk.shellEscapePostQuotesMakeCall);
|
||||||
|
-- Function for raw text without arguments containing whitespaces that need to be wrapped in true, unescaped quotes.
|
||||||
|
p.w(
|
||||||
|
"%s = $(call %s,$(call %s,$(1)))",
|
||||||
|
androidndk.shellEscapeMakeCall,
|
||||||
|
androidndk.shellEscapePostQuotesMakeCall,
|
||||||
|
androidndk.shellEscapePreQuotesMakeCall);
|
||||||
|
-- Function for LOCAL_MODULE_FILENAME.
|
||||||
|
-- : must be \-escaped on Linux.
|
||||||
|
-- It's a drive letter separator on Windows, however, so it's disallowed in LOCAL_MODULE_FILENAME there (it's a name, not a path).
|
||||||
|
-- Therefore, there's no need to handle it separately on Windows and Linux - just \-escape : unconditionally.
|
||||||
|
p.w("%s = $(subst :,\\:,$(call %s,$(1)))", androidndk.shellEscapeModuleFileNameMakeCall, androidndk.shellEscapeMakeCall);
|
||||||
|
-- Function for LOCAL_SRC_FILES and LOCAL_PCH.
|
||||||
|
-- : must be \-escaped on Linux, but cannot be escaped on non-Cygwin Windows, and is a drive letter separator there supported directly.
|
||||||
|
p.push("ifeq ($(HOST_OS),windows)");
|
||||||
|
p.w("%s = $(call %s,$(1))", androidndk.shellEscapeSrcFilesMakeCall, androidndk.shellEscapeMakeCall);
|
||||||
|
p.pop();
|
||||||
|
p.push("else");
|
||||||
|
p.w("%s = $(subst :,\\:,$(call %s,$(1)))", androidndk.shellEscapeSrcFilesMakeCall, androidndk.shellEscapeMakeCall);
|
||||||
|
p.pop("endif");
|
||||||
|
|
||||||
|
-- Include makefiles of all projects.
|
||||||
|
-- Same path logic as in p.generate.
|
||||||
|
local workspaceDirectory = path.getdirectory(p.filename(workspace, ".wks.Android.mk"));
|
||||||
|
for project in p.workspace.eachproject(workspace) do
|
||||||
|
if androidndk.isProjectSupported(project, false) then
|
||||||
|
p.w(
|
||||||
|
"include %s",
|
||||||
|
androidndk.preventWhitespaceTrimming(
|
||||||
|
path.join(
|
||||||
|
"$(PREMAKE_ANDROIDNDK_WORKSPACE_DIR)",
|
||||||
|
p.esc(path.getrelative(workspaceDirectory, p.filename(project, ".prj.Android.mk"))))));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
end
|
156
src_rebuild/tools/font_tool/font_tool_main.cpp
Normal file
156
src_rebuild/tools/font_tool/font_tool_main.cpp
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#include "stb_truetype.h"
|
||||||
|
#include "targa.h"
|
||||||
|
|
||||||
|
#include "hqfont.h"
|
||||||
|
|
||||||
|
struct FN2RangeInfo
|
||||||
|
{
|
||||||
|
OUT_FN2RANGE hdr;
|
||||||
|
OUT_FN2INFO* chars;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FN2RangeInfo fontRanges[4];
|
||||||
|
static int fontRangeCount = 0;
|
||||||
|
|
||||||
|
void Usage()
|
||||||
|
{
|
||||||
|
printf("example: FontTool -i <file.ttf> -o <name without ext>\n\nAdditional arguments:");
|
||||||
|
printf("\t-r <start> <count> : add range of characters");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FN2RangeInfo& firstRange = fontRanges[0];
|
||||||
|
|
||||||
|
firstRange.hdr.start = 32;
|
||||||
|
firstRange.hdr.count = 224;
|
||||||
|
firstRange.chars = new OUT_FN2INFO[firstRange.hdr.count];
|
||||||
|
++fontRangeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* inputFilename = nullptr;
|
||||||
|
const char* outpitFilename = nullptr;
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; ++i)
|
||||||
|
{
|
||||||
|
if (!strcmp(argv[i], "-i") && i + 1 < argc)
|
||||||
|
{
|
||||||
|
inputFilename = argv[i+1];
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[i], "-o") && i + 1 < argc)
|
||||||
|
{
|
||||||
|
outpitFilename = argv[i + 1];
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[i], "-r") && i + 2 < argc)
|
||||||
|
{
|
||||||
|
FN2RangeInfo& newRange = fontRanges[fontRangeCount];
|
||||||
|
|
||||||
|
newRange.hdr.start = atoi(argv[i + 1]);
|
||||||
|
newRange.hdr.count = atoi(argv[i + 2]);
|
||||||
|
newRange.chars = new OUT_FN2INFO[newRange.hdr.count];
|
||||||
|
++fontRangeCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inputFilename)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outpitFilename)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* fp = fopen(inputFilename, "rb");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
printf("Cannot open %s\n", inputFilename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read whole file
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
const long size = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
u_char* data = (u_char*)malloc(size);
|
||||||
|
fread(data, 1, size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
// gen font
|
||||||
|
u_char* tmpBitmap = (u_char*)malloc(HIRES_FONT_SIZE_W * HIRES_FONT_SIZE_H);
|
||||||
|
u_int* bitmapRGBA = (u_int*)malloc(HIRES_FONT_SIZE_W * HIRES_FONT_SIZE_H * 4);
|
||||||
|
|
||||||
|
stbtt_pack_context pc;
|
||||||
|
stbtt_PackBegin(&pc, tmpBitmap, HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, 0, 2, NULL);
|
||||||
|
stbtt_PackSetOversampling(&pc, 1, 1);
|
||||||
|
stbtt_PackSetSkipMissingCodepoints(&pc, 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < fontRangeCount; ++i)
|
||||||
|
{
|
||||||
|
FN2RangeInfo& range = fontRanges[i];
|
||||||
|
stbtt_PackFontRange(&pc, data, 0, 65.0f, range.hdr.start, range.hdr.count, (stbtt_packedchar*)range.chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
stbtt_PackEnd(&pc);
|
||||||
|
|
||||||
|
for (int x = 0; x < HIRES_FONT_SIZE_W; ++x)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < HIRES_FONT_SIZE_H; ++y)
|
||||||
|
{
|
||||||
|
bitmapRGBA[x + y * HIRES_FONT_SIZE_W] = tmpBitmap[x + y * HIRES_FONT_SIZE_W] << 24 | 0xffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char tgaFileName[256];
|
||||||
|
strcpy(tgaFileName, outpitFilename);
|
||||||
|
strcat(tgaFileName, ".tga");
|
||||||
|
|
||||||
|
SaveTGAImage(tgaFileName, (u_char*)bitmapRGBA, HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char fntFileName[256];
|
||||||
|
strcpy(fntFileName, outpitFilename);
|
||||||
|
strcat(fntFileName, ".fn2");
|
||||||
|
|
||||||
|
FILE* fntFp = fopen(fntFileName, "wb");
|
||||||
|
if (fntFp)
|
||||||
|
{
|
||||||
|
OUT_FN2HEADER fn2hdr;
|
||||||
|
fn2hdr.version = FN2_VERSION;
|
||||||
|
fn2hdr.range_count = fontRangeCount;
|
||||||
|
fwrite(&fn2hdr, sizeof(fn2hdr), 1, fntFp);
|
||||||
|
|
||||||
|
for (int i = 0; i < fontRangeCount; ++i)
|
||||||
|
{
|
||||||
|
FN2RangeInfo& range = fontRanges[i];
|
||||||
|
fwrite(&range.hdr, sizeof(OUT_FN2RANGE), 1, fntFp);
|
||||||
|
fwrite(range.chars, sizeof(OUT_FN2INFO), range.hdr.count, fntFp);
|
||||||
|
|
||||||
|
delete[] range.chars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(bitmapRGBA);
|
||||||
|
free(tmpBitmap);
|
||||||
|
free(data);
|
||||||
|
}
|
@ -1,21 +1,19 @@
|
|||||||
#include "Game/driver2.h"
|
#include "driver2.h"
|
||||||
|
|
||||||
#include "Game/C/mission.h"
|
|
||||||
#include "Game/C/convert.h"
|
|
||||||
#include "Game/C/camera.h"
|
|
||||||
#include "Game/C/dr2roads.h"
|
|
||||||
#include "Game/C/system.h"
|
|
||||||
#include "Game/C/pres.h"
|
|
||||||
#include "Game/C/spool.h"
|
|
||||||
#include "Game/C/cars.h"
|
|
||||||
#include "Game/C/draw.h"
|
|
||||||
#include "Game/C/players.h"
|
|
||||||
#include "Game/C/glaunch.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
#include "C/mission.h"
|
||||||
|
#include "C/convert.h"
|
||||||
|
#include "C/camera.h"
|
||||||
|
#include "C/dr2roads.h"
|
||||||
|
#include "C/system.h"
|
||||||
|
#include "C/pres.h"
|
||||||
|
#include "C/spool.h"
|
||||||
|
#include "C/cars.h"
|
||||||
|
#include "C/draw.h"
|
||||||
|
#include "C/players.h"
|
||||||
|
#include "C/glaunch.h"
|
||||||
#include "C/felony.h"
|
#include "C/felony.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
int gDisplayDrawStats = 0;
|
int gDisplayDrawStats = 0;
|
||||||
|
|
||||||
@ -245,7 +243,7 @@ void Debug_Line2D(SXYPAIR& pointA, SXYPAIR& pointB, CVECTOR& color)
|
|||||||
line->g0 = color.g;
|
line->g0 = color.g;
|
||||||
line->b0 = color.b;
|
line->b0 = color.b;
|
||||||
|
|
||||||
#if defined(USE_PGXP) && defined(USE_EXTENDED_PRIM_POINTERS)
|
#if USE_PGXP && USE_EXTENDED_PRIM_POINTERS
|
||||||
line->pgxp_index = 0xFFFF;
|
line->pgxp_index = 0xFFFF;
|
||||||
#endif
|
#endif
|
||||||
|
|
27
src_rebuild/utils/hqfont.h
Normal file
27
src_rebuild/utils/hqfont.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef HQFONT_H
|
||||||
|
#define HQFONT_H
|
||||||
|
|
||||||
|
#define FN2_VERSION 1
|
||||||
|
#define HIRES_FONT_SIZE_W 768
|
||||||
|
#define HIRES_FONT_SIZE_H 768
|
||||||
|
|
||||||
|
struct OUT_FN2INFO
|
||||||
|
{
|
||||||
|
u_short x0, y0, x1, y1;
|
||||||
|
float xoff, yoff, xadvance;
|
||||||
|
float xoff2, yoff2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OUT_FN2RANGE
|
||||||
|
{
|
||||||
|
u_short start;
|
||||||
|
u_short count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OUT_FN2HEADER
|
||||||
|
{
|
||||||
|
u_short version;
|
||||||
|
u_short range_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HQFONT_H
|
@ -179,3 +179,59 @@ bool LoadTGAImage(const char* filename, u_char** data, int& width, int& height,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SaveTGAImage(const char* filename, u_char* data, int width, int height, int bpp)
|
||||||
|
{
|
||||||
|
TGAHeader tgaHeader;
|
||||||
|
|
||||||
|
// Initialize the Targa header
|
||||||
|
tgaHeader.descriptionlen = 0;
|
||||||
|
tgaHeader.cmaptype = 0;
|
||||||
|
tgaHeader.imagetype = 2;
|
||||||
|
tgaHeader.cmapstart = 0;
|
||||||
|
tgaHeader.cmapentries = 0;
|
||||||
|
tgaHeader.cmapbits = 0;
|
||||||
|
tgaHeader.xoffset = 0;
|
||||||
|
tgaHeader.yoffset = 0;
|
||||||
|
tgaHeader.width = width;
|
||||||
|
tgaHeader.height = height;
|
||||||
|
tgaHeader.bpp = bpp;
|
||||||
|
tgaHeader.attrib = 0;
|
||||||
|
|
||||||
|
int imageSize = width * height * (bpp / 8);
|
||||||
|
|
||||||
|
FILE* fp = fopen(filename, "wb");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Write the header
|
||||||
|
fwrite(&tgaHeader, sizeof(TGAHeader), 1, fp);
|
||||||
|
|
||||||
|
// Write the image data
|
||||||
|
u_char* src = data + (bpp / 8) * width * (height - 1);
|
||||||
|
|
||||||
|
switch (bpp)
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
for (int y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
u_char pixel[4];
|
||||||
|
pixel[0] = src[2];
|
||||||
|
pixel[1] = src[1];
|
||||||
|
pixel[2] = src[0];
|
||||||
|
pixel[3] = src[3];
|
||||||
|
|
||||||
|
fwrite(pixel, sizeof(pixel), 1, fp);
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
src -= 8 * width;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -24,5 +24,6 @@ struct TGAHeader
|
|||||||
#pragma pack (pop)
|
#pragma pack (pop)
|
||||||
|
|
||||||
bool LoadTGAImage(const char* filename, u_char** data, int& width, int& height, int& bpp);
|
bool LoadTGAImage(const char* filename, u_char** data, int& width, int& height, int& bpp);
|
||||||
|
bool SaveTGAImage(const char* filename, u_char* data, int width, int height, int bpp);
|
||||||
|
|
||||||
#endif // TARGA_H
|
#endif // TARGA_H
|
@ -180,7 +180,7 @@ void SetupMovieRectangle(int image_w, int image_h)
|
|||||||
u_char r = 1;
|
u_char r = 1;
|
||||||
u_char b = 1;
|
u_char b = 1;
|
||||||
|
|
||||||
#ifdef USE_PGXP
|
#if USE_PGXP
|
||||||
GR_SetViewPort(0, 0, windowWidth, windowHeight);
|
GR_SetViewPort(0, 0, windowWidth, windowHeight);
|
||||||
|
|
||||||
GrVertex blit_vertices[] =
|
GrVertex blit_vertices[] =
|
||||||
|
Loading…
Reference in New Issue
Block a user