Compare commits

...

17 Commits

Author SHA1 Message Date
Xavier Del Campo Romero 3eef29c327 menu: Implement join_menu 2022-09-20 17:34:25 +02:00
Xavier Del Campo Romero 8f9737b776 Implement GUI line edit 2022-09-20 17:34:25 +02:00
Xavier Del Campo Romero e3356fde2d gui: Implement gui_deinit 2022-09-20 17:34:25 +02:00
Xavier Del Campo Romero 84c834c000 Implement net component 2022-09-20 17:34:21 +02:00
Xavier Del Campo Romero f42f5f69c8 Implement FindENET.cmake
This library will be later used for networking over UDP/IPv4 in future
commits.
2022-09-20 17:22:45 +02:00
Xavier Del Campo Romero 4c5630b0d4 Remap calls to pad/mouse/keyboard to input 2022-09-20 16:56:30 +02:00
Xavier Del Campo Romero 684587a3c3 Implement input component
It is required to redirect keyboard input (both physical or not) when
a GUI line edit is focused. This means other components cannot be
activated on key presses.

Therefore, this new component is meant as a higher-level abstraction
compared to the `keyboard`/`pad`/`mouse` components, which:

- Implements the same APIs provided by `keyboard`, `mouse` and `pad`.
- Returns the same results as the APIs above if no GUI element is
focused, no input otherwise.

Note: replacing calls to `keyboard`/`pad`/`mouse` with `input` will be
implemented in a future commit.
2022-09-20 13:52:14 +02:00
Xavier Del Campo Romero b8d3eff412 keyboard: Add new public functions
These will be used by future commits.
2022-09-20 13:52:14 +02:00
Xavier Del Campo Romero 39dc70c385 orig/LICENSE: Minor changes 2022-09-20 13:52:12 +02:00
Xavier Del Campo Romero ade4a509e9 Minor code style fixes 2022-09-20 13:51:08 +02:00
Xavier Del Campo Romero a3f167ee04 sdl-1.2: Remap missing keyboard keys 2022-09-20 12:30:06 +02:00
Xavier Del Campo Romero 481a312e76 keyboard_key.h: add more keys 2022-09-20 12:29:45 +02:00
Xavier Del Campo Romero b8def012d5 sdl-1.2: Remap SDLK_ESCAPE to KEYBOARD_KEY_ESC 2022-09-16 20:35:04 +02:00
Xavier Del Campo Romero 76a49ba3d5 mouse.c: Reduce threshold 2022-09-16 20:33:39 +02:00
Xavier Del Campo Romero da22c8d922 Split CMakeLists.txt for src 2022-09-16 20:29:47 +02:00
Xavier Del Campo Romero 7bc21417c5 Split res-related CMake functions into their own file 2022-09-16 14:28:53 +02:00
Xavier Del Campo Romero a30aee8b90 CMakeLists.txt: bump minimum CMake version 2022-09-16 14:27:18 +02:00
63 changed files with 2053 additions and 265 deletions

View File

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.13)
# SDL::SDL was defined on 3.20.
cmake_minimum_required(VERSION 3.20)
set(TOOLS_PREFIX ${CMAKE_BINARY_DIR}/tools)
include(ExternalProject)
@ -34,10 +35,12 @@ if(SDL1_2_BUILD)
target_link_libraries(SDL::SDL_mixer INTERFACE SDL::SDL)
endif()
if(NOT PS1_BUILD)
find_package(ENET 1.3 REQUIRED)
endif()
set(cdroot ${CMAKE_BINARY_DIR}/cdimg)
file(MAKE_DIRECTORY ${cdroot})
# Avoid C11 since it is not supported by the i386-mingw32 toolchain.
set(cflags -Wall -g3 -ffunction-sections -fdata-sections -pedantic -std=c99)
if(PS1_BUILD)
include("cmake/ps1.cmake")
@ -48,48 +51,4 @@ elseif(HOST_BUILD)
endif()
add_subdirectory("res")
set(components
building
camera
container
font
game
gfx
gui
header
instance
keyboard
menu
mouse
pad
peripheral
player
resource
sfx
system
terrain
unit
util
)
set(interfaces
tech
)
target_compile_options(${PROJECT_NAME} PUBLIC ${cflags})
# Dependencies for main.c
target_link_libraries(${PROJECT_NAME} PRIVATE system menu)
foreach(c ${components})
add_subdirectory("src/${c}")
target_compile_options(${c} PUBLIC ${cflags})
endforeach()
foreach(i ${interfaces})
add_subdirectory("src/${i}")
target_compile_options(${i} INTERFACE ${cflags})
target_link_libraries(${PROJECT_NAME} PRIVATE ${c})
endforeach()
target_link_options(${PROJECT_NAME} PRIVATE -Wl,--gc-sections)
add_subdirectory("src")

View File

@ -91,6 +91,7 @@ cd build
SDLDIR=<sdl-prefix> \
SDLMIXERDIR=<sdl_mixer-prefix> \
SDLGFXDIR=<sdl_gfx-prefix> \
ENETDIR=<enet-prefix> \
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/win9x-toolchain.cmake
make -j$(nproc --all)
```
@ -106,6 +107,9 @@ building `SDL_mixer`.
- `SDLGFXDIR` is the path to the cross-compiled version for `SDL_gfx`,
which would correspond to `./configure --prefix=$SDLGFXDIR` used in
building `SDL_gfx`.
- `ENETDIR` is the path to the cross-compiled version for `enet`,
which would correspond to `./configure --prefix=$ENETDIR` used in
building `enet`.
A stripped version of the executable, as well as game assets, will be
located in `build/cdimg`.

88
cmake/FindENET.cmake Executable file
View File

@ -0,0 +1,88 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindENET
-----------
Locate ENET library
This module defines:
::
ENET, the name of the target to use with target_*() commands
ENET_LIBRARIES, the name of the library to link against
ENET_INCLUDE_DIRS, where to find the headers
ENET_FOUND, if false, do not try to link against
ENET_VERSION_STRING - human-readable string containing the
version of ENET
$ENETDIR is an environment variable that would correspond to the
./configure --prefix=$ENETDIR used in building ENET.
#]=======================================================================]
find_path(ENET_INCLUDE_DIRS
NAMES
enet/callbacks.h
enet/enet.h
enet/list.h
enet/protocol.h
enet/time.h
enet/types.h
enet/unix.h
enet/utility.h
enet/win32.h
HINTS
ENV ENETDIR
PATH_SUFFIXES
enet
# path suffixes to search inside ENV{ENETDIR}
include
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(VC_LIB_PATH_SUFFIX lib/x64)
else()
set(VC_LIB_PATH_SUFFIX lib/x86)
endif()
find_library(ENET_LIBRARIES
NAMES enet
HINTS
ENV ENETDIR
PATH_SUFFIXES
lib
${VC_LIB_PATH_SUFFIX}
)
if(ENET_INCLUDE_DIRS AND EXISTS "${ENET_INCLUDE_DIRS}/enet.h")
file(STRINGS "${ENET_INCLUDE_DIRS}/enet.h" ENET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+ENET_VERSION_MAJOR[ \t]+[0-9]+$")
file(STRINGS "${ENET_INCLUDE_DIRS}/enet.h" ENET_VERSION_MINOR_LINE REGEX "^#define[ \t]+ENET_VERSION_MINOR[ \t]+[0-9]+$")
file(STRINGS "${ENET_INCLUDE_DIRS}/enet.h" ENET_VERSION_PATCH_LINE REGEX "^#define[ \t]+ENET_VERSION_PATCH[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+ENET_VERSION_MAJOR[ \t]+([0-9]+)$" "\\1" ENET_VERSION_MAJOR "${ENET_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+ENET_VERSION_MINOR[ \t]+([0-9]+)$" "\\1" ENET_VERSION_MINOR "${ENET_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+ENET_VERSION_PATCH[ \t]+([0-9]+)$" "\\1" ENET_VERSION_PATCH "${ENET_VERSION_PATCH_LINE}")
set(ENET_VERSION_STRING ${ENET_VERSION_MAJOR}.${ENET_VERSION_MINOR}.${ENET_VERSION_PATCH})
unset(ENET_VERSION_MAJOR_LINE)
unset(ENET_VERSION_MINOR_LINE)
unset(ENET_VERSION_PATCH_LINE)
unset(ENET_VERSION_MAJOR)
unset(ENET_VERSION_MINOR)
unset(ENET_VERSION_PATCH)
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ENET
REQUIRED_VARS ENET_LIBRARIES ENET_INCLUDE_DIRS
VERSION_VAR ENET_VERSION_STRING)
if(ENET_FOUND)
if(NOT TARGET ENET)
add_library(ENET INTERFACE IMPORTED)
set_target_properties(ENET PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ENET_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${ENET_LIBRARIES}")
endif()
endif()

View File

@ -6,6 +6,7 @@ add_custom_command(OUTPUT ${cdroot}/${PROJECT_NAME}
add_custom_target(stripped-exe ALL DEPENDS ${cdroot}/${PROJECT_NAME})
target_link_libraries(SDL::SDL INTERFACE gdi32 user32 winmm dxguid)
target_link_libraries(ENET INTERFACE ws2_32)
add_compile_options(-march=i386)

View File

@ -132,3 +132,11 @@ WAVE files, support for other audio formats is not required.
CFLAGS='-ffunction-sections -fdata-sections' \
CC=i386-mingw32-gcc
```
## ENET
```sh
../enet-1.3.17/configure --prefix=$HOME/enet-1.3.17-win32 \
--host=i386-mingw32 CFLAGS='-ffunction-sections -fdata-sections' \
CC=i386-mingw32-gcc
```

View File

@ -1,112 +1,4 @@
function(sprite)
set(options "")
set(multiValueArgs "")
set(oneValueArgs NAME X Y TRANSPARENT BPP CX CY)
cmake_parse_arguments(SPRITE "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(PS1_BUILD)
if(${SPRITE_TRANSPARENT})
set(trans -mpink)
endif()
if(NOT "${SPRITE_BPP}" STREQUAL "16")
set(clut "-clut=${SPRITE_CX},${SPRITE_CY}")
endif()
add_custom_target(${SPRITE_NAME}_img ALL
bmp2tim ${SPRITE_NAME}.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
${SPRITE_BPP} -org=${SPRITE_X},${SPRITE_Y} ${clut} ${trans}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SPRITE_NAME}.bmp
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
add_dependencies(iso ${SPRITE_NAME}_img)
elseif(SDL1_2_BUILD)
if(${SPRITE_TRANSPARENT})
set(trans "transparent=1")
else()
set(trans "transparent=0")
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
COMMAND ${TOOLS_PREFIX}/bin/add-header ${trans} ${SPRITE_NAME}_24.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SPRITE_NAME}_24.bmp
VERBATIM)
add_custom_target(${SPRITE_NAME}_img
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
add_dependencies(${SPRITE_NAME}_img tools)
endif()
endfunction()
function(sound)
set(options "")
set(multiValueArgs "")
set(oneValueArgs NAME LOOP)
cmake_parse_arguments(SOUND "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(PS1_BUILD)
if(${SOUND_LOOP})
set(loop -L)
endif()
add_custom_target(${SOUND_NAME}_snd ALL
wav2vag ${SOUND_NAME}.wav
${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME} ${loop}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SOUND_NAME}.wav
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(iso ${SOUND_NAME}_snd)
elseif(SDL1_2_BUILD)
if(${SOUND_LOOP})
set(loop "loop=1")
else()
set(loop "loop=0")
endif()
# Reference: https://gist.github.com/socantre/7ee63133a0a3a08f3990
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
COMMAND ${TOOLS_PREFIX}/bin/add-header ${loop} ${SOUND_NAME}.wav ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SOUND_NAME}.wav
VERBATIM)
add_custom_target(${SOUND_NAME}_snd
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(${SOUND_NAME}_snd tools)
endif()
endfunction()
function(container)
set(options "")
set(multiValueArgs SPRITES SOUNDS)
set(oneValueArgs NAME)
cmake_parse_arguments(CONTAINER "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
add_custom_command(OUTPUT ${cdroot}/${CONTAINER_NAME}.cnt
COMMAND ${TOOLS_PREFIX}/bin/container ${CONTAINER_SPRITES} ${CONTAINER_SOUNDS}
${cdroot}/${CONTAINER_NAME}.cnt
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM)
add_custom_target(${CONTAINER_NAME}_container
DEPENDS ${cdroot}/${CONTAINER_NAME}.cnt)
add_dependencies(${PROJECT_NAME} ${CONTAINER_NAME}_container)
add_dependencies(${CONTAINER_NAME}_container tools)
foreach(sprite ${CONTAINER_SPRITES})
add_dependencies(${CONTAINER_NAME}_container ${sprite}_img)
endforeach()
foreach(sound ${CONTAINER_SOUNDS})
add_dependencies(${CONTAINER_NAME}_container ${sound}_snd)
endforeach()
if(PS1_BUILD)
add_dependencies(iso ${CONTAINER_NAME}_container)
endif()
endfunction()
include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake)
sprite(NAME worker_n
X 384
@ -292,6 +184,30 @@ sprite(NAME btn_mid
CY 493
TRANSPARENT FALSE)
sprite(NAME line_edit_left
X 368
Y 148
BPP 4
CX 368
CY 492
TRANSPARENT FALSE)
sprite(NAME line_edit_mid
X 370
Y 148
BPP 4
CX 368
CY 491
TRANSPARENT FALSE)
sprite(NAME line_edit_right
X 378
Y 148
BPP 4
CX 368
CY 491
TRANSPARENT FALSE)
sound(NAME acknowledge_01)
sound(NAME acknowledge_02)
sound(NAME selected_01)
@ -321,6 +237,9 @@ container(NAME rts
sel_down_right
sel_mid
sel_mid_v
line_edit_left
line_edit_mid
line_edit_right
SOUNDS
acknowledge_01
acknowledge_02

View File

@ -51,6 +51,12 @@ btn_mid.bmp:
btn_mid_24.bmp:
btn_right.bmp:
btn_right_24.bmp:
line_edit_left.bmp:
line_edit_left_24.bmp:
line_edit_mid.bmp:
line_edit_mid_24.bmp:
line_edit_right.bmp:
line_edit_right_24.bmp:
Derived works from ui_sheet.png
font.bmp:

109
res/functions.cmake Normal file
View File

@ -0,0 +1,109 @@
function(sprite)
set(options "")
set(multiValueArgs "")
set(oneValueArgs NAME X Y TRANSPARENT BPP CX CY)
cmake_parse_arguments(SPRITE "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(PS1_BUILD)
if(${SPRITE_TRANSPARENT})
set(trans -mpink)
endif()
if(NOT "${SPRITE_BPP}" STREQUAL "16")
set(clut "-clut=${SPRITE_CX},${SPRITE_CY}")
endif()
add_custom_target(${SPRITE_NAME}_img ALL
bmp2tim ${SPRITE_NAME}.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
${SPRITE_BPP} -org=${SPRITE_X},${SPRITE_Y} ${clut} ${trans}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SPRITE_NAME}.bmp
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
add_dependencies(iso ${SPRITE_NAME}_img)
elseif(SDL1_2_BUILD)
if(${SPRITE_TRANSPARENT})
set(trans "transparent=1")
else()
set(trans "transparent=0")
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
COMMAND ${TOOLS_PREFIX}/bin/add-header ${trans} ${SPRITE_NAME}_24.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SPRITE_NAME}_24.bmp
VERBATIM)
add_custom_target(${SPRITE_NAME}_img
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
add_dependencies(${SPRITE_NAME}_img tools)
endif()
endfunction()
function(sound)
set(options "")
set(multiValueArgs "")
set(oneValueArgs NAME LOOP)
cmake_parse_arguments(SOUND "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(PS1_BUILD)
if(${SOUND_LOOP})
set(loop -L)
endif()
add_custom_target(${SOUND_NAME}_snd ALL
wav2vag ${SOUND_NAME}.wav
${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME} ${loop}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SOUND_NAME}.wav
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(iso ${SOUND_NAME}_snd)
elseif(SDL1_2_BUILD)
if(${SOUND_LOOP})
set(loop "loop=1")
else()
set(loop "loop=0")
endif()
# Reference: https://gist.github.com/socantre/7ee63133a0a3a08f3990
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
COMMAND ${TOOLS_PREFIX}/bin/add-header ${loop} ${SOUND_NAME}.wav ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${SOUND_NAME}.wav
VERBATIM)
add_custom_target(${SOUND_NAME}_snd
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
add_dependencies(${SOUND_NAME}_snd tools)
endif()
endfunction()
function(container)
set(options "")
set(multiValueArgs SPRITES SOUNDS)
set(oneValueArgs NAME)
cmake_parse_arguments(CONTAINER "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
add_custom_command(OUTPUT ${cdroot}/${CONTAINER_NAME}.cnt
COMMAND ${TOOLS_PREFIX}/bin/container ${CONTAINER_SPRITES} ${CONTAINER_SOUNDS}
${cdroot}/${CONTAINER_NAME}.cnt
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM)
add_custom_target(${CONTAINER_NAME}_container
DEPENDS ${cdroot}/${CONTAINER_NAME}.cnt)
add_dependencies(${PROJECT_NAME} ${CONTAINER_NAME}_container)
add_dependencies(${CONTAINER_NAME}_container tools)
foreach(sprite ${CONTAINER_SPRITES})
add_dependencies(${CONTAINER_NAME}_container ${sprite}_img)
endforeach()
foreach(sound ${CONTAINER_SOUNDS})
add_dependencies(${CONTAINER_NAME}_container ${sound}_snd)
endforeach()
if(PS1_BUILD)
add_dependencies(iso ${CONTAINER_NAME}_container)
endif()
endfunction()

BIN
res/line_edit_left.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

BIN
res/line_edit_left_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

BIN
res/line_edit_mid.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

BIN
res/line_edit_mid_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
res/line_edit_right.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

BIN
res/line_edit_right_24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

View File

@ -32,7 +32,7 @@ saxon_swordsman.png:
Author: b_o
barracks.zip:
https://opengameart.org/content/6-isometric-buildings:
https://opengameart.org/content/6-isometric-buildings
License(s): CC-BY-SA 3.0
Author: Scribe

49
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,49 @@
# Avoid C11 since it is not supported by the i386-mingw32 toolchain.
set(cflags -Wall -g3 -ffunction-sections -fdata-sections -pedantic -std=c99)
set(components
building
camera
container
font
game
gfx
gui
header
input
instance
keyboard
menu
mouse
net
pad
peripheral
player
resource
sfx
system
terrain
unit
util
)
set(interfaces
tech
)
target_compile_options(${PROJECT_NAME} PUBLIC ${cflags})
# Dependencies for main.c
target_link_libraries(${PROJECT_NAME} PRIVATE system menu)
foreach(c ${components})
add_subdirectory("${c}")
target_compile_options(${c} PUBLIC ${cflags})
endforeach()
foreach(i ${interfaces})
add_subdirectory("${i}")
target_compile_options(${i} INTERFACE ${cflags})
target_link_libraries(${PROJECT_NAME} PRIVATE ${c})
endforeach()
target_link_options(${PROJECT_NAME} PRIVATE -Wl,--gc-sections)

View File

@ -1,3 +1,12 @@
add_library(camera "src/camera.c" "src/pad.c" "src/mouse.c" "src/touch.c")
target_include_directories(camera PUBLIC "inc" PRIVATE "privinc")
target_link_libraries(camera PUBLIC container mouse pad peripheral util PRIVATE gfx)
target_link_libraries(camera
PUBLIC
container
input
peripheral
util
PRIVATE
gfx
mouse
pad)

View File

@ -1,8 +1,7 @@
#ifndef CAMERA_H
#define CAMERA_H
#include <mouse.h>
#include <pad.h>
#include <input.h>
#include <peripheral.h>
#include <util.h>
#include <stdbool.h>
@ -50,7 +49,7 @@ struct camera
extern struct sprite cursor_sprite;
void camera_update(struct camera *cam, const union peripheral *p);
void camera_update(struct camera *cam, const union peripheral *p, const struct input *in);
bool camera_translate(const struct camera *cam, const struct util_rect *dim, short *x, short *y);
void cursor_init(struct cursor *c);
bool cursor_collision(const struct camera *cam, const struct util_rect *d);

View File

@ -2,6 +2,9 @@
#define CAMERA_PRIVATE_H
#include <camera.h>
#include <input.h>
#include <mouse.h>
#include <pad.h>
#ifdef __cplusplus
extern "C"
@ -15,9 +18,11 @@ enum
};
void camera_update_pos(struct camera *cam);
void camera_update_pad(struct camera *cam, const struct pad *p);
void camera_update_pad(struct camera *cam, const struct pad *p,
const struct input *in);
void camera_update_mouse(struct camera *cam, const struct mouse *m);
void camera_update_touch(struct camera *cam, const struct mouse *m);
void camera_update_touch(struct camera *cam, const struct mouse *m,
const struct input *in);
#ifdef __cplusplus
}

View File

@ -124,12 +124,13 @@ void cursor_set_pos_list(struct cursor *const c,
};
}
void camera_update(struct camera *const cam, const union peripheral *const p)
void camera_update(struct camera *const cam,
const union peripheral *const p, const struct input *const in)
{
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
camera_update_pad(cam, &p->pad.pad);
camera_update_pad(cam, &p->pad.pad, in);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
@ -137,7 +138,7 @@ void camera_update(struct camera *const cam, const union peripheral *const p)
break;
case PERIPHERAL_TYPE_TOUCH:
camera_update_touch(cam, &p->kbm.mouse);
camera_update_touch(cam, &p->kbm.mouse, in);
break;
}
}

View File

@ -21,8 +21,8 @@ static void update_speed(struct camera *const cam, const struct mouse *const m)
{
MAX_SPEED = 10,
STEP = 1,
THRESHOLD_X = CAMERA_CURSOR_WIDTH * 3,
THRESHOLD_Y = CAMERA_CURSOR_HEIGHT * 3
THRESHOLD_X = CAMERA_CURSOR_WIDTH / 2,
THRESHOLD_Y = CAMERA_CURSOR_HEIGHT / 2
};
const struct cursor *const c = &cam->cursor;

View File

@ -1,5 +1,6 @@
#include <camera.h>
#include <camera_private.h>
#include <input.h>
#include <pad.h>
#include <peripheral.h>
#include <gfx.h>
@ -7,7 +8,8 @@
#include <stdbool.h>
#include <stdlib.h>
static void cursor_update(struct camera *const cam, const struct pad *const p)
static void cursor_update(struct camera *const cam,
const struct pad *const p, const struct input *const in)
{
struct cursor *const c = &cam->cursor;
enum {STEP = 4};
@ -16,29 +18,31 @@ static void cursor_update(struct camera *const cam, const struct pad *const p)
|| c->screen.last_h != screen_h)
cursor_init(c);
if (pad_pressed(p, PAD_KEY_LEFT)
if (input_pad_pressed(in, p, PAD_KEY_LEFT)
&& (c->x - STEP)
&& (!cam->x || c->x != c->x_init))
c->x -= STEP;
else if (pad_pressed(p, PAD_KEY_RIGHT)
else if (input_pad_pressed(in, p, PAD_KEY_RIGHT)
&& (c->x + STEP < screen_w)
&& (c->x != c->x_init || cam->x <= -cam->dim.w))
c->x += STEP;
if (pad_pressed(p, PAD_KEY_UP)
if (input_pad_pressed(in, p, PAD_KEY_UP)
&& (c->y - STEP)
&& (c->y != c->y_init || !cam->y))
c->y -= STEP;
else if (pad_pressed(p, PAD_KEY_DOWN)
else if (input_pad_pressed(in, p, PAD_KEY_DOWN)
&& (c->y + STEP < screen_h)
&& (c->y != c->y_init || cam->y <= -cam->dim.h))
c->y += STEP;
c->state = pad_pressed(p, PAD_KEY_A) || pad_pressed(p, PAD_KEY_B) ?
c->state = input_pad_pressed(in, p, PAD_KEY_A) ||
input_pad_pressed(in, p, PAD_KEY_B) ?
CURSOR_STATE_PRESSED: CURSOR_STATE_IDLE;
}
static void update_speed(struct camera *const cam, const struct pad *const p)
static void update_speed(struct camera *const cam,
const struct pad *const p, const struct input *const in)
{
enum
{
@ -52,14 +56,14 @@ static void update_speed(struct camera *const cam, const struct pad *const p)
if (c->x == c->x_init
&& (!cam->x_speed || ++cam->xt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_RIGHT))
if (input_pad_pressed(in, p, PAD_KEY_RIGHT))
{
if (cam->x_speed > 0)
cam->x_speed = -STEP;
else if (cam->x_speed - STEP >= -MAX_SPEED)
cam->x_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_LEFT))
else if (input_pad_pressed(in, p, PAD_KEY_LEFT))
{
if (cam->x_speed < 0)
cam->x_speed = STEP;
@ -77,14 +81,14 @@ static void update_speed(struct camera *const cam, const struct pad *const p)
if (c->y == c->y_init
&& (!cam->y_speed || ++cam->yt >= T_STEP))
{
if (pad_pressed(p, PAD_KEY_DOWN))
if (input_pad_pressed(in, p, PAD_KEY_DOWN))
{
if (cam->y_speed > 0)
cam->y_speed = STEP;
else if (cam->y_speed - STEP >= -MAX_SPEED)
cam->y_speed -= STEP;
}
else if (pad_pressed(p, PAD_KEY_UP))
else if (input_pad_pressed(in, p, PAD_KEY_UP))
{
if (cam->y_speed < 0)
cam->y_speed = -STEP;
@ -119,7 +123,7 @@ static enum pad_key get_ref_key(struct cursor_pos_rt *const rt,
}
static void cursor_update_fixed(struct camera *const cam,
const struct pad *const p)
const struct pad *const p, const struct input *const in)
{
struct cursor *const c = &cam->cursor;
struct cursor_pos_rt *const rt = &c->rt;
@ -129,7 +133,7 @@ static void cursor_update_fixed(struct camera *const cam,
{
const enum pad_key key = get_ref_key(rt, next);
if (pad_justpressed(p, key))
if (input_pad_justpressed(in, p, key))
rt->i = next;
}
else if (rt->i)
@ -137,7 +141,7 @@ static void cursor_update_fixed(struct camera *const cam,
const size_t prev = rt->i - 1;
const enum pad_key key = get_ref_key(rt, prev);
if (pad_justpressed(p, key))
if (input_pad_justpressed(in, p, key))
rt->i = prev;
}
@ -147,14 +151,15 @@ static void cursor_update_fixed(struct camera *const cam,
c->y = cur->y;
}
void camera_update_pad(struct camera *const cam, const struct pad *const p)
void camera_update_pad(struct camera *const cam, const struct pad *const p,
const struct input *const in)
{
if (cam->cursor.rt.list)
cursor_update_fixed(cam, p);
cursor_update_fixed(cam, p, in);
else
{
cursor_update(cam, p);
update_speed(cam, p);
cursor_update(cam, p, in);
update_speed(cam, p, in);
camera_update_pos(cam);
}
}

View File

@ -13,11 +13,12 @@ static void cursor_update(struct cursor *const c, const struct mouse *const m)
c->y = m->y;
}
static void update_speed(struct camera *const cam, const struct mouse *const m)
static void update_speed(struct camera *const cam, const struct mouse *const m,
const struct input *const in)
{
int *const sx = &cam->x_speed, *const sy = &cam->y_speed;
if (mouse_pressed(m, MOUSE_BUTTON_LEFT))
if (input_mouse_pressed(in, m, MOUSE_BUTTON_LEFT))
{
*sx = m->dx;
*sy = m->dy;
@ -42,9 +43,10 @@ static void update_speed(struct camera *const cam, const struct mouse *const m)
}
}
void camera_update_touch(struct camera *const cam, const struct mouse *const m)
void camera_update_touch(struct camera *const cam, const struct mouse *const m,
const struct input *const in)
{
cursor_update(&cam->cursor, m);
update_speed(cam, m);
update_speed(cam, m, in);
camera_update_pos(cam);
}

View File

@ -5,6 +5,7 @@
#include <gfx.h>
#include <gui/bar.h>
#include <gui/button.h>
#include <gui/line_edit.h>
#include <gui/rounded_rect.h>
#include <resource.h>
#include <terrain.h>
@ -246,6 +247,33 @@ static const struct container c[] =
.sprite = &gui_button_sprites[GUI_BUTTON_RIGHT]
}
},
{
.path = "line_edit_left",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_LEFT]
}
},
{
.path = "line_edit_mid",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_MID]
}
},
{
.path = "line_edit_right",
.type = CONTAINER_TYPE_SPRITE,
.data =
{
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_RIGHT]
}
}
};
static bool init;

View File

@ -5,8 +5,9 @@ add_library(gui
"src/container.c"
"src/gui.c"
"src/label.c"
"src/line_edit.c"
"src/progress_bar.c"
"src/rounded_rect.c"
)
target_include_directories(gui PUBLIC "inc" PRIVATE "privinc")
target_link_libraries(gui PUBLIC camera gfx peripheral font)
target_link_libraries(gui PUBLIC camera gfx input net peripheral font)

View File

@ -3,6 +3,7 @@
#include <camera.h>
#include <gfx.h>
#include <input.h>
#include <peripheral.h>
#ifdef __cplusplus
@ -16,9 +17,10 @@ struct gui_common
{
void (*add_child)(struct gui_common *parent, struct gui_common *child);
int (*update)(struct gui_common *, const union peripheral *,
const struct camera *);
const struct camera *, struct input *);
int (*render)(const struct gui_common *);
void (*get_dim)(const struct gui_common *, short *w, short *h);
void (*deinit)(struct gui_common *, struct input *);
} *cb;
short x, y, xoff, yoff;
@ -29,8 +31,9 @@ struct gui_common
void gui_add_child(struct gui_common *parent, struct gui_common *child);
void gui_add_sibling(struct gui_common *g, struct gui_common *sibling);
int gui_update(struct gui_common *g, const union peripheral *p,
const struct camera *c);
const struct camera *c, struct input *in);
int gui_render(const struct gui_common *g);
void gui_deinit(struct gui_common *g, struct input *in);
#ifdef __cplusplus
}

View File

@ -0,0 +1,47 @@
#ifndef GUI_LINE_EDIT_H
#define GUI_LINE_EDIT_H
#include <gui.h>
#include <gui/label.h>
#include <gfx.h>
#include <util.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
struct gui_line_edit
{
struct gui_common common;
struct gui_label label;
short w;
bool focus, blink;
unsigned blt;
char *text;
size_t i, sz;
};
void gui_line_edit_init(struct gui_line_edit *l, char *buf, size_t sz);
UTIL_STATIC_ASSERT(!offsetof(struct gui_line_edit, common),
"unexpected offset for struct gui_line_edit");
enum
{
GUI_LINE_EDIT_LEFT,
GUI_LINE_EDIT_MID,
GUI_LINE_EDIT_RIGHT,
MAX_GUI_LINE_EDIT_SPRITES
};
extern struct sprite gui_line_edit_sprites[MAX_GUI_LINE_EDIT_SPRITES];
#ifdef __cplusplus
}
#endif
#endif /* GUI_LINE_EDIT_H */

View File

@ -2,6 +2,9 @@
#define GUI_PRIVATE_H
#include <gui.h>
#include <input.h>
#include <peripheral.h>
#include <camera.h>
#ifdef __cplusplus
extern "C"
@ -9,6 +12,10 @@ extern "C"
#endif
void gui_coords(const struct gui_common *g, short *x, short *y);
bool gui_pressed(const struct gui_common *g, const struct input *in,
const union peripheral *p, const struct camera *cam, short w, short h);
bool gui_released(const struct gui_common *g, const union peripheral *p,
const struct camera *cam, short w, short h);
#ifdef __cplusplus
}

View File

@ -4,6 +4,7 @@
#include <gui_private.h>
#include <camera.h>
#include <gfx.h>
#include <input.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
@ -37,47 +38,22 @@ static void get_dim(const struct gui_common *const g,
static bool pressed(const struct gui_button *const b,
const union peripheral *const p,
const struct camera *const cam)
const struct camera *const cam,
const struct input *const in)
{
bool check = false;
short w, h;
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
check = pad_justpressed(&p->pad.pad, PAD_KEY_A);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
check = mouse_justreleased(&p->kbm.mouse, MOUSE_BUTTON_LEFT);
break;
case PERIPHERAL_TYPE_TOUCH:
check = mouse_justpressed(&p->kbm.mouse, MOUSE_BUTTON_LEFT);
break;
}
if (check)
{
short x, y;
struct util_rect d;
gui_coords(&b->common, &x, &y);
get_dim(&b->common, &d.w, &d.h);
d.x = x;
d.y = y;
return cursor_collision(cam, &d);
}
return false;
get_dim(&b->common, &w, &h);
return gui_pressed(&b->common, in, p, cam, w, h);
}
static int update(struct gui_common *const g,
const union peripheral *const p, const struct camera *const c)
const union peripheral *const p, const struct camera *const c,
struct input *const in)
{
struct gui_button *const b = (struct gui_button *)g;
if (pressed(b, p, c) && b->on_pressed)
if (pressed(b, p, c, in) && b->on_pressed)
b->on_pressed(b->arg);
return 0;

View File

@ -1,6 +1,7 @@
#include <gui/container.h>
#include <gui.h>
#include <camera.h>
#include <input.h>
#include <peripheral.h>
static void add_child(struct gui_common *const parent,
@ -52,7 +53,8 @@ static void get_dim(const struct gui_common *const g,
}
static int update(struct gui_common *const g,
const union peripheral *const p, const struct camera *const cam)
const union peripheral *const p, const struct camera *const cam,
struct input *const in)
{
struct gui_container *const c = (struct gui_container *)g;

View File

@ -1,4 +1,7 @@
#include <gui.h>
#include <camera.h>
#include <input.h>
#include <peripheral.h>
static void get_centered(const struct gui_common *const g,
short *const x, short *const y)
@ -51,6 +54,79 @@ void gui_coords(const struct gui_common *const g, short *const x,
get_centered(g, x, y);
}
static bool check_collision(const struct gui_common *const g,
const union peripheral *const p,
const struct camera *cam, const short w, const short h)
{
short x, y;
gui_coords(g, &x, &y);
const struct util_rect d =
{
.x = x,
.y = y,
.w = w,
.h = h
};
return cursor_collision(cam, &d);
}
bool gui_pressed(const struct gui_common *const g,
const struct input *const in,
const union peripheral *const p,
const struct camera *cam, const short w, const short h)
{
bool check = false;
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
check = input_pad_justpressed(in, &p->pad.pad, PAD_KEY_A);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
/* Fall through. */
case PERIPHERAL_TYPE_TOUCH:
check = input_mouse_justreleased(in, &p->kbm.mouse,
MOUSE_BUTTON_LEFT);
break;
}
if (check)
return check_collision(g, p, cam, w, h);
return false;
}
bool gui_released(const struct gui_common *const g,
const union peripheral *const p,
const struct camera *cam, const short w, const short h)
{
bool check = false;
switch (p->common.type)
{
case PERIPHERAL_TYPE_PAD:
check = pad_justpressed(&p->pad.pad, PAD_KEY_A);
break;
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
/* Fall through. */
case PERIPHERAL_TYPE_TOUCH:
check = mouse_justreleased(&p->kbm.mouse,
MOUSE_BUTTON_LEFT);
break;
}
if (check)
return !check_collision(g, p, cam, w, h);
return false;
}
void gui_add_sibling(struct gui_common *const g,
struct gui_common *const s)
{
@ -77,16 +153,16 @@ void gui_add_child(struct gui_common *const p,
}
int gui_update(struct gui_common *const g, const union peripheral *const p,
const struct camera *const c)
const struct camera *const c, struct input *const in)
{
if (g->child && gui_update(g->child, p, c))
if (g->child && gui_update(g->child, p, c, in))
return -1;
if (g->cb && g->cb->update && g->cb->update(g, p, c))
if (g->cb && g->cb->update && g->cb->update(g, p, c, in))
return -1;
for (struct gui_common *s = g->sibling; s; s = s->sibling)
if (gui_update(s, p, c))
if (gui_update(s, p, c, in))
return -1;
return 0;
@ -106,3 +182,15 @@ int gui_render(const struct gui_common *const g)
return 0;
}
void gui_deinit(struct gui_common *const g, struct input *const in)
{
if (g->cb && g->cb->deinit)
g->cb->deinit(g, in);
if (g->child)
gui_deinit(g->child, in);
for (struct gui_common *s = g->sibling; s; s = s->sibling)
gui_deinit(s, in);
}

195
src/gui/src/line_edit.c Normal file
View File

@ -0,0 +1,195 @@
#include <gui.h>
#include <gui_private.h>
#include <gui/label.h>
#include <gui/line_edit.h>
#include <camera.h>
#include <gfx.h>
#include <input.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
#include <string.h>
struct sprite gui_line_edit_sprites[MAX_GUI_LINE_EDIT_SPRITES];
/* Alias for readability. */
static const struct sprite *const refs = gui_line_edit_sprites;
static int render_left(const struct gui_line_edit *const l,
short *const x, const short y)
{
sprite_get_or_ret(s, -1);
if (sprite_clone(&refs[GUI_LINE_EDIT_LEFT], s))
return -1;
s->x = *x;
s->y = y;
sprite_sort(s);
*x = s->x + s->w;
return 0;
}
static int render_mid(const struct gui_line_edit *const l,
short *const x, const short y)
{
const short mid_w = refs[GUI_LINE_EDIT_MID].w,
lw = refs[GUI_LINE_EDIT_LEFT].w,
rw = refs[GUI_LINE_EDIT_RIGHT].w,
w = l->w - lw - rw;
if (w > 0)
{
const short rem_mid = w > 0 ? w % mid_w : 0,
whole_mid = w / mid_w,
n_mid = rem_mid ? whole_mid + 1 : whole_mid;
for (struct
{
size_t i;
short x;
} a = {.x = lw};
a.i < n_mid;
a.i++, a.x += mid_w)
{
sprite_get_or_ret(m, -1);
if (sprite_clone(&refs[GUI_LINE_EDIT_MID], m))
return -1;
m->x = *x;
m->y = y;
if (rem_mid && a.i + 1 == n_mid)
m->w = rem_mid;
else
m->w = mid_w;
sprite_sort(m);
*x += m->w;
}
}
else
return -1;
return 0;
}
static int render_right(const short x, const short y)
{
sprite_get_or_ret(s, -1);
if (sprite_clone(&refs[GUI_LINE_EDIT_RIGHT], s))
return -1;
s->x = x;
s->y = y;
sprite_sort(s);
return 0;
}
static int render(const struct gui_common *const g)
{
const struct gui_line_edit *const l = (const struct gui_line_edit *)g;
short x, y;
gui_coords(&l->common, &x, &y);
if (render_left(l, &x, y)
|| render_mid(l, &x, y)
|| render_right(x, y))
return -1;
return 0;
}
static void get_dim(const struct gui_common *const g,
short *const w, short *const h)
{
struct gui_line_edit *const l = (struct gui_line_edit *)g;
*w = l->w;
*h = refs->h;
}
static void on_char(const char ch, void *const user)
{
struct gui_line_edit *const l = user;
if (l->i + 1 < l->sz)
l->text[l->i++] = ch;
}
static void on_erase(void *const user)
{
struct gui_line_edit *const l = user;
if (l->i)
l->text[--l->i] = '\0';
}
static int update(struct gui_common *const g,
const union peripheral *const p, const struct camera *const c,
struct input *const in)
{
struct gui_line_edit *const l = (struct gui_line_edit *)g;
if (gui_pressed(&l->common, in, p, c, l->w, refs->h))
{
l->focus = true;
*in = (const struct input)
{
.cb = on_char,
.erase = on_erase,
.user = l
};
}
else if (l->focus && gui_released(&l->common, p, c, l->w, refs->h))
{
l->focus = false;
if (in->user == l)
*in = (const struct input){0};
}
return 0;
}
static void deinit(struct gui_common *const g, struct input *const in)
{
struct gui_line_edit *const l = (struct gui_line_edit *)g;
if (l->focus)
*in = (const struct input){0};
}
void gui_line_edit_init(struct gui_line_edit *const l, char *const buf,
const size_t sz)
{
static const struct gui_common_cb cb =
{
.get_dim = get_dim,
.update = update,
.render = render,
.deinit = deinit
};
*l = (const struct gui_line_edit)
{
.common =
{
.cb = &cb
},
.text = buf,
.sz = sz
};
gui_label_init(&l->label);
memset(l->text, '\0', l->sz);
l->label.common.hcentered = true;
l->label.common.vcentered = true;
l->label.text = l->text;
gui_add_child(&l->common, &l->label.common);
}

5
src/input/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
add_library(input
"src/input.c"
)
target_include_directories(input PUBLIC "inc")
target_link_libraries(input PUBLIC keyboard mouse pad peripheral)

56
src/input/inc/input.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef INPUT_H
#define INPUT_H
#include <keyboard.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef void (*input_ch)(char ch, void *user);
typedef void (*input_erase)(void *user);
struct input
{
input_ch cb;
input_erase erase;
void *user;
unsigned char t;
bool repeat;
struct keyboard_combo prev;
};
void input_update(struct input *in, const union peripheral *p);
int input_render(const struct input *in, const union peripheral *p);
bool input_keyboard_justpressed(const struct input *in,
const struct keyboard *k,
const struct keyboard_combo *c);
bool input_keyboard_pressed(const struct input *in,
const struct keyboard *k,
const struct keyboard_combo *c);
bool input_keyboard_justreleased(const struct input *in,
const struct keyboard *k,
const struct keyboard_combo *c);
bool input_pad_pressed(const struct input *in, const struct pad *p,
enum pad_key k);
bool input_pad_justpressed(const struct input *in, const struct pad *p,
enum pad_key k);
bool input_pad_released(const struct input *in, const struct pad *p,
enum pad_key k);
bool input_mouse_pressed(const struct input *in, const struct mouse *m,
enum mouse_button b);
bool input_mouse_justpressed(const struct input *in, const struct mouse *m,
enum mouse_button b);
bool input_mouse_justreleased(const struct input *in, const struct mouse *m,
enum mouse_button b);
#ifdef __cplusplus
}
#endif
#endif /* INPUT_H */

175
src/input/src/input.c Normal file
View File

@ -0,0 +1,175 @@
#include <input.h>
#include <keyboard.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
#include <ctype.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
static void send_input(struct input *const in, const struct keyboard *const k,
const enum keyboard_key key)
{
if (key != KEYBOARD_KEY_NONE)
{
switch (key)
{
case KEYBOARD_KEY_BACKSPACE:
in->erase(in->user);
break;
case KEYBOARD_KEY_ESC:
*in = (const struct input){0};
break;
default:
{
const char ch = keyboard_to_char(k, key);
if (isprint(ch))
in->cb(ch, in->user);
}
break;
}
}
}
static void update_keyboard(struct input *const in,
const struct keyboard *const k)
{
struct keyboard_combo c;
if (keyboard_any_justpressed(k, &c))
for (size_t i = 0; i < sizeof c.keys / sizeof *c.keys; i++)
send_input(in, k, c.keys[i]);
else if (keyboard_any_pressed(k, &c))
{
if (memcmp(&c, &in->prev, sizeof c))
{
in->repeat = false;
in->t = 0;
}
else
{
enum {LONG_INTERVAL = 25, SHORT_INTERVAL = 2};
if (!in->repeat)
{
if (++in->t >= LONG_INTERVAL)
in->repeat = true;
}
else if (++in->t >= SHORT_INTERVAL)
{
for (size_t i = 0;
i < sizeof c.keys / sizeof *c.keys; i++)
send_input(in, k, c.keys[i]);
in->t = 0;
}
}
in->prev = c;
}
else
{
in->repeat = false;
in->t = 0;
}
}
void input_update(struct input *const in, const union peripheral *const p)
{
switch (p->common.type)
{
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
if (in->cb && in->erase)
update_keyboard(in, &p->kbm.keyboard);
break;
case PERIPHERAL_TYPE_TOUCH:
/* Fall through. */
case PERIPHERAL_TYPE_PAD:
break;
}
}
int input_render(const struct input *const in, const union peripheral *const p)
{
switch (p->common.type)
{
case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
return 0;
case PERIPHERAL_TYPE_TOUCH:
/* Fall through. */
case PERIPHERAL_TYPE_PAD:
break;
}
return -1;
}
bool input_keyboard_justpressed(const struct input *const in,
const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return in->cb ? false : keyboard_justpressed(k, c);
}
bool input_keyboard_pressed(const struct input *const in,
const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return in->cb ? false : keyboard_pressed(k, c);
}
bool input_keyboard_justreleased(const struct input *const in,
const struct keyboard *const k,
const struct keyboard_combo *const c)
{
return in->cb ? false : keyboard_justreleased(k, c);
}
bool input_pad_pressed(const struct input *const in,
const struct pad *const p,
const enum pad_key k)
{
return in->cb ? false : pad_pressed(p, k);
}
bool input_pad_justpressed(const struct input *const in,
const struct pad *const p,
const enum pad_key k)
{
return in->cb ? false : pad_justpressed(p, k);
}
bool input_pad_released(const struct input *const in,
const struct pad *const p,
const enum pad_key k)
{
return in->cb ? false : pad_released(p, k);
}
bool input_mouse_pressed(const struct input *const in,
const struct mouse *const m,
const enum mouse_button b)
{
return in->cb ? false : mouse_pressed(m, b);
}
bool input_mouse_justpressed(const struct input *const in,
const struct mouse *const m,
const enum mouse_button b)
{
return in->cb ? false : mouse_justpressed(m, b);
}
bool input_mouse_justreleased(const struct input *const in,
const struct mouse *const m,
const enum mouse_button b)
{
return in->cb ? false : mouse_justreleased(m, b);
}

View File

@ -29,6 +29,9 @@ void keyboard_update(struct keyboard *k);
bool keyboard_justpressed(const struct keyboard *k, const struct keyboard_combo *c);
bool keyboard_pressed(const struct keyboard *k, const struct keyboard_combo *c);
bool keyboard_justreleased(const struct keyboard *k, const struct keyboard_combo *c);
bool keyboard_any_justpressed(const struct keyboard *k, struct keyboard_combo *c);
bool keyboard_any_pressed(const struct keyboard *k, struct keyboard_combo *c);
char keyboard_to_char(const struct keyboard *k, enum keyboard_key key);
const char *keyboard_key_str(enum keyboard_key k);
#ifdef __cplusplus

View File

@ -54,7 +54,11 @@ extern "C"
X(KEYBOARD_KEY_RIGHT) \
X(KEYBOARD_KEY_UP) \
X(KEYBOARD_KEY_DOWN) \
X(KEYBOARD_KEY_EXIT)
X(KEYBOARD_KEY_EXIT) \
X(KEYBOARD_KEY_BACKSPACE) \
X(KEYBOARD_KEY_SPACE) \
X(KEYBOARD_KEY_MINUS) \
X(KEYBOARD_KEY_DOT)
enum keyboard_key
{

View File

@ -41,6 +41,7 @@ static void key_event(const SDL_KeyboardEvent *const ev,
SDLKey sdl_key;
} keymap[] =
{
{.key = KEYBOARD_KEY_BACKSPACE, .sdl_key = SDLK_BACKSPACE},
{.key = KEYBOARD_KEY_LEFT, .sdl_key = SDLK_LEFT},
{.key = KEYBOARD_KEY_RIGHT, .sdl_key = SDLK_RIGHT},
{.key = KEYBOARD_KEY_UP, .sdl_key = SDLK_UP},
@ -49,12 +50,58 @@ static void key_event(const SDL_KeyboardEvent *const ev,
{.key = KEYBOARD_KEY_RCTRL, .sdl_key = SDLK_RCTRL},
{.key = KEYBOARD_KEY_LSHIFT, .sdl_key = SDLK_LSHIFT},
{.key = KEYBOARD_KEY_RSHIFT, .sdl_key = SDLK_RSHIFT},
{.key = KEYBOARD_KEY_EXIT, .sdl_key = SDLK_ESCAPE},
{.key = KEYBOARD_KEY_ESC, .sdl_key = SDLK_ESCAPE},
{.key = KEYBOARD_KEY_F11, .sdl_key = SDLK_F11},
{.key = KEYBOARD_KEY_W, .sdl_key = SDLK_w},
{.key = KEYBOARD_KEY_SPACE, .sdl_key = SDLK_SPACE},
{.key = KEYBOARD_KEY_MINUS, .sdl_key = SDLK_MINUS},
{.key = KEYBOARD_KEY_A, .sdl_key = SDLK_a},
{.key = KEYBOARD_KEY_B, .sdl_key = SDLK_b},
{.key = KEYBOARD_KEY_C, .sdl_key = SDLK_c},
{.key = KEYBOARD_KEY_D, .sdl_key = SDLK_d},
{.key = KEYBOARD_KEY_E, .sdl_key = SDLK_e},
{.key = KEYBOARD_KEY_F, .sdl_key = SDLK_f},
{.key = KEYBOARD_KEY_G, .sdl_key = SDLK_g},
{.key = KEYBOARD_KEY_H, .sdl_key = SDLK_h},
{.key = KEYBOARD_KEY_I, .sdl_key = SDLK_i},
{.key = KEYBOARD_KEY_J, .sdl_key = SDLK_j},
{.key = KEYBOARD_KEY_K, .sdl_key = SDLK_k},
{.key = KEYBOARD_KEY_L, .sdl_key = SDLK_l},
{.key = KEYBOARD_KEY_M, .sdl_key = SDLK_m},
{.key = KEYBOARD_KEY_N, .sdl_key = SDLK_n},
{.key = KEYBOARD_KEY_O, .sdl_key = SDLK_o},
{.key = KEYBOARD_KEY_P, .sdl_key = SDLK_p},
{.key = KEYBOARD_KEY_Q, .sdl_key = SDLK_q},
{.key = KEYBOARD_KEY_R, .sdl_key = SDLK_r},
{.key = KEYBOARD_KEY_S, .sdl_key = SDLK_s},
{.key = KEYBOARD_KEY_D, .sdl_key = SDLK_d}
{.key = KEYBOARD_KEY_T, .sdl_key = SDLK_t},
{.key = KEYBOARD_KEY_U, .sdl_key = SDLK_u},
{.key = KEYBOARD_KEY_V, .sdl_key = SDLK_v},
{.key = KEYBOARD_KEY_W, .sdl_key = SDLK_w},
{.key = KEYBOARD_KEY_X, .sdl_key = SDLK_x},
{.key = KEYBOARD_KEY_Y, .sdl_key = SDLK_y},
{.key = KEYBOARD_KEY_Z, .sdl_key = SDLK_z},
{.key = KEYBOARD_KEY_0, .sdl_key = SDLK_0},
{.key = KEYBOARD_KEY_1, .sdl_key = SDLK_1},
{.key = KEYBOARD_KEY_2, .sdl_key = SDLK_2},
{.key = KEYBOARD_KEY_3, .sdl_key = SDLK_3},
{.key = KEYBOARD_KEY_4, .sdl_key = SDLK_4},
{.key = KEYBOARD_KEY_5, .sdl_key = SDLK_5},
{.key = KEYBOARD_KEY_6, .sdl_key = SDLK_6},
{.key = KEYBOARD_KEY_7, .sdl_key = SDLK_7},
{.key = KEYBOARD_KEY_8, .sdl_key = SDLK_8},
{.key = KEYBOARD_KEY_9, .sdl_key = SDLK_9},
{.key = KEYBOARD_KEY_0, .sdl_key = SDLK_KP0},
{.key = KEYBOARD_KEY_1, .sdl_key = SDLK_KP1},
{.key = KEYBOARD_KEY_2, .sdl_key = SDLK_KP2},
{.key = KEYBOARD_KEY_3, .sdl_key = SDLK_KP3},
{.key = KEYBOARD_KEY_4, .sdl_key = SDLK_KP4},
{.key = KEYBOARD_KEY_5, .sdl_key = SDLK_KP5},
{.key = KEYBOARD_KEY_6, .sdl_key = SDLK_KP6},
{.key = KEYBOARD_KEY_7, .sdl_key = SDLK_KP7},
{.key = KEYBOARD_KEY_8, .sdl_key = SDLK_KP8},
{.key = KEYBOARD_KEY_9, .sdl_key = SDLK_KP9},
{.key = KEYBOARD_KEY_DOT, .sdl_key = SDLK_PERIOD},
{.key = KEYBOARD_KEY_DOT, .sdl_key = SDLK_KP_PERIOD}
};
for (size_t i = 0; i < sizeof keymap / sizeof *keymap; i++)

View File

@ -1,8 +1,88 @@
#include <keyboard.h>
#include <keyboard_key.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
bool keyboard_any_justpressed(const struct keyboard *const k,
struct keyboard_combo *const c)
{
bool ret = false;
for (size_t i = 0; i < sizeof c->keys / sizeof c->keys; i++)
c->keys[i] = KEYBOARD_KEY_NONE;
for (size_t i = 0, j = 0;
i < sizeof k->combo.keys / sizeof *k->combo.keys; i++)
{
const enum keyboard_key key = k->combo.keys[i];
if (key != KEYBOARD_KEY_NONE
&& k->oldcombo.keys[i] == KEYBOARD_KEY_NONE)
{
c->keys[j++] = key;
ret = true;
}
}
return ret;
}
bool keyboard_any_pressed(const struct keyboard *const k,
struct keyboard_combo *const c)
{
for (size_t i = 0; i < sizeof k->combo.keys / sizeof *k->combo.keys; i++)
{
const enum keyboard_key key = k->combo.keys[i];
if (key != KEYBOARD_KEY_NONE)
{
*c = k->combo;
return true;
}
}
return false;
}
char keyboard_to_char(const struct keyboard *const k,
const enum keyboard_key key)
{
if (key >= KEYBOARD_KEY_0 && key <= KEYBOARD_KEY_9)
return '0' + key - KEYBOARD_KEY_0;
else if (key >= KEYBOARD_KEY_A && key <= KEYBOARD_KEY_Z)
{
if (keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_LSHIFT))
|| keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_RSHIFT)))
return 'A' + key - KEYBOARD_KEY_A;
else
return 'a' + key - KEYBOARD_KEY_A;
}
else
{
static const struct map
{
enum keyboard_key key;
char ch;
} map[] =
{
{.key = KEYBOARD_KEY_DOT, .ch = '.'},
{.key = KEYBOARD_KEY_SPACE, .ch = ' '},
{.key = KEYBOARD_KEY_MINUS, .ch = '-'}
};
for (size_t i = 0; i < sizeof map / sizeof *map; i++)
{
const struct map *const m = &map[i];
if (key == m->key)
return m->ch;
}
}
return -1;
}
static bool combo_pressed(const struct keyboard_combo *const ref,
const struct keyboard_combo *const c)
{

View File

@ -1,8 +1,9 @@
add_library(menu
"src/gamecfg_menu.c"
"src/hostjoin_menu.c"
"src/join_menu.c"
"src/menu.c"
"src/main_menu.c"
)
target_include_directories(menu PUBLIC "inc" PRIVATE "privinc")
target_link_libraries(menu PRIVATE camera game gfx gui system)
target_link_libraries(menu PRIVATE camera game gfx gui input system)

View File

@ -2,6 +2,7 @@
#define MENU_PRIVATE_H
#include <camera.h>
#include <input.h>
#include <peripheral.h>
#include <stdbool.h>
@ -14,6 +15,7 @@ struct menu_common
{
struct camera cam;
union peripheral p;
struct input in;
};
int menu_update(struct menu_common *c,
@ -22,6 +24,7 @@ int menu_update(struct menu_common *c,
void *arg);
int menu_main(struct menu_common *c);
int menu_hostjoin(struct menu_common *c, bool *back);
int menu_join(struct menu_common *c);
int menu_gamecfg(struct menu_common *c);
void menu_on_pressed(void *arg);

View File

@ -23,8 +23,8 @@ static int update(struct menu_common *const c, void *const arg)
m->r.w = screen_w / 2;
m->r.h = screen_h / 2;
if (gui_update(&m->cnt.common, &c->p, &c->cam)
|| gui_update(&m->bcnt.common, &c->p, &c->cam))
if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in)
|| gui_update(&m->bcnt.common, &c->p, &c->cam, &c->in))
return -1;
return 0;
@ -77,10 +77,8 @@ int menu_gamecfg(struct menu_common *const c)
gui_add_child(&m.bcnt.common, &m.back.common);
while (!back && !c->p.common.exit && !start)
{
if (menu_update(c, update, render, &m))
return -1;
}
if (start)
return game(NULL);

View File

@ -16,7 +16,7 @@ static int update(struct menu_common *const c, void *const arg)
{
struct menu_hostjoin *const m = arg;
if (gui_update(&m->cnt.common, &c->p, &c->cam))
if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in))
return -1;
return 0;
@ -75,9 +75,16 @@ int menu_hostjoin(struct menu_common *const c, bool *const back)
return -1;
}
if (host || join)
if (host)
{
if (menu_gamecfg(c))
return -1;
}
else if (join)
{
if (menu_join(c))
return -1;
}
} while (!*back && !c->p.common.exit);

262
src/menu/src/join_menu.c Normal file
View File

@ -0,0 +1,262 @@
#include <menu.h>
#include <menu_private.h>
#include <game.h>
#include <gui.h>
#include <gui/button.h>
#include <gui/container.h>
#include <gui/label.h>
#include <gui/line_edit.h>
#include <gui/rounded_rect.h>
#include <net.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
struct join_menu
{
struct gui_container cnt, bcnt;
struct gui_label type_label, address, port, connecting;
struct gui_button type_btn, back, connect;
struct gui_line_edit address_le, port_le;
enum
{
IDLE,
CONNECT,
CONNECTING,
CONNECTED,
CONNECT_FAILED
} state;
struct net_socket *socket;
size_t domain_i;
};
static const enum net_domain domains[] =
{
NET_DOMAIN_IPV4,
NET_DOMAIN_SERIAL
};
static void on_connected(void *const arg)
{
struct join_menu *const m = arg;
if (m->state == IDLE)
{
m->state = CONNECT;
m->connecting.text = "Connecting...";
}
}
static void on_disconnected(void *const arg)
{
struct join_menu *const m = arg;
m->connecting.text = "Failed to connect";
m->state = CONNECT_FAILED;
m->socket = NULL;
}
static int on_connect(struct join_menu *const m)
{
const enum net_domain d = domains[m->domain_i];
union net_connect c =
{
.common =
{
.domain = d,
.on_connected = on_connected,
.on_disconnected = on_disconnected,
.arg = m
}
};
switch (d)
{
case NET_DOMAIN_IPV4:
{
errno = 0;
const unsigned long port = strtoul(m->port_le.text, NULL, 0);
if (errno)
return -1;
c.ipv4.addr = m->address_le.text;
c.ipv4.port = port;
}
break;
case NET_DOMAIN_SERIAL:
break;
}
if (!(m->socket = net_connect(&c)))
{
fprintf(stderr, "%s: net_connect failed\n", __func__);
return -1;
}
return 0;
}
static int update(struct menu_common *const c, void *const arg)
{
struct join_menu *const m = arg;
m->bcnt.common.y = screen_h - 40;
if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in)
|| gui_update(&m->bcnt.common, &c->p, &c->cam, &c->in))
return -1;
if (m->socket && net_update(m->socket))
return -1;
switch (m->state)
{
case CONNECT:
if (on_connect(m))
return -1;
m->state = CONNECTING;
if (!m->connecting.common.parent)
gui_add_child(&m->cnt.common, &m->connecting.common);
break;
case CONNECT_FAILED:
net_close(m->socket);
m->socket = NULL;
m->state = IDLE;
break;
default:
break;
}
return 0;
}
static int render(const struct menu_common *const c, void *const arg)
{
const struct join_menu *const m = arg;
if (gui_render(&m->cnt.common)
|| gui_render(&m->bcnt.common))
return -1;
return 0;
}
static void on_type_pressed(void *const arg)
{
struct join_menu *const m = arg;
if (++m->domain_i >= sizeof domains / sizeof *domains)
m->domain_i = 0;
m->type_btn.u.type1.label.text = net_domain_str(domains[m->domain_i]);
}
static void on_connect_pressed(void *const arg)
{
struct join_menu *const m = arg;
m->state = CONNECT;
}
int menu_join(struct menu_common *const c)
{
int ret = -1;
struct join_menu m = {0};
bool connect = false;
bool back = false;
gui_container_init(&m.cnt);
m.cnt.common.hcentered = true;
m.cnt.common.vcentered = true;
m.cnt.mode = GUI_CONTAINER_MODE_V;
m.cnt.spacing = 2;
gui_label_init(&m.type_label);
m.type_label.common.hcentered = true;
m.type_label.text = "Type:";
gui_add_child(&m.cnt.common, &m.type_label.common);
gui_button_init(&m.type_btn, GUI_BUTTON_TYPE_1);
m.type_btn.arg = &m;
m.type_btn.u.type1.w = 140;
m.type_btn.common.hcentered = true;
m.type_btn.on_pressed = on_type_pressed;
m.type_btn.u.type1.label.text = net_domain_str(*domains);
gui_add_child(&m.cnt.common, &m.type_btn.common);
gui_label_init(&m.address);
m.address.common.hcentered = true;
m.address.text = "Address:";
gui_add_child(&m.cnt.common, &m.address.common);
char address[sizeof "255.255.255.255"];
gui_line_edit_init(&m.address_le, address, sizeof address);
m.address_le.w = 140;
m.address_le.common.hcentered = true;
gui_add_child(&m.cnt.common, &m.address_le.common);
gui_label_init(&m.port);
m.port.common.hcentered = true;
m.port.text = "Port:";
gui_add_child(&m.cnt.common, &m.port.common);
char port[sizeof "65535"];
gui_line_edit_init(&m.port_le, port, sizeof port);
m.port_le.w = 80;
m.port_le.common.hcentered = true;
gui_add_child(&m.cnt.common, &m.port_le.common);
gui_label_init(&m.connecting);
m.connecting.common.hcentered = true;
gui_container_init(&m.bcnt);
m.bcnt.common.hcentered = true;
m.bcnt.mode = GUI_CONTAINER_MODE_H;
gui_button_init(&m.connect, GUI_BUTTON_TYPE_1);
m.connect.u.type1.label.text = "Connect";
m.connect.u.type1.w = 140;
m.connect.common.vcentered = true;
m.connect.on_pressed = on_connect_pressed;
m.connect.arg = &m;
m.back.common.vcentered = true;
gui_add_child(&m.bcnt.common, &m.connect.common);
gui_button_init(&m.back, GUI_BUTTON_TYPE_1);
m.back.u.type1.label.text = "Back";
m.back.u.type1.w = 100;
m.back.common.vcentered = true;
m.back.on_pressed = menu_on_pressed;
m.back.arg = &back;
m.back.common.vcentered = true;
gui_add_child(&m.bcnt.common, &m.back.common);
while (!back && !c->p.common.exit && !connect)
{
if (menu_update(c, update, render, &m))
goto end;
}
if (connect)
{
}
ret = 0;
end:
gui_deinit(&m.cnt.common, &c->in);
return ret;
}

View File

@ -18,7 +18,7 @@ static int update(struct menu_common *const c, void *const arg)
{
struct main_menu *const m = arg;
if (gui_update(&m->play.common, &c->p, &c->cam))
if (gui_update(&m->play.common, &c->p, &c->cam, &c->in))
return -1;
return 0;

View File

@ -3,6 +3,7 @@
#include <camera.h>
#include <game.h>
#include <gfx.h>
#include <input.h>
#include <peripheral.h>
#include <system.h>
#include <stdbool.h>
@ -19,7 +20,8 @@ int menu_update(struct menu_common *const c,
{
system_loop();
peripheral_update(&c->p);
camera_update(&c->cam, &c->p);
input_update(&c->in, &c->p);
camera_update(&c->cam, &c->p, &c->in);
if (update && update(c, arg))
return -1;
@ -32,6 +34,8 @@ int menu_update(struct menu_common *const c,
if (render && render(c, arg))
return -1;
else if (input_render(&c->in, &c->p))
return -1;
switch (c->p.common.type)
{
@ -66,7 +70,7 @@ int menu(void)
struct menu_common c = {0};
if (game_resinit())
return -1;
return -1;
cursor_init(&c.cam.cursor);
peripheral_init(&cfg, &c.p);

View File

@ -0,0 +1,62 @@
#include <menu_private.h>
#include <gui.h>
#include <gui/container.h>
#include <gui/label.h>
#include <gui/line_edit.h>
#include <gui/button.h>
#include <stdbool.h>
struct menu_settings
{
struct gui_container cnt;
struct gui_button back;
};
static int update(struct menu_common *const c, void *const arg)
{
struct menu_settings *const m = arg;
if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in))
return -1;
return 0;
}
static int render(const struct menu_common *const c, void *const arg)
{
const struct menu_settings *const m = arg;
if (gui_render(&m->cnt.common))
return -1;
return 0;
}
int menu_settings(struct menu_common *const c, bool *const back)
{
do
{
struct menu_settings m;
gui_container_init(&m.cnt);
m.cnt.common.hcentered = true;
m.cnt.common.vcentered = true;
m.cnt.spacing = 4;
m.cnt.mode = GUI_CONTAINER_MODE_V;
gui_button_init(&m.back, GUI_BUTTON_TYPE_1);
m.back.u.type1.label.text = "Back";
m.back.common.hcentered = true;
m.back.u.type1.w = 140;
m.back.arg = back;
m.back.on_pressed = menu_on_pressed;
gui_add_child(&m.cnt.common, &m.back.common);
while (!*back && !c->p.common.exit)
if (menu_update(c, update, render, &m))
return -1;
} while (!*back && !c->p.common.exit);
return 0;
}

32
src/net/CMakeLists.txt Normal file
View File

@ -0,0 +1,32 @@
set(src "src/common.c")
if(PS1_BUILD)
set(src ${src}
"src/ps1/net.c"
)
else()
set(src ${src}
"src/net.c"
"src/enet/ipv4.c"
)
if(WIN9X_BUILD OR ${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
set(src ${src} "src/win9x/serial.c")
else()
# Assume POSIX if the command below executes successfully
execute_process(COMMAND uname -m RESULT_VARIABLE result OUTPUT_QUIET)
if(result)
message(FATAL_ERROR "Unknown operating system")
else()
set(src ${src} "src/posix/serial.c")
endif()
endif()
set(priv_deps ${priv_deps} util ENET)
set(privinc ${privinc} "privinc")
endif()
add_library(net ${src})
target_include_directories(net PUBLIC "inc" PRIVATE ${privinc})
target_link_libraries(net PRIVATE ${priv_deps})

78
src/net/inc/net.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef NET_H
#define NET_H
#include <stddef.h>
#include <stdint.h>
enum net_domain
{
NET_DOMAIN_IPV4,
NET_DOMAIN_SERIAL
};
union net_connect
{
struct net_connect_common
{
enum net_domain domain;
void (*on_connected)(void *arg);
void (*on_disconnected)(void *arg);
void *arg;
} common;
struct net_connect_ipv4
{
struct net_connect_common common;
const char *addr;
uint16_t port;
} ipv4;
struct net_connect_serial
{
struct net_connect_common common;
const char *dev;
unsigned long baud;
enum
{
NET_PARITY_NONE,
NET_PARITY_ODD,
NET_PARITY_EVEN
} parity;
} serial;
};
union net_server
{
struct net_server_common
{
enum net_domain domain;
unsigned max_players;
} common;
struct net_server_ipv4
{
struct net_server_common common;
uint16_t port;
} ipv4;
struct net_server_serial
{
struct net_server_common common;
} serial;
};
struct net_socket;
int net_init(void);
void net_deinit(void);
int net_update(struct net_socket *s);
struct net_socket *net_server(const union net_server *srv);
struct net_socket *net_connect(const union net_connect *c);
int net_read(struct net_socket *s, void *buf, size_t n);
int net_write(struct net_socket *s, const void *buf, size_t n);
int net_close(struct net_socket *s);
const char *net_domain_str(enum net_domain d);
#endif /* NET_H */

View File

@ -0,0 +1,30 @@
#ifndef NET_PRIVATE_H
#define NET_PRIVATE_H
#include <net.h>
struct net_socket
{
enum net_domain d;
struct net_socket_domain *s;
};
int net_init_ipv4(void);
void net_deinit_ipv4(void);
struct net_socket_domain *net_server_ipv4(const union net_server *srv);
struct net_socket_domain *net_connect_ipv4(const union net_connect *c);
int net_read_ipv4(struct net_socket_domain *h, void *buf, size_t n);
int net_write_ipv4(struct net_socket_domain *h, const void *buf, size_t n);
int net_close_ipv4(struct net_socket_domain *h);
int net_update_ipv4(struct net_socket_domain *h);
int net_init_serial(void);
void net_deinit_serial(void);
struct net_socket_domain *net_server_serial(const union net_server *srv);
struct net_socket_domain *net_connect_serial(const union net_connect *c);
int net_read_serial(struct net_socket_domain *h, void *buf, size_t n);
int net_write_serial(struct net_socket_domain *h, const void *buf, size_t n);
int net_close_serial(struct net_socket_domain *h);
int net_update_serial(struct net_socket_domain *h);
#endif /* NET_PRIVATE_H */

12
src/net/src/common.c Normal file
View File

@ -0,0 +1,12 @@
#include <net.h>
const char *net_domain_str(const enum net_domain d)
{
static const char *const s[] =
{
[NET_DOMAIN_IPV4] = "UDP/IPv4",
[NET_DOMAIN_SERIAL] = "Serial"
};
return s[d];
}

161
src/net/src/enet/ipv4.c Normal file
View File

@ -0,0 +1,161 @@
#include <net.h>
#include <net_private.h>
#include <enet/enet.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
struct net_socket_domain
{
ENetHost *host;
ENetPeer *peers;
void (*on_connected)(void *arg);
void (*on_disconnected)(void *arg);
void *arg;
};
enum
{
CHANNEL,
MAX_CHANNELS
};
struct net_socket_domain *net_connect_ipv4(const union net_connect *const c)
{
struct net_socket_domain *const s = calloc(1, sizeof *s);
if (!s)
goto failure;
s->on_connected = c->common.on_connected;
s->on_disconnected = c->common.on_disconnected;
s->arg = c->common.arg;
s->host = enet_host_create(NULL, 1, MAX_CHANNELS, 0, 0);
if (!s->host)
{
fprintf(stderr, "%s: enet_host_create failed\n", __func__);
goto failure;
}
ENetAddress addr;
if (enet_address_set_host(&addr, c->ipv4.addr))
{
fprintf(stderr, "%s: enet_address_set_host failed\n", __func__);
goto failure;
}
addr.port = c->ipv4.port;
if (!(s->peers = enet_host_connect(s->host, &addr, MAX_CHANNELS, 0)))
{
fprintf(stderr, "%s: enet_host_connect failed\n", __func__);
goto failure;
}
return s;
failure:
if (s && s->host)
enet_host_destroy(s->host);
free(s);
return NULL;
}
int net_read_ipv4(struct net_socket_domain *const s, void *const buf,
const size_t n)
{
return -1;
}
int net_write_ipv4(struct net_socket_domain *const s, const void *const buf,
const size_t n)
{
return -1;
}
int net_close_ipv4(struct net_socket_domain *const s)
{
if (s && s->host)
enet_host_destroy(s->host);
free(s);
return 0;
}
int net_update_ipv4(struct net_socket_domain *const s)
{
int res;
ENetEvent ev;
while ((res = enet_host_service(s->host, &ev, 0)) > 0)
{
switch (ev.type)
{
case ENET_EVENT_TYPE_CONNECT:
if (s->on_connected)
s->on_connected(s->arg);
break;
case ENET_EVENT_TYPE_DISCONNECT:
if (s->on_disconnected)
s->on_disconnected(s->arg);
case ENET_EVENT_TYPE_RECEIVE:
break;
case ENET_EVENT_TYPE_NONE:
break;
}
}
if (res < 0)
{
fprintf(stderr, "%s: enet_host_service failed\n", __func__);
return res;
}
return 0;
}
struct net_socket_domain *net_server_ipv4(const union net_server *const srv)
{
struct net_socket_domain *const s = calloc(1, sizeof *s);
if (!s)
goto failure;
const ENetAddress addr =
{
.port = srv->ipv4.port
};
s->host = enet_host_create(&addr, srv->common.max_players,
MAX_CHANNELS, 0, 0);
if (!s->host)
{
fprintf(stderr, "%s: enet_host_create failed\n", __func__);
goto failure;
}
return s;
failure:
free(s);
return NULL;
}
int net_init_ipv4(void)
{
return enet_initialize();
}
void net_deinit_ipv4(void)
{
enet_deinitialize();
}

111
src/net/src/net.c Normal file
View File

@ -0,0 +1,111 @@
#include <net.h>
#include <net_private.h>
#include <stddef.h>
#include <stdlib.h>
struct net_socket *net_connect(const union net_connect *const c)
{
struct net_socket *const s = calloc(1, sizeof *s);
if (!s)
goto failure;
static struct net_socket_domain *(*const f[])(const union net_connect *) =
{
[NET_DOMAIN_IPV4] = net_connect_ipv4,
[NET_DOMAIN_SERIAL] = net_connect_serial
};
if (!(s->s = f[c->common.domain](c)))
goto failure;
return s;
failure:
free(s);
return NULL;
}
int net_read(struct net_socket *const s, void *const buf, const size_t n)
{
static int (*const f[])(struct net_socket_domain *, void *, size_t) =
{
[NET_DOMAIN_IPV4] = net_read_ipv4,
[NET_DOMAIN_SERIAL] = net_read_serial
};
return f[s->d](s->s, buf, n);
}
int net_write(struct net_socket *const s, const void *const buf, const size_t n)
{
static int (*const f[])(struct net_socket_domain *, const void *, size_t) =
{
[NET_DOMAIN_IPV4] = net_write_ipv4,
[NET_DOMAIN_SERIAL] = net_write_serial
};
return f[s->d](s->s, buf, n);
}
int net_close(struct net_socket *const s)
{
if (!s)
return 0;
static int (*const f[])(struct net_socket_domain *) =
{
[NET_DOMAIN_IPV4] = net_close_ipv4,
[NET_DOMAIN_SERIAL] = net_close_serial
};
const int res = f[s->d](s->s);
free(s);
return res;
}
int net_update(struct net_socket *const s)
{
static int (*const f[])(struct net_socket_domain *) =
{
[NET_DOMAIN_IPV4] = net_update_ipv4,
[NET_DOMAIN_SERIAL] = net_update_serial
};
return f[s->d](s->s);
}
struct net_socket *net_server(const union net_server *const srv)
{
struct net_socket *const s = calloc(1, sizeof *s);
if (!s)
goto failure;
s->d = srv->common.domain;
static struct net_socket_domain *(*const f[])(const union net_server *) =
{
[NET_DOMAIN_IPV4] = net_server_ipv4,
[NET_DOMAIN_SERIAL] = net_server_serial
};
if (!(s->s = f[s->d](srv)))
goto failure;
failure:
net_close(s);
return NULL;
}
int net_init(void)
{
return net_init_ipv4() || net_init_serial();
}
void net_deinit(void)
{
net_deinit_ipv4();
net_deinit_serial();
}

View File

@ -0,0 +1,44 @@
#include <net.h>
#include <net_private.h>
#include <stddef.h>
int net_read_serial(struct net_socket_domain *const h, void *const buf,
const size_t n)
{
return -1;
}
int net_write_serial(struct net_socket_domain *const h, const void *const buf,
const size_t n)
{
return -1;
}
int net_close_serial(struct net_socket_domain *const h)
{
return -1;
}
int net_update_serial(struct net_socket_domain *const h)
{
return -1;
}
struct net_socket_domain *net_connect_serial(const union net_connect *const srv)
{
return NULL;
}
struct net_socket_domain *net_server_serial(const union net_server *const srv)
{
return NULL;
}
int net_init_serial(void)
{
return 0;
}
void net_deinit_serial(void)
{
}

42
src/net/src/ps1/net.c Normal file
View File

@ -0,0 +1,42 @@
#include <net.h>
#include <errno.h>
#include <stddef.h>
int net_read(struct net_socket *const h, void *const buf, const size_t n)
{
return -1;
}
int net_write(struct net_socket *const h, const void *const buf, const size_t n)
{
return -1;
}
int net_close(struct net_socket *const h)
{
return -1;
}
int net_update(struct net_socket *const h)
{
return -1;
}
struct net_socket *net_connect(const union net_connect *const c)
{
return NULL;
}
struct net_socket *net_server(const union net_server *const c)
{
return NULL;
}
int net_init(void)
{
return -1;
}
void net_deinit(void)
{
}

View File

@ -0,0 +1,44 @@
#include <net.h>
#include <net_private.h>
#include <stddef.h>
int net_read_serial(struct net_socket_domain *const h, void *const buf,
const size_t n)
{
return -1;
}
int net_write_serial(struct net_socket_domain *const h, const void *const buf,
const size_t n)
{
return -1;
}
int net_close_serial(struct net_socket_domain *const h)
{
return -1;
}
int net_update_serial(struct net_socket_domain *const h)
{
return -1;
}
struct net_socket_domain *net_connect_serial(const union net_connect *const srv)
{
return NULL;
}
struct net_socket_domain *net_server_serial(const union net_server *const srv)
{
return NULL;
}
int net_init_serial(void)
{
return 0;
}
void net_deinit_serial(void)
{
}

View File

@ -56,6 +56,7 @@ UTIL_STATIC_ASSERT(!offsetof(struct peripheral_kbm, common),
"unexpected offsetof for struct peripheral_kbm");
void peripheral_init(const struct peripheral_cfg *cfg, union peripheral *p);
void peripheral_input_set(union peripheral *p, void (*cb)(char, void *));
void peripheral_update(union peripheral *p);
#ifdef __cplusplus

View File

@ -11,6 +11,7 @@ target_link_libraries(player
gfx
keyboard
instance
input
mouse
pad
resource

View File

@ -4,6 +4,7 @@
#include <camera.h>
#include <keyboard.h>
#include <instance.h>
#include <input.h>
#include <mouse.h>
#include <pad.h>
#include <peripheral.h>
@ -32,6 +33,7 @@ struct human_player
struct player pl;
struct camera cam;
union peripheral periph;
struct input in;
struct sel_instance
{

View File

@ -6,6 +6,7 @@
#include <gfx.h>
#include <gui.h>
#include <instance.h>
#include <input.h>
#include <keyboard.h>
#include <pad.h>
#include <resource.h>
@ -542,26 +543,28 @@ static void update_target(struct human_player *const h)
static void update_from_pad(struct human_player *const h,
struct player_others *const o)
{
struct pad *const p = &h->periph.pad.pad;
const struct pad *const p = &h->periph.pad.pad;
const struct input *const in = &h->in;
if (pad_justpressed(p, PAD_KEY_A))
if (input_pad_justpressed(in, p, PAD_KEY_A))
select_instances(h, o, false, false);
else if (pad_justpressed(p, PAD_KEY_B))
else if (input_pad_justpressed(in, p, PAD_KEY_B))
move_units(h, o);
else if (pad_justpressed(p, PAD_KEY_C))
else if (input_pad_justpressed(in, p, PAD_KEY_C))
deselect_instances(h);
else if (pad_justpressed(p, PAD_KEY_E))
else if (input_pad_justpressed(in, p, PAD_KEY_E))
h->top_gui ^= true;
}
static void update_from_touch(struct human_player *const h,
struct player_others *const o)
{
struct mouse *const m = &h->periph.kbm.mouse;
const struct mouse *const m = &h->periph.kbm.mouse;
const struct input *const in = &h->in;
struct peripheral_kbm *const kbm = &h->periph.kbm;
bool *const pan = &h->cam.pan;
if (mouse_pressed(m, MOUSE_BUTTON_LEFT) && !*pan)
if (input_mouse_pressed(in, m, MOUSE_BUTTON_LEFT) && !*pan)
{
enum {LONG_PRESS_THRESHOLD = 30};
@ -573,7 +576,7 @@ static void update_from_touch(struct human_player *const h,
deselect_instances(h);
}
}
else if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
else if (input_mouse_justreleased(in, m, MOUSE_BUTTON_LEFT))
{
if (!*pan && !select_instances(h, o, false, true))
move_units(h, o);
@ -587,19 +590,22 @@ static void update_from_touch(struct human_player *const h,
static void update_from_keyboard_mouse(struct human_player *const h,
struct player_others *const o)
{
struct mouse *const m = &h->periph.kbm.mouse;
struct keyboard *const k = &h->periph.kbm.keyboard;
const struct mouse *const m = &h->periph.kbm.mouse;
const struct keyboard *const k = &h->periph.kbm.keyboard;
const struct input *const in = &h->in;
if (mouse_justreleased(m, MOUSE_BUTTON_LEFT))
if (input_mouse_justreleased(in, m, MOUSE_BUTTON_LEFT))
{
const bool shift_pressed =
keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_LSHIFT))
|| keyboard_pressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_RSHIFT));
input_keyboard_pressed(in, k,
&KEYBOARD_COMBO(KEYBOARD_KEY_LSHIFT))
|| input_keyboard_pressed(in, k,
&KEYBOARD_COMBO(KEYBOARD_KEY_RSHIFT));
if (!select_instances(h, o, !shift_pressed, false))
deselect_instances(h);
}
else if (mouse_justreleased(m, MOUSE_BUTTON_RIGHT))
else if (input_mouse_justreleased(in, m, MOUSE_BUTTON_RIGHT))
move_units(h, o);
}
@ -614,6 +620,7 @@ void human_player_update(struct human_player *const h,
update_selected(h);
update_target(h);
peripheral_update(&h->periph);
input_update(&h->in, &h->periph);
switch (h->periph.common.type)
{
@ -630,7 +637,7 @@ void human_player_update(struct human_player *const h,
break;
}
camera_update(&h->cam, &h->periph);
camera_update(&h->cam, &h->periph, &h->in);
player_update(p);
}
}
@ -702,7 +709,8 @@ int human_player_render(const struct human_player *const h,
|| render_own_units(h)
|| render_own_buildings(h)
|| render_resources(h, o->res, o->n_res)
|| human_player_gui_render(h))
|| human_player_gui_render(h)
|| input_render(&h->in, &h->periph))
return -1;
switch (h->periph.common.type)

View File

@ -1,5 +1,5 @@
set(inc "inc")
set(privdeps gfx sfx)
set(privdeps gfx sfx net)
if(PS1_BUILD)
set(src "ps1/src/init.c")

View File

@ -1,4 +1,5 @@
#include <gfx.h>
#include <net.h>
#include <sfx.h>
#include <system.h>
#include <psx.h>
@ -20,13 +21,14 @@ void system_deinit(void)
{
gfx_deinit();
sfx_deinit();
net_deinit();
}
int system_init(void)
{
SetVBlankHandler(vblank);
if (gfx_init() || sfx_init())
if (gfx_init() || sfx_init() || net_init())
return -1;
return 0;

View File

@ -1,5 +1,6 @@
#include <gfx.h>
#include <sfx.h>
#include <net.h>
#include <system.h>
#include <SDL.h>
#include <stdio.h>
@ -19,6 +20,7 @@ void system_deinit(void)
{
gfx_deinit();
sfx_deinit();
net_deinit();
SDL_Quit();
}
@ -29,7 +31,7 @@ int system_init(void)
fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
goto failure;
}
else if (gfx_init() || sfx_init())
else if (gfx_init() || sfx_init() || net_init())
goto failure;
SDL_WM_SetCaption("rts", NULL);