diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34f07696b..e1db3e63f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,10 @@ jobs: wget -O license/FatFs.txt https://raw.githubusercontent.com/hhuOS/FatFs/master/LICENSE && wget -O license/doomgeneric.txt https://raw.githubusercontent.com/hhuOS/doomgeneric/master/LICENSE && wget -O license/quakegeneric.txt https://raw.githubusercontent.com/hhuOS/quakegeneric/master/LICENSE && - wget -O license/tinygl.txt https://raw.githubusercontent.com/C-Chads/tinygl/main/LICENSE + wget -O license/tinygl.txt https://raw.githubusercontent.com/C-Chads/tinygl/main/LICENSE && + head -n 30 src/application/peanut-gb/Peanut-GB/peanut_gb.h > license/peanut-gb.txt + wget -O license/2048-gb.txt https://raw.githubusercontent.com/Sanqui/2048-gb/master/LICENSE && + wget -O license/5-mazes.txt https://raw.githubusercontent.com/godai78/5-Mazes/main/LICENSE - name: Create artifact run: mkdir -p hhuOS-${{ steps.commit.outputs.short }} && cp -r hhuOS-limine.iso hhuOS-towboot.img hdd0.img floppy0.img run.sh README.md license hhuOS-${{ steps.commit.outputs.short }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a0d70c8ad..f7ca13709 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,9 @@ jobs: wget -O license/doomgeneric.txt https://raw.githubusercontent.com/hhuOS/doomgeneric/master/LICENSE && wget -O license/quakegeneric.txt https://raw.githubusercontent.com/hhuOS/quakegeneric/master/LICENSE && wget -O license/tinygl.txt https://raw.githubusercontent.com/C-Chads/tinygl/main/LICENSE + head -n 30 src/application/peanut-gb/Peanut-GB/peanut_gb.h > license/peanut-gb.txt + wget -O license/2048-gb.txt https://raw.githubusercontent.com/Sanqui/2048-gb/master/LICENSE && + wget -O license/5-mazes.txt https://raw.githubusercontent.com/godai78/5-Mazes/main/LICENSE - name: Create artifact run: mkdir -p hhuOS-${{ steps.commit.outputs.short }} && cp -r hhuOS-limine.iso hhuOS-towboot.img hdd0.img floppy0.img run.sh README.md license hhuOS-${{ steps.commit.outputs.short }} diff --git a/.gitignore b/.gitignore index f365b5229..f67410131 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ disk/hdd0/user/asciimation disk/hdd0/user/beep disk/hdd0/user/books disk/hdd0/user/doom +disk/hdd0/user/gameboy/ disk/hdd0/user/quake disk/hdd0/user/wav tools/nettest/nettest-server diff --git a/.gitmodules b/.gitmodules index 13fbafc89..b5e8a53c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,15 @@ [submodule "src/filesystem/fat/ff"] path = src/filesystem/fat/ff url = https://github.com/hhuos/fatfs -[submodule "src/application/doomgeneric"] - path = src/application/doomgeneric - url = https://github.com/hhuOS/doomgeneric.git -[submodule "src/application/quakegeneric"] - path = src/application/quakegeneric - url = https://github.com/hhuOS/quakegeneric [submodule "src/lib/tinygl"] path = src/lib/tinygl url = https://github.com/hhuOS/tinygl.git +[submodule "src/application/peanut-gb/Peanut-GB"] + path = src/application/peanut-gb/Peanut-GB + url = https://github.com/hhuOS/Peanut-GB.git +[submodule "src/application/quake/quakegeneric"] + path = src/application/quake/quakegeneric + url = https://github.com/hhuOS/quakegeneric +[submodule "src/application/doom/doomgeneric"] + path = src/application/doom/doomgeneric + url = https://github.com/hhuOS/doomgeneric diff --git a/README.md b/README.md index 365d05ccd..2de632fd3 100644 --- a/README.md +++ b/README.md @@ -115,5 +115,16 @@ Music for the SoundBlaster demo has been taken from [Bensound](https://www.benso Ported software: - Doom has been ported to hhuOS using [doomgeneric](https://github.com/ozkl/doomgeneric) by [*ozkl*](https://github.com/ozkl/) ([GPLv2](https://github.com/ozkl/doomgeneric/blob/master/LICENSE)) + - Available as `doom` command in hhuOS. + - Prebuilt versions of hhuOS on [GitHub Releases](https://github.com/hhuOS/hhuOS/releases) do not include a WAD file. If you want to play Doom, build hhuOS from source. The shareware WAD file will be downloaded automatically. - Quake has been ported to hhuOS using [quakegeneric](https://github.com/erysdren/quakegeneric) by [*erysdren*](https://github.com/erysdren/) ([GPLv2](https://github.com/erysdren/quakegeneric/blob/master/LICENSE)) -- [TinyGL](https://github.com/C-Chads/tinygl) by [*C-Chads*](https://github.com/C-Chads/) ([License](https://github.com/C-Chads/tinygl/blob/main/LICENSE)) \ No newline at end of file + - Available as `quake` command in hhuOS. + - Prebuilt versions of hhuOS on [GitHub Releases](https://github.com/hhuOS/hhuOS/releases) do not include a PAK file. If you want to play Quake, build hhuOS from source. The shareware PAK file will be downloaded automatically. +- [TinyGL](https://github.com/C-Chads/tinygl) by [*C-Chads*](https://github.com/C-Chads/) ([License](https://github.com/C-Chads/tinygl/blob/main/LICENSE)) + - Try out the `opengl` command in hhuOS for some demos. +- [Peanut-GB](https://github.com/deltabeard/Peanut-GB) by [*deltabeard*](https://github.com/deltabeard): + - Available as `peanut-gb` command in hhuOS. + - Arrow keys are mapped to WASD, A and B are mapped to K and J, Start is mapped to Space, Select is mapped to Enter. + - The following games are included in `/user/gameboy/`: + - [2048-gb](https://github.com/Sanqui/2048-gb) by [*Sanqui*](https://github.com/Sanqui) ([zlib](https://github.com/Sanqui/2048-gb/blob/master/LICENSE)) + - [5 Mazes](https://github.com/godai78/5-Mazes/) by [*godai78*](https://github.com/godai78) ([MIT](https://github.com/godai78/5-Mazes/blob/main/LICENSE)) \ No newline at end of file diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2343cd792..4cd0bab9e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -102,13 +102,13 @@ if (Python3_Interpreter_FOUND AND iwyu_tool_path AND iwyu_fix_includes_path) ProcessorCount(ncpus) add_custom_target(optimize_includes COMMAND "${Python3_EXECUTABLE}" "${iwyu_tool_path}" -j "${ncpus}" -p "${CMAKE_BINARY_DIR}" | - "${Python3_EXECUTABLE}" "${iwyu_fix_includes_path}" --nocomments --noupdate_comments --blank_lines --nosafe_headers --ignore_re "(.*/ff/source.*)|(.*/tinygl.*)|(.*/libc.*)|(.*/doomgeneric/doomgeneric.*)|(.*/quakegeneric/source.*)" -p "${HHUOS_SRC_DIR}" + "${Python3_EXECUTABLE}" "${iwyu_fix_includes_path}" --nocomments --noupdate_comments --blank_lines --nosafe_headers --ignore_re "(.*/ff/source.*)|(.*/tinygl.*)|(.*/libc.*)|(.*/doomgeneric/doomgeneric.*)|(.*/quakegeneric/source.*)|(.*/Peanut-GB.*)" -p "${HHUOS_SRC_DIR}" VERBATIM) endif() find_program(cloc_path NAMES cloc) if (cloc_path) - add_custom_target(cloc COMMAND "${cloc_path}" "${HHUOS_SRC_DIR}" --exclude-dir=ff,tinygl,doomgeneric,quakegeneric VERBATIM) + add_custom_target(cloc COMMAND "${cloc_path}" "${HHUOS_SRC_DIR}" --exclude-dir=ff,tinygl,doomgeneric,quakegeneric,Peanut-GB VERBATIM) endif() diff --git a/cmake/application/CMakeLists.txt b/cmake/application/CMakeLists.txt index 518b5028d..d7b93319e 100644 --- a/cmake/application/CMakeLists.txt +++ b/cmake/application/CMakeLists.txt @@ -52,6 +52,7 @@ add_subdirectory(mkdir) add_subdirectory(mount) add_subdirectory(nettest) add_subdirectory(opengl) +add_subdirectory(peanut-gb) add_subdirectory(ping) add_subdirectory(play) add_subdirectory(ps) diff --git a/cmake/application/ctest/CMakeLists.txt b/cmake/application/ctest/CMakeLists.txt index 3163f9b38..490415b1f 100644 --- a/cmake/application/ctest/CMakeLists.txt +++ b/cmake/application/ctest/CMakeLists.txt @@ -11,4 +11,4 @@ set(SOURCE_FILES add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} lib.user.libc lib.user.runtime lib.user.base) \ No newline at end of file +target_link_libraries(${PROJECT_NAME} lib.user.runtime lib.user.base lib.user.libc) \ No newline at end of file diff --git a/cmake/application/doomgeneric/CMakeLists.txt b/cmake/application/doomgeneric/CMakeLists.txt index 1202ab546..272ec5680 100644 --- a/cmake/application/doomgeneric/CMakeLists.txt +++ b/cmake/application/doomgeneric/CMakeLists.txt @@ -39,90 +39,90 @@ endif() # Set source files set(SOURCE_FILES - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/am_map.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_event.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_items.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_iwad.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_loop.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_main.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_mode.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/d_net.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/doomdef.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/doomgeneric.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/doomgeneric_hhuos.cpp - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/doomstat.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/dstrings.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/dummy.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/f_finale.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/f_wipe.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/g_game.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/gusconf.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/hu_lib.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/hu_stuff.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_cdmus.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/icon.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_endoom.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_input.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_joystick.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/info.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_scale.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_sound.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_system.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_timer.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/i_video.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_argv.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_bbox.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_cheat.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_config.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_controls.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/memio.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_fixed.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_menu.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_misc.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/m_random.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/mus2mid.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_ceilng.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_doors.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_enemy.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_floor.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_inter.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_lights.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_map.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_maputl.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_mobj.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_plats.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_pspr.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_saveg.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_setup.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_sight.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_spec.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_switch.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_telept.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_tick.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/p_user.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_bsp.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_data.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_draw.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_main.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_plane.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_segs.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_sky.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/r_things.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/sha1.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/sounds.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/s_sound.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/statdump.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/st_lib.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/st_stuff.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/tables.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/v_video.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/w_checksum.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/w_file.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/w_file_stdc.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/wi_stuff.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/w_main.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/w_wad.c - ${HHUOS_SRC_DIR}/application/doomgeneric/doomgeneric/z_zone.c) + ${HHUOS_SRC_DIR}/application/doom/doomgeneric_hhuos.cpp + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/am_map.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_event.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_items.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_iwad.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_loop.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_main.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_mode.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/d_net.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/doomdef.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/doomgeneric.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/doomstat.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/dstrings.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/dummy.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/f_finale.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/f_wipe.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/g_game.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/gusconf.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/hu_lib.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/hu_stuff.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_cdmus.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/icon.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_endoom.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_input.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_joystick.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/info.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_scale.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_sound.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_system.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_timer.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/i_video.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_argv.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_bbox.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_cheat.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_config.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_controls.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/memio.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_fixed.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_menu.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_misc.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/m_random.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/mus2mid.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_ceilng.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_doors.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_enemy.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_floor.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_inter.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_lights.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_map.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_maputl.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_mobj.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_plats.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_pspr.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_saveg.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_setup.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_sight.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_spec.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_switch.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_telept.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_tick.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/p_user.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_bsp.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_data.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_draw.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_main.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_plane.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_segs.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_sky.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/r_things.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/sha1.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/sounds.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/s_sound.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/statdump.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/st_lib.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/st_stuff.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/tables.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/v_video.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/w_checksum.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/w_file.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/w_file_stdc.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/wi_stuff.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/w_main.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/w_wad.c + ${HHUOS_SRC_DIR}/application/doom/doomgeneric/doomgeneric/z_zone.c) add_executable(doom ${SOURCE_FILES}) diff --git a/cmake/application/peanut-gb/CMakeLists.txt b/cmake/application/peanut-gb/CMakeLists.txt new file mode 100644 index 000000000..75120e129 --- /dev/null +++ b/cmake/application/peanut-gb/CMakeLists.txt @@ -0,0 +1,45 @@ +# Copyright (C) 2018-2024 Heinrich-Heine-Universitaet Duesseldorf, +# Institute of Computer Science, Department Operating Systems +# Burak Akguel, Christian Gesse, Fabian Ruhland, Filip Krakowski, Michael Schoettner +# +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see + +cmake_minimum_required(VERSION 3.14) + +project(peanut-gb) +message(STATUS "Project " ${PROJECT_NAME}) + +add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/gameboy" + COMMAND /bin/mkdir -p "${CMAKE_BINARY_DIR}/gameboy") + +add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/gameboy/2048.gb" + COMMAND wget "http://sanqui.rustedlogic.net/etc/2048.gb" -O "${CMAKE_BINARY_DIR}/gameboy/2048.gb" + DEPENDS "${CMAKE_BINARY_DIR}/gameboy") + +add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/gameboy/5-mazes.gb" + COMMAND wget "https://hh3.gbdev.io/static/database-gb/entries/5-mazes/5%20mazes.gb" -O "${CMAKE_BINARY_DIR}/gameboy/5-mazes.gb" + DEPENDS "${CMAKE_BINARY_DIR}/gameboy") + +add_custom_target(gameboy-roms DEPENDS + "${CMAKE_BINARY_DIR}/gameboy/2048.gb" + "${CMAKE_BINARY_DIR}/gameboy/5-mazes.gb") + +include_directories(${HHUOS_SRC_DIR}) + +# Set source files +set(SOURCE_FILES + ${HHUOS_SRC_DIR}/application/peanut-gb/peanut_gb.cpp) + +add_executable(${PROJECT_NAME} ${SOURCE_FILES}) + +target_link_libraries(${PROJECT_NAME} lib.user.runtime lib.user.base lib.user.libc) \ No newline at end of file diff --git a/cmake/application/quakegeneric/CMakeLists.txt b/cmake/application/quakegeneric/CMakeLists.txt index 4be17b660..b4a28ee02 100644 --- a/cmake/application/quakegeneric/CMakeLists.txt +++ b/cmake/application/quakegeneric/CMakeLists.txt @@ -38,75 +38,75 @@ include_directories(${HHUOS_SRC_DIR}) # Set source files set(SOURCE_FILES - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cd_null.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/chase.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cl_demo.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cl_input.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cl_main.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cl_parse.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cl_tent.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cmd.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/common.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/console.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/crc.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/cvar.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_edge.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_fill.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_init.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_modech.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_part.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_polyse.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/draw.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_scan.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_sky.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_sprite.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_surf.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_vars.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/d_zpoint.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/host.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/host_cmd.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/in_null.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/keys.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/mathlib.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/menu.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/model.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/net_loop.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/net_main.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/net_none.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/net_vcr.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/nonintel.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/pr_cmds.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/pr_edict.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/pr_exec.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/quakegeneric.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/quakegeneric_hhuos.cpp - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_aclip.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_alias.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_bsp.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_draw.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_edge.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_efrag.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_light.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_main.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_misc.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_part.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_sky.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_sprite.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_surf.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/r_vars.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sbar.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/screen.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/snd_null.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sv_main.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sv_move.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sv_phys.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sv_user.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/sys_null.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/vid_null.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/view.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/wad.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/world.c - ${HHUOS_SRC_DIR}/application/quakegeneric/source/zone.c) + ${HHUOS_SRC_DIR}/application/quake/quakegeneric_hhuos.cpp + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cd_null.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/chase.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cl_demo.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cl_input.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cl_main.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cl_parse.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cl_tent.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cmd.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/common.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/console.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/crc.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/cvar.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_edge.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_fill.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_init.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_modech.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_part.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_polyse.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/draw.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_scan.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_sky.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_sprite.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_surf.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_vars.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/d_zpoint.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/host.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/host_cmd.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/in_null.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/keys.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/mathlib.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/menu.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/model.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/net_loop.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/net_main.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/net_none.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/net_vcr.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/nonintel.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/pr_cmds.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/pr_edict.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/pr_exec.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/quakegeneric.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_aclip.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_alias.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_bsp.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_draw.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_edge.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_efrag.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_light.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_main.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_misc.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_part.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_sky.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_sprite.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_surf.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/r_vars.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sbar.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/screen.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/snd_null.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sv_main.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sv_move.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sv_phys.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sv_user.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/sys_null.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/vid_null.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/view.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/wad.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/world.c + ${HHUOS_SRC_DIR}/application/quake/quakegeneric/source/zone.c) add_executable(quake ${SOURCE_FILES}) diff --git a/cmake/application/shell/CMakeLists.txt b/cmake/application/shell/CMakeLists.txt index 6fea83abe..b28cc18fd 100644 --- a/cmake/application/shell/CMakeLists.txt +++ b/cmake/application/shell/CMakeLists.txt @@ -28,4 +28,4 @@ set(SOURCE_FILES add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} lib.user.libc lib.user.runtime lib.user.base lib.user.graphic) \ No newline at end of file +target_link_libraries(${PROJECT_NAME} lib.user.runtime lib.user.base lib.user.graphic lib.user.libc) \ No newline at end of file diff --git a/cmake/hdd0/CMakeLists.txt b/cmake/hdd0/CMakeLists.txt index 28a0ef284..909ccc107 100644 --- a/cmake/hdd0/CMakeLists.txt +++ b/cmake/hdd0/CMakeLists.txt @@ -50,6 +50,7 @@ add_custom_command(OUTPUT "${HHUOS_ROOT_DIR}/hdd0.img" COMMAND /bin/cp "$" "bin/mount" COMMAND /bin/cp "$" "bin/nettest" COMMAND /bin/cp "$" "bin/opengl" + COMMAND /bin/cp "$" "bin/peanut-gb" COMMAND /bin/cp "$" "bin/ping" COMMAND /bin/cp "$" "bin/play" COMMAND /bin/cp "$" "bin/ps" @@ -69,6 +70,7 @@ add_custom_command(OUTPUT "${HHUOS_ROOT_DIR}/hdd0.img" COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/beep" "user" COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/books" "user" COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/doom" "user" + COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/gameboy" "user" COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/quake" "user" COMMAND /bin/cp -r "${CMAKE_BINARY_DIR}/wav" "user" COMMAND /bin/rm -f "${CMAKE_BINARY_DIR}/part.img" @@ -78,6 +80,6 @@ add_custom_command(OUTPUT "${HHUOS_ROOT_DIR}/hdd0.img" COMMAND /bin/cat "${CMAKE_BINARY_DIR}/fill.img" "${CMAKE_BINARY_DIR}/part.img" "${CMAKE_BINARY_DIR}/fill.img" > "${HHUOS_ROOT_DIR}/hdd0.img" COMMAND /bin/rm "${CMAKE_BINARY_DIR}/part.img" "${CMAKE_BINARY_DIR}/fill.img" COMMAND /bin/echo -e "'o\\nn\\np\\n1\\n2048\\n$,196607,131071>\\nt\\ne\\nw\\n'" | fdisk "${HHUOS_ROOT_DIR}/hdd0.img" - DEPENDS asciimation-star-wars books-gutenberg doom-wad quake-pak music shell asciimate battlespace beep bug cat cp ctest date demo dino doom echo head hexdump ip keyboard kill ls membench mkdir mount nettest opengl ping play ps pwd quake rm rmdir shutdown smbios touch tree uecho unmount uptime view3d doom-wad) + DEPENDS asciimation-star-wars books-gutenberg doom-wad gameboy-roms music quake-pak shell asciimate battlespace beep bug cat cp ctest date demo dino doom echo head hexdump ip keyboard kill ls membench mkdir mount nettest opengl peanut-gb ping play ps pwd quake rm rmdir shutdown smbios touch tree uecho unmount uptime view3d doom-wad) -add_custom_target(${PROJECT_NAME} DEPENDS asciimation-star-wars books-gutenberg doom-wad music quake-pak shell asciimate battlespace beep bug cat cp ctest date demo dino doom echo head hexdump ip keyboard kill ls membench mkdir mount nettest opengl ping play ps pwd quake rm rmdir shutdown smbios touch tree uecho unmount uptime view3d "${HHUOS_ROOT_DIR}/hdd0.img") +add_custom_target(${PROJECT_NAME} DEPENDS asciimation-star-wars books-gutenberg doom-wad gameboy-roms music quake-pak shell asciimate battlespace beep bug cat cp ctest date demo dino doom echo head hexdump ip keyboard kill ls membench mkdir mount nettest opengl peanut-gb ping play ps pwd quake rm rmdir shutdown smbios touch tree uecho unmount uptime view3d "${HHUOS_ROOT_DIR}/hdd0.img") diff --git a/cmake/lib/runtime/CMakeLists.txt b/cmake/lib/runtime/CMakeLists.txt index 7dd47696d..4835ed2c6 100644 --- a/cmake/lib/runtime/CMakeLists.txt +++ b/cmake/lib/runtime/CMakeLists.txt @@ -23,7 +23,7 @@ include_directories(${HHUOS_SRC_DIR}) add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} lib.user.libc lib.graphic) +target_link_libraries(${PROJECT_NAME} lib.graphic lib.user.libc) target_sources(${PROJECT_NAME} PUBLIC ${HHUOS_SRC_DIR}/lib/runtime/runtime.asm diff --git a/src/application/battlespace/battlespace.cpp b/src/application/battlespace/battlespace.cpp index 4ff057026..d4fa989a7 100644 --- a/src/application/battlespace/battlespace.cpp +++ b/src/application/battlespace/battlespace.cpp @@ -37,7 +37,7 @@ int32_t main(int32_t argc, char *argv[]) { argumentParser.setHelpText("Battlespace.\nFly around and shoot enemies.\nTurn using ARROW KEYS or the MOUSE. Fire using SPACEBAR.\nStrafe using WASD. Change speed using Q and E.\n\n" "Usage: battlespace\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/bug/bug.cpp b/src/application/bug/bug.cpp index 65f12537d..a91afe976 100644 --- a/src/application/bug/bug.cpp +++ b/src/application/bug/bug.cpp @@ -34,7 +34,7 @@ int32_t main(int32_t argc, char *argv[]) { argumentParser.setHelpText("EnemyBug Defender - A space invaders clone.\n" "Usage: bug\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/demo/demo.cpp b/src/application/demo/demo.cpp index 17c92d426..10e851d0d 100644 --- a/src/application/demo/demo.cpp +++ b/src/application/demo/demo.cpp @@ -41,7 +41,7 @@ int32_t main(int32_t argc, char *argv[]) { "Usage: demo [DEMO] [OPTIONS]...\n" "Demos: ant, color, fonts, mouse, polygons, sprites\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/demo/mouse/mouse.cpp b/src/application/demo/mouse/mouse.cpp index 69eeebf5d..72a09738c 100644 --- a/src/application/demo/mouse/mouse.cpp +++ b/src/application/demo/mouse/mouse.cpp @@ -34,7 +34,7 @@ int32_t main(int32_t argc, char *argv[]) { argumentParser.setHelpText("Test application for the mouse.\n" "Usage: mouse\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/dino/dino.cpp b/src/application/dino/dino.cpp index 263b80c75..45458a5d9 100644 --- a/src/application/dino/dino.cpp +++ b/src/application/dino/dino.cpp @@ -37,7 +37,7 @@ int32_t main(int32_t argc, char *argv[]) { argumentParser.setHelpText("Endless runner game.\n" "Usage: dino\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/doom/doomgeneric b/src/application/doom/doomgeneric new file mode 160000 index 000000000..848d3fb82 --- /dev/null +++ b/src/application/doom/doomgeneric @@ -0,0 +1 @@ +Subproject commit 848d3fb821982e36a1297b0323289d618aae3088 diff --git a/src/application/doom/doomgeneric_hhuos.cpp b/src/application/doom/doomgeneric_hhuos.cpp new file mode 100644 index 000000000..da4e52620 --- /dev/null +++ b/src/application/doom/doomgeneric_hhuos.cpp @@ -0,0 +1,447 @@ +#include +#include +#include +#include +#include + +#include "doomgeneric/doomgeneric/doomgeneric.h" +#include "doomgeneric/doomgeneric/doomkeys.h" +#include "doomgeneric/doomgeneric/doomtype.h" +#include "doomgeneric/doomgeneric/i_sound.h" + +#include "lib/util/graphic/Ansi.h" +#include "lib/util/graphic/LinearFrameBuffer.h" +#include "lib/util/io/file/File.h" +#include "lib/util/base/Address.h" +#include "lib/util/async/Thread.h" +#include "lib/util/time/Timestamp.h" +#include "lib/util/io/key/KeyDecoder.h" +#include "lib/util/io/key/layout/DeLayout.h" +#include "lib/util/sound/PcSpeaker.h" +#include "lib/util/graphic/BufferedLinearFrameBuffer.h" + +Util::Graphic::LinearFrameBuffer *lfb; +Util::Graphic::BufferedLinearFrameBuffer *bufferedlfb; +Util::Io::KeyDecoder *kd; + +uint32_t scaleFactor = 1; +uint32_t offsetX = 0; +uint32_t offsetY = 0; + +int32_t main(int argc, char **argv) { + if (!Util::Io::File::changeDirectory("/user/doom")) { + Util::System::error << "doomgeneric: '/user/doom' not found!" << Util::Io::PrintStream::endl << Util::Io::PrintStream::flush; + return -1; + } + + doomgeneric_Create(argc, argv); + + // Prepare graphics + Util::Graphic::Ansi::prepareGraphicalApplication(true); + auto lfbFile = new Util::Io::File("/device/lfb"); + + // If '-res is given, try to change display resolution + for (int32_t i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-res") && i < argc - 1) { + auto resSplit = Util::String(argv[i + 1]).split("x"); + uint32_t x = Util::String::parseInt(resSplit[0]); + uint32_t y = Util::String::parseInt(resSplit[1]); + lfbFile->controlFile(Util::Graphic::LinearFrameBuffer::SET_RESOLUTION, Util::Array({x, y, 32})); + + break; + } + } + + // Use double buffering to avoid tearing + lfb = new Util::Graphic::LinearFrameBuffer(*lfbFile); + bufferedlfb = new Util::Graphic::BufferedLinearFrameBuffer(*lfb); + + // Calculate scale factor to display the game as large as possible + scaleFactor = lfb->getResolutionX() / DOOMGENERIC_RESX; + if (lfb->getResolutionY() / DOOMGENERIC_RESY < scaleFactor) { + scaleFactor = lfb->getResolutionY() / DOOMGENERIC_RESY; + } + if (scaleFactor == 0) { + scaleFactor = 1; + } + + // Calculate offset to center the game + offsetX = lfb->getResolutionX() - DOOMGENERIC_RESX * scaleFactor > 0 ? (lfb->getResolutionX() - DOOMGENERIC_RESX * scaleFactor) / 2 : 0; + offsetY = lfb->getResolutionY() - DOOMGENERIC_RESY * scaleFactor > 0 ? (lfb->getResolutionY() - DOOMGENERIC_RESY * scaleFactor) / 2 : 0; + + // Run game loop + auto oldTime = clock(); + while (true) { + auto newTime = clock(); + if (oldTime == newTime) { + Util::Async::Thread::yield(); + } else { + doomgeneric_Tick(); + oldTime = newTime; + } + } +} + +void DG_Init() { + kd = new Util::Io::KeyDecoder(new Util::Io::DeLayout()); +} + +void DG_DrawFrame() { + if (bufferedlfb == nullptr) { + return; + } + + auto screenBuffer = reinterpret_cast(bufferedlfb->getBuffer().add(offsetX * 4 + offsetY * bufferedlfb->getPitch()).get()); + auto resX = DOOMGENERIC_RESX * scaleFactor > bufferedlfb->getResolutionX() ? bufferedlfb->getResolutionX() : DOOMGENERIC_RESX * scaleFactor; + auto resY = DOOMGENERIC_RESY * scaleFactor > bufferedlfb->getResolutionY() ? bufferedlfb->getResolutionY() : DOOMGENERIC_RESY * scaleFactor; + + for (uint32_t y = 0; y < resY; y++) { + for (uint32_t x = 0; x < resX; x++) { + screenBuffer[x] = DG_ScreenBuffer[(y / scaleFactor) * DOOMGENERIC_RESX + (x / scaleFactor)]; + } + + screenBuffer += (bufferedlfb->getPitch() / sizeof(uint32_t)); + } + + bufferedlfb->flush(); +} + +void DG_SleepMs(uint32_t ms) { + Util::Async::Thread::sleep(Util::Time::Timestamp::ofMilliseconds(ms)); +} + +uint32_t DG_GetTicksMs() { + return clock(); +} + +int DG_GetKey(int * pressed, unsigned char * key) { + if (!stdin->isReadyToRead()) { + return 0; + } else { + uint8_t scancode = fgetc(stdin); + + if ((scancode & ~0x80) == 0x1d) { + *pressed = !(scancode & 0x80); + *key = KEY_FIRE; + return 1; + } + if ((scancode & ~0x80) == 0x38) { + *pressed = !(scancode & 0x80); + *key = KEY_LALT; + return 1; + } + + + if (kd->parseScancode(scancode)) { + auto k = kd->getCurrentKey(); + if (!k.isValid()) { + return 0; + } + + *pressed = k.isPressed() ? 1:0; + + if (k.getScancode() >= 0x3b && k.getScancode() <= 0x44) { // handle F1-10 + *key = k.getScancode() + 0x80; + return 1; + } + + switch(k.getScancode()) { + case Util::Io::Key::UP: + *key = KEY_UPARROW; + return 1; + case Util::Io::Key::DOWN: + *key = KEY_DOWNARROW; + return 1; + case Util::Io::Key::LEFT: + *key = KEY_LEFTARROW; + return 1; + case Util::Io::Key::RIGHT: + *key = KEY_RIGHTARROW; + return 1; + case Util::Io::Key::SPACE: + *key = KEY_USE; + return 1; + case Util::Io::Key::ESC: + *key = KEY_ESCAPE; + return 1; + case Util::Io::Key::ENTER: + *key = KEY_ENTER; + return 1; + case Util::Io::Key::TAB: + *key = KEY_TAB; + return 1; + case Util::Io::Key::BACKSPACE: + *key = KEY_BACKSPACE; + return 1; + case Util::Io::Key::HOME: + *key = KEY_HOME; + return 1; + case Util::Io::Key::END: + *key = KEY_END; + return 1; + case Util::Io::Key::INSERT: + *key = KEY_INS; + return 1; + case Util::Io::Key::DEL: + *key = KEY_DEL; + return 1; + case Util::Io::Key::PAGE_UP: + *key = KEY_PGUP; + return 1; + case Util::Io::Key::PAGE_DOWN: + *key = KEY_PGDN; + return 1; + case Util::Io::Key::F1: + *key = KEY_F1; + return 1; + case Util::Io::Key::F2: + *key = KEY_F2; + return 1; + case Util::Io::Key::F3: + *key = KEY_F3; + return 1; + case Util::Io::Key::F4: + *key = KEY_F4; + return 1; + case Util::Io::Key::F5: + *key = KEY_F5; + return 1; + case Util::Io::Key::F6: + *key = KEY_F6; + return 1; + case Util::Io::Key::F7: + *key = KEY_F7; + return 1; + case Util::Io::Key::F8: + *key = KEY_F8; + return 1; + case Util::Io::Key::F9: + *key = KEY_F9; + return 1; + case Util::Io::Key::F10: + *key = KEY_F10; + return 1; + case Util::Io::Key::F11: + *key = KEY_F11; + return 1; + case Util::Io::Key::F12: + *key = KEY_F12; + return 1; + default: + if (k.getAscii()) { + *key = tolower(k.getAscii()); + return 1; + } + + return 0; + } + } + + } + return 0; +} + +void DG_SetWindowTitle(const char * title) {} + +Util::Sound::PcSpeaker *speaker; + +bool I_SDL_InitMusic() { + speaker = new Util::Sound::PcSpeaker(Util::Io::File("/device/speaker")); + return true; +} + +void I_SDL_ShutdownMusic() { + speaker->turnOff(); + delete speaker; +} + +void I_SDL_SetMusicVolume(int volume) {} + +struct MUSheader { + char ID[4]; + uint16_t scoreLen; + uint16_t scoreStart; + uint16_t channels; + uint16_t sec_channels; + uint16_t instrCnt; + uint16_t dummy; +}; + +struct Song { + uint8_t * musicData; + uint8_t * musicDataEnd; + uint8_t * currentPoint; +}; + +void * I_SDL_RegisterSong(void * data, int len) { + MUSheader * header = (MUSheader *) data; + uint8_t * scoreStart = (uint8_t*)data + header->scoreStart; + + Song * newSong = new Song(); + newSong->musicData = new uint8_t[header->scoreLen]; + newSong->musicDataEnd = newSong->musicData + header->scoreLen; + memcpy(newSong->musicData, scoreStart, header->scoreLen); + + newSong->currentPoint = newSong->musicData ; + return (void*)newSong; +} + +void I_SDL_UnRegisterSong(void* handle) { + Song * song = (Song*)handle; + delete [] song->musicData; + delete song; +} + + +bool playing = false; +bool loop = false; +Song * current; + +void I_SDL_PauseSong() { + playing = false; +} + +void I_SDL_ResumeSong() { + playing = true; +} + +int channelVolumes[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +clock_t waitClock = 0; + +int channelPlaying = -1; +int notePlaying = -1; +int noteVolume = -1; + +void I_SDL_PlaySong(void * handle, bool looping) { + current = (Song*) handle; + if ((current->musicDataEnd - current->musicData) != 17237) { + speaker->turnOff(); + return; //only play Hangar 1 music + } + + current->currentPoint = current->musicData; + playing = true; + loop = looping; + + for (int i = 0; i < 16; i++)channelVolumes[i] = -1; + + channelPlaying = -1; + notePlaying = -1; + noteVolume = -1; +} + +void I_SDL_StopSong() { + playing = false; + current->currentPoint = current->musicData; +} + +bool I_SDL_MusicIsPlaying() { + return playing; +} + +int32_t eigthOctaveFreqs[12] = { 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7458 }; + +int freqFromNoteNum(int noteNum) { + return eigthOctaveFreqs[noteNum % 12] * pow(0.5, 8 - (noteNum / 12)); +} + +int focalNote = 60; + +void I_SDL_PollMusic() { // MUS file parsing + if (playing && clock() >= waitClock) { + bool last = false; + while (!last) { + uint8_t eventDesc = *(current->currentPoint++); + last = eventDesc & 0x80; + int32_t channelNum = eventDesc & 0b1111; + int32_t eventType = (eventDesc>>4) & 0b111; + uint8_t data, vol; + vol = channelVolumes[channelNum]; + + switch (eventType) { + case 0: // release + data = *(current->currentPoint++); + if (channelPlaying == channelNum && data == notePlaying) { + speaker->turnOff(); + notePlaying = -1; + channelPlaying = -1; + noteVolume = -1; + } + + break; + case 1: // play + data = *(current->currentPoint++); + if (data & 0x80) vol = *(current->currentPoint++); //volume info; + data &= ~0x80; + if (channelNum == 15) break; //percussion channel + if (notePlaying == -1 || (abs(focalNote-data) < abs(focalNote - notePlaying) && data > 30)) { + channelPlaying = channelNum; + notePlaying = data; + noteVolume = vol; + speaker->play(freqFromNoteNum(data)); + } + + break; + case 2: // pitch bend - ignore + current->currentPoint++; + break; + case 3: // event + data = *(current->currentPoint++); + if (data == 10 || data == 11 || data == 14) { + speaker->turnOff(); + } + + break; + case 4: // change controller - ignored + data = *(current->currentPoint++); + vol = *(current->currentPoint++); + if (data == 3) { + channelVolumes[channelNum] = vol; + } + + break; + case 5: + break; + case 6: + I_SDL_StopSong(); + if (loop) { + I_SDL_PlaySong((void*)current, loop); + } + + return; + case 7: + break; + } + } + + int time = 0; + uint8_t byte; + do { + byte = *(current->currentPoint++); + time = time * 128 + (byte & 127); + } while (byte & 128); + + waitClock = clock() + time * 1000 / 180; // should be 140, accelerated cause VM + } +} + +static snddevice_t music_sdl_devices[] = { + SNDDEVICE_PCSPEAKER +}; + +music_module_t DG_music_module = { + music_sdl_devices, + arrlen(music_sdl_devices), + I_SDL_InitMusic, + I_SDL_ShutdownMusic, + I_SDL_SetMusicVolume, + I_SDL_PauseSong, + I_SDL_ResumeSong, + I_SDL_RegisterSong, + I_SDL_UnRegisterSong, + I_SDL_PlaySong, + I_SDL_StopSong, + I_SDL_MusicIsPlaying, + I_SDL_PollMusic, +}; \ No newline at end of file diff --git a/src/application/doomgeneric b/src/application/doomgeneric deleted file mode 160000 index 3a7c49e28..000000000 --- a/src/application/doomgeneric +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3a7c49e282c41bda4e10438d9d83fd6eab288170 diff --git a/src/application/opengl/opengl.cpp b/src/application/opengl/opengl.cpp index 88be39576..7e5f1fa1c 100644 --- a/src/application/opengl/opengl.cpp +++ b/src/application/opengl/opengl.cpp @@ -40,7 +40,7 @@ int32_t main(int32_t argc, char *argv[]) { "Usage: opengl \n" "Demos: info, triangle, gears\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/application/peanut-gb/Peanut-GB b/src/application/peanut-gb/Peanut-GB new file mode 160000 index 000000000..4596d56dd --- /dev/null +++ b/src/application/peanut-gb/Peanut-GB @@ -0,0 +1 @@ +Subproject commit 4596d56ddb85a1aa45b1197c77f05e236a23bd94 diff --git a/src/application/peanut-gb/peanut_gb.cpp b/src/application/peanut-gb/peanut_gb.cpp new file mode 100644 index 000000000..647229f5e --- /dev/null +++ b/src/application/peanut-gb/peanut_gb.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2018-2024 Heinrich-Heine-Universitaet Duesseldorf, + * Institute of Computer Science, Department Operating Systems + * Burak Akguel, Christian Gesse, Fabian Ruhland, Filip Krakowski, Michael Schoettner + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#include "Peanut-GB/peanut_gb.h" +#include "lib/util/base/Exception.h" +#include "stdio.h" +#include "lib/util/base/Address.h" +#include "lib/util/base/ArgumentParser.h" +#include "lib/util/base/System.h" +#include "lib/util/io/file/File.h" +#include "lib/util/io/stream/FileInputStream.h" +#include "lib/util/graphic/LinearFrameBuffer.h" +#include "lib/util/graphic/PixelDrawer.h" +#include "lib/util/graphic/Colors.h" +#include "lib/util/graphic/Ansi.h" +#include "lib/util/time/Timestamp.h" +#include "lib/util/async/Thread.h" +#include "lib/util/io/key/KeyDecoder.h" +#include "lib/util/io/key/layout/DeLayout.h" +#include "lib/util/graphic/BufferedLinearFrameBuffer.h" +#include "lib/util/graphic/StringDrawer.h" +#include "lib/util/graphic/font/Terminal8x8.h" + +const constexpr uint32_t TARGET_FRAME_RATE = 60; +const auto targetFrameTime = Util::Time::Timestamp::ofMicroseconds(static_cast(1000000.0 / TARGET_FRAME_RATE)); + +auto palette = new uint32_t[4] { + Util::Graphic::Color(155, 188, 15).getRGB32(), + Util::Graphic::Color(139, 172, 15).getRGB32(), + Util::Graphic::Color(48, 98, 48).getRGB32(), + Util::Graphic::Color(15, 56, 15).getRGB32() +}; + +uint8_t *rom = nullptr; +uint8_t *ram = nullptr; +uint8_t scale = 1; +uint8_t maxScale = 1; +uint16_t offsetX = 0; +uint16_t offsetY = 0; +Util::Graphic::LinearFrameBuffer *lfb = nullptr; + +Util::Time::Timestamp fpsTimer; +uint32_t fpsCounter = 0; +uint32_t fps = 0; + +uint8_t gb_rom_read(struct gb_s* gb, const uint_fast32_t addr) { + return rom[addr]; +} + +uint8_t gb_cart_ram_read(struct gb_s* gb, const uint_fast32_t addr) { + return ram[addr]; +} + +void gb_cart_ram_write(struct gb_s* gb, const uint_fast32_t addr, const uint8_t val) { + ram[addr] = val; +} + +void gb_error(struct gb_s* gb, const enum gb_error_e error, const uint16_t addr) { + switch (error) { + case GB_UNKNOWN_ERROR: + printf("Unknown error at address 0x%04X\n", addr); + break; + case GB_INVALID_OPCODE: + printf("Invalid opcode at address 0x%04X\n", addr); + break; + case GB_INVALID_READ: + printf("Invalid read at address 0x%04X\n", addr); + break; + case GB_INVALID_WRITE: + printf("Invalid write at address 0x%04X\n", addr); + break; + case GB_HALT_FOREVER: + printf("Halting forever at address 0x%04X\n", addr); + break; + case GB_INVALID_MAX: + printf("Invalid max at address 0x%04X\n", addr); + break; + } + + exit(error); +} + +void lcd_draw_line(struct gb_s *gb, const uint8_t *pixels, const uint_fast8_t line) { + auto screenBuffer = reinterpret_cast(lfb->getBuffer().add(offsetX * 4 + (offsetY + line * scale) * lfb->getPitch()).get()); + uint32_t resX = LCD_WIDTH * scale; + + for (uint32_t y = 0; y < scale; y++) { + for (uint32_t x = 0; x < resX; x++) { + uint8_t pixel = pixels[x / scale]; + auto color = palette[pixel & 0x03]; + screenBuffer[x] = color; + } + + screenBuffer += (lfb->getPitch() / sizeof(uint32_t)); + } +} + +int32_t main(int32_t argc, char *argv[]) { + auto argumentParser = Util::ArgumentParser(); + argumentParser.setHelpText("GameBoy emulator by 'deltabeard' (https://github.com/deltabeard/Peanut-GB).\n" + "Arrow keys are mapped to WASD, A and B are mapped to K and J, Start is mapped to Space, Select is mapped to Enter. Use '+' and '-' to adjust screen scaling.\n" + "Usage: peanut-gb [FILE]...\n" + "Options:\n" + " -r, --resolution: Set display resolution\n" + " -h, --help: Show this help message"); + + argumentParser.addArgument("resolution", false, "r"); + + if (!argumentParser.parse(argc, argv)) { + Util::System::error << argumentParser.getErrorString() << Util::Io::PrintStream::endl << Util::Io::PrintStream::flush; + return -1; + } + + auto arguments = argumentParser.getUnnamedArguments(); + if (arguments.length() == 0) { + Util::System::error << "peanut-gb: No arguments provided!" << Util::Io::PrintStream::endl << Util::Io::PrintStream::flush; + return -1; + } + + auto file = Util::Io::File(arguments[0]); + auto stream = Util::Io::FileInputStream(file); + + rom = new uint8_t[file.getLength()]; + stream.read(rom, 0, file.getLength()); + + auto lfbFile = Util::Io::File("/device/lfb"); + + if (argumentParser.hasArgument("resolution")) { + auto split1 = argumentParser.getArgument("resolution").split("x"); + auto split2 = split1[1].split("@"); + + uint32_t resolutionX = Util::String::parseInt(split1[0]); + uint32_t resolutionY = Util::String::parseInt(split2[0]); + uint32_t colorDepth = split2.length() > 1 ? Util::String::parseInt(split2[1]) : 32; + + lfbFile.controlFile(Util::Graphic::LinearFrameBuffer::SET_RESOLUTION, Util::Array({resolutionX, resolutionY, colorDepth})); + } + + lfb = new Util::Graphic::LinearFrameBuffer(lfbFile); + maxScale = lfb->getResolutionX() / LCD_WIDTH > lfb->getResolutionY() / LCD_HEIGHT ? lfb->getResolutionY() / LCD_HEIGHT : lfb->getResolutionX() / LCD_WIDTH; + scale = maxScale; + offsetX = lfb->getResolutionX() - LCD_WIDTH * scale > 0 ? (lfb->getResolutionX() - LCD_WIDTH * scale) / 2 : 0; + offsetY = lfb->getResolutionY() - LCD_HEIGHT * scale > 0 ? (lfb->getResolutionY() - LCD_HEIGHT * scale) / 2 : 0; + + gb_s gb{}; + + auto initResult = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read, &gb_cart_ram_write, &gb_error, nullptr); + if (initResult != GB_INIT_NO_ERROR) { + Util::System::error << "peanut-gb: Failed to initialize emulator!" << Util::Io::PrintStream::endl << Util::Io::PrintStream::flush; + return -1; + } + + ram = new uint8_t[gb_get_save_size(&gb)]; + + Util::Graphic::Ansi::prepareGraphicalApplication(true); + gb_init_lcd(&gb, &lcd_draw_line); + + lfb->clear(); + + Util::Io::File::setAccessMode(Util::Io::STANDARD_INPUT, Util::Io::File::NON_BLOCKING); + auto keyDecoder = Util::Io::KeyDecoder(new Util::Io::DeLayout()); + auto stringDrawer = Util::Graphic::StringDrawer(Util::Graphic::PixelDrawer(*lfb)); + + while (true) { + auto startTime = Util::Time::getSystemTime(); + + auto c = Util::System::in.read(); + if (c != -1 && keyDecoder.parseScancode(c)) { + auto key = keyDecoder.getCurrentKey(); + uint8_t joyKey = 0; + + switch (key.getScancode()) { + case Util::Io::Key::UP: + joyKey = JOYPAD_UP; + break; + case Util::Io::Key::LEFT: + joyKey = JOYPAD_LEFT; + break; + case Util::Io::Key::DOWN: + joyKey = JOYPAD_DOWN; + break; + case Util::Io::Key::RIGHT: + joyKey = JOYPAD_RIGHT; + break; + case Util::Io::Key::K: + joyKey = JOYPAD_A; + break; + case Util::Io::Key::J: + joyKey = JOYPAD_B; + break; + case Util::Io::Key::SPACE: + joyKey = JOYPAD_START; + break; + case Util::Io::Key::ENTER: + joyKey = JOYPAD_SELECT; + break; + case Util::Io::Key::PLUS: + if (key.isPressed() && scale < maxScale) { + scale++; + offsetX = lfb->getResolutionX() - LCD_WIDTH * scale > 0 ? (lfb->getResolutionX() - LCD_WIDTH * scale) / 2 : 0; + offsetY = lfb->getResolutionY() - LCD_HEIGHT * scale > 0 ? (lfb->getResolutionY() - LCD_HEIGHT * scale) / 2 : 0; + lfb->clear(); + } + break; + case Util::Io::Key::MINUS: + if (key.isPressed() && scale > 1) { + scale--; + offsetX = lfb->getResolutionX() - LCD_WIDTH * scale > 0 ? (lfb->getResolutionX() - LCD_WIDTH * scale) / 2 : 0; + offsetY = lfb->getResolutionY() - LCD_HEIGHT * scale > 0 ? (lfb->getResolutionY() - LCD_HEIGHT * scale) / 2 : 0; + lfb->clear(); + } + break; + case Util::Io::Key::ESC: + return 0; + default: + break; + } + + if (key.isPressed()) { + gb.direct.joypad &= ~joyKey; + } else { + gb.direct.joypad |= joyKey; + } + } + + gb_run_frame(&gb); + stringDrawer.drawString(Util::Graphic::Fonts::TERMINAL_8x8, 0, 0, static_cast(Util::String::format("FPS: %u", fps)), Util::Graphic::Colors::WHITE, Util::Graphic::Colors::BLACK); + + auto renderTime = Util::Time::getSystemTime() - startTime; + if (renderTime < targetFrameTime) { + Util::Async::Thread::sleep(targetFrameTime - renderTime); + } + + fpsCounter++; + auto frameTime = Util::Time::getSystemTime() - startTime; + fpsTimer += frameTime; + + if (fpsTimer >= Util::Time::Timestamp::ofSeconds(1)) { + fps = fpsCounter; + fpsCounter = 0; + fpsTimer.reset(); + } + } +} \ No newline at end of file diff --git a/src/application/quake/quakegeneric b/src/application/quake/quakegeneric new file mode 160000 index 000000000..55f48dd59 --- /dev/null +++ b/src/application/quake/quakegeneric @@ -0,0 +1 @@ +Subproject commit 55f48dd598edde6561f29af72082e8ed8a66f12c diff --git a/src/application/quake/quakegeneric_hhuos.cpp b/src/application/quake/quakegeneric_hhuos.cpp new file mode 100644 index 000000000..ed948f9b6 --- /dev/null +++ b/src/application/quake/quakegeneric_hhuos.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2018-2024 Heinrich-Heine-Universitaet Duesseldorf, + * Institute of Computer Science, Department Operating Systems + * Burak Akguel, Christian Gesse, Fabian Ruhland, Filip Krakowski, Michael Schoettner + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#include +#include +#include +#include +#include + +#include "quakegeneric/source/quakegeneric.h" + +#include "lib/util/base/Address.h" +#include "lib/util/graphic/Ansi.h" +#include "lib/util/io/file/File.h" +#include "lib/util/graphic/LinearFrameBuffer.h" +#include "lib/util/io/key/KeyDecoder.h" +#include "lib/util/io/key/layout/DeLayout.h" +#include "lib/util/game/Engine.h" + +uint8_t palette[768]; +Util::Graphic::LinearFrameBuffer *lfb; +Util::Graphic::BufferedLinearFrameBuffer *bufferedlfb; +Util::Io::KeyDecoder *kd; + +uint32_t scaleFactor = 1; +uint32_t offsetX = 0; +uint32_t offsetY = 0; + +int32_t main(int argc, char *argv[]) { + if (!Util::Io::File::changeDirectory("/user/quake")) { + Util::System::error << "quake: '/user/quake' not found!" << Util::Io::PrintStream::endl << Util::Io::PrintStream::flush; + return -1; + } + + QG_Create(argc, argv); + + // Prepare graphics + Util::Graphic::Ansi::prepareGraphicalApplication(true); + auto lfbFile = new Util::Io::File("/device/lfb"); + + // If '-res is given, try to change display resolution + for (int32_t i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-res") && i < argc - 1) { + auto resSplit = Util::String(argv[i + 1]).split("x"); + uint32_t x = Util::String::parseInt(resSplit[0]); + uint32_t y = Util::String::parseInt(resSplit[1]); + lfbFile->controlFile(Util::Graphic::LinearFrameBuffer::SET_RESOLUTION, Util::Array({x, y, 32})); + + break; + } + } + + // Use double buffering to avoid tearing + lfb = new Util::Graphic::LinearFrameBuffer(*lfbFile); + bufferedlfb = new Util::Graphic::BufferedLinearFrameBuffer(*lfb); + + // Calculate scale factor the game as large as possible + scaleFactor = lfb->getResolutionX() / QUAKEGENERIC_RES_X; + if (lfb->getResolutionY() / QUAKEGENERIC_RES_Y < scaleFactor) { + scaleFactor = lfb->getResolutionY() / QUAKEGENERIC_RES_Y; + } + if (scaleFactor == 0) { + scaleFactor = 1; + } + + // Calculate offset to center the game + offsetX = lfb->getResolutionX() - QUAKEGENERIC_RES_X * scaleFactor > 0 ? (lfb->getResolutionX() - QUAKEGENERIC_RES_X * scaleFactor) / 2 : 0; + offsetY = lfb->getResolutionY() - QUAKEGENERIC_RES_Y * scaleFactor > 0 ? (lfb->getResolutionY() - QUAKEGENERIC_RES_Y * scaleFactor) / 2 : 0; + + // Run game loop + auto oldTime = clock(); + while (true) { + auto newTime = clock(); + if (oldTime == newTime) { + Util::Async::Thread::yield(); + } else { + QG_Tick((newTime - oldTime) / static_cast(CLOCKS_PER_SEC)); + oldTime = newTime; + } + } +} + +void QG_Init(void) { + kd = new Util::Io::KeyDecoder(new Util::Io::DeLayout()); +} + +void QG_SetPalette(uint8_t source[768]) { + memcpy(palette, source, 768); +} + +void QG_DrawFrame(void *pixels) { + if (bufferedlfb == nullptr) { + return; + } + + auto screenBuffer = reinterpret_cast(bufferedlfb->getBuffer().add(offsetX * 4 + offsetY * bufferedlfb->getPitch()).get()); + auto resX = QUAKEGENERIC_RES_X * scaleFactor > bufferedlfb->getResolutionX() ? bufferedlfb->getResolutionX() : QUAKEGENERIC_RES_X * scaleFactor; + auto resY = QUAKEGENERIC_RES_Y * scaleFactor > bufferedlfb->getResolutionY() ? bufferedlfb->getResolutionY() : QUAKEGENERIC_RES_Y * scaleFactor; + + for (uint32_t y = 0; y < resY; y++) { + for (uint32_t x = 0; x < resX; x++) { + uint8_t pixel = reinterpret_cast(pixels)[(y / scaleFactor) * QUAKEGENERIC_RES_X + (x / scaleFactor)]; + uint8_t *paletteEntry = &((uint8_t*) palette)[pixel * 3]; + screenBuffer[x] = (*(paletteEntry) << 16) + (*(paletteEntry + 1) << 8) + *(paletteEntry + 2); + } + + screenBuffer += (bufferedlfb->getPitch() / sizeof(uint32_t)); + } + + bufferedlfb->flush(); +} + +int QG_GetKey(int *down, int *key) { + if (!stdin->isReadyToRead() || kd == nullptr) { + return 0; + } else { + uint8_t scancode = fgetc(stdin); + + if ((scancode & ~0x80) == 0x1d) { + *down = !(scancode & 0x80); + *key = K_CTRL; + return 1; + } + if ((scancode & ~0x80) == 0x38) { + *down = !(scancode & 0x80); + *key = K_ALT; + return 1; + } + + if (kd->parseScancode(scancode)) { + auto k = kd->getCurrentKey(); + if (!k.isValid()) { + return 0; + } + + *down = k.isPressed() ? 1:0; + + if (k.getScancode() >= 0x3b && k.getScancode() <= 0x44) { // handle F1-10 + *key = k.getScancode() + 0x80; + return 1; + } + + switch(k.getScancode()) { + case Util::Io::Key::UP: + *key = K_UPARROW; + return 1; + case Util::Io::Key::DOWN: + *key = K_DOWNARROW; + return 1; + case Util::Io::Key::LEFT: + *key = K_LEFTARROW; + return 1; + case Util::Io::Key::RIGHT: + *key = K_RIGHTARROW; + return 1; + case Util::Io::Key::SPACE: + *key = K_SPACE; + return 1; + case Util::Io::Key::ESC: + *key = K_ESCAPE; + return 1; + case Util::Io::Key::ENTER: + *key = K_ENTER; + return 1; + case Util::Io::Key::TAB: + *key = K_TAB; + return 1; + case Util::Io::Key::BACKSPACE: + *key = K_BACKSPACE; + return 1; + case Util::Io::Key::HOME: + *key = K_HOME; + return 1; + case Util::Io::Key::END: + *key = K_END; + return 1; + case Util::Io::Key::INSERT: + *key = K_INS; + return 1; + case Util::Io::Key::DEL: + *key = K_DEL; + return 1; + case Util::Io::Key::PAGE_UP: + *key = K_PGUP; + return 1; + case Util::Io::Key::PAGE_DOWN: + *key = K_PGDN; + return 1; + case Util::Io::Key::F1: + *key = K_F1; + return 1; + case Util::Io::Key::F2: + *key = K_F2; + return 1; + case Util::Io::Key::F3: + *key = K_F3; + return 1; + case Util::Io::Key::F4: + *key = K_F4; + return 1; + case Util::Io::Key::F5: + *key = K_F5; + return 1; + case Util::Io::Key::F6: + *key = K_F6; + return 1; + case Util::Io::Key::F7: + *key = K_F7; + return 1; + case Util::Io::Key::F8: + *key = K_F8; + return 1; + case Util::Io::Key::F9: + *key = K_F9; + return 1; + case Util::Io::Key::F10: + *key = K_F10; + return 1; + case Util::Io::Key::F11: + *key = K_F11; + return 1; + case Util::Io::Key::F12: + *key = K_F12; + return 1; + default: + if (k.getAscii()) { + *key = tolower(k.getAscii()); + return 1; + } + + return 0; + } + } + } + + return 0; +} + +void QG_GetJoyAxes(float *axes) { + *axes = 0; +} + +void QG_GetMouseMove(int *x, int *y) { + *x = 0; + *y = 0; +} + +void QG_Quit(void) { + Util::Graphic::Ansi::cleanupGraphicalApplication(); + delete lfb; + delete kd; +} \ No newline at end of file diff --git a/src/application/quakegeneric b/src/application/quakegeneric deleted file mode 160000 index 06af1c925..000000000 --- a/src/application/quakegeneric +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 06af1c925e9323febc1c39a7f7e90c8c1e62caef diff --git a/src/application/view3d/view3d.cpp b/src/application/view3d/view3d.cpp index 0df7e9af1..4e1beb44b 100644 --- a/src/application/view3d/view3d.cpp +++ b/src/application/view3d/view3d.cpp @@ -40,7 +40,7 @@ int32_t main(int32_t argc, char *argv[]) { "ESC to exit.\n\n" "Usage: view3do [FILE]\n" "Options:\n" - " -r, --resolution: Set display resolution" + " -r, --resolution: Set display resolution\n" " -h, --help: Show this help message"); argumentParser.addArgument("resolution", false, "r"); diff --git a/src/lib/util/io/key/Key.h b/src/lib/util/io/key/Key.h index ba02038a6..b265535b0 100644 --- a/src/lib/util/io/key/Key.h +++ b/src/lib/util/io/key/Key.h @@ -54,14 +54,20 @@ friend class KeyboardLayout; enum Scancode { ESC = 0x01, DIV = 0x08, + Q = 0x10, W = 0x11, A = 0x1e, S = 0x1f, D = 0x20, - Q = 0x10, + J = 0x24, + K = 0x25, E = 0x12, R = 0x13, F = 0x21, + Y = 0x2c, + X = 0x2d, + C = 0x2e, + V = 0x2f, PLUS = 0x1b, MINUS = 0x35, ENTER = 0x1c,