Repository: ICTeam28/PiFox Branch: master Commit: 4ae6f73c4913 Files: 28 Total size: 174.3 KB Directory structure: gitextract_441jipqv/ ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── assets/ │ ├── enemy.s │ ├── pillar.s │ ├── rock.s │ ├── rocket.s │ └── ship.s ├── bullets.s ├── enemies.s ├── game.s ├── gfx.s ├── imager.py ├── input.s ├── kernel.ld ├── kernel.s ├── math.s ├── mbox.s ├── objects.s ├── pillars.s ├── player.s ├── ports.s ├── printf.s ├── rockets.s ├── sound.s ├── test.s └── toolchains/ └── arm-none-eabi.cmake ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # CMake build/ # Object files *.o *.ko *.obj *.elf # Libraries *.lib *.a # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex ================================================ FILE: CMakeLists.txt ================================================ # This file is part of the Team 28 Project # Licensing information can be found in the LICENSE file # (C) 2014 The Team 28 Authors. All rights reserved. cmake_minimum_required(VERSION 2.8) project(PiFox ASM) # Find the python interpreter set( PythonInterp_FIND_VERSION 2 ) find_package( PythonInterp REQUIRED ) set(SOURCES kernel.s math.s mbox.s gfx.s ports.s input.s printf.s game.s bullets.s objects.s pillars.s player.s sound.s rockets.s enemies.s assets/rock.s assets/ship.s assets/enemy.s assets/rocket.s ) SET(IMAGES bullet.png rocket.png wrench.png flare.png mountains.png tristan.png monkey.png pifox.png ) set( CMAKE_EXECUTABLE_SUFFIX .elf ) set( CMAKE_ASM_FLAGS "-march=armv6zk -mfpu=vfp -g -Wa,--fatal-warnings -nostartfiles -nostdlib" ) set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${PROJECT_SOURCE_DIR}/kernel.ld" ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) # Compile all images foreach(file ${IMAGES}) get_filename_component(file_path ${file} PATH) get_filename_component(file_name ${file} NAME_WE) set(file "${file_name}") set(object "${CMAKE_BINARY_DIR}/assets${file_path}/${file_name}.bin") set(source "${CMAKE_SOURCE_DIR}/assets${file_path}/${file_name}.png") get_filename_component(dir ${object} PATH) file(MAKE_DIRECTORY ${dir}) add_custom_command( OUTPUT ${object} DEPENDS ${source} COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/imager.py ${source} --out=${object} ) list(APPEND IMAGES_BIN ${object}) endforeach(file) # Build a binary file out of the elf add_executable( kernel ${SOURCES} ${IMAGES_BIN} ) # Without an operating system, there is no executable loader, so we just need # the raw machine code (or binary) from the ELF output of the toolchain. # objcopy can do that for us. add_custom_command( TARGET kernel POST_BUILD COMMAND ${CMAKE_OBJCOPY} ${CMAKE_BINARY_DIR}/kernel.elf -O binary ./kernel.img WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Convert the ELF output file to a binary image" ) ================================================ FILE: LICENSE ================================================ Copyright (c) 2014, Licker Nandor, Ilija Radosavovic, David Avedissian, Nic Prettejohn All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the {organization} nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ PiFox ===== Video of the game in action: https://www.youtube.com/watch?v=-5n9IxSQH1M Developed as an extension to a first year group project at Imperial College London. Bare Metal 3D rail shooter game * 5800 lines of ARM assembly (ARMv6 + VFP1) * Software rasterizer * 3D objects * 2D billboards * Sound using DMA * NES controller input * Math & utility library * GitHub: https://github.com/ICTeam28/PiFox * Emulator: https://github.com/ICTeam28/PiEmu Dependencies ----- Using your favourite Linux package manager, install: * arm-none-eabi-binutils * cmake Build ----- The project uses CMake and requires an ARM assembler supporting GNU as syntax. mkdir build cd build cmake .. make Emulation ----- PiEmu (https://github.com/ICTeam28/PiEmu) can run the game without sound. Assuming PiFox and PiEmu have been cloned in the same directory and both are built, PiEmu must be invoked with the following command inside PiFox's build directory: ../../PiEmu/build/piemu --graphics --quiet --memory=256M --addr=65536 --nes kernel.img A qemu branch can be used to emulate the game at a higher framerate, but sound must be disabled. (https://github.com/Torlus/qemu/tree/rpi) config.txt ---------- In order to be compatible with qemu, the kernel must be loaded at address 0x10000. disable_overscan=1 disable_pvt=1 force_turbo=1 gpu_mem_256=160 gpu_mem_512=316 cma_lwm=16 cma_hwm=32 kernel_address=65536 Wiring the controller --------------------- | NES | Raspberry Pi | |:--------:|:--------------:| | GND | Ground | | VCC | 3v3 | | CUP | GPIO 10 | | OUT 0 | GPIO 11 | | D1 | GPIO 4 | ![NES Pinout](https://raw.github.com/ICTeam28/PiFox/master/assets/nes-controller-pinout.png) ![Raspberry PI Pinout](https://raw.github.com/ICTeam28/PiFox/master/assets/raspbery-pi-pinout.png) Authors ------- Nandor Licker - Email: nandor.licker13[at]imperial.ac.uk - Github [@nandor](https://github.com/nandor) Ilija Radosavovic - Email: ilija.radosavovic13[at]imperial.ac.uk - Github [@ir413](https://github.com/ir413) David Avedissian - Email: david.avedissian13[at]imperial.ac.uk - Github [@davedissian](https://github.com/davedissian) - Twitter [@davedissian](https://twitter.com/davedissian) Nic Prettejohn - Email: nicolas.prettejohn13[at]imperial.ac.uk - Github [@nkp](https://github.com/nkp) - Twitter [@thisisnkp](https://twitter.com/thisisnkp) Special thanks -------------- * https://github.com/dwelch67/raspberrypi * https://github.com/PeterLemon/RaspberryPi Special thanks to chpatrick (Patrick Chilton) for his advice. ================================================ FILE: assets/enemy.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global enemy_vtx .global enemy_idx @ ------------------------------------------------------------------------------ @ Enemy model @ X Y Z 1.0 @ ------------------------------------------------------------------------------ .align 2 enemy_vtx: .float 0.00, 0.75, 0.0, 1.0 @ 0 .float -0.75, 0.00, 0.0, 1.0 @ 1 .float 0.00, -0.75, 0.0, 1.0 @ 2 .float 0.75, 0.00, 0.0, 1.0 @ 3 .float -0.90, 0.90, 0.0, 1.0 @ 4 .float -0.90, -0.90, 0.0, 1.0 @ 5 .float 0.90, -0.90, 0.0, 1.0 @ 6 .float 0.90, 0.90, 0.0, 1.0 @ 7 .float 0.00, 0.00, 2.0, 1.0 @ 8 .float -0.60, 0.60, 1.0, 1.0 @ 9 .float -0.60, -0.60, 1.0, 1.0 @ 10 .float 0.60, -0.60, 1.0, 1.0 @ 11 .float 0.60, 0.60, 1.0, 1.0 @ 12 enemy_idx: .long 0, 1, 8 .float 1.0, 0.2, 0.2 .long 1, 2, 8 .float 1.0, 0.2, 0.2 .long 2, 3, 8 .float 1.0, 0.2, 0.2 .long 3, 0, 8 .float 1.0, 0.2, 0.2 .long 1, 0, 9 .float 1.0, 0.7, 0.2 .long 0, 4, 9 .float 1.0, 0.7, 0.2 .long 4, 1, 9 .float 1.0, 0.7, 0.2 .long 2, 1, 10 .float 1.0, 0.7, 0.2 .long 1, 5, 10 .float 1.0, 0.7, 0.2 .long 5, 2, 10 .float 1.0, 0.7, 0.2 .long 3, 2, 11 .float 1.0, 0.7, 0.2 .long 2, 6, 11 .float 1.0, 0.7, 0.2 .long 6, 3, 11 .float 1.0, 0.7, 0.2 .long 0, 3, 12 .float 1.0, 0.7, 0.2 .long 7, 0, 12 .float 1.0, 0.7, 0.2 .long 3, 7, 12 .float 1.0, 0.7, 0.2 ================================================ FILE: assets/pillar.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global pillar_vtx .global pillar_idx @ ------------------------------------------------------------------------------ @ Cube model @ X Y Z 1.0 @ ------------------------------------------------------------------------------ .align 2 pillar_vtx: @ Front .float -0.5, -0.5, 0.5, 1.0 .float 0.5, -0.5, 0.5, 1.0 .float 0.5, 0.5, 0.5, 1.0 .float -0.5, 0.5, 0.5, 1.0 @ Back .float -0.5, -0.5, -0.5, 1.0 .float 0.5, -0.5, -0.5, 1.0 .float 0.5, 0.5, -0.5, 1.0 .float -0.5, 0.5, -0.5, 1.0 @ Top .float 0.5, 0.5, -0.5, 1.0 .float -0.5, 0.5, -0.5, 1.0 .float -0.5, 0.5, 0.5, 1.0 .float 0.5, 0.5, 0.5, 1.0 @ Left .float 0.5, -0.5, -0.5, 1.0 .float 0.5, 0.5, -0.5, 1.0 .float 0.5, 0.5, 0.5, 1.0 .float 0.5, -0.5, 0.5, 1.0 @ Right .float -0.5, 0.5, -0.5, 1.0 .float -0.5, -0.5, -0.5, 1.0 .float -0.5, -0.5, 0.5, 1.0 .float -0.5, 0.5, 0.5, 1.0 pillar_idx: .long 0, 1, 3 .float 0.5, 0.5, 0.5 .long 3, 1, 2 .float 0.5, 0.5, 0.5 .long 4, 7, 5 .float 0.5, 0.5, 0.5 .long 7, 6, 5 .float 0.5, 0.5, 0.5 .long 8, 9, 11 .float 0.5, 0.5, 0.5 .long 11, 9, 10 .float 0.5, 0.5, 0.5 .long 12, 13, 15 .float 0.5, 0.5, 0.5 .long 15, 13, 14 .float 0.5, 0.5, 0.5 .long 16, 17, 19 .float 0.5, 0.5, 0.5 .long 19, 17, 18 .float 0.5, 0.5, 0.5 ================================================ FILE: assets/rock.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global rock_vtx .global rock_idx @ ------------------------------------------------------------------------------ @ Rock model @ X Y Z 1.0 @ ------------------------------------------------------------------------------ .align 2 rock_vtx: .float 0.0, 0.75, 1.2135, 1.0 .float 0.0, 0.75, -1.2135, 1.0 .float 0.0, -0.75, 1.2135, 1.0 .float 0.0, -0.75, -1.2135, 1.0 .float 0.75, 1.2135, 0.0, 1.0 .float 0.75, -1.2135, 0.0, 1.0 .float -0.75, 1.2135, 0.0, 1.0 .float -0.75, -1.2135, 0.0, 1.0 .float 1.2135, 0.0, 0.75, 1.0 .float 1.2135, 0.0, -0.75, 1.0 .float -1.2135, 0.0, 0.75, 1.0 .float -1.2135, 0.0, -0.75, 1.0 rock_idx: .long 0, 2, 8 .float 0.9, 0.2, 0.2 .long 10, 2, 0 .float 0.9, 0.2, 0.2 .long 0, 4, 6 .float 0.9, 0.2, 0.2 .long 8, 4, 0 .float 0.9, 0.2, 0.2 .long 0, 6, 10 .float 0.9, 0.2, 0.2 .long 1, 9, 3 .float 0.9, 0.2, 0.2 .long 11, 1, 3 .float 0.9, 0.2, 0.2 .long 4, 1, 6 .float 0.9, 0.2, 0.2 .long 9, 1, 4 .float 0.9, 0.2, 0.2 .long 6, 1, 11 .float 0.9, 0.2, 0.2 .long 2, 7, 5 .float 0.9, 0.2, 0.2 .long 5, 8, 2 .float 0.9, 0.2, 0.2 .long 10, 7, 2 .float 0.9, 0.2, 0.2 .long 7, 3, 5 .float 0.9, 0.2, 0.2 .long 3, 9, 5 .float 0.9, 0.2, 0.2 .long 11, 3, 7 .float 0.9, 0.2, 0.2 .long 4, 8, 9 .float 0.9, 0.2, 0.2 .long 5, 9, 8 .float 0.9, 0.2, 0.2 .long 11, 10, 6 .float 0.9, 0.2, 0.2 .long 10, 11, 7 .float 0.9, 0.2, 0.2 .long 0, 2, 8 .float 0.7, 0.5, 0.5 .long 10, 2, 0 .float 0.7, 0.5, 0.5 .long 0, 4, 6 .float 0.7, 0.5, 0.5 .long 8, 4, 0 .float 0.7, 0.5, 0.5 .long 0, 6, 10 .float 0.7, 0.5, 0.5 .long 1, 9, 3 .float 0.7, 0.5, 0.5 .long 11, 1, 3 .float 0.7, 0.5, 0.5 .long 4, 1, 6 .float 0.7, 0.5, 0.5 .long 9, 1, 4 .float 0.7, 0.5, 0.5 .long 6, 1, 11 .float 0.7, 0.5, 0.5 .long 2, 7, 5 .float 0.7, 0.5, 0.5 .long 5, 8, 2 .float 0.7, 0.5, 0.5 .long 10, 7, 2 .float 0.7, 0.5, 0.5 .long 7, 3, 5 .float 0.7, 0.5, 0.5 .long 3, 9, 5 .float 0.7, 0.5, 0.5 .long 11, 3, 7 .float 0.7, 0.5, 0.5 .long 4, 8, 9 .float 0.7, 0.5, 0.5 .long 5, 9, 8 .float 0.7, 0.5, 0.5 .long 11, 10, 6 .float 0.7, 0.5, 0.5 .long 10, 11, 7 .float 0.7, 0.5, 0.5 .long 0, 2, 8 .float 0.5, 0.5, 0.5 .long 10, 2, 0 .float 0.5, 0.5, 0.5 .long 0, 4, 6 .float 0.5, 0.5, 0.5 .long 8, 4, 0 .float 0.5, 0.5, 0.5 .long 0, 6, 10 .float 0.5, 0.5, 0.5 .long 1, 9, 3 .float 0.5, 0.5, 0.5 .long 11, 1, 3 .float 0.5, 0.5, 0.5 .long 4, 1, 6 .float 0.5, 0.5, 0.5 .long 9, 1, 4 .float 0.5, 0.5, 0.5 .long 6, 1, 11 .float 0.5, 0.5, 0.5 .long 2, 7, 5 .float 0.5, 0.5, 0.5 .long 5, 8, 2 .float 0.5, 0.5, 0.5 .long 10, 7, 2 .float 0.5, 0.5, 0.5 .long 7, 3, 5 .float 0.5, 0.5, 0.5 .long 3, 9, 5 .float 0.5, 0.5, 0.5 .long 11, 3, 7 .float 0.5, 0.5, 0.5 .long 4, 8, 9 .float 0.5, 0.5, 0.5 .long 5, 9, 8 .float 0.5, 0.5, 0.5 .long 11, 10, 6 .float 0.5, 0.5, 0.5 .long 10, 11, 7 .float 0.5, 0.5, 0.5 ================================================ FILE: assets/rocket.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global rocket_vtx .global rocket_idx @------------------------------------------------------------------------------- @ Rocket model @ X Y Z 1.0 @------------------------------------------------------------------------------- .align 2 rocket_vtx: @ base .float 0.2, 0.0, 0.5, 1.0 @b0 .float 0.06, 0.19, 0.5, 1.0 @b1 .float -0.16, 0.1174, 0.5, 1.0 @b2 .float -0.16, -0.1174, 0.5, 1.0 @b3 .float 0.06, -0.19, 0.5, 1.0 @b4 .float 0.0, 0.0, 0.5, 1.0 @b5 @ top .float 0.2, 0.0, -0.5, 1.0 @t0 .float 0.06, 0.19, -0.5, 1.0 @t1 .float -0.16, 0.1174, -0.5, 1.0 @t2 .float -0.16, -0.1174, -0.5, 1.0 @t3 .float 0.06, -0.19, -0.5, 1.0 @t4 .float 0.0, 0.0, -1.5, 1.0 @t5 @ mid .float 0.2, 0.0, 0.0, 1.0 @m0 .float 0.06, 0.19, 0.0, 1.0 @m1 .float -0.16, 0.1174, 0.0, 1.0 @m2 .float -0.16, -0.1174, 0.0, 1.0 @m3 .float 0.06, -0.19, 0.0, 1.0 @m4 @ wings .float 0.4, 0.0, 0.5, 1.0 @w0 .float 0.12, 0.38, 0.5, 1.0 @w1 .float -0.32, 0.2348, 0.5, 1.0 @w2 .float -0.32, -0.2348, 0.5, 1.0 @w3 .float 0.12, -0.38, 0.5, 1.0 @w4 rocket_idx: @ base .long 0, 5, 4 .float 1.0, 0.4, 0.0 .long 3, 4, 5 .float 1.0, 0.4, 0.0 .long 2, 3, 5 .float 1.0, 0.4, 0.0 .long 1, 2, 5 .float 1.0, 0.4, 0.0 .long 0, 1, 5 .float 1.0, 0.4, 0.0 @ sides .long 0, 4, 10 .float 1.0, 0.0, 0.0 .long 0, 10, 6 .float 1.0, 0.0, 0.0 .long 4, 3, 9 .float 1.0, 0.0, 0.0 .long 4, 9, 10 .float 1.0, 0.0, 0.0 .long 3, 2, 8 .float 1.0, 0.0, 0.0 .long 3, 8, 9 .float 1.0, 0.0, 0.0 .long 2, 1, 7 .float 1.0, 0.0, 0.0 .long 2, 7, 8 .float 1.0, 0.0, 0.0 .long 1, 0, 6 .float 1.0, 0.0, 0.0 .long 1, 6, 7 .float 1.0, 0.0, 0.0 @ top .long 6, 10, 11 .float 1.0, 1.0, 1.0 .long 10, 9, 11 .float 1.0, 1.0, 1.0 .long 9, 8, 11 .float 1.0, 1.0, 1.0 .long 8, 7, 11 .float 1.0, 1.0, 1.0 .long 7, 6, 11 .float 1.0, 1.0, 1.0 @ wings .long 0, 17, 12 .float 1.0, 1.0, 1.0 .long 1, 18, 13 .float 1.0, 1.0, 1.0 .long 2, 19, 14 .float 1.0, 1.0, 1.0 .long 3, 20, 15 .float 1.0, 1.0, 1.0 .long 4, 21, 16 .float 1.0, 1.0, 1.0 .long 17, 0, 12 .float 1.0, 1.0, 1.0 .long 18, 1, 13 .float 1.0, 1.0, 1.0 .long 19, 2, 14 .float 1.0, 1.0, 1.0 .long 20, 3, 15 .float 1.0, 1.0, 1.0 .long 21, 4, 16 .float 1.0, 1.0, 1.0 ================================================ FILE: assets/ship.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global ship_vtx .global ship_idx @ ------------------------------------------------------------------------------ @ Cube model @ X Y Z 1.0 @ ------------------------------------------------------------------------------ .align 2 ship_vtx: @ Center - backside .float -0.4, 0.0, 0.0, 1.0 .float 0.0, 0.2, 0.0, 1.0 .float 0.4, 0.0, 0.0, 1.0 .float -0.0, -0.1, 0.0, 1.0 @ Left - backside .float -0.8, 0.0, 0.0, 1.0 .float -0.6, 0.1, 0.0, 1.0 .float -0.6, -0.2, 0.0, 1.0 @ Right - backside .float 0.6, 0.1, 0.0, 1.0 .float 0.8, 0.0, 0.0, 1.0 .float 0.6, -0.2, 0.0, 1.0 @ Left tip .float -0.6, 0.0, -2.0, 1.0 @ Center tip .float 0.0, 0.0, -3.0, 1.0 @ Right tip .float 0.6, 0.0, -2.0, 1.0 @ Engine .float 0.3, 0.0, -1.0, 1.0 .float 0.7, 0.5, 0.0, 1.0 .float -0.3, 0.0, -1.0, 1.0 .float -0.7, 0.5, 0.0, 1.0 ship_idx: .long 1, 0, 2 .float 0.0, 0.0, 1.0 .long 0, 3, 2 .float 0.0, 0.0, 1.0 .long 5, 4, 0 .float 1.0, 1.0, 1.0 .long 0, 4, 6 .float 1.0, 1.0, 1.0 .long 7, 2, 8 .float 1.0, 1.0, 1.0 .long 8, 2, 9 .float 1.0, 1.0, 1.0 .long 10, 4, 5 .float 1.0, 0.0, 0.0 .long 10, 6, 4 .float 1.0, 0.0, 0.0 .long 10, 5, 0 .float 1.0, 0.0, 0.0 .long 10, 0, 6 .float 1.0, 0.0, 0.0 .long 11, 0, 1 .float 1.0, 1.0, 1.0 .long 11, 3, 0 .float 1.0, 1.0, 1.0 .long 11, 1, 2 .float 1.0, 1.0, 1.0 .long 11, 2, 3 .float 1.0, 1.0, 1.0 .long 12, 2, 7 .float 1.0, 0.0, 0.0 .long 12, 9, 2 .float 1.0, 0.0, 0.0 .long 12, 7, 8 .float 1.0, 0.0, 0.0 .long 12, 8, 9 .float 1.0, 0.0, 0.0 .long 14, 13, 2 .float 0.0, 0.0, 20.0 .long 14, 2, 13 .float 0.0, 0.0, 20.0 .long 16, 0, 15 .float 0.0, 0.0, 20.0 .long 16, 15, 0 .float 0.0, 0.0, 20.0 ================================================ FILE: bullets.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global draw_bullets .global collide_bullets .global reset_bullets .include "ports.s" .section .data @ ------------------------------------------------------------------------------ @ List of bullets @ ------------------------------------------------------------------------------ .equ BULLET_COUNT, 20 bullet_last: .long 0 bullet_list: .rept BULLET_COUNT .float 0.0, 0.0, 0.0, 1.0 .long 0 .endr .section .text @ ------------------------------------------------------------------------------ @ Renders all bullets @ ------------------------------------------------------------------------------ draw_bullets: stmfd sp!, {lr} @ Reset model matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_model vstm.f32 r0, {s0 - s15} @ Read system timer ldr r7, =STIMER_CLO ldr r7, [r7] @ Loop through all bullets ldr r12, =BULLET_COUNT ldr r11, =bullet_list ldr r10, =bullet_last ldr r6, [r10] 1: vldmia.f32 r11!, {s3 - s6} ldmia r11!, {r9} ldr r0, =0x40400000 vmov.f32 s2, r0 vsub.f32 s5, s5, s2 tst r9, r9 bne 2f @ Check if sprite can be spawned sub r8, r7, r6 cmp r8, #0x50000 blt 2f ldr r5, =button_pressed ldr r5, [r5] tst r5, #0x01 beq 2f @ Play shot sound bl snd_play_bullet @ Spawn a new sprite add r9, r7, #0x100000 mov r6, r7 str r7, [r10] ldr r0, =player_pos vldm.f32 r0, {s3 - s6} ldr r1, =0xc0000000 vmov.f32 s7, r1 vsub.f32 s4, s4, s7 ldr r1, =0xc1200000 vmov.f32 s5, r1 b 3f 2: cmp r9, r7 movlt r9, #0 3: stmdb r11!, {r9} vstmdb r11!, {s3 - s6} @ Check if bullet is active tst r9, r9 blne draw_bullet 2: add r11, r11, #20 subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Renders a single bullet @ ------------------------------------------------------------------------------ draw_bullet: stmfd sp!, {lr} ldr r0, =mtx_model vmov.f32 s0, s3 vneg.f32 s1, s4 vmov.f32 s2, s5 bl mat4_translate ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 @ Draw a sprite ldr r0, =bullet ldr r1, =mtx_mvp ldr r2, =mtx_view ldr r3, =0x3e800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Checks whether the bullet collided with something. @ In case of a collision, the bullet is destroyed @ Arguments: @ s0 - x @ s1 - y @ s2 - z @ s31 - radius @ Returns: @ r0 - 0 if collision happened @ Clobbers: @ none @ ------------------------------------------------------------------------------ collide_bullets: stmfd sp!, {r1 - r12, lr} mov r0, #1 ldr r12, =BULLET_COUNT ldr r11, =bullet_list 1: vldmia.f32 r11!, {s27 - s30} ldmia r11!, {r9} tst r9, r9 beq 2f vsub.f32 s26, s0, s27 vabs.f32 s26, s26 vcmp.f32 s26, s31 fmstat bgt 2f @ x vsub.f32 s26, s1, s28 vabs.f32 s26, s26 vcmp.f32 s26, s31 fmstat bgt 2f @ y vsub.f32 s26, s2, s29 vabs.f32 s26, s26 vcmp.f32 s26, s31 fmstat bgt 2f @ z mov r0, #0 str r0, [r11, #-4] b 3f 2: subs r12, r12, #1 bne 1b 3: ldmfd sp!, {r1 - r12, pc} @------------------------------------------------------------------------------- @ Resets bullets @------------------------------------------------------------------------------- reset_bullets: stmfd sp!, {r0 - r3, lr} vstmdb.f32 sp!, {s0 - s4} ldr r3, =bullet_last mov r0, #0 str r0, [r3] ldr r3, =BULLET_COUNT ldr r2, =bullet_list ldr r1, =0x3F800000 @ 1.0 1: vldm.f32 r2, {s0 -s4} vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r0 vmov.f32 s3, r1 vmov.f32 s4, r0 vstm.f32 r2!, {s0 - s4} subs r3, #1 bne 1b vldm.f32 sp!, {s0 - s4} ldmfd sp!, {r0 - r3, pc} ================================================ FILE: enemies.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global setup_enemies .global draw_enemies .global reset_enemies .global reset_flares .global enemy_count .global enemies .global ENEMY_COUNT .section .data @ ------------------------------------------------------------------------------ @ List of enemies @ ------------------------------------------------------------------------------ .equ ENEMY_COUNT, 5 .equ FLARE_COUNT, 30 enemy_count: .long 0 enemy_counter: .long 0 enemy_timer: .long 0 enemies: .rept ENEMY_COUNT .float 0.0, 0.0, 0.0 @ x, y, z .float 0.0 @ s3 - target z .float 0.0 @ s4 - rot .float 0.0 @ s5 - move dir .long 0 @ s6 - lives .long 0 @ s7 - bullet timer .endr flares: .rept FLARE_COUNT .float 0.0, 0.0, -20.0 @ x, y, z .float 0.0, 0.0, 0.0 @ dx, dy, dz .long 0 @ s6 - alive .endr .section .text @ ------------------------------------------------------------------------------ @ Resets counters @ ------------------------------------------------------------------------------ setup_enemies: ldr r0, =enemy_count mov r1, #0 str r1, [r0] ldr r0, =enemy_counter mov r1, #0 str r1, [r0] ldr r0, =enemy_timer mov r1, #1000 str r1, [r0] mov pc, lr @ ------------------------------------------------------------------------------ @ Renders all enemies @ ------------------------------------------------------------------------------ draw_enemies: stmfd sp!, {lr} ldr r0, =enemy_count ldr r0, [r0] tst r0, r0 bne 2f @ Test if enemies can be spawned ldr r0, =enemy_timer ldr r1, [r0] subs r1, r1, #1 moveq r1, #1000 str r1, [r0] ldmnefd sp!, {pc} @ Pop-up the monkey ldr r0, =monkey_timer mov r1, #120 str r1, [r0] @ Play cant let you do that bl snd_play_cantlet @ Increment number of enemies, clamp to 5 ldr r0, =enemy_counter ldr r11, [r0] add r11, r11, #1 cmp r11, #5 movgt r11, #5 str r11, [r0] ldr r0, =enemy_count str r11, [r0] @ Initialise them ldr r12, =enemies mov r10, #0 1: bl spawn_enemy vstm.f32 r12!, {s0 - s7} subs r11, r11, #1 bne 1b 2: ldr r12, =enemies ldr r11, =enemy_count ldr r11, [r11] mov r10, #0 3: @ Update & draw enemies vldm.f32 r12, {s0 - s7} vmov.f32 r0, s6 tst r0, r0 addeq r12, r12, #32 beq 4f bl update_enemy vstm.f32 r12!, {s0 - s7} vmov.f32 r0, s6 tst r0, r0 blne draw_enemy 4: subs r11, r11, #1 bne 3b tst r10, r10 ldr r11, =enemy_count streq r10, [r11] @ Reset model matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_model vstm.f32 r0, {s0 - s15} @ Draw flares shot by enemies ldr r11, =FLARE_COUNT ldr r12, =flares 1: vldm.f32 r12, {s0 - s6} vmov.f32 r0, s6 tst r0, r0 addeq r12, r12, #28 beq 2f bl update_flare vstm.f32 r12!, {s0 - s6} bl draw_flare 2: subs r11, r11, #1 bne 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Updates an enemy @ Arguments: @ @ Returns: @ @ Clobbers: @ @ ------------------------------------------------------------------------------ update_enemy: stmfd sp!, {lr} @ Move down z axis up to target z ldr r0, =player_speed vldr.f32 s8, [r0] vadd.f32 s2, s2, s8 ldr r0, =0x3f800000 vmov.f32 s9, r0 vadd.f32 s2, s2, s9 vcmp.f32 s2, s3 fmstat vmovgt.f32 s2, s3 @ Lateral movement vadd.f32 s0, s0, s5 ldr r0, =0xc1080000 vmov.f32 s8, r0 vcmp.f32 s0, s8 fmstat vmovlt.f32 s0, s8 vneglt.f32 s5, s5 vneg.f32 s8, s8 vcmp.f32 s0, s8 fmstat vmovgt.f32 s0, s8 vneggt.f32 s5, s5 @ Rotation ldr r0, =0x3c23d70a vmov.f32 s8, r0 vadd.f32 s4, s4, s8 @ Decrement bullet timeout vmov.f32 r0, s7 subs r0, r0, #1 moveq r0, #40 vmov.f32 s7, r0 bne 2f @ Fire a flare vcmp.f32 s2, s3 fmstat blge fire_flare 2: @ Test for collision with bullets ldr r0, =0x40000000 vmov.f32 s31, r0 bl collide_bullets tst r0, r0 vmoveq.f32 r0, s6 subeq r0, r0, #1 vmoveq.f32 s6, r0 @ Increment score ldreq r0, =player_score @ Add to score ldreq r1, [r0] addeq r1, r1, #50 streq r1, [r0] @ Increment live enemy count add r10, r10, #1 ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Renders an enemy @ Arguments: @ none @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ draw_enemy: stmfd sp!, {lr} ldr r0, =mtx_id vldm.f32 r0, {s16 - s31} ldr r0, =mtx_model vstm.f32 r0, {s16 - s31} ldr r0, =mtx_temp vstm.f32 r0, {s16 - s31} @ Damage vmov.f32 r5, s6 subs r5, r5, #1 mov r6, #4 mov r7, #3 mla r5, r7, r5, r6 @ Translate & rotate vneg.f32 s1, s1 ldr r0, =mtx_model bl mat4_translate vmov.f32 s0, s4 ldr r0, =mtx_temp bl mat4_rot_z ldr r0, =mtx_model ldr r1, =mtx_temp ldr r2, =mtx_model bl mat4_mul_mat4 @ Compute MVP matrix ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 @ Draw the enemy ldr r0, =enemy_vtx ldr r1, =enemy_idx mov r2, r5 ldr r3, =mtx_mvp ldr r4, =light_dir bl gfx_draw_trgs ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Creates a randomized enemy @ Arguments: @ r10 - index of enemy @ Returns: @ s0 - s5: enemy data @ Clobbers: @ Increments r10 @ ------------------------------------------------------------------------------ spawn_enemy: stmfd sp!, {lr} @ Randomize x in range [-8.5, 8.5] bl random and r1, r0, #0xFF sub r1, r1, #0x7F vmov.f32 s8, r1 fsitos s8, s8 ldr r1, =0x41400000 vmov.f32 s9, r1 vdiv.f32 s0, s8, s9 @ Randomize y in range [-2.8, 5.2] bl random and r1, r0, #0xFF sub r1, r1, #0x7F vmov.f32 s8, r1 fsitos s8, s8 ldr r1, =0x42700000 vmov.f32 s9, r1 vdiv.f32 s1, s8, s9 @ Set z to -300.0 ldr r0, =0xc3960000 vmov.f32 s2, r0 vmov.f32 s8, r10 fsitos s8, s8 ldr r0, =0x40a00000 vmov.f32 s9, r0 vmul.f32 s8, s8, s9 ldr r0, =0xc2480000 vmov.f32 s9, r0 vsub.f32 s3, s9, s8 @ Rotation ldr r0, =0 vmov.f32 s4, r0 @ Random lateral movement ldr r0, =0x3e4ccccd vmov.f32 s5, r0 bl random tst r0, #1 vnegne.f32 s5, s5 and r0, #1 add r0, #1 vmov.f32 s8, r0 fsitos s8, s8 vmul.f32 s5, s5, s8 @ Lives mov r0, #5 vmov.f32 s6, r0 @ Bullet timer mov r1, #15 add r10, r10, #1 mul r0, r1, r10 vmov.f32 s7, r0 ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Updates a flare @ Arguments: @ none @ Returns: @ none @ Clobers: @ none @ ------------------------------------------------------------------------------ update_flare: stmfd sp!, {lr} vadd.f32 s0, s0, s3 vadd.f32 s1, s1, s4 vadd.f32 s2, s2, s5 @ Check whether bullet is still active ldr r0, =0xc1200000 vmov.f32 s31, r0 vcmp.f32 s2, s31 fmstat ldmltfd sp!, {pc} @ Despawn bullet and damage player mov r0, #0 vmov.f32 s6, r0 ldr r0, =player_pos vldm.f32 r0, {s30 - s31} vsub.f32 s7, s0, s30 vabs.f32 s7, s7 vsub.f32 s8, s1, s31 vabs.f32 s8, s8 ldr r0, =0x3fe00000 vmov.f32 s9, r0 vcmp.f32 s7, s9 fmstat ldmgtfd sp!, {pc} vcmp.f32 s8, s9 fmstat ldmgtfd sp!, {pc} ldr r0, =player_rolling ldr r0, [r0] tst r0, r0 ldmnefd sp!, {pc} mov r0, #20 bl player_damage 1: ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Draws a flare @ Arguments: @ s0 - s2: position @ Returns: @ none @ Clobers: @ none @ ------------------------------------------------------------------------------ draw_flare: stmfd sp!, {lr} ldr r0, =mtx_model vneg.f32 s1, s1 bl mat4_translate ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 @ Draw a sprite ldr r0, =flare ldr r1, =mtx_mvp ldr r2, =mtx_view ldr r3, =0x3e800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Fires a flare @ Arguments: @ none @ Returns: @ none @ Clobers: @ none @ ------------------------------------------------------------------------------ fire_flare: stmfd sp!, {r11 - r12, lr} @ Load player position ldr r11, =player_pos vldm.f32 r11, {s22 - s24} @ Draw flares shot by enemies ldr r11, =FLARE_COUNT ldr r12, =flares 1: vldm.f32 r12, {s25 - s31} vmov.f32 r0, s31 tst r0, r0 addne r12, r12, #28 beq 2f subs r11, r11, #1 bne 1b 2: @ Position vmov.f32 s25, s0 vmov.f32 s26, s1 vmov.f32 s27, s2 vabs.f32 s21, s27 @ Direction vsub.f32 s28, s22, s25 vsub.f32 s29, s23, s26 vsub.f32 s30, s24, s27 vdiv.f32 s28, s28, s21 vdiv.f32 s29, s29, s21 vdiv.f32 s30, s30, s21 @ Live flag mov r0, #1 vmov.f32 s31, r0 vstm.f32 r12!, {s25 - s31} ldmfd sp!, {r11 - r12, pc} @------------------------------------------------------------------------------- @ Resets enemies @------------------------------------------------------------------------------- reset_enemies: stmfd sp!, {r0 - r2, lr} vstmdb.f32 sp!, {s0 - s7} ldr r2, =ENEMY_COUNT ldr r1, =enemies mov r0, #0 1: vldm.f32 r1, {s0 - s7} vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r0 vmov.f32 s3, r0 vmov.f32 s4, r0 vmov.f32 s5, r0 vmov.f32 s6, r0 vmov.f32 s7, r0 vstm.f32 r1!, {s0 - s7} subs r2, #1 bne 1b vldmia.f32 sp!, {s0 - s7} ldmfd sp!, {r0 - r2, pc} @------------------------------------------------------------------------------- @ Resets flares @------------------------------------------------------------------------------- reset_flares: stmfd sp!, {r0 - r3, lr} vstmdb.f32 sp!, {s0 - s6} ldr r3, =FLARE_COUNT ldr r2, =flares ldr r1, =0xC1A00000 @ r1 = -20 mov r0, #0 1: vldm.f32 r2, {s0 - s6} vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r1 vmov.f32 s3, r0 vmov.f32 s4, r0 vmov.f32 s5, r0 vmov.f32 s6, r0 vstm.f32 r2!, {s0 - s6} subs r3, #1 bne 1b vldmia.f32 sp!, {s0 - s6} ldmfd sp!, {r0 - r3, pc} ================================================ FILE: game.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global setup_game .global mtx_proj .global mtx_model .global mtx_view .global mtx_temp .global mtx_vp .global mtx_mvp .global mtx_mp .global mtx_id .global player_pos .global light_dir .global wrench .global rocket .global bullet .global flare .global score .global building_small .global building_medium .global building_large .global mountains .global tristan .global monkey .include "ports.s" .section .data @ ------------------------------------------------------------------------------ @ Common assets @ ------------------------------------------------------------------------------ bullet: .incbin "assets/bullet.bin" rocket: .incbin "assets/rocket.bin" wrench: .incbin "assets/wrench.bin" flare: .incbin "assets/flare.bin" mountains: .incbin "assets/mountains.bin" tristan: .incbin "assets/tristan.bin" monkey: .incbin "assets/monkey.bin" pixfox: .incbin "assets/pifox.bin" @ ------------------------------------------------------------------------------ @ Pad ascii to a fixed width @ ------------------------------------------------------------------------------ .macro death_msg x, string 8: .long \x .ascii "\string" 9: .iflt 64 - (9b - 8b) .error "String too long" .endif .ifgt 64 - (9b - 8b) .zero 64 - (9b - 8b) .endif .endm @ ------------------------------------------------------------------------------ @ Transformation matrices @ ------------------------------------------------------------------------------ mtx_proj: .float 1.810660, 0.0, 0.0, 0.0 .float 0.0, 2.4142136, 0.0, 0.0 .float 0.0, 0.0, -1.0040080, -1.0 .float 0.0, 0.0, -2.0040080, 0.0 mtx_model: .float 1.0, 0.0, 0.0, 0.0 .float 0.0, 1.0, 0.0, 0.0 .float 0.0, 0.0, 1.0, 0.0 .float 0.0, 0.0, 0.0, 1.0 mtx_view: .float 1.0, 0.0, 0.0, 0.0 .float 0.0, 1.0, 0.0, 0.0 .float 0.0, 0.0, 1.0, 0.0 .float 0.0, 0.0, 0.0, 1.0 mtx_temp: .space 64, 0 mtx_vp: .space 64, 0 mtx_mvp: .space 64, 0 mtx_mp: .space 64, 0 mtx_id: .float 1.0, 0.0, 0.0, 0.0 .float 0.0, 1.0, 0.0, 0.0 .float 0.0, 0.0, 1.0, 0.0 .float 0.0, 0.0, 0.0, 1.0 @ ------------------------------------------------------------------------------ @ Light direction @ ------------------------------------------------------------------------------ light_dir: .float 0.3, -0.57, -0.57, 0.0 .section .text @ ------------------------------------------------------------------------------ @ Enables interrupts & starts the game @ ------------------------------------------------------------------------------ setup_game: mov r0, #0xDF msr cpsr, r0 b start_loop @ ------------------------------------------------------------------------------ @ Start screen displayed on boot @ ------------------------------------------------------------------------------ start_loop: ldr r0, =0xFF441111 bl gfx_clear @ Draw pifox title card ldr r0, =pixfox mov r1, #203 mov r2, #30 bl gfx_draw_image bl draw_sprites bl draw_start bl gfx_swap bl update_sound bl update_input @ Loop until start is pressed ldr r0, =button_pressed ldr r0, [r0] tst r0, #0x08 beq start_loop b game_loop @ ------------------------------------------------------------------------------ @ Death screen @ ------------------------------------------------------------------------------ death_loop: @ Clear sounds bl snd_stop_roll bl snd_stop_bullet bl snd_stop_rock bl snd_stop_crash bl snd_stop_rocket bl snd_stop_cantlet bl snd_stop_pickup @ Play fail sound bl snd_play_fail @ Record high score ldr r1, =player_score ldr r1, [r1] ldr r0, =player_high_score ldr r0, [r0] cmp r1, r0 ldrgt r0, =player_high_score strgt r1, [r0] @ Generate random death message index bl random and r1, r0, #0x3 1: ldr r0, =0xFF0044ff bl gfx_clear bl draw_death bl draw_sprites bl draw_start bl gfx_swap bl update_sound bl update_input @ Loop until start is pressed ldr r0, =button_pressed ldr r0, [r0] tst r0, #0x08 beq 1b bl snd_stop_fail bl reset_enemies bl reset_flares bl reset_rockets bl reset_objects bl reset_bullets bl reset_player_mov b game_loop @------------------------------------------------------------------------------- @ Pause loop @------------------------------------------------------------------------------- pause_loop: stmfd sp!, {lr} 1: bl update_input bl update_sound @ Loop until select is pressed ldr r0, =button_clicked ldr r0, [r0] tst r0, #0x04 beq 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Main game loop @ ------------------------------------------------------------------------------ game_loop: bl setup_player bl setup_enemies bl snd_play_rock 1: bl gfx_swap bl update_input ldr r0, =button_clicked ldr r0, [r0] tst r0, #0x04 blne pause_loop bl update_player bl update_sound bl draw_pillars bl draw_enemies bl draw_rocks bl draw_bullets bl draw_rockets bl draw_player bl draw_fps bl draw_high_score ldr r0, =player_health ldr r0, [r0] cmp r0, #0 bgt 1b b death_loop .section .data @ ------------------------------------------------------------------------------ @ FPS counter @ ------------------------------------------------------------------------------ frame_counter: .long 0 last_frame: .long 0 fps: .long 0 .section .text @ ------------------------------------------------------------------------------ @ Renders the FPS counter on screen @ ------------------------------------------------------------------------------ draw_fps: stmfd sp!, {lr} @ Updates the FPS counter ldr r0, =last_frame ldr r1, [r0] ldr r2, =1000000 add r1, r1, r2 @ Update fps once every second ldr r2, =STIMER_CLO @ Read system timer ldr r2, [r2] ldr r3, =frame_counter @ Increment frame count ldr r4, [r3] add r4, r4, #1 str r4, [r3] cmp r1, r2 bgt 1f @ If 1s passed, update fps ldr r1, =fps str r4, [r1] str r2, [r0] mov r4, #0 1: str r4, [r3] @ Renders the FPS on screen ldr r0, =1f mov r1, #15 mov r2, #10 ldr r3, =0xFFFFFFFF ldr r4, =fps ldr r4, [r4] push {r4} ldr r4, =player_score ldr r4, [r4] push {r4} bl printf add sp, sp, #8 ldmfd sp!, {pc} 1: .ascii "Score: %5d\nFPS: %2d" .byte 0x0 .align 2 @ ------------------------------------------------------------------------------ @ Renders the high score for this session @ ------------------------------------------------------------------------------ draw_high_score: stmfd sp!, {lr} ldr r0, =1f mov r1, #512 sub r1, r1, #23 mov r2, #10 ldr r3, =0xFFFFFFFF ldr r4, =player_high_score ldr r4, [r4] push {r4} bl printf add sp, sp, #4 ldmfd sp!, {pc} 1: .ascii "High Score: %5d\n" .byte 0x0 .align 2 @ ------------------------------------------------------------------------------ @ Renders the welcome message @ ------------------------------------------------------------------------------ draw_start: stmfd sp!, {r0 - r3, lr} ldr r0, =1f mov r1, #240 mov r2, #400 ldr r3, =0xFFFFFFFF bl printf ldmfd sp!, {r0 - r3, pc} 1: .ascii "Press START to begin" .byte 0x0 .align 2 @ ------------------------------------------------------------------------------ @ Prints the death message @ Arguments: @ r0 - Random number between 0 and number of strings @ Returns: @ Nothing @ ------------------------------------------------------------------------------ draw_death: stmfd sp!, {r0 - r4, lr} @ Draw death message text ldr r0, =2f add r0, r0, r1, lsl #6 ldr r1, [r0], #4 mov r2, #170 ldr r3, =0xFFFFFFFF bl printf @ Draw score ldr r0, =1f mov r1, #272 mov r2, #300 ldr r3, =0xFFFFFFFF ldr r4, =player_score ldr r4, [r4] push {r4} bl printf add sp, sp, #4 ldmfd sp!, {r0 - r4, pc} 1: .ascii "Score: %5d\0" .align 2 2: death_msg 200, "You have died, what a tragedy!\0" death_msg 172, "You have died, better luck next time!\0" death_msg 124, "You have died, maybe you should go back to Mario?\0" death_msg 184, "You have died, give it another go?\0" .section .text @ ------------------------------------------------------------------------------ @ Prints rotating sprites @ Arguments: @ none @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ draw_sprites: stmfd sp!, {r0 - r4, lr} @ Clear model matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_model vstm.f32 r0, {s0 - s15} ldr r0, =mtx_temp vstm.f32 r0, {s0 - s15} @ Compute the proj - view matrix ldr r0, =0 vmov.f32 s0, r0 ldr r0, =0 vmov.f32 s1, r0 ldr r0, =0xc0e00000 vmov.f32 s2, r0 ldr r0, =mtx_view bl mat4_translate ldr r0, =mtx_proj ldr r1, =mtx_view ldr r2, =mtx_vp bl mat4_mul_mat4 @ Prepare the model matrix ldr r0, =0x3f800000 @ 1.0 vmov.f32 s0, r0 ldr r0, =0 vmov.f32 s1, r0 ldr r0, =0 vmov.f32 s2, r0 ldr r0, =mtx_model bl mat4_translate @ Update rotation around y ldr r0, =1f vldr.f32 s0, [r0] ldr r1, =0x3d000000 @ 0.03125 vmov.f32 s1, r1 vadd.f32 s0, s1 vstr.f32 s0, [r0] ldr r0, =mtx_temp bl mat4_rot_y ldr r0, =mtx_temp ldr r1, =mtx_model ldr r2, =mtx_model bl mat4_mul_mat4 @ Rotate around y by 120 degrees ldr r0, =0x40060a92 @ 2 * PI / 3 vmov.f32 s0, r0 ldr r0, =mtx_temp bl mat4_rot_y @ Draw a bullet ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 ldr r0, =bullet ldr r1, =mtx_mvp ldr r2, =mtx_model @ don't ask me why ldr r3, =0x3e800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite @ Draw a rocket ldr r0, =mtx_temp ldr r1, =mtx_model ldr r2, =mtx_model bl mat4_mul_mat4 ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 ldr r0, =rocket ldr r1, =mtx_mvp ldr r2, =mtx_model ldr r3, =0x3e800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite @ Draw a wrench ldr r0, =mtx_temp ldr r1, =mtx_model ldr r2, =mtx_model bl mat4_mul_mat4 ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 ldr r0, =wrench ldr r1, =mtx_mvp ldr r2, =mtx_model ldr r3, =0x3e800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite ldmfd sp!, {r0 - r4, pc} 1: .float 0.0 ================================================ FILE: gfx.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global setup_gfx .global gfx_fb .global gfx_swap .global gfx_clear .global gfx_draw_trgs .global gfx_draw_char .global gfx_draw_text .global gfx_draw_sprite .global gfx_draw_image .global gfx_draw_rect .global gfx_draw_frame .include "ports.s" @ ------------------------------------------------------------------------------ @ Useful macros @ ------------------------------------------------------------------------------ .macro vswap a, b, c vmov.f32 \c, \a vmov.f32 \a, \b vmov.f32 \b, \c .endm .macro swap a, b, c mov \c, \a mov \a, \b mov \b, \c .endm .section .data @ ------------------------------------------------------------------------------ @ Framebuffer structure @ ------------------------------------------------------------------------------ .align 4 gfx_fb: .int 640 @ +0x00: Physical width .int 480 @ +0x04: Physical height .int 640 @ +0x08: Virtual width .int 480 @ +0x0C: Virtual height .int 0 @ +0x10: Pitch .int 32 @ +0x14: Bit depth .int 0 @ +0x18: X .int 0 @ +0x1C: Y .int 0 @ +0x20: Address .int 0 @ +0x24: Size .align 2 @------------------------------------------------------------------------------- @ Font bitmap @ Uses 8x16 bits per character, stored left to right top to bottom @ 1 - white pixel @ 0 - black pixel @------------------------------------------------------------------------------- .align 4 font: .incbin "assets/font.bin" .align 2 .section .text @ ------------------------------------------------------------------------------ @ Initialises the framebuffer, retrieving its address @ ------------------------------------------------------------------------------ setup_gfx: stmfd sp!, {lr} @ Request a framebuffer config ldr r0, =0x1 ldr r1, =gfx_fb orr r1, #0x40000000 bl mbox_write bl mbox_read ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Clears the screen and depth buffer, setting depth to -1.0f and filling the @ colour buffer to a given value @ @ Arguments: @ r0 - colour @ Returns: @ none @ Clobbers: @ s0 - s16 @ ------------------------------------------------------------------------------ gfx_clear: stmfd sp!, {r0 - r3} ldr r3, =0x3f800000 @ Clear registers vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r0 vmov.f32 s3, r0 vmov.f32 s4, r0 vmov.f32 s5, r0 vmov.f32 s6, r0 vmov.f32 s7, r0 vmov.f32 s8, r0 vmov.f32 s9, r0 vmov.f32 s10, r0 vmov.f32 s11, r0 vmov.f32 s12, r0 vmov.f32 s13, r0 vmov.f32 s14, r0 vmov.f32 s15, r0 @ Clear 8 pixels at once ldr r0, =gfx_buffer ldr r2, =640 * 480 1: vstm.f32 r0!, {s0 - s15} subs r2, r2, #16 bne 1b ldmfd sp!, {r0 - r3} mov pc, lr @ ------------------------------------------------------------------------------ @ Copies color data from back buffer to framebuffer (color data is interleaved @ with depth data, so it must be extracted). Sets back buffer to the default @ colour and depth. Every iteration of the loop processes 8 pixels. pld is used @ to hint the CPU to prefetch data @ Arguments: @ none @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ gfx_swap: stmfd sp!, {r0 - r12, lr} @ Compute addreses ldr r0, =gfx_fb ldr r0, [r0, #0x20] ldr r1, =gfx_buffer @ Top half of the screen - blue gradient ldr r12, =0xffffee00 ldr r11, =240 1: ldr r2, =640 * 4 ldr r4, =0x00020200 sub r12, r12, r4 vmov.f32 s0, r12 vmov.f32 s1, r12 vmov.f32 s2, r12 vmov.f32 s3, r12 vmov.f32 s4, r12 vmov.f32 s5, r12 vmov.f32 s6, r12 vmov.f32 s7, r12 vmov.f32 s8, r12 vmov.f32 s9, r12 vmov.f32 s10, r12 vmov.f32 s11, r12 vmov.f32 s12, r12 vmov.f32 s13, r12 vmov.f32 s14, r12 vmov.f32 s15, r12 @ Fill 4 lines with one colour 2: pld [r1, #0x100] vldm.f32 r1, {s16 - s31} vstm.f32 r0!, {s16 - s31} vstm.f32 r1!, {s0 - s15} subs r2, r2, #16 bne 2b subs r11, r11, #4 bne 1b @ Bottom half of the screen - green gradient ldr r12, =0xFF8C9C63 ldr r11, =240 3: ldr r2, =640 * 4 vmov.f32 s0, r12 vmov.f32 s1, r12 vmov.f32 s2, r12 vmov.f32 s3, r12 vmov.f32 s4, r12 vmov.f32 s5, r12 vmov.f32 s6, r12 vmov.f32 s7, r12 vmov.f32 s8, r12 vmov.f32 s9, r12 vmov.f32 s10, r12 vmov.f32 s11, r12 vmov.f32 s12, r12 vmov.f32 s13, r12 vmov.f32 s14, r12 vmov.f32 s15, r12 ldr r4, =0x00010101 sub r12, r12, r4 @ Fill 4 lines 4: pld [r1, #0x100] vldm.f32 r1, {s16 - s31} vstm.f32 r0!, {s16 - s31} vstm.f32 r1!, {s0 - s15} subs r2, r2, #16 bne 4b subs r11, r11, #4 bne 3b @ Draw mountains ldr r0, =mountains mov r1, #0 mov r2, #110 bl gfx_draw_image ldmfd sp!, {r0 - r12, pc} @------------------------------------------------------------------------------- @ Renders a character to the screen @ Arguments: @ r0 - Character @ r1 - x coordinate @ r2 - y coordinate @ r3 - RGBA @ Returns: @ none @ Clobbers: @ r0 - r12 @------------------------------------------------------------------------------- gfx_draw_char: cmp r0, #127 @ guard against invalid character inputs movgt pc, lr stmfd sp!, {r0 - r10} @ calculate start address of the character ldr r9, =font add r9, r9, r0, lsl #4 @ r3 = font + ASCII value * 16 @ Store address of the buffer & size of the pitch ldr r6, =gfx_buffer ldr r7, =gfx_fb ldr r7, [r7, #0x10] @ r7 = pitch @ loop through the rows 1: ldrb r4, [r9] @ load byte @ loop through the columns mov r5, #0 2: tst r4, #1 beq 3f @ draw pixel at (x + r5, y) add r10, r1, r5 mla r8, r7, r2, r6 @ r8 = gfx_buffer + y * pitch add r8, r8, r10, lsl #2 @ r8 = gfx_buffer + y * pitch + (x + r5) * 8 str r3, [r8] 3: add r5, #1 lsr r4, #1 cmp r5, #8 blt 2b add r2, #1 @ y = y + 1 add r9, #1 @ process next byte tst r9, #15 @ check if address of the next char reached bne 1b ldmfd sp!, {r0 - r10} mov pc, lr @ ------------------------------------------------------------------------------ @ Renders text on screen @ Arguments: @ r0 - Address of null terminated string @ r1 - X position @ r2 - Y position @ r3 - RGBA @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ gfx_draw_text: stmfd sp!, {r0 - r5, lr} mov r4, r0 mov r5, r1 @ save intial x coordinate 1: ldrb r0, [r4] @ load next character add r4, #1 cmp r0, #0 @ check if '\0' reached beq 2f cmp r0, #9 @ check if '\t' addeq r1, #64 @ move 8 characters horizontally beq 1b cmp r0, #10 @ check if '\n' moveq r1, r5 addeq r2, #16 @ go to the new line beq 1b bl gfx_draw_char add r1, #8 b 1b 2: ldmfd sp!, {r0 - r5, pc} mov pc, lr @ ------------------------------------------------------------------------------ @ Renders a textured sprite on screen @ Arguments: @ r0 - address of the texture @ r1 - Projection * view matrix @ r2 - View matrix @ s0 - width of the quad @ s1 - height of the quad @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ gfx_draw_sprite: stmfd sp!, {r0 - r12, lr} @ Get right vector vldr.f32 s25, [r2] vldr.f32 s26, [r2, #0x10] vldr.f32 s27, [r2, #0x20] vmul.f32 s25, s25, s0 vmul.f32 s26, s26, s0 vmul.f32 s27, s27, s0 @ Get up vector vldr.f32 s28, [r2, #0x04] vldr.f32 s29, [r2, #0x14] vldr.f32 s30, [r2, #0x24] vmla.f32 s25, s28, s1 vmla.f32 s26, s29, s1 vmla.f32 s27, s30, s1 vldm.f32 r1, {s0 - s16} @ Top left ldr r3, =0x3f800000 vmov.f32 s31, r3 vmov.f32 s16, s25 vmov.f32 s17, s26 vmov.f32 s18, s27 vmov.f32 s19, s31 bl mat4_fmul_vec4 bl transform_vertex @ Bottom right vneg.f32 s16, s25 vneg.f32 s17, s26 vneg.f32 s18, s27 vmov.f32 s19, s31 vmov.f32 s28, s20 vmov.f32 s26, s21 vmov.f32 s30, s22 bl mat4_fmul_vec4 bl transform_vertex vmov.f32 s29, s20 vmov.f32 s25, s21 @ Check depth range ldr r5, =0xbf800000 vmov.f32 s21, r5 vcmp.f32 s30, s21 fmstat ldmltfd sp!, {r0 -r12, pc} vneg.f32 s21, s21 vcmp.f32 s30, s21 fmstat ldmgtfd sp!, {r0 -r12, pc} mov r7, #0 vmov.f32 s2, r7 @ pixelY vmov.f32 s3, r7 @ pixelX ldr r5, =479 ftosizs s24, s26 vmov.f32 r1, s24 cmp r1, #0 movlt r1, #0 vneglt.f32 s2, s26 cmp r1, r5 movgt r1, r5 @ y0 ftosizs s24, s25 vmov.f32 r2, s24 cmp r2, #0 movlt r2, #0 cmp r2, r5 movgt r2, r5 @ y1 ldr r5, =639 ftosizs s24, s29 vmov.f32 r3, s24 cmp r3, #0 movlt r3, #0 vneglt.f32 s3, s29 cmp r3, r5 movgt r3, r5 @ x0 ftosizs s24, s28 vmov.f32 r4, s24 cmp r4, #0 movlt r4, #0 cmp r4, r5 movgt r4, r5 @ x1 ldr r5, =gfx_fb ldr r5, [r5, #0x10] @ r5 = pitch ldr r6, =gfx_buffer mla r6, r5, r1, r6 add r6, r6, r3, lsl #2 @ Check bounds subs r2, r2, r1 ble 3f cmp r4, r3 ble 3f ldr r8, [r0], #4 vmov.f32 s0, r8 fsitos s0, s0 vsub.f32 s6, s25, s26 @ height vdiv.f32 s0, s0, s6 ldr r9, [r0], #4 vmov.f32 s1, r9 fsitos s1, s1 vsub.f32 s6, s28, s29 @ width vdiv.f32 s1, s1, s6 lsl r9, r9, #2 ldr r7, =0x3f800000 @ 1.0f vmov.f32 s4, r7 @ Loop over scanline 1: mov r12, r6 subs r7, r4, r3 vmul.f32 s6, s2, s0 ftosizs s6, s6 vmov.f32 r1, s6 vmov.f32 s7, s3 mla r8, r1, r9, r0 2: vmul.f32 s6, s7, s1 ftosizs s6, s6 vmov.f32 r1, s6 @ Texture lookup ldr r11, [r8, r1, lsl #2] lsrs r1, r11, #24 strne r11, [r6] add r6, #4 vadd.f32 s7, s7, s4 subs r7, r7, #1 bgt 2b add r6, r12, r5 vadd.f32 s2, s2, s4 subs r2, r2, #1 bgt 1b 3: ldmfd sp!, {r0 -r12, pc} @ ------------------------------------------------------------------------------ @ Draws an image on screen @ Arguments: @ r0 - image @ r1 - x on screen @ r2 - y on screen @ ------------------------------------------------------------------------------ gfx_draw_image: cmp r1, #640 movge pc, lr cmp r2, #480 movge pc, lr stmfd sp!, {r0 - r12, lr} ldr r4, [r0], #4 @ Width ldr r3, [r0], #4 @ Height cmn r0, r3 stmmifd sp!, {r0 - r12, pc} cmn r1, r4 stmmifd sp!, {r0 - r12, pc} ldr r10, =gfx_fb ldr r10, [r10, #0x10] @ r10 = pitch lsl r12, r3, #2 @ image pitch ldr r11, =gfx_buffer @ buffer tst r1, r1 addmi r3, r3, r1 submi r0, r0, r1, lsl #2 @ Clamp left movmi r1, #0 tst r2, r2 addmi r4, r4, r2 negmi r2, r2 mlami r0, r12, r2, r0 movmi r2, #0 @ Clamp top add r6, r1, r3 cmp r6, #640 subge r6, #640 subge r3, r3, r6 add r6, r2, r4 cmp r6, #480 subge r6, #480 subge r4, r4, r6 mla r11, r2, r10, r11 add r11, r11, r1, lsl #2 tst r1, r1 addmi r3, r3, r1 negmi r1, r1 1: mov r7, r0 mov r8, r11 mov r6, r3 2: ldr r9, [r0], #4 tst r9, #0xFF000000 strne r9, [r11], #4 addeq r11, r11, #4 subs r6, r6, #1 bne 2b add r0, r7, r12 add r11, r8, r10 subs r4, r4, #1 bne 1b ldmfd sp!, {r0 - r12, pc} @ ------------------------------------------------------------------------------ @ Draws a line using Bresenham's algorithm @ r0 - x0 @ r1 - y0 @ r2 - x1 @ r3 - y1 @ r4 - colour @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ gfx_draw_line: stmfd sp!, {r0 - r12, lr} subs r5, r2, r0 neglt r5, r5 @ r5 = dx = abs(x1 - x0) subs r6, r3, r1 neggt r6, r6 @ r6 = -dy = -abs(y1 - y0) cmp r0, r2 movle r7, #1 movgt r7, #-1 @ r7 = x0 < x1 ? 1 : -1 cmp r1, r3 movle r8, #1 movgt r8, #-1 @ r8 = y0 < y1 ? 1 : -1 adds r9, r5, r6 @ err = dx - dy ldr r10, =gfx_fb ldr r10, [r10, #0x10] @ r10 = pitch ldr r11, =gfx_buffer 1: cmp r0, #0 blt 2f cmp r1, #0 blt 2f ldr r12, =639 cmp r0, r12 bge 2f ldr r12, =479 cmp r1, r12 bge 2f mla r12, r10, r1, r11 add r12, r12, r0, lsl #3 @ emit (x0, y0) str r4, [r12] 2: teq r0, r2 teqeq r1, r3 @ bail if x0 == x1 && y0 == y1 beq 3f lsl r12, r9, #1 cmp r12, r6 addgt r9, r9, r6 addgt r0, r0, r7 cmp r12, r5 addlt r9, r9, r5 addlt r1, r1, r8 b 1b 3: ldmfd sp!, {r0 - r12, pc} @ ------------------------------------------------------------------------------ @ Renders a list of triangles @ Arguments: @ r0 - Vertex data @ r1 - Index data @ r2 - Number of triangles @ r3 - MVP matrix @ r4 - Light direction @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ gfx_draw_trgs: stmfd sp!, {r0 - r12, lr} 1: subs r2, r2, #1 blt 3f ldm r1!, {r10, r11, r12} @ Indices vldm.f32 r3, {s0 - s15} @ MVP matrix eor r5, r5, r5 @ Number of visible vertices add r1, #12 add r10, r0, r10, lsl #4 vldm.f32 r10, {s16 - s19} @ r10 = &v0.xyz bl mat4_fmul_vec4 bl transform_vertex vmov.f32 s30, s22 vmov.f32 s29, s21 vmov.f32 s28, s20 @ v0 add r11, r0, r11, lsl #4 vldm.f32 r11, {s16 - s19} @ r11 = &v1.xyz bl mat4_fmul_vec4 bl transform_vertex vmov.f32 s27, s22 vmov.f32 s26, s21 vmov.f32 s25, s20 @ v1 add r12, r0, r12, lsl #4 vldm.f32 r12, {s16 - s19} @ r12 = &v2.xyz bl mat4_fmul_vec4 bl transform_vertex vmov.f32 s24, s22 vmov.f32 s23, s21 vmov.f32 s22, s20 @ v2 @ If at least one vertex is not clipped, continue tst r5, r5 bne 2f @ Check whether triangle intersects the viewport vcmp.f32 s22, #0 fmstat vcmplt.f32 s25, #0 fmstat vcmplt.f32 s28, #0 fmstat blt 1b vcmp.f32 s23, #0 fmstat vcmplt.f32 s26, #0 fmstat vcmplt.f32 s29, #0 fmstat blt 1b ldr r5, =0xbf800000 vmov.f32 s21, r5 vcmp.f32 s24, s21 fmstat vcmplt.f32 s27, s21 fmstat vcmplt.f32 s30, s21 fmstat blt 1b vneg.f32 s21, s21 vcmp.f32 s24, s21 fmstat vcmpgt.f32 s27, s21 fmstat vcmpgt.f32 s30, s21 fmstat bgt 1b ldr r5, =0x43ef8000 vmov.f32 s21, r5 vcmp.f32 s23, s21 fmstat vcmpgt.f32 s26, s21 fmstat vcmpgt.f32 s29, s21 fmstat bgt 1b ldr r5, =0x441fc000 vmov.f32 s21, r5 vcmp.f32 s22, s21 fmstat vcmpgt.f32 s25, s21 fmstat vcmpgt.f32 s28, s21 fmstat bgt 1b @ Cull back faces 2: vmul.f32 s0, s28, s26 @ Check if vertices are in ccw order vmla.f32 s0, s22, s29 @ (note: y coordinates are flipped) vmla.f32 s0, s25, s23 @ | x0 y0 1 | vmls.f32 s0, s22, s26 @ | x1 y1 1 | < 0 vmls.f32 s0, s28, s23 @ | x2 y2 1 | vmls.f32 s0, s25, s29 vmov.f32 r5, s0 tst r5, r5 beq 1b bpl 1b bl shade_triangle bl draw_triangle b 1b 3: ldmfd sp!, {r0 - r12, pc} @ ------------------------------------------------------------------------------ @ Computes window coordinates from normalised device coordinates by performing @ perspective division. Also checks if the vertex is visble on the screen. @ If the vertex is not clipped, r5 is incremented. @ Arguments: @ s16 - s19: Vector @ Returns: @ s20 - s23: (x, y, z, w) @ Clobbers: @ s20 - s24, r5, r6 @ ------------------------------------------------------------------------------ transform_vertex: vcmp.f32 s23, #0 fmstat ble 1f @ w <= 0.0f vcmp.f32 s20, s23 fmstat vcmple.f32 s21, s23 fmstat vcmple.f32 s22, s23 fmstat vneg.f32 s23, s23 bgt 1f @ x > w || y > w || z > w vcmp.f32 s23, s20 fmstat vcmple.f32 s23, s21 fmstat vcmple.f32 s23, s22 fmstat addle r5, #1 @ -w <= x || -w <= y || -w <= z 1: ldr r6, =0x3f800000 vmov.f32 s31, r6 @ 1.0f vdiv.f32 s20, s20, s23 @ x = (1.0f - x) * 320 vsub.f32 s20, s31, s20 ldr r6, =0x43a00000 vmov.f32 s24, r6 @ s24 = 320.0f vmul.f32 s20, s20, s24 vdiv.f32 s21, s21, s23 @ y = (1.0f + y) * 240 vadd.f32 s21, s31, s21 ldr r6, =0x43700000 vmov.f32 s24, r6 @ s24 = 320.0f vmul.f32 s21, s21, s24 vdiv.f32 s22, s22, s23 @ w = -w vneg.f32 s22, s22 mov pc, lr @ ------------------------------------------------------------------------------ @ Performs per-polygon shading, computing a colour value for the entire @ triangle @ Arguments: @ r10, r11, r12 - triangle indices @ Returns: @ r12 - colour value @ Clobbers: @ s0 - s15 @ ------------------------------------------------------------------------------ shade_triangle: vldm.f32 r10, {s0 - s2} @ r10 = &v0.rgb vldm.f32 r11, {s3 - s5} @ r11 = &v1.rgb vldm.f32 r12, {s6 - s8} @ r12 = &v2.rgb @ Compute the normal vector vsub.f32 s0, s0, s3 vsub.f32 s1, s1, s4 vsub.f32 s2, s2, s5 vsub.f32 s6, s6, s3 vsub.f32 s7, s7, s4 vsub.f32 s8, s8, s5 vmul.f32 s3, s1, s8 vmls.f32 s3, s7, s2 vmul.f32 s4, s6, s2 vmls.f32 s4, s0, s8 vmul.f32 s5, s0, s7 vmls.f32 s5, s1, s6 @ Normalize it vmul.f32 s0, s3, s3 vmla.f32 s0, s4, s4 vmla.f32 s0, s5, s5 vsqrt.f32 s0, s0 vdiv.f32 s3, s3, s0 vdiv.f32 s4, s4, s0 vdiv.f32 s5, s5, s0 @ Compute the dot product between the normal @ and the light direction vldm.f32 r4, {s0 - s2} vmul.f32 s0, s0, s3 vmla.f32 s0, s1, s4 vmla.f32 s0, s2, s5 @ Compute light intensity: ambient + diffuse ldr r5, =0x3e4ccccd ldr r6, =0x3f800000 vmov.f32 s1, r5 vmov.f32 s2, r6 vcmp.f32 s0, #0 fmstat vmovlt.f32 s0, s1 vaddgt.f32 s0, s1 ldr r5, =0x437f0000 vmov.f32 s1, r5 vmul.f32 s0, s1 sub r1, #12 vldm.f32 r1, {s3 - s5} add r1, #12 vmul.f32 s3, s3, s0 vmul.f32 s4, s4, s0 vmul.f32 s5, s5, s0 ldr r12, =0xff000000 ftosizs s3, s3 vmov.f32 r11, s3 cmp r11, #0 movlt r11, #0 andgt r11, r11, #0xFF orr r12, r12, r11, lsl #0 ftosizs s4, s4 vmov.f32 r11, s4 cmp r11, #0 movlt r11, #0 andgt r11, r11, #0xFF orr r12, r12, r11, lsl #8 ftosizs s5, s5 vmov.f32 r11, s5 cmp r11, #0 movlt r11, #0 andgt r11, r11, #0xFF orr r12, r12, r11, lsl #16 mov pc, lr @ ------------------------------------------------------------------------------ @ Rasterises a triangle with colour interpolation @ Arguments: @ r10: v0 data @ s28 - s30: v0(x, y, z) @ r11: v1 data @ s25 - s27: v1(x, y, z) @ r12: v2 data @ s22 - s24: v2(x, y, z) @ Returns: @ none @ Clobers: @ s0 - s31, r0 - r12 @ ------------------------------------------------------------------------------ draw_triangle: stmfd sp!, {r0 - r4, lr} @ Sort the points: v0.y < v1.y < v2.y vcmp.f32 s29, s26 fmstat ble 1f vswap s28, s25, s16 vswap s29, s26, s16 vswap s30, s27, s16 1: vcmp.f32 s29, s23 fmstat ble 1f vswap s28, s22, s16 vswap s29, s23, s16 vswap s30, s24, s16 1: vcmp.f32 s26, s23 fmstat ble 1f vswap s25, s22, s16 vswap s26, s23, s16 vswap s27, s24, s16 1: @ Convert y coordinates to integers and clamp them to range [0, 480) ldr r3, =479 ftosizs s0, s29 vmov.s32 r0, s0 cmp r0, #0 movlt r0, #0 cmp r0, r3 movgt r0, r3 @ r0 = clamp(v0.y, 0, 479) ftosizs s0, s26 vmov.s32 r1, s0 cmp r1, #0 movlt r1, #0 cmp r1, r3 movgt r1, r3 @ r1 = clamp(v1.y, 0, 479) ftosizs s0, s23 vmov.s32 r2, s0 cmp r2, #0 movlt r2, #0 cmp r2, r3 movgt r2, r3 @ r2 = clamp(v2.y, 0, 479) @ Compute bounds on x axis vcmp.f32 s25, s22 fmstat vmovgt.f32 s1, s25 vmovgt.f32 s0, s22 vmovle.f32 s1, s22 vmovle.f32 s0, s25 vcmp.f32 s28, s0 fmstat vmovle.f32 s0, s28 @ s0 = min(v0.x, v1.x, v2.x) vcmp.f32 s28, s1 fmstat vmovgt.f32 s1, s28 @ s1 = max(v0.x, v1.x, v2.x) ldr r3, =0 vmov.f32 s21, r3 vcmp.f32 s0, s21 fmstat vmovlt.f32 s0, s21 vcmp.f32 s1, s21 fmstat vmovlt.f32 s1, s21 ldr r3, =0x441fc000 @ r3 = 639.0f vmov.f32 s21, r3 vcmp.f32 s0, s21 fmstat vmovgt.f32 s0, s21 @ s0 = clamp(s0, 0, 639) vcmp.f32 s1, s21 fmstat vmovgt.f32 s1, s21 @ s1 = clamp(s1, 0, 639) @ Compute scanline length ldr r3, =gfx_fb ldr r3, [r3, #0x10] @ r3 = pitch @ ------------------------------------------------------------------------------ @ Rasterizes the top triangle @ ------------------------------------------------------------------------------ raster_top: stmfd sp!, {r0, r1, r2} vstmdb.f32 sp!, {s22 - s30} @ Gradient for v2 - v0 vsub.f32 s31, s23, s29 vsub.f32 s2, s22, s28 vdiv.f32 s2, s2, s31 @ gradLeftX @ Gradient for v1 - v0 vsub.f32 s22, s26, s29 vsub.f32 s7, s25, s28 vdiv.f32 s7, s7, s22 @ gradRightX @ If gradient of v1 - v0 is larger than the gradient @ of v2 - v0, the gradients must be swapped vcmp.f32 s7, s2 fmstat blt 1f vswap s7, s2, s4 vswap s3, s8, s4 vswap s31, s22, s4 1: @ Loop through all scanlines and fill triangles line by line ldr r5, =0x3f800000 vmov.f32 s22, r5 ftosis s31, s29 vmov.f32 r5, s31 cmp r5, #0 neglt r5, r5 movgt r5, #0 subs r1, r1, r0 ble 1f ldr r4, =gfx_buffer mla r4, r0, r3, r4 @ r4 = first row 2: vmov.f32 s31, r5 fsitos s31, s31 bl draw_span add r4, r3 add r5, #1 subs r1, #1 bge 2b 1: vldmia.f32 sp!, {s22 - s30} ldmfd sp!, {r0, r1, r2} @ ------------------------------------------------------------------------------ @ Rasterizes the bottom triangle @ ------------------------------------------------------------------------------ raster_bottom: @ Gradient for v0 - v2 vsub.f32 s2, s28, s22 vsub.f32 s31, s23, s29 vsub.f32 s3, s30, s24 vdiv.f32 s2, s2, s31 @ gradLeftX @ Gradient for v1 - v2 vsub.f32 s7, s25, s22 vsub.f32 s29, s23, s26 vsub.f32 s8, s27, s24 vdiv.f32 s7, s7, s29 @ gradRightX @ If gradient of v1 - v0 is larger than the gradient @ of v2 - v0, the gradients must be swapped vcmp.f32 s7, s2 fmstat blt 1f vswap s2, s7, s4 vswap s3, s8, s4 vswap s4, s9, s4 vswap s29, s31, s4 1: @ Setup origins vmov.f32 s28, s22 vmov.f32 s30, s24 @ Loop through all scanlines and fill triangles line by line ldr r4, =gfx_buffer mla r4, r2, r3, r4 @ r4 = first row subs r2, r1 ble 1f ftosis s24, s23 vmov.f32 r6, s24 ldr r7, =479 cmp r6, r7 subge r5, r6, r7 movlt r5, #0 2: vmov.f32 s31, r5 fsitos s31, s31 bl draw_span sub r4, r3 add r5, #1 subs r2, #1 bge 2b 1: ldmfd sp!, {r0 - r4, pc} @ ------------------------------------------------------------------------------ @ Draws a span between two points on a scanline, interpolating colour and @ depth values and writing data into the back buffer. Note that instructions @ are arranged in order to make full use of the CPUs ability to place up to @ 8 instructions in the pipeline @ @ Arguments: @ r4 - address of scanline @ s0 - min X @ s1 - max X @ s2 - s6 - right edge gradient (x, d, r, g, b) @ s7 - s11 - left edge gradient (x, d, r, g, b) @ Returns: @ none @ Clobbers: @ r6 - r12, s12 - s27 @ ------------------------------------------------------------------------------ draw_span: mov r8, #0 vmov.f32 s12, s28 vmla.f32 s12, s7, s31 @ x0 ftosizs s12, s12 fsitos s12, s12 vmov.f32 s16, s28 vmla.f32 s16, s2, s31 @ x1 vsub.f32 s20, s16, s12 @ length of span vcmp.f32 s0, s12 fmstat vsubgt.f32 s26, s0, s12 ftosizsgt s26, s26 vmovgt.f32 r8, s26 @ x0' vmovgt.f32 s12, s0 vcmp.f32 s1, s12 fmstat vmovlt.f32 s12, s1 @ clamp(x0, s0, s1) vcmp.f32 s1, s16 fmstat vmovlt.f32 s16, s1 vcmp.f32 s0, s16 fmstat vmovgt.f32 s16, s0 @ clamp(x1, s0, s1) ftosis s12, s12 vmov.f32 r6, s12 @ x0 ftosis s16, s16 vmov.f32 r7, s16 @ x1 subs r7, r6 movle pc, lr @ x0 < x1 add r6, r4, r6, lsl #2 @ r6 - first pixel in scanline ldr r10, =0x437f0000 vmov.f32 s22, r10 @ 255.0f 1: vmov.f32 s26, r8 fsitos s26, s26 @ Interpolate colour str r12, [r6], #4 add r8, #1 subs r7, #1 bge 1b mov pc, lr @------------------------------------------------------------------------------- @ Renders a rectangle of size r2xr3 and colour r4 starting at (r0, r1) @ Arguments: @ r0 - x coordinate @ r1 - y coordinate @ r2 - width @ r3 - height @ r4 - colour @ Returns: @ none @ Clobbers: @ none @------------------------------------------------------------------------------- gfx_draw_rect: cmp r2, #0 moveq pc, lr stmfd sp!, {r0 - r10} ldr r6, =gfx_buffer ldr r7, =gfx_fb ldr r7, [r7, #0x10] @ r7 = pitch add r10, r1, r3 @ r10 = y + height 1: mov r5, #0 2: add r9, r0, r5 @ r9 = x + r5 mla r8, r7, r1, r6 @ r8 = gfx_buffer + y * pitch add r8, r8, r9, lsl #2 @ r8 = gfx_buffer + y * pitch + (x + r5) * 4 str r4, [r8] add r5, #1 cmp r5, r2 ble 2b add r1, #1 cmp r1, r10 ble 1b 3: ldmfd sp!, {r0 - r10} mov pc, lr @------------------------------------------------------------------------------- @ Renders a 2px frame of size r2xr3 and colour r4 starting at (r0, r1) @ Arguments: @ r0 - x coordinate @ r1 - y coordinate @ r2 - width @ r3 - height @ r4 - colour @ Returns: @ none @ Clobbers: @ none @------------------------------------------------------------------------------- gfx_draw_frame: cmp r2, #0 moveq pc, lr stmfd sp!, {r0 - r12} ldr r6, =gfx_buffer ldr r7, =gfx_fb ldr r7, [r7, #0x10] @ Draw horizontal lines add r10, r1, #1 add r11, r1, r3 sub r12, r11, #1 mov r5, #0 1: add r9, r0, r5 mla r8, r7, r1, r6 add r8, r8, r9, lsl #2 str r4, [r8] mla r8, r7, r10, r6 add r8, r8, r9, lsl #2 str r4, [r8] mla r8, r7, r11, r6 add r8, r8, r9, lsl #2 str r4, [r8] mla r8, r7, r12, r6 add r8, r8, r9, lsl #2 str r4, [r8] add r5, #1 cmp r5, r2 ble 1b @ Draw vertical lines add r10, r0, #1 add r11, r0, r2 sub r5, r11, #1 add r1, r1, #2 2: mla r2, r7, r1, r6 add r8, r2, r0, lsl #2 str r4, [r8] add r8, r2, r10, lsl #2 str r4, [r8] add r8, r2, r11, lsl #2 str r4, [r8] add r8, r2, r5, lsl #2 str r4, [r8] add r1, #1 cmp r1, r12 blt 2b ldmfd sp!, {r0 - r12} mov pc, lr ================================================ FILE: imager.py ================================================ #!/usr/bin/python2 """ This file is part of the Team 28 Project Licensing information can be found in the LICENSE file (C) 2014 The Team 28 Authors. All rights reserved. """ from PIL import Image import struct import sys import os import argparse def main(): # Parse arguments parser = argparse.ArgumentParser(description='Converts an image to binary') parser.add_argument('file', metavar='N', type=str, nargs=1, help='Input file') parser.add_argument('-o', '--out', help='output .bin file') parser.add_argument('-d', '--add-depth', action='store_true') # Get file names args = parser.parse_args() in_path = args.file[0] root, ext = os.path.splitext(in_path) out_path = args.out if args.out is not None else root + ".bmap" # Read image image = Image.open(in_path) f = open(out_path, 'wb') # Write size width, height = image.size f.write(struct.pack(' down biceq r5, r5, r9 bicne r4, r4, r9 orrne r5, r5, r9 @ Double click: up -> down -> up -> down 3: @ Pulse mov r6, #0x400 str r6, [r0] wait r12, #128 str r6, [r1] wait r12, #128 lsl r9, r9, #1 subs r8, r8, #1 bgt 1b teq r7, #0xFF moveq r7, #0 ldr r0, =button_pressed str r7, [r0] ldr r0, =button_hclicked str r4, [r0] ldr r0, =button_dclicked str r5, [r0] ldmfd sp!, {r0 - r9, pc} ================================================ FILE: kernel.ld ================================================ SECTIONS { /** * Start address of the kernel. * * In QEMU, this is hardcoded to 0x100000 (64Kb). * On the actual device, it can be modified, but it defaults to 0x8000 (32Kb). */ . = 0x10000; /** * Executable code. * * All text segments are copied here. The first file in the object file * is kernel.s and the first function in kernel.s is the kernel function * which initializes everything, so it gets placed at the start address * by the bootstrap code. After the text segment, padding is added in * order to align the next segment to a page boundary. */ .text : { *(.text) } . = ALIGN(0x1000); /** * Program data, all .data segments concatenated after each other. Padding * is added afterwards to align the next segment to page boundary. */ .data : { *(.data) } . = ALIGN(0x1000); /** * Stack spaces. These come after the data from the binary file, * thus they are not actually present in it. They are not loaded, * but the addresses are set up for them after the file. If the * length of the file is x, then the stack addresses are located * at the page boundary after x + 64Kb. */ . = . + 0x800; stack_svc = .; . = . + 0x800; stack_und = .; . = . + 0x800; stack_abt = .; . = . + 0x800; stack_irq = .; . = . + 0x800; stack_fiq = .; . = . + 0x400000; stack_sys = .; /** * Front buffer. Since this buffer is quite large, around 2Mb in size, * it should not appear in the binary file since it would increase the * time it takes to load the kernel. Thus, the address space it requires * is only defined in the linker script and placed at the end of the * kernel, after all data that is loaded from the binary file. */ . = . + 640 * 480 * 8; gfx_buffer = .; } ================================================ FILE: kernel.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global start .include "ports.s" .section .text @ ------------------------------------------------------------------------------ @ Entry point of the application @ ------------------------------------------------------------------------------ kernel: bl setup_stack bl setup_ivt bl setup_vfp bl setup_gfx bl setup_cache bl setup_input bl setup_sound b setup_game @ ------------------------------------------------------------------------------ @ Sets up stacks for all operating modes @ ------------------------------------------------------------------------------ setup_stack: mov r0, #0xD1 @ FIQ msr cpsr, r0 ldr sp, =stack_fiq mov r0, #0xD2 @ IRQ msr cpsr, r0 ldr sp, =stack_irq mov r0, #0xD7 @ ABT msr cpsr, r0 ldr sp, =stack_abt mov r0, #0xDB @ UND msr cpsr, r0 ldr sp, =stack_und mov r0, #0xDF @ SYS msr cpsr, r0 ldr sp, =stack_sys mov r0, #0xD3 @ SVC msr cpsr, r0 ldr sp, =stack_svc mov pc, lr @ ------------------------------------------------------------------------------ @ Relocates the interrupt vector table @ ------------------------------------------------------------------------------ setup_ivt: ldr r10, =ivt_start ldr r11, =0x00000000 ldm r10!, {r0 - r7} stm r11!, {r0 - r7} ldm r10, {r0 - r7} stm r11, {r0 - r7} mov pc, lr @ ------------------------------------------------------------------------------ @ Enables the L1 cache @ ------------------------------------------------------------------------------ setup_cache: mov r0, #0 mcr p15, 0, r0, c7, c7, 0 @ Invalidate caches mcr p15, 0, r0, c8, c7, 0 @ Invalidate TLB mrc p15, 0, r0, c1, c0, 0 ldr r1, =0x1004 orr r0, r0, r1 @ Set L1 enable bit mcr p15, 0, r0, c1, c0, 0 mov pc, lr @ ------------------------------------------------------------------------------ @ Enables the vectored floating point unit @ ------------------------------------------------------------------------------ setup_vfp: mrc p15, #0, r0, c1, c0, #2 orr r0, r0, #0xF00000 @ Single + double precision mcr p15, #0, r0, c1, c0, #2 mov r0, #0x40000000 @ Set VFP enable bit fmxr fpexc, r0 mov pc, lr @ ------------------------------------------------------------------------------ @ Interrupt vector table @ @ On startup, this table has to be relocated to the start of memory. @ It contains jump to interrupt handlers. @ ------------------------------------------------------------------------------ ivt_start: .rept 8 ldr pc, [pc, #0x18] .endr .word handler_hang .word handler_undef .word handler_hang .word handler_hang .word handler_hang .word . .word handler_hang .word handler_hang @ ------------------------------------------------------------------------------ @ Hang when something bad happens @ ------------------------------------------------------------------------------ handler_hang: b . @ ------------------------------------------------------------------------------ @ Undefined instructions - clears FP exception bit @ Like pro windows devs, we put a shitton of effort @ into making an awesome, blue panic screeen @ ------------------------------------------------------------------------------ handler_undef: @ Reset VFP mov r0, #0x40000000 fmxr fpexc, r0 @ Arguments for printf vstm.f32 sp!, {s0 - s31} stmfd sp!, {r0 - r12} stmfd sp!, {lr} @ Nice blue background ldr r0, =0xFFFF0000 bl gfx_clear @ Print address ldr r0, =1f mov r1, #100 mov r2, #100 ldr r3, =0xFFFFFFFF bl printf add sp, sp, #4 @ Present error message bl gfx_swap @ Hang b . 1: .ascii "VFP crashed:\n" .ascii " PC: %8x\n" .ascii " r0: %8x r1: %8x r2: %8x r3: %8x\n" .ascii " r4: %8x r5: %8x r6: %8x r7: %8x\n" .ascii " r8: %8x r9: %8x r10: %8x r11: %8x\n" .ascii " s0: %8x s1: %8x s2: %8x s3: %8x\n" .ascii " s4: %8x s5: %8x s6: %8x s7: %8x\n" .ascii " s8: %8x s9: %8x s10: %8x s11: %8x\n" .ascii "s12: %8x s13: %8x s14: %8x s15: %8x\n" .ascii "s16: %8x s17: %8x s18: %8x s19: %8x\n" .ascii "s20: %8x s21: %8x s22: %8x s23: %8x\n" .ascii "s24: %8x s25: %8x s26: %8x s27: %8x\n" .ascii "s28: %8x s29: %8x s30: %8x s31: %8x\n" .ascii "\0" .align 2 ================================================ FILE: math.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global sin .global cos .global extract_frustum .global mat4_mul_mat4 .global mat4_mul_vec4 .global mat4_fmul_vec4 .global mat4_view .global mat4_translate .global mat4_scale .global mat4_rot_x .global mat4_rot_y .global mat4_rot_z .global vec4_add .global vec4_sub .global vec4_len .global vec4_norm .global vec4_dot .global vec4_cross .global random .global fmod .section .text @ ------------------------------------------------------------------------------ @ s1 = sin(s0) @ Approximation of sine @ Arguments: @ s0 - angle in radians @ Returns: @ s1 - sine of angle @ Clobbers: @ None @ ------------------------------------------------------------------------------ sin: stmfd sp!, {r0} vstmdb.f32 sp!, {s2 - s6} ldr r0, =0x40490FDB vmov.f32 s4, r0 @ s4 = pi ldr r0, =0x40C90FDB vadd.f32 s2, s0, s4 @ s2 = angle + pi = x vmov.f32 s3, r0 @ s3 = 2 * pi = y @ compute (angle + pi) % 2pi; vdiv.f32 s5, s2, s3 @ s5 = x / y vcvt.s32.f32 s5, s5 vcvt.f32.s32 s5, s5 @ s5 = floor(x/y) vmls.f32 s2, s3, s5 @ s2 = x - y * floor(x/y) = m mov r0, #0 vcmp.f32 s2, s3 fmstat vmovge.f32 s2, r0 bge 2f 1:@ m < y vcmp.f32 s2, #0 fmstat bge 2f @ s2 = m @ m < 0 vadd.f32 s2, s2, s3 @ m = m + y vcmp.f32 s2, s3 fmstat vmoveq.f32 s2, r0 2: vsub.f32 s6, s2, s4 @ s6 = ((angle + pi) % 2pi) - pi ldr r0, =0x3fa2f983 @ 4 / pi vmov.f32 s1, r0 vmul.f32 s1, s6 @ s1 = 4 / pi * x vcmp.f32 s6, #0 @ sin(0) = 0 fmstat beq 3f ldr r0, =0x3ecf817b @ 4 / pi ^ 2 vmov.f32 s2, r0 vmul.f32 s2, s2, s6 vmul.f32 s2, s2, s6 vmul.f32 s2, s2, s6 @ s2 = (4 * x * x * x) / pi ^ 2 vabs.f32 s3, s6 vdiv.f32 s2, s2, s3 vsub.f32 s1, s1, s2 3: vldmia.f32 sp!, {s2 - s6} ldmfd sp!, {r0} mov pc, lr @ ------------------------------------------------------------------------------ @ s1 = cos(s0) @ Approximation of cos using sin(x) = cos(pi/2 - x) @ Arguments: @ s0 - angle in radians @ Returns: @ s1 - sine of angle @ Clobbers: @ None @ ------------------------------------------------------------------------------ cos: stmfd sp!, {r0} vstmdb.f32 sp!, {s2 - s6} ldr r0, =0x3FC90FDB vmov.f32 s4, r0 @ s4 = pi/2 vsub.f32 s6, s4, s0 @ angle = pi/2 - angle ldr r0, =0x40490FDB vmov.f32 s4, r0 @ s4 = pi ldr r0, =0x40C90FDB vadd.f32 s2, s6, s4 @ s2 = angle + pi = x vmov.f32 s3, r0 @ s3 = 2 * pi = y @ compute (angle + pi) % 2pi; vdiv.f32 s5, s2, s3 @ s5 = x / y vcvt.s32.f32 s5, s5 vcvt.f32.s32 s5, s5 @ s5 = floor(x/y) vmls.f32 s2, s3, s5 @ s2 = x - y * floor(x/y) = m mov r0, #0 vcmp.f32 s2, s3 fmstat blt 1f vmov.f32 s2, r0 @ s2 = 0 b 2f 1: @ m < y vcmp.f32 s2, #0 fmstat bge 2f @ s2 = m @ m < 0 vadd.f32 s2, s2, s3 @ m = m + y vcmp.f32 s2, s3 fmstat vmoveq.f32 s2, r0 2: vsub.f32 s6, s2, s4 @ s6 = ((angle + pi) % 2pi) - pi ldr r0, =0x3fa2f983 @ 4 / pi vmov.f32 s1, r0 vmul.f32 s1, s6 @ s1 = 4 / pi * x vcmp.f32 s6, #0 fmstat beq 3f ldr r0, =0x3ecf817b @ 4 / pi ^ 2 vmov.f32 s2, r0 vmul.f32 s2, s2, s6 vmul.f32 s2, s2, s6 vmul.f32 s2, s2, s6 @ s2 = (4 * x * x * x) / pi ^ 2 vabs.f32 s3, s6 vdiv.f32 s2, s2, s3 vsub.f32 s1, s1, s2 3: vldmia.f32 sp!, {s2 - s6} ldmfd sp!, {r0} mov pc, lr @ ------------------------------------------------------------------------------ @ Multiplies two matrices together @ r2 = r1 * r0 @ Arguments: @ r0 - location of first matrix @ r1 - location of second matrix @ r2 - output matrix address @ Return values: @ none @ Clobbers: @ s0 - s23 @ ------------------------------------------------------------------------------ mat4_mul_mat4: stmfd sp!, {r3, r4} vldm.f32 r0, {s0 - s15} mov r4, #4 1: vldm.f32 r1!, {s16 - s19} vmul.f32 s20, s0, s16 vmla.f32 s20, s4, s17 vmla.f32 s20, s8, s18 vmla.f32 s20, s12, s19 vmul.f32 s21, s1, s16 vmla.f32 s21, s5, s17 vmla.f32 s21, s9, s18 vmla.f32 s21, s13, s19 vmul.f32 s22, s2, s16 vmla.f32 s22, s6, s17 vmla.f32 s22, s10, s18 vmla.f32 s22, s14, s19 vmul.f32 s23, s3, s16 vmla.f32 s23, s7, s17 vmla.f32 s23, s11, s18 vmla.f32 s23, s15, s19 vstm.f32 r2!, {s20 - s23} subs r4, #1 bne 1b @ Restore pointers sub r1, #64 sub r2, #64 ldmfd sp!, {r3, r4} mov pc, lr @ ------------------------------------------------------------------------------ @ Multiplies a matrix with a vector @ Arguments: @ r0 - location of the matrix @ r1 - location of the vector @ r2 - output vector address @ Returns: @ none @ Clobbers: @ s0 - s19 @ ------------------------------------------------------------------------------ mat4_mul_vec4: vldm.f32 r0, {s0 - s15} vldm.f32 r1, {s16 - s19} vmul.f32 s20, s0, s16 vmul.f32 s21, s1, s16 vmul.f32 s22, s2, s16 vmul.f32 s23, s3, s16 vmla.f32 s20, s4, s17 vmla.f32 s21, s5, s17 vmla.f32 s22, s6, s17 vmla.f32 s23, s7, s17 vmla.f32 s20, s8, s18 vmla.f32 s21, s9, s18 vmla.f32 s22, s10, s18 vmla.f32 s23, s11, s18 vmla.f32 s20, s12, s19 vmla.f32 s21, s13, s19 vmla.f32 s22, s14, s19 vmla.f32 s23, s15, s19 vstm.f32 r2, {s20 - s23} mov pc, lr @ ------------------------------------------------------------------------------ @ Multiplies a matrix with a vector in registers @ Arguments: @ s0 - s15: matrix @ s16 - s19: vector @ s20 - s23: output @ Returns: @ none @ Clobbers: @ s0 - s19 @ ------------------------------------------------------------------------------ mat4_fmul_vec4: vmul.f32 s20, s0, s16 vmul.f32 s21, s1, s16 vmul.f32 s22, s2, s16 vmul.f32 s23, s3, s16 vmla.f32 s20, s4, s17 vmla.f32 s21, s5, s17 vmla.f32 s22, s6, s17 vmla.f32 s23, s7, s17 vmla.f32 s20, s8, s18 vmla.f32 s21, s9, s18 vmla.f32 s22, s10, s18 vmla.f32 s23, s11, s18 vmla.f32 s20, s12, s19 vmla.f32 s21, s13, s19 vmla.f32 s22, s14, s19 vmla.f32 s23, s15, s19 mov pc, lr @ ------------------------------------------------------------------------------ @ Computes a view matrix @ Arguments: @ r0 - eye @ r1 - at @ r2 - up @ r3 - destination matrix @ Returns: @ none @ Clobbers: @ s0 - s15 @ ------------------------------------------------------------------------------ mat4_view: stmfd sp!, {r4} vldm.f32 r0, {s0 - s3} @ eye{s0, s1, s2} vldm.f32 r1, {s3 - s6} @ at{s3, s4, s5} vldm.f32 r2, {s6 - s9} @ up{s6, s7, s8} @ z{s9, s10, s11} = norm(eye - at) vsub.f32 s9, s0, s3 vsub.f32 s10, s1, s4 vsub.f32 s11, s2, s5 vmul.f32 s12, s9, s9 vmla.f32 s12, s10, s10 vmla.f32 s12, s11, s11 vsqrt.f32 s12, s12 vdiv.f32 s9, s9, s12 vdiv.f32 s10, s10, s12 vdiv.f32 s11, s11, s12 @ x{s3, s4, s5} = norm(cross(up, z)) vmul.f32 s3, s7, s11 vmls.f32 s3, s8, s10 vmul.f32 s4, s8, s9 vmls.f32 s4, s6, s11 vmul.f32 s5, s6, s10 vmls.f32 s5, s7, s9 vmul.f32 s12, s3, s3 vmla.f32 s12, s4, s4 vmla.f32 s12, s5, s5 vsqrt.f32 s12, s12 vdiv.f32 s3, s3, s12 vdiv.f32 s4, s4, s12 vdiv.f32 s5, s5, s12 @ y{s6, s7, s8} = cross(z, x) vmul.f32 s6, s10, s5 vmls.f32 s6, s11, s4 vmul.f32 s7, s11, s3 vmls.f32 s7, s9, s5 vmul.f32 s8, s9, s4 vmls.f32 s8, s10, s3 mov r4, #0 vmov.f32 s15, r4 @ First column vmov.f32 s12, s3 vmov.f32 s13, s6 vmov.f32 s14, s9 vstm.f32 r3!, {s12 - s15} @ Second column vmov.f32 s12, s4 vmov.f32 s13, s7 vmov.f32 s14, s10 vstm.f32 r3!, {s12 - s15} @ Third column vmov.f32 s12, s5 vmov.f32 s13, s8 vmov.f32 s14, s11 vstm.f32 r3!, {s12 - s15} @ Fourth column vmov.f32 s12, s15 vmls.f32 s12, s0, s3 vmls.f32 s12, s1, s4 vmls.f32 s12, s2, s5 vmov.f32 s13, s15 vmls.f32 s13, s0, s6 vmls.f32 s13, s1, s7 vmls.f32 s13, s2, s8 vmov.f32 s14, s15 vmls.f32 s14, s0, s9 vmls.f32 s14, s1, s10 vmls.f32 s14, s2, s11 mov r4, #0x3f800000 vmov.f32 s15, r4 vstm.f32 r3, {s12 - s15} sub r3, r3, #48 ldmfd sp!, {r4} mov pc, lr @ ------------------------------------------------------------------------------ @ Builds a translation matrix @ Arguments: @ r0 - matrix @ s0 - s3: translation @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mat4_translate: vstr.f32 s0, [r0, #48] vstr.f32 s1, [r0, #52] vstr.f32 s2, [r0, #56] mov pc, lr @ ------------------------------------------------------------------------------ @ Builds a scaling matrix @ Arguments: @ r0 - matrix @ s0 - s3: translation @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mat4_scale: vstr.f32 s0, [r0] vstr.f32 s1, [r0, #20] vstr.f32 s2, [r0, #40] mov pc, lr @ ------------------------------------------------------------------------------ @ Creates a rotation matrix around X @ Arguments: @ r0 - matrix @ s0 - angle @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mat4_rot_x: stmfd sp!, {lr} bl sin vstr.f32 s1, [r0, #24] vneg.f32 s1, s1 vstr.f32 s1, [r0, #36] bl cos vstr.f32 s1, [r0, #20] vstr.f32 s1, [r0, #40] ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Creates a rotation matrix @ Arguments: @ r0 - matrix @ s0 - angle @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mat4_rot_y: stmfd sp!, {lr} bl sin vstr.f32 s1, [r0, #32] vneg.f32 s1, s1 vstr.f32 s1, [r0, #8] bl cos vstr.f32 s1, [r0, #0] vstr.f32 s1, [r0, #40] ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Creates a rotation matrix around Z @ Arguments: @ r0 - matrix @ s0 - angle @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mat4_rot_z: stmfd sp!, {lr} bl sin vstr.f32 s1, [r0, #4] vneg.f32 s1, s1 vstr.f32 s1, [r0, #16] bl cos vstr.f32 s1, [r0, #0] vstr.f32 s1, [r0, #20] ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Computes a 3x3 determinant @ Arguments: @ s23 - s31: coefficients @ Returns: @ s22 - determinant @ Clobbers: @ s21 @ ------------------------------------------------------------------------------ mat3_fdet: vmul.f32 s21, s27, s31 vmls.f32 s21, s28, s30 vmul.f32 s22, s23, s21 vmul.f32 s21, s28, s29 vmls.f32 s21, s26, s31 vmla.f32 s22, s24, s21 vmul.f32 s21, s26, s30 vmls.f32 s21, s27, s29 vmla.f32 s22, s25, s21 mov pc, lr @ ------------------------------------------------------------------------------ @ Adds two 4D vectors @ Arguments: @ r0 - location of first vector @ r1 - location of second vector @ r2 - location of destination @ Return values: @ None @ Clobbers: @ s0 - s11 @ ------------------------------------------------------------------------------ vec4_add: vldm.f32 r0, {s0 - s3} vldm.f32 r1, {s4 - s7} vadd.f32 s8, s0, s4 vadd.f32 s9, s1, s5 vadd.f32 s10, s2, s6 vadd.f32 s11, s3, s7 vstm.f32 r2, {s8 - s11} mov pc, lr @ ------------------------------------------------------------------------------ @ Subtracts a vector from another @ Arguments: @ r0 - location of first vector @ r1 - location of second vector @ r2 - location of destination @ Return values: @ None @ Clobbers @ s0 - s11 @ ------------------------------------------------------------------------------ vec4_sub: vldm.f32 r0, {s0 - s3} vldm.f32 r1, {s4 - s7} vsub.f32 s8, s0, s4 vsub.f32 s9, s1, s5 vsub.f32 s10, s2, s6 vsub.f32 s11, s3, s7 vstm.f32 r2, {s8 - s11} mov pc, lr @ ------------------------------------------------------------------------------ @ Computes the length of a vector @ Arguments: @ r0 - location of first vector @ Return values: @ s0 - length of the vector @ Clobers: @ s1 - s3 @ ------------------------------------------------------------------------------ vec4_len: vldm.f32 r0, {s0 - s3} vmul.f32 s0, s0, s0 vmla.f32 s0, s1, s1 vmla.f32 s0, s2, s2 vsqrt.f32 s0, s0 mov pc, lr @ ------------------------------------------------------------------------------ @ Computes the normalised vector(unit vector) of the given vector @ Arguments: @ r0 - location of the vector @ r1 - location of the destination @ Return values: @ None @ Clobbers @ s0 - s4 @ ------------------------------------------------------------------------------ vec4_norm: vldm.f32 r0, {s0 - s3} vmul.f32 s4, s0, s0 vmla.f32 s4, s1, s2 vmla.f32 s4, s2, s2 vsqrt.f32 s4, s4 @ s4 = |v| vdiv.f32 s0, s0, s4 vdiv.f32 s1, s1, s4 vdiv.f32 s2, s2, s4 vstm.f32 r1, {s0 - s3} mov pc, lr @ ------------------------------------------------------------------------------ @ Computes the dot product of two vectors @ Arguments: @ r0 - location of the first vector @ r1 - location of the second vector @ Return values: @ s0 - dot product @ Clobbers @ s0 - s6 @ ------------------------------------------------------------------------------ vec4_dot: vldm.f32 r0, {s1 - s3} vldm.f32 r1, {s4 - s6} vmul.f32 s0, s1, s4 vmla.f32 s0, s2, s5 vmla.f32 s0, s3, s6 mov pc, lr @ ------------------------------------------------------------------------------ @ Computes the cross product of two vectors @ Arguments: @ r0 - location of the first vector @ r1 - location of the second vector @ r2 - location of the destination @ Return values: @ None @ Clobbers: @ s0 - s10 @ ------------------------------------------------------------------------------ vec4_cross: stmfd sp!, {r3} vldm.f32 r0, {s0 - s3} @ s0 = x1; s1 = y1; s2 = z1 vldm.f32 r1, {s3 - s6} @ s3 = x2; s4 = y2; s5 = z2 vmul.f32 s6, s1, s5 @ s6 = y1 * z2 vmls.f32 s6, s4, s2 @ s6 = s6 - (y2 * z1) vmul.f32 s7, s3, s2 @ s7 = x2 * z1 vmls.f32 s7, s0, s5 @ s7 = s7 - (x1 * z2) vmul.f32 s8, s0, s4 @ s8 = x1 * y2 vmls.f32 s8, s1, s3 @ s8 = s8 - (x2 * y1) mov r3, #0 vmov.f32 s9, r3 vstm.f32 r2, {s6 - s9} ldmfd sp!, {r3} mov pc, lr @ ------------------------------------------------------------------------------ @ Floating point modulo @ Arguments: @ s0 - x @ s1 - y @ Returns: @ s2 - x % y @ Clobbers: @ None @ ------------------------------------------------------------------------------ fmod: stmfd sp!, {r0} vstmdb.f32 sp!, {s3} vcmp.f32 s1, #0 fmstat beq 4f mov r0, #0 vdiv.f32 s3, s0, s1 @ s3 = x / y vcvt.s32.f32 s3, s3 vcvt.f32.s32 s3, s3 @ s3 = floor(x/y) vmls.f32 s0, s1, s3 @ s0 = x - y * floor(x/y) = m vcmp.f32 s1, #0 fmstat ble 2f vcmp.f32 s0, s1 fmstat blt 1f vmov.f32 s0, r0 b 4f @ s0 = 0 1: vcmp.f32 s0, #0 fmstat bge 4f @ s0 = m vadd.f32 s0, s0, s1 @ s0 = m + y vcmp.f32 s0, s1 vmoveq.f32 s0, r0 @ s0 = 0 b 4f 2: vcmp.f32 s0, s1 fmstat bgt 3f vmov.f32 s0, r0 b 4f @ s0 = 0 3: vcmp.f32 s0, #0 fmstat ble 4f @ s0 = m vadd.f32 s0, s0, s1 @ s0 = m + y vcmp.f32 s0, s1 fmstat vmoveq.f32 s0, r0 @ s0 = 0 4: vmov.f32 s2, s0 @ s2 = s0 vldmia.f32 sp!, {s3} ldmfd sp!, {r0} mov pc, lr @ ------------------------------------------------------------------------------ @ Computes the intersection point of three planes using Kramer's rule @ Arguments: @ s0 - s3: (a1, b1, c1, d1) @ s4 - s7: (a1, b1, c1, d1) @ s8 - s11: (a1, b1, c1, d1) @ Returns: @ s12 - s14: (x, y, z) @ Clobbers: @ s15, s22 - s31 @ ------------------------------------------------------------------------------ insersect_planes: mov r11, lr vmov.f32 s23, s0 vmov.f32 s24, s4 vmov.f32 s25, s8 vmov.f32 s26, s1 vmov.f32 s27, s5 vmov.f32 s28, s9 vmov.f32 s29, s2 vmov.f32 s30, s6 vmov.f32 s31, s10 bl mat3_fdet vmov.f32 s15, s22 @ det vmov.f32 s23, s3 vmov.f32 s24, s7 vmov.f32 s25, s11 bl mat3_fdet vdiv.f32 s12, s22, s15 @ x vneg.f32 s12, s12 vmov.f32 s23, s0 vmov.f32 s24, s4 vmov.f32 s25, s8 vmov.f32 s26, s3 vmov.f32 s27, s7 vmov.f32 s28, s11 bl mat3_fdet vdiv.f32 s13, s22, s15 @ y vneg.f32 s13, s13 vmov.f32 s26, s1 vmov.f32 s27, s5 vmov.f32 s28, s9 vmov.f32 s29, s3 vmov.f32 s30, s7 vmov.f32 s31, s11 bl mat3_fdet vdiv.f32 s14, s22, s15 @ z vneg.f32 s14, s14 mov pc, r11 @ ------------------------------------------------------------------------------ @ Extracts clip planes from a view-projection matrix @ Arguments: @ r0 - matrix @ r1 - frustum @ Returns: @ 8 vertices on the stack @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ extract_frustum: mov r12, lr add r2, r1, #96 vldr.f32 s16, [r0, #12] vldr.f32 s17, [r0, #28] vldr.f32 s18, [r0, #44] vldr.f32 s19, [r0, #60] bl load_near vstmia.f32 r2!, {s0 - s3} bl load_left vstmia.f32 r2!, {s8 - s11} bl load_bottom vstmia.f32 r2!, {s4 - s7} bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ near-left-bottom bl load_top bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ near-left-top bl load_right bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ near-right-top bl load_bottom bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ near-right-bottom bl load_far vstmia.f32 r2!, {s0 - s3} bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ far-right-bottom bl load_left bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ far-left-bottom bl load_top vstmia.f32 r2!, {s4 - s7} bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ far-left-top bl load_right vstmia.f32 r2!, {s8 - s11} bl insersect_planes vstmia.f32 r1!, {s12 - s14} @ far-right-top mov pc, r12 @ ------------------------------------------------------------------------------ @ Loads near plane into registers @ ------------------------------------------------------------------------------ load_near: vldr.f32 s12, [r0, #8] vldr.f32 s13, [r0, #24] vldr.f32 s14, [r0, #40] vldr.f32 s15, [r0, #56] vadd.f32 s0, s16, s12 vadd.f32 s1, s17, s13 vadd.f32 s2, s18, s14 vadd.f32 s3, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Loads far plane into registers @ ------------------------------------------------------------------------------ load_far: vldr.f32 s12, [r0, #8] vldr.f32 s13, [r0, #24] vldr.f32 s14, [r0, #40] vldr.f32 s15, [r0, #56] vsub.f32 s0, s16, s12 vsub.f32 s1, s17, s13 vsub.f32 s2, s18, s14 vsub.f32 s3, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Loads bottom plane into registers @ ------------------------------------------------------------------------------ load_bottom: vldr.f32 s12, [r0, #4] vldr.f32 s13, [r0, #20] vldr.f32 s14, [r0, #36] vldr.f32 s15, [r0, #52] vadd.f32 s4, s16, s12 vadd.f32 s5, s17, s13 vadd.f32 s6, s18, s14 vadd.f32 s7, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Loads top plane into registers @ ------------------------------------------------------------------------------ load_top: vldr.f32 s12, [r0, #4] vldr.f32 s13, [r0, #20] vldr.f32 s14, [r0, #36] vldr.f32 s15, [r0, #52] vsub.f32 s4, s16, s12 vsub.f32 s5, s17, s13 vsub.f32 s6, s18, s14 vsub.f32 s7, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Loads top plane into registers @ ------------------------------------------------------------------------------ load_left: vldr.f32 s12, [r0, #0] vldr.f32 s13, [r0, #16] vldr.f32 s14, [r0, #32] vldr.f32 s15, [r0, #48] vadd.f32 s8, s16, s12 vadd.f32 s9, s17, s13 vadd.f32 s10, s18, s14 vadd.f32 s11, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Loads top plane into registers @ ------------------------------------------------------------------------------ load_right: vldr.f32 s12, [r0, #0] vldr.f32 s13, [r0, #16] vldr.f32 s14, [r0, #32] vldr.f32 s15, [r0, #48] vsub.f32 s8, s16, s12 vsub.f32 s9, s17, s13 vsub.f32 s10, s18, s14 vsub.f32 s11, s19, s15 mov pc, lr @ ------------------------------------------------------------------------------ @ Generates a random number using a linear shift register @ Arguments: @ none @ Returns: @ r0 - random number @ Clobbers: @ none @ ------------------------------------------------------------------------------ random: stmfd sp!, {r1 - r2} ldr r1, =1f ldr r0, [r1] mov r2, r0 eor r2, r2, r0, lsr #2 eor r2, r2, r0, lsr #3 eor r2, r2, r0, lsr #5 and r2, r2, #1 lsr r0, r0, #1 orr r0, r0, r2, lsl #15 str r0, [r1] ldmfd sp!, {r1 - r2} mov pc, lr 1: .long 0xACE1 ================================================ FILE: mbox.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global mbox_read .global mbox_write .include "ports.s" .section .text @ ------------------------------------------------------------------------------ @ Reads a value from the mailbox @ @ Arguments: @ r0 - Channel @ Returns: @ none @ Clobbers: @ r1 - Return data @ ------------------------------------------------------------------------------ mbox_read: stmfd sp!, {r2 - r4} ldr r2, =MBOX_BASE eor r4, r4, r4 1: @ Timeout add r4, #1 tst r4, #0x80000 mvnne r1, #1 bne 2f @ Flush cache mcr p15, #0, r1, c7, c14, #0 @ Check for ready flag ldr r3, [r2, #0x18] tst r3, #0x40000000 bne 1b @ Read in data (dmb first) mcr p15, #0, r1, c7, c10, #5 ldr r3, [r2, #0x00] @ Check if the channel is right and r1, r3, #0x0F teq r0, r1 bne 1b @ Extract data bic r1, r3, #0xF 2: ldmfd sp!, {r2 - r4} mov pc, lr @ ------------------------------------------------------------------------------ @ Writes a value to the mailbox @ @ Arguments: @ r0 - channel @ r1 - data @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ mbox_write: stmfd sp!, {r1 - r4} ldr r2, =MBOX_BASE eor r4, r4 @ Wait until mailbox is ready 1: add r4, #1 tst r4, #0x80000 bne 2f @ Flush cache mcr p15, #0, r3, c7, c14, #0 ldr r3, [r2, #0x18] tst r3, #0x80000000 bne 1b @ Send message (dmb first) mcr p15, #0, r3, c7, c10, #5 orr r1, r0, r1 str r1, [r2, #0x20] 2: ldmfd sp!, {r1 - r4} mov pc, lr ================================================ FILE: objects.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global draw_rocks .global reset_objects .global OBJECT_COUNT .global object_list .include "ports.s" .section .data @ ------------------------------------------------------------------------------ @ Obstacles @ ------------------------------------------------------------------------------ .equ OBJECT_COUNT, 35 .equ ROCK_LIVES, 3 object_spawn: .long 0xfffff @ Frame number of the last spawned rock object_list: .rept OBJECT_COUNT .float 0.0, 0.0, 0.0 @ Position (x, y, z) .float 1.5 @ Movement speed .float 0.0 @ Rotation .long 0 @ Type .long ROCK_LIVES @ Lives .endr .section .text @ ------------------------------------------------------------------------------ @ Renders the rocks on the sides @ ------------------------------------------------------------------------------ draw_rocks: stmfd sp!, {lr} bl update_rocks bl sort_objects ldr r12, =OBJECT_COUNT ldr r11, =object_list 1: vldm.f32 r11!, {s0 - s6} ldr r0, =0xc1200000 @ -7.0 vmov.f32 s7, r0 vcmp.f32 s2, s7 fmstat bllt draw_object subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Updates the position of the rocks @ ------------------------------------------------------------------------------ update_rocks: stmfd sp!, {lr} ldr r12, =OBJECT_COUNT ldr r11, =object_list 1: vldm.f32 r11, {s0 - s6} @ Check whether rock is 'live' ldr r0, =0xc1200000 vmov.f32 s7, r0 vcmp.f32 s2, s7 fmstat blt 4f @ Rock moving out of bound ldr r2, [r11, #8] tst r2, r2 beq 5f @ Clear depth mov r1, #0 vmov.f32 s2, r1 @ Test for collision with player ldr r0, =player_pos vldm.f32 r0, {s30 - s31} vsub.f32 s7, s0, s30 vabs.f32 s7, s7 vsub.f32 s8, s1, s31 ldr r0, =0x40000000 vmov.f32 s9, r0 vsub.f32 s8, s8, s9 vabs.f32 s8, s8 ldr r0, =0x3fe00000 vmov.f32 s9, r0 vcmp.f32 s7, s9 fmstat bgt 3f vcmp.f32 s8, s9 fmstat bgt 3f vmov.f32 r0, s6 tst r0, #0x1E beq 2f @ Decrease health ldr r0, =player_rolling ldr r0, [r0] tst r0, r0 bne 5f mov r0, #20 bl player_damage b 5f 2: tst r0, #1 ldreq r0, =player_wrenches ldrne r0, =player_rockets ldr r1, [r0] add r1, r1, #1 cmp r1, #4 movge r1, #3 str r1, [r0] bllt snd_play_pickup b 5f 3: ldr r0, =player_score @ Add to score ldr r1, [r0] add r1, r1, #5 str r1, [r0] 5: @ Spawn a new rock once every 30 frames ldr r0, =object_spawn ldr r1, [r0] add r1, r1, #1 cmp r1, #0x20 movge r1, #0 blge spawn_object str r1, [r0] ldr r0, =enemy_count ldr r0, [r0] tst r0, r0 movne r0, #0 vmovne.f32 s2, r0 vstm.f32 r11!, {s0 - s6} b 5f 4: @ Check whether object collided with a bullet ldr r0, =0x40000000 vmov.f32 s31, r0 bl collide_bullets tst r0, r0 bne 6f vmov.f32 r0, s5 subs r0, r0, #1 vmov.f32 s5, r0 vmoveq s2, r0 beq 3b 6: @ Updates position ldr r0, =player_speed vldr.f32 s9, [r0] ldr r0, =0x3dcccccd vmov.f32 s8, r0 vadd.f32 s2, s2, s3 vadd.f32 s2, s2, s9 vmov.f32 r0, s6 tst r0, #0x1E vaddne.f32 s4, s4, s8 vstm.f32 r11!, {s0 - s6} 5: subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Sorts rocks by their z coordinate @ ------------------------------------------------------------------------------ sort_objects: ldr r12, =OBJECT_COUNT sub r10, r12, #1 ldr r11, =object_list ldr r4, =28 @ size of rock in bytes ldr r5, =0x0 @ i 1: @ outer loop start ldr r6, =0x0 @ j 2: @ inner loop start @ Calculate address of j and j+1 mla r7, r6, r4, r11 add r8, r7, r4 @ Compare Z coordinates ldr r0, [r7, #8] vmov.f32 s0, r0 ldr r1, [r8, #8] vmov.f32 s1, r1 vcmp.f32 s0, s1 fmstat ble 3f @ Swap vldm.f32 r7, {s18 - s24} vldm.f32 r8, {s25 - s31} vstm.f32 r8, {s18 - s24} vstm.f32 r7, {s25 - s31} 3: @ inner loop end add r6, r6, #1 cmp r6, r10 blt 2b 4: @ outer loop end add r5, r5, #1 sub r10, r10, #1 cmp r5, r12 blt 1b mov pc, lr @ ------------------------------------------------------------------------------ @ Spawns a new rock @ Arguments: @ none @ Returns: @ s0 - s4: rock attributes @ Clobbers: @ none @ ------------------------------------------------------------------------------ spawn_object: stmfd sp!, {r0 - r1, lr} @ Randomize x in range [-8.5, 8.5] bl random and r1, r0, #0xFF sub r1, r1, #0x7F vmov.f32 s8, r1 fsitos s8, s8 ldr r1, =0x41400000 vmov.f32 s9, r1 vdiv.f32 s0, s8, s9 @ Randomize y in range [-2.8, 5.2] bl random and r1, r0, #0xFF sub r1, r1, #0x7F vmov.f32 s8, r1 fsitos s8, s8 ldr r1, =0x41f00000 vmov.f32 s9, r1 vdiv.f32 s1, s8, s9 @ Set z to -300.0 ldr r0, =0xc3960000 vmov.f32 s2, r0 @ Reset rotation ldr r0, =0x00000000 vmov.f32 s4, r0 @ Randomize type bl random and r0, #0x1F vmov.f32 s6, r0 @ Lives for rocks ldr r0, =ROCK_LIVES vmov.f32 s5, r0 ldmfd sp!, {r0 - r1, pc} @ ------------------------------------------------------------------------------ @ Draws an object @ @ Arguments: @ s0 - s4: Rock attributes @ Returns: @ none @ Clobbers: @ s0 - s31 @ Remarks: @ tail call - called function pops return address from stack @ ------------------------------------------------------------------------------ draw_object: stmfd sp!, {lr} vstmdb.f32 sp!, {s5 - s6} @ Reset model matrix ldr r0, =mtx_id vldm.f32 r0, {s16 - s31} ldr r0, =mtx_model vstm.f32 r0, {s16 - s31} ldr r0, =mtx_temp vstm.f32 r0, {s16 - s31} @ Translate & rotate vneg.f32 s1, s1 ldr r0, =mtx_model bl mat4_translate vmov.f32 s0, s4 ldr r0, =mtx_temp bl mat4_rot_y ldr r0, =mtx_model ldr r1, =mtx_temp ldr r2, =mtx_model bl mat4_mul_mat4 @ Render the cube ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 vldmia.f32 sp!, {s5 - s6} vmov.f32 r0, s6 teq r0, #0 beq draw_wrench_sprite teq r0, #1 beq draw_rocket_sprite b draw_rock @ ------------------------------------------------------------------------------ @ Draws a single rock @ Arguments: @ s0 - s4: Rock attributes @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ draw_rock: vmov.f32 r5, s5 sub r5, r5, #1 ldr r6, =480 ldr r0, =rock_vtx ldr r1, =rock_idx mla r1, r5, r6, r1 ldr r2, =20 ldr r3, =mtx_mvp ldr r4, =light_dir bl gfx_draw_trgs ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Draws a wrench sprite @ Arguments: @ s0 - s4: Rock attributes @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ draw_wrench_sprite: ldr r0, =wrench ldr r1, =mtx_mvp ldr r2, =mtx_view ldr r3, =0x3f800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Draws a rocket sprite @ Arguments: @ s0 - s4: Rock attributes @ Returns: @ none @ Clobbers: @ s0 - s31 @ ------------------------------------------------------------------------------ draw_rocket_sprite: ldr r0, =rocket ldr r1, =mtx_mvp ldr r2, =mtx_view ldr r3, =0x3f800000 vmov.f32 s0, r3 vmov.f32 s1, r3 bl gfx_draw_sprite ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Resets objects @------------------------------------------------------------------------------- reset_objects: stmfd sp!, {r0 - r4, lr} vstmdb.f32 sp!, {s0 - s6} ldr r4, =OBJECT_COUNT ldr r3, =object_list ldr r2, =ROCK_LIVES ldr r1, =0x3FC00000 @ 1.5 mov r0, #0 1: vldm.f32 r3, {s0 - s6} vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r0 vmov.f32 s3, r1 vmov.f32 s4, r0 vmov.f32 s5, r0 vmov.f32 s6, r2 vstm.f32 r3!, {s0 - s6} subs r4, #1 bne 1b vldmia.f32 sp!, {s0 - s6} ldmfd sp!, {r0 - r4, pc} ================================================ FILE: pillars.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global draw_pillars .global pillar_pos .section .data .include "assets/pillar.s" .section .text @ ------------------------------------------------------------------------------ @ Cubes on the sides @ ------------------------------------------------------------------------------ .equ PILLAR_COUNT, 24 pillar_pos: .float 0.0 pillar_list: .float -10.0, 0.0, -142.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -130.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -118.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -106.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -94.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -82.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -70.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -58.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -46.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -34.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -22.0 .float 1.0, 6.0, 1.0 .float -10.0, 0.0, -10.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -142.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -130.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -118.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -106.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -94.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -82.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -70.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -58.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -46.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -34.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -22.0 .float 1.0, 6.0, 1.0 .float 10.0, 0.0, -10.0 .float 1.0, 6.0, 1.0 @ ------------------------------------------------------------------------------ @ Renders the pillars on the sides @ ------------------------------------------------------------------------------ draw_pillars: stmfd sp!, {lr} ldr r12, =PILLAR_COUNT ldr r11, =pillar_list @ Reset model matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_model vstm.f32 r0, {s0 - s15} @ Get player position ldr r0, =player_speed vldr.f32 s3, [r0] ldr r0, =pillar_pos vldr.f32 s4, [r0] vadd.f32 s4, s4, s3 ldr r1, =0x41400000 vmov.f32 s5, r1 vcmp.f32 s4, s5 fmstat ldr r1, =0x00000000 vmovgt.f32 s4, r1 vstr.f32 s4, [r0] 1: vldm.f32 r11!, {s0 - s2} vstmdb.f32 sp!, {s4} vadd.f32 s2, s2, s4 bl draw_pillar vldmia.f32 sp!, {s4} subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Draws a single pillar @ ------------------------------------------------------------------------------ draw_pillar: stmfd sp!, {lr} ldr r0, =mtx_model bl mat4_translate vldm.f32 r11!, {s0 - s2} bl mat4_scale ldr r0, =mtx_vp ldr r1, =mtx_model ldr r2, =mtx_mvp bl mat4_mul_mat4 ldr r0, =pillar_vtx ldr r1, =pillar_idx ldr r2, =10 ldr r3, =mtx_mvp ldr r4, =light_dir bl gfx_draw_trgs ldmfd sp!, {pc} ================================================ FILE: player.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global player_pos .global player_health .global player_rolling .global player_speed .global player_shake .global player_score .global player_high_score .global player_wrenches .global player_rockets .global draw_player .global player_damage .global update_player .global setup_player .global reset_player_mov .global monkey_timer .global rock_timer .section .data @ ------------------------------------------------------------------------------ @ Player resources @ ------------------------------------------------------------------------------ player_charge: .long 0 player_health: .long 200 player_wrenches: .long 3 player_rockets: .long 3 tristan_timer: .long 0 monkey_timer: .long 0 rock_timer: .long 0 @ ------------------------------------------------------------------------------ @ Player movement @ ------------------------------------------------------------------------------ player_tilt_z: .float 0.0 player_tilt_x: .float 0.0 player_rolling: .long 0 player_shake: .long 0 player_score: .long 0 player_high_score: .long 0 player_roll_dir: .float 0.15 player_pos: .float 0.0, 0.0, 0.0 player_speed: .float 0.0 player_speed_mod: .long 0 .section .text @ ------------------------------------------------------------------------------ @ Initialises the player @ ------------------------------------------------------------------------------ setup_player: stmfd sp!, {r0 - r1, lr} ldr r0, =player_charge ldr r1, =0 str r1, [r0] ldr r0, =player_health ldr r1, =200 str r1, [r0] ldr r0, =player_wrenches ldr r1, =3 str r1, [r0] ldr r0, =player_rockets ldr r1, =3 str r1, [r0] ldr r0, =player_score mov r1, #0 str r1, [r0] ldr r0, =player_speed_mod mov r1, #0 str r1, [r0] ldr r0, =tristan_timer mov r1, #0 str r1, [r0] ldr r0, =monkey_timer mov r1, #0 str r1, [r0] ldr r0, =rock_timer mov r1, #130 str r1, [r0] ldr r0, =player_pos mov r1, #0 vmov.f32 s0, r1 vmov.f32 s1, r1 vmov.f32 s2, r1 vstm.f32 r0, {s0 - s2} ldmfd sp!, {r0 - r1, pc} @ ------------------------------------------------------------------------------ @ Renders the player's plane @ ------------------------------------------------------------------------------ draw_player: stmfd sp!, {lr} @ Reset model matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_model vstm.f32 r0, {s0 - s15} mov r1, #0 vmov.f32 s0, r1 ldr r1, =0xc0000000 vmov.f32 s1, r1 ldr r1, =0xc0e00000 vmov.f32 s2, r1 bl mat4_translate @ Tilt around Z ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_temp vstm.f32 r0, {s0 - s15} ldr r0, =player_tilt_z vldr.f32 s0, [r0] ldr r0, =mtx_temp bl mat4_rot_z ldr r0, =mtx_model ldr r1, =mtx_temp ldr r2, =mtx_model bl mat4_mul_mat4 @ Tilt around X ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_temp vstm.f32 r0, {s0 - s15} ldr r0, =player_tilt_x vldr.f32 s0, [r0] ldr r0, =mtx_temp bl mat4_rot_x ldr r0, =mtx_model ldr r1, =mtx_temp ldr r2, =mtx_model bl mat4_mul_mat4 @ Compute proj * model ldr r0, =mtx_proj ldr r1, =mtx_model ldr r2, =mtx_mp bl mat4_mul_mat4 @ Draw the plane ldr r0, =ship_vtx ldr r1, =ship_idx ldr r2, =22 ldr r3, =mtx_mp ldr r4, =light_dir bl gfx_draw_trgs @ Draw wrenches ldr r3, =player_wrenches ldr r3, [r3] ldr r1, =582 ldr r2, =410 ldr r0, =wrench tst r3, r3 beq 2f 1: bl gfx_draw_image sub r1, r1, #20 subs r3, r3, #1 bne 1b 2: @ Draw rockets ldr r3, =player_rockets ldr r3, [r3] mov r1, #34 ldr r2, =410 ldr r0, =rocket tst r3, r3 beq 2f 1: bl gfx_draw_image add r1, r1, #20 subs r3, r3, #1 bne 1b 2: @ Draw health bar ldr r0, =522 ldr r1, =450 ldr r5, =player_health ldr r6, =0xFF0000cc bl draw_bar @ Draw charge bar mov r0, #10 ldr r1, =450 ldr r5, =player_charge ldr r6, =0xFFFF4400 bl draw_bar @ Test if monkey should pop-up ldr r0, =monkey_timer ldr r1, [r0] subs r1, r1, #1 str r1, [r0] ble 2f @ Draw monkey ldr r0, =124 ldr r1, =420 ldr r5, =monkey ldr r6, =5f bl draw_pop_up ldmfd sp!, {pc} 2: @ Test if Tristan should pop-up ldr r0, =tristan_timer ldr r1, [r0] subs r1, r1, #1 str r1, [r0] ble 3f @ Draw Tristan barrel roll ldr r0, =124 ldr r1, =420 ldr r5, =tristan ldr r6, =4f bl draw_pop_up ldmfd sp!, {pc} 3: @ Test if Tristan should pop-up ldr r0, =rock_timer ldr r1, [r0] subs r1, r1, #1 str r1, [r0] ldmlefd sp!, {pc} @ Draw Tristan rock-and-roll ldr r0, =124 ldr r1, =420 ldr r5, =tristan ldr r6, =6f bl draw_pop_up ldmfd sp!, {pc} 4: .ascii "\nDo a barrel roll!" .byte 0x0 .align 2 5: .ascii "\nCan't let you do that PiFox!" .byte 0x0 .align 2 6: .ascii "I see 'em up ahead.\nLet's Rock and Roll!" .byte 0x0 .align 2 @ ------------------------------------------------------------------------------ @ Rotates the camera around origin @ ------------------------------------------------------------------------------ update_player: stmfd sp!, {lr} bl do_barrel_roll bl do_speed bl do_movement bl do_repair bl do_rocket bl do_charge bl do_matrices bl do_speed_inc ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Continues a barrell roll @ ------------------------------------------------------------------------------ do_barrel_roll: stmfd sp!, {lr} @ If we are already rolling, continue ldr r0, =player_rolling ldr r1, [r0] tst r1, r1 bne 1f @ Roll when left/right is double clicked ldr r2, =button_dclicked ldr r2, [r2] tst r2, #0xC0 ldmeqfd sp!, {pc} @ Charge must be full ldr r3, =player_charge ldr r4, [r3] cmp r4, #200 ldmltfd sp!, {pc} mov r4, #0 str r4, [r3] @ Play sounds bl snd_play_boost @ Start the roll ldr r3, =player_roll_dir vldr.f32 s0, [r3] vabs.f32 s0, s0 tst r2, #0x80 vnegne.f32 s0, s0 vstr.f32 s0, [r3] mov r1, #1 str r1, [r0] ldmfd sp!, {pc} 1: @ Update rotation ldr r2, =player_roll_dir vldr.f32 s0, [r2] ldr r2, =player_tilt_z vldr.f32 s1, [r2] vadd.f32 s1, s1, s0 vcmp.f32 s0, #0 fmstat bgt 2f ldr r3, =0xc0c90fdb vmov.f32 s2, r3 vcmp.f32 s1, s2 fmstat movlt r1, #0 vmovlt.f32 s1, r1 b 3f 2: ldr r3, =0x40c90fdb vmov.f32 s2, r3 vcmp.f32 s1, s2 fmstat movgt r1, #0 vmovgt.f32 s1, r1 3: str r1, [r0] vstr.f32 s1, [r2] ldr r0, =0x3f800000 @ 1.0 ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Updates the movement speed of the player @ ------------------------------------------------------------------------------ do_speed: ldr r0, =player_speed_mod vldr.f32 s0, [r0] fsitos s0, s0 ldr r0, =0x3a378034 @ 0.0007 vmov.f32 s1, r0 vmul.f32 s0, s0, s1 ldr r0, =0x3f800000 vmov.f32 s1, r0 vadd.f32 s0, s0, s1 ldr r0, =0x40600000 @ 3.5 vmov.f32 s1, r0 ldr r0, =player_rolling ldr r0, [r0] tst r0, r0 vmulne.f32 s0, s0, s1 ldr r0, =0x40a00000 vmov.f32 s1, r0 vcmp.f32 s0, s1 fmstat vmovgt.f32 s0, s1 ldr r0, =player_speed vstr.f32 s0, [r0] mov pc, lr @ ------------------------------------------------------------------------------ @ Increase player's speed modifier @ ------------------------------------------------------------------------------ do_speed_inc: stmfd sp!, {r0, r1} ldr r0, =player_speed_mod ldr r1, [r0] add r1, r1, #1 str r1, [r0] ldmfd sp!, {r0, r1} mov pc, lr @ ------------------------------------------------------------------------------ @ Updates the position of the player @ ------------------------------------------------------------------------------ do_movement: @ Normal speed ldr r0, =player_rolling ldr r0, [r0] tst r0, r0 movne pc, lr stmfd sp!, {lr} @ Get button state ldr r2, =button_pressed ldr r2, [r2] @ Move player forward ldr r0, =player_pos vldm.f32 r0, {s0 - s2} ldr r3, =0x3f800000 @ 1.0 vmov.f32 s4, r3 tst r2, #0x80 vaddne.f32 s0, s4 @ right tst r2, #0x40 vsubne.f32 s0, s4 @ left tst r2, #0x10 vsubne.f32 s1, s4 @ up tst r2, #0x20 vaddne.f32 s1, s4 @ down bl clamp vstm.f32 r0, {s0 - s2} @ Tilt left/right ldr r3, =player_tilt_z vldr.f32 s0, [r3] ldr r0, =0x3d23d70a @ 0.04 vmov.f32 s1, r0 tst r2, #0x80 beq 1f vsub.f32 s0, s1 ldr r0, =0xbecccccd @ -0.4 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovlt.f32 s0, s2 b 4f 1: tst r2, #0x40 beq 2f vadd.f32 s0, s1 ldr r0, =0x3ecccccd @ 0.4 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovgt.f32 s0, s2 b 4f 2: vcmp.f32 s0, #0 fmstat blt 3f vsub.f32 s0, s1 ldr r0, =0 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovlt.f32 s0, s2 b 4f 3: vadd.f32 s0, s1 ldr r0, =0 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovgt.f32 s0, s2 4: vstr.f32 s0, [r3] @ Tilt up/down ldr r3, =player_tilt_x vldr.f32 s0, [r3] ldr r0, =0x3d23d70a @ 0.04 vmov.f32 s1, r0 tst r2, #0x20 beq 1f vsub.f32 s0, s1 ldr r0, =0xbecccccd @ -0.4 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovlt.f32 s0, s2 b 4f 1: tst r2, #0x10 beq 2f vadd.f32 s0, s1 ldr r0, =0x3dcccccd @ 0.1 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovgt.f32 s0, s2 b 4f 2: vcmp.f32 s0, #0 fmstat blt 3f vsub.f32 s0, s1 ldr r0, =0 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovlt.f32 s0, s2 b 4f 3: vadd.f32 s0, s1 ldr r0, =0 vmov.f32 s2, r0 vcmp.f32 s0, s2 fmstat vmovgt.f32 s0, s2 4: vstr.f32 s0, [r3] ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Handles repairs @------------------------------------------------------------------------------- do_repair: @ Repair when B was double clicked ldr r0, =button_dclicked ldr r0, [r0] tst r0, #0x02 moveq pc, lr @ Check number of repairs left ldr r0, =player_wrenches ldr r1, [r0] tst r1, r1 moveq pc, lr sub r1, #1 str r1, [r0] @ Update health ldr r0, =player_health ldr r1, [r0] add r1, #50 cmp r1, #200 movgt r1, #200 str r1, [r0] mov pc, lr @------------------------------------------------------------------------------- @ Handles firing rockets @------------------------------------------------------------------------------- do_rocket: stmfd sp!, {lr} @ Fire when B was clicked ldr r0, =button_clicked ldr r1, [r0] tst r1, #0x02 moveq pc, lr @ Check number of rockets left ldr r0, =player_rockets ldr r1, [r0] tst r1, r1 moveq pc, lr sub r1, #1 str r1, [r0] @ Play rocket sound bl snd_play_rocket @ Fire the rocket bl spawn_rocket ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Increses the charge of barrell roll @------------------------------------------------------------------------------- do_charge: @ Check for roll ldr r0, =player_rolling ldr r0, [r0] tst r0, r0 movne pc, lr @ Update charge ldr r0, =player_charge ldr r1, [r0] cmp r1, #200 add r1, #1 strlt r1, [r0] mov pc, lr @ ------------------------------------------------------------------------------ @ Computes mtx_view and mtx_vp @ ------------------------------------------------------------------------------ do_matrices: stmfd sp!, {lr} @ Clear the view matrix ldr r0, =mtx_id vldm.f32 r0, {s0 - s15} ldr r0, =mtx_view vstm.f32 r0, {s0 - s15} @ Shake the world ldr r0, =player_shake ldr r1, [r0] tst r1, r1 subne r1, r1, #1 str r1, [r0] vmov.f32 s0, r1 fsitos s0, s0 bl sin ldr r0, =0x42700000 vmov.f32 s2, r0 vmul.f32 s5, s0, s1 vdiv.f32 s5, s5, s2 @ Compute the view matrix (translation) ldr r0, =player_pos vldm.f32 r0, {s0 - s2} vadd.f32 s1, s1, s5 vabs.f32 s5, s5 vsub.f32 s0, s5, s0 ldr r0, =mtx_view bl mat4_translate @ Compute the proj * view matrix ldr r0, =mtx_proj ldr r1, =mtx_view ldr r2, =mtx_vp bl mat4_mul_mat4 ldmfd sp!, {pc} @ ------------------------------------------------------------------------------ @ Clamps a coordinate, forcing it inside bounds on X and Y axis @ @ Arguments: @ s0 - x @ s1 - y @ s2 - z @ Returns: @ s0 - clamped x @ s1 - clamped y @ s2 - clamped z @ Clobbers @ none @ ------------------------------------------------------------------------------ clamp: stmfd sp!, {r0} vstmdb.f32 sp!, {s3} ldr r0, =0x41080000 @ 8.5 vmov.f32 s3, r0 vcmp.f32 s0, s3 fmstat vmovgt.f32 s0, s3 ldr r0, =0xc1080000 @ -8.5 vmov.f32 s3, r0 vcmp.f32 s0, s3 fmstat vmovlt.f32 s0, s3 ldr r0, =0x3f000000 @ 0.5 vmov.f32 s3, r0 vcmp.f32 s1, s3 fmstat vmovgt.f32 s1, s3 ldr r0, =0xc0900000 @ -4.5 vmov.f32 s3, r0 vcmp.f32 s1, s3 fmstat vmovlt.f32 s1, s3 vldmia.f32 sp!, {s3} ldmfd sp!, {r0} mov pc, lr @------------------------------------------------------------------------------- @ Draws health / charge bar @ @ Arguments: @ r0 - x @ r1 - y @ r5 - current amount address @ r6 - colour @ Returns: @ none @ Clobbers: @ none @------------------------------------------------------------------------------- draw_bar: stmfd sp!, {r0 - r6, lr} @ Draw frame mov r2, #108 mov r3, #20 ldr r4, =0xFFFFFF00 bl gfx_draw_frame @ Draw current charge add r0, #4 add r1, #4 ldr r2, [r5] lsr r2, r2, #1 sub r3, r3, #8 mov r4, r6 bl gfx_draw_rect ldmfd sp!, {r0 - r6, pc} @------------------------------------------------------------------------------- @ Draws character @ Arguments: @ r0 - x @ r1 - y @ r5 - picture address @ r6 - message address @ Returns: @ none @ Clobbers: @ none @------------------------------------------------------------------------------- draw_pop_up: stmfd sp!, {r0 - r6, lr} @ Draw frame mov r2, #58 mov r3, #57 ldr r4, =0xFFFFFF00 bl gfx_draw_frame add r2, r1, #3 add r1, r0, #3 mov r0, r5 bl gfx_draw_image mov r0, r6 add r1, r1, #60 add r2, r2, #16 ldr r3, =0xFFFFFF00 bl printf ldmfd sp!, {r0 - r6, pc} @ ------------------------------------------------------------------------------ @ Applies damage to the player @ Arguments: @ r0 - damage @ Returns: @ none @ Clobbers: @ none @ ------------------------------------------------------------------------------ player_damage: stmfd sp!, {r0 - r4, lr} ldr r3, =player_speed_mod @ Decrement score ldr r4, [r3] subs r4, r4, #300 movlt r4, #0 str r4, [r3] @ Play damage sound bl snd_play_crash ldr r1, =player_health @ Decrement health ldr r2, [r1] cmp r2, #100 blt 1f sub r3, r2, r0 cmp r3, #100 bgt 1f @ Pop-up Tristan ldr r3, =tristan_timer mov r4, #110 str r4, [r3] bl snd_play_roll 1: sub r2, r2, r0 cmp r2, #0 movle r2, #0 str r2, [r1] ldr r1, =player_shake mov r2, #40 str r2, [r1] ldmfd sp!, {r0 - r4, pc} @------------------------------------------------------------------------------- @ Resets player movement @------------------------------------------------------------------------------- reset_player_mov: stmfd sp!, {r0 -r1, lr} vstmdb.f32 sp!, {s0} mov r0, #0 vmov.f32 s0, r0 ldr r1, =player_tilt_z vstm.f32 r1, {s0} ldr r1, =player_tilt_x vstm.f32 r1, {s0} ldr r1, =player_rolling str r0, [r1] ldr r1, =player_shake str r0, [r1] ldr r1, =player_speed vstm.f32 r1, {s0} ldr r1, =player_roll_dir ldr r0, =0x3E19999A @ 0.15 vmov.f32 s0, r0 vstm.f32 r1, {s0} vldmia.f32 sp!, {s0} ldmfd sp!, {r0 - r1, pc} ================================================ FILE: ports.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. @ ------------------------------------------------------------------------------ @ System timer @ ------------------------------------------------------------------------------ .equ STIMER_CS, 0x20003000 .equ STIMER_CLO, 0x20003004 .equ STIMER_CHI, 0x20003008 .equ STIMER_C0, 0x2000300C .equ STIMER_C1, 0x20003010 .equ STIMER_C2, 0x20003014 .equ STIMER_C3, 0x20003018 @ ------------------------------------------------------------------------------ @ Interrupt register @ ------------------------------------------------------------------------------ .equ IRQ_PENDING, 0x2000B200 .equ IRQ_GPU_PENDING1, 0x2000B204 .equ IRQ_GPU_PENDING2, 0x2000B208 .equ IRQ_FIQ, 0x2000B20C .equ IRQ_EN1, 0x2000B210 .equ IRQ_EN2, 0x2000B214 .equ IRQ_ENB, 0x2000B218 .equ IRQ_DS1, 0x2000B21C .equ IRQ_DS2, 0x2000B220 .equ IRQ_DSB, 0x2000B224 @ ------------------------------------------------------------------------------ @ ARM timer @ ------------------------------------------------------------------------------ .equ TIMER_LOD, 0x2000B400 .equ TIMER_VAL, 0x2000B404 .equ TIMER_CTL, 0x2000B408 .equ TIMER_CLI, 0x2000B40C .equ TIMER_RIS, 0x2000B410 .equ TIMER_MIS, 0x2000B414 .equ TIMER_RLD, 0x2000B418 .equ TIMER_DIV, 0x2000B41C .equ TIMER_CNT, 0x2000B420 @ ------------------------------------------------------------------------------ @ Mailbox Ports @ ------------------------------------------------------------------------------ .equ MBOX_BASE, 0x2000B880 .equ MBOX_READ, 0x2000B880 .equ MBOX_POLL, 0x2000B890 .equ MBOX_SENDER, 0x2000B894 .equ MBOX_STATUS, 0x2000B898 .equ MBOX_CONFIG, 0x2000B89C .equ MBOX_WRITE, 0x2000B8A0 @ ------------------------------------------------------------------------------ @ GPIO Ports @ ------------------------------------------------------------------------------ .equ GPIO_FSEL0, 0x20200000 .equ GPIO_FSEL1, 0x20200004 .equ GPIO_FSEL2, 0x20200008 .equ GPIO_FSEL3, 0x2020000C .equ GPIO_FSEL4, 0x20200010 .equ GPIO_FSEL5, 0x20200014 .equ GPIO_SET0, 0x2020001C .equ GPIO_SET1, 0x20200020 .equ GPIO_CLR0, 0x20200028 .equ GPIO_CLR1, 0x2020002C .equ GPIO_LEV0, 0x20200034 .equ GPIO_LEV1, 0x20200038 .equ GPIO_EDS0, 0x20200040 .equ GPIO_EDS1, 0x20200044 .equ GPIO_REN0, 0x2020004C .equ GPIO_REN1, 0x20200050 .equ GPIO_FEN0, 0x20200058 .equ GPIO_FEN1, 0x2020005C .equ GPIO_HEN0, 0x20200064 .equ GPIO_HEN1, 0x20200068 .equ GPIO_LEN0, 0x20200070 .equ GPIO_LEN1, 0x20200074 .equ GPIO_AREN0, 0x2020007C .equ GPIO_AREN1, 0x20200080 .equ GPIO_AFEN0, 0x20200088 .equ GPIO_AFEN1, 0x2020008C .equ GPIO_PUD, 0x20200094 .equ GPIO_UDCLK0, 0x20200098 .equ GPIO_UDCLK1, 0x2020009C @ ------------------------------------------------------------------------------ @ PL011 UART Ports @ ------------------------------------------------------------------------------ .equ UART_DR, 0x20201000 .equ UART_RSECR, 0x20201004 .equ UART_FR, 0x20201018 .equ UART_ILPR, 0x20201020 .equ UART_IBRD, 0x20201024 .equ UART_FBRC, 0x20201028 .equ UART_LCRH, 0x2020102C .equ UART_CR, 0x20201030 .equ UART_IFLS, 0x20201034 .equ UART_IMSC, 0x20201038 .equ UART_RIS, 0x2020103C .equ UART_MIS, 0x20201040 .equ UART_ICR, 0x20201044 .equ UART_DMACR, 0x20201048 .equ UART_ITCR, 0x20201080 .equ UART_ITIP, 0x20201084 .equ UART_ITOP, 0x20201088 .equ UART_TDR, 0x2020108C @ ------------------------------------------------------------------------------ @ Clock manager @ ------------------------------------------------------------------------------ .equ CM_PWMCTL, 0x201010A0 .equ CM_PWMDIV, 0x201010A4 @ ------------------------------------------------------------------------------ @ Direct Memory Access @ ------------------------------------------------------------------------------ .equ DMA0_CS, 0x20007000 .equ DMA0_CONBLK, 0x20007004 .equ DMA_INT_STATUS, 0x20007FE0 .equ DMA_ENABLE, 0x20007FF0 @ ------------------------------------------------------------------------------ @ Pulse Width modulator @ ------------------------------------------------------------------------------ .equ PWM_CTL, 0x2020C000 .equ PWM_STA, 0x2020C004 .equ PWM_DMAC, 0x2020C008 .equ PWM_RNG1, 0x2020C010 .equ PWM_DAT1, 0x2020C014 .equ PWM_FIF1, 0x2020C018 .equ PWM_RNG2, 0x2020C020 .equ PWM_DAT2, 0x2020C024 ================================================ FILE: printf.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved..global printf .global printf .section .text @ ------------------------------------------------------------------------------ @ Print formatted string. @ The format string may contain the following sequences: @ %[n]x - print hexadecimal, pad to n chars @ %[n]d - print decimal, pad to n chars @ %s - print string @ Arguments are taken from the stack and they must be pushed from the right to @ the left. Stack cleanup is the responsibility of the caller. @ @ Arguments: @ r0 - address of the output format string @ stack - number(s)/string(s) to be printed, in reversed order @ Return: @ None @ Clobbers: @ None @ ------------------------------------------------------------------------------ printf: stmfd sp!, {r0 - r12, lr} @ r0 will store address of the format string @ r1 will store beginning of the output string add r4, sp, #56 mov r3, sp ldr lr, =1f 1: mov r2, #0 ldrb r1, [r0], #1 @ put next char in r1 tst r1, r1 beq 4f @ exit if r2 == '\0' cmp r1, #37 beq 2f strb r1, [sp, #-1]! @ store character on stack b 1b 2: ldrb r1, [r0], #1 cmp r1, #100 @ d = decimal beq printf_d cmp r1, #115 @ s = string beq printf_s cmp r1, #120 @ x = hexadecimal beq printf_x cmp r1, #48 blo 3f cmp r1, #57 bhi 3f @ Charater is a digit subs r2, r1, #48 b 2b 3: mov r2, #37 strb r2, [sp, #-1]! strb r1, [sp, #-1]! tst r1, r1 bne 1b 4: mov r1, #0 strb r1, [sp, #-1]! @ Store a null terminator @ Reverse buffer mov r4, sp sub r5, r3, #1 5: ldrb r1, [r4] ldrb r2, [r5] strb r1, [r5], #-1 strb r2, [r4], #1 cmp r4, r5 blo 5b @ Print to stdout with a syscall mov r4, r3 mov r0, sp ldr r1, [r3, #4] ldr r2, [r3, #8] ldr r3, [r3, #12] bl gfx_draw_text mov sp, r4 ldmfd sp!, {r0 - r12, pc} @ ------------------------------------------------------------------------------ @ Decimal helper for printf @ Arguments: @ r5 - Number to print @ r2 - Max size of buffer @ ------------------------------------------------------------------------------ printf_d: ldr r5, [r4], #4 ldr r7, =429496730 sub r10, sp, #1 cmp r5, #0 @ check sign bge 1f mov r6, #45 @ r6 = '-' neg r5, r5 1: cmp r2, #0 bne 3f @ if r2 != 0 then write the digits with padding 2: @ Handles the case where padding is not required i.e. r2 = 0 mov r9, r5 sub r5, r5, r5, lsr #30 umull r8, r5, r7, r5 mov r8, #10 mul r8, r5, r8 sub r9, r9, r8 add r9, #48 strb r9, [sp, #-1]! cmp r5, #0 bgt 2b b 5f 3: mov r11, #32 @ r11 = ' ' 4: @ Handles padding mov r9, r5 sub r5, r5, r5, lsr #30 umull r8, r5, r7, r5 mov r8, #10 mul r8, r5, r8 sub r9, r9, r8 add r9, #48 strb r9, [sp, #-1]! sub r2, r2, #1 cmp r2, #0 beq 5f cmp r5, #0 bgt 4b 5: @ Puts minus if negative cmp r6, #45 bne 6f strb r6, [sp, #-1]! sub r2, r2, #1 6: @ Padds with spaces if necessary cmp r2, #0 ble 7f strb r11, [sp, #-1]! sub r2, r2, #1 b 6b 7: mov r11, sp 8: @ Reverses the buffer ldrb r8, [r10] ldrb r9, [r11] strb r8, [r11], #1 strb r9, [r10], #-1 cmp r10, r11 bgt 8b mov pc, lr @ ------------------------------------------------------------------------------ @ Hexadecimal helper for printf @ Arguments: @ r5 - Number to print @ ------------------------------------------------------------------------------ printf_x: ldr r5, [r4], #4 tst r2, r2 bne 2f mov r6, r5 1: add r2, #1 lsrs r6, r6, #4 bne 1b 2: sub sp, r2 @ Unroll for first digit and r6, r5, #0xF lsr r5, r5, #4 cmp r6, #10 addlo r6, #48 addhs r6, #55 strb r6, [sp] mov r7, #1 subs r2, r2, #1 beq 4f 3: @ Write the rest of the digits with padding and r6, r5, #0xF cmp r6, #10 addlo r6, #48 addhs r6, #55 lsr r5, r5, #4 strb r6, [sp, r7] add r7, r7, #1 subs r2, r2, #1 bne 3b 4: mov pc, lr @ ------------------------------------------------------------------------------ @ String helper for printf @ Arguments: @ r5 - Address of the string @ ------------------------------------------------------------------------------ printf_s: ldr r5, [r4], #4 1: ldrb r6, [r5], #1 cmp r6, #0 beq 2f strb r6, [sp, #-1]! b 1b 2: mov pc, lr ================================================ FILE: rockets.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global draw_rockets .global spawn_rocket .global reset_rockets .section .data @------------------------------------------------------------------------------- @ Rockets @------------------------------------------------------------------------------- .equ ROCKET_COUNT, 5 rocket_list: .rept ROCKET_COUNT .float 0.0, 0.0, 0.0 @ (x, y, z) .float 0.25 @ speed .float 0.0 @ rotation .long 0 @ active .endr .section .text @------------------------------------------------------------------------------- @ Draws rockets @------------------------------------------------------------------------------- draw_rockets: stmfd sp!, {lr} ldr r12, =ROCKET_COUNT ldr r11, =rocket_list ldr r10, =0x40a00000 vmov.f32 s31, r10 @ radius = 5 1: vldmia.f32 r11!, {s0 - s4} ldmia r11!, {r9} tst r9, r9 beq 3f vmov.f32 s11, s0 vmov.f32 s12, s1 vmov.f32 s13, s2 mov r0, r9 bl collide_objects bl collide_enemies mov r9, r0 @ Update position vsub.f32 s2, s2, s3 @ Update rotation ldr r0, =0x3C23D70A @ r0 = 0.01 vmov.f32 s5, r0 vadd.f32 s4, s4, s5 ldr r0, =0xc3480000 vmov.f32 s5, r0 @ s5 = -200 vcmp.f32 s2, s5 fmstat movle r9, #0 3: stmdb r11!, {r9} vstmdb.f32 r11!, {s0 - s4} tst r9, r9 blne draw_rocket add r11, r11, #24 subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Spawn rocket @------------------------------------------------------------------------------- spawn_rocket: stmfd sp!, {lr} ldr r12, =ROCKET_COUNT ldr r11, =rocket_list 1: vldmia.f32 r11!, {s0 - s4} ldmia r11!, {r9} @ do not overwrite an existing rocket tst r9, r9 bne 2f ldr r0, =player_pos vldmia.f32 r0, {s0 - s2} @ set z ldr r0, =0xC1200000 vmov.f32 s2, r0 @ z = -10 @ set y ldr r0, =0xc0000000 vmov.f32 s5, r0 vsub.f32 s1, s1, s5 @ y = p.y + 2 @ set speed ldr r0, =0x3f800000 vmov.f32 s3, r0 @ speed = 0.25 @ set rotation ldr r0, =0 vmov.f32 s4, r0 @ activate mov r9, #1 stmdb r11!, {r9} vstmdb.f32 r11!, {s0 - s4} ldmfd sp!, {pc} 2: stmdb r11!, {r9} vstmdb.f32 r11!, {s0 - s4} add r11, r11, #24 subs r12, r12, #1 bne 1b ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Draws a single rocket @ Arguments: @ s0 - s4: Rocket attributes @ Returns: @ none @ Clobbers: @ s0 - s31, r0 -r4 @------------------------------------------------------------------------------- draw_rocket: stmfd sp!, {lr} @ Clear model matrix ldr r0, =mtx_id vldm.f32 r0, {s16 - s31} ldr r0, =mtx_model vstm.f32 r0, {s16 - s31} ldr r0, =mtx_temp vstm.f32 r0, {s16 - s31} @ Translate vneg.f32 s1, s1 ldr r0, =mtx_model bl mat4_translate @ Rotate vmov.f32 s0, s4 @ s0 = angle ldr r0, =mtx_temp bl mat4_rot_z ldr r0, =mtx_model ldr r1, =mtx_temp ldr r2, =mtx_model bl mat4_mul_mat4 @ Compute mvp ldr r0, =mtx_vp ldr r1, =mtx_model @ v' = MVP * v ldr r2, =mtx_mvp bl mat4_mul_mat4 ldr r0, =rocket_vtx ldr r1, =rocket_idx ldr r2, =30 ldr r3, =mtx_mvp ldr r4, =light_dir bl gfx_draw_trgs ldmfd sp!, {pc} @------------------------------------------------------------------------------- @ Collide rocket at (s11, s12, s13) with all objects @ Arguments: @ s11 - x @ s12 - y @ s13 - z @ s31 - radius @ Returns: @ @ Clobbers: @------------------------------------------------------------------------------- collide_objects: stmfd sp!, {r0 - r12, lr} vstmdb.f32 sp!, {s0 - s7} ldr r12, =OBJECT_COUNT ldr r11, =object_list 1: vldm.f32 r11, {s0 - s6} @ Check x vsub.f32 s7, s11, s0 vabs.f32 s7, s7 vcmp.f32 s7, s31 fmstat bgt 2f @ Check y vsub.f32 s7, s12, s1 vabs.f32 s7, s7 vcmp.f32 s7, s31 fmstat bgt 2f @ Check z vsub.f32 s7, s13, s2 vabs.f32 s7, s7 vcmp.f32 s7, s31 fmstat bgt 2f @ Cause damage & update score if needed vmov.f32 r9, s5 cmp r9, #2 moveq r9, #0 movgt r9, #1 ldreq r1, =player_score ldreq r2, [r1] addeq r2, r2, #5 streq r2, [r1] vmoveq.f32 s2, r9 vmov.f32 s5, r9 2: vstm.f32 r11!, {s0 - s6} subs r12, r12, #1 bne 1b vldmia.f32 sp!, {s0 - s7} ldmfd sp!, {r0 - r12, pc} @------------------------------------------------------------------------------- @ Collide rocket at (s11, s12, s13) with all enemies @ Arguments: @ s11 - x @ s12 - y @ s13 - z @ s31 - radius @ Returns: @ r0 - 0 if collision happened @ Clobbers: @------------------------------------------------------------------------------- collide_enemies: stmfd sp!, {r1 - r12, lr} vstmdb.f32 sp!, {s0 - s8} ldr r12, =ENEMY_COUNT ldr r11, =enemies 1: vldm.f32 r11, {s0 - s7} @ Check x vsub.f32 s8, s11, s0 vabs.f32 s8, s8 vcmp.f32 s8, s31 fmstat bgt 2f @ Check y vsub.f32 s8, s12, s1 vabs.f32 s8, s8 vcmp.f32 s8, s31 fmstat bgt 2f @ Check z vsub.f32 s8, s13, s2 vabs.f32 s8, s8 vcmp.f32 s8, s31 fmstat bgt 2f @ Cause damage & update score if needed vmov.f32 r9, s6 subs r9, r9, #2 movlt r9, #0 ldr r1, =player_score ldr r2, [r1] addlt r2, r2, #50 addge r2, r2, #100 str r2, [r1] vmovle.f32 s2, r9 vmov.f32 s6, r9 mov r0, #0 2: vstm.f32 r11!, {s0 - s7} subs r12, r12, #1 bne 1b vldmia.f32 sp!, {s0 - s8} ldmfd sp!, {r1 - r12, pc} @------------------------------------------------------------------------------- @ Resets rockets @------------------------------------------------------------------------------- reset_rockets: stmfd sp!, {r0 - r3, lr} vstmdb.f32 sp!, {s0 - s5} ldr r3, =ROCKET_COUNT ldr r2, =rocket_list ldr r1, =0x3E800000 @ 0.25 mov r0, #0 1: vldm.f32 r2, {s0 - s5} vmov.f32 s0, r0 vmov.f32 s1, r0 vmov.f32 s2, r0 vmov.f32 s3, r1 vmov.f32 s4, r0 vmov.f32 s5, r0 vstm.f32 r2!, {s0 - s5} subs r3, #1 bne 1b vldmia.f32 sp!, {s0 - s5} ldmfd sp!, {r0 - r3, pc} ================================================ FILE: sound.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global setup_sound .global update_sound .include "ports.s" @ ------------------------------------------------------------------------------ @ Macro that simplifies adding new sounds @ ------------------------------------------------------------------------------ .macro sound name .long 0 @ Play flag .long \name\()_start @ Address of current chunk .long \name\()_start @ Start address of sample .long \name\()_end @ End address of sample .global snd_play_\name snd_play_\name: @ Start playing push {r0} mov r0, #1 str r0, [pc, #-32] pop {r0} mov pc, lr .global snd_stop_\name snd_stop_\name: push {r0} mov r0, #0 str r0, [pc, #-52] pop {r0} mov pc, lr .endm .section .text @ ------------------------------------------------------------------------------ @ Initialises the sound module, setting up GPIO 40 and 45 to use PWM and @ programming DMA channel 1 with two control blocks chained together that @ write data to the GPIO ports @ @ Arguments: @ none @ Returns: @ none @ Clobbers: @ r0 - r3 @ ------------------------------------------------------------------------------ setup_sound: @ Copy first chunk of background music into buffers ldr r0, =corneria_start ldr r1, =dma_buffer_0 ldr r2, =0x2000 mov r3, #0 1: ldrb r3, [r0], #1 str r3, [r1], #4 subs r2, r2, #1 bne 1b ldr r1, =dma_buffer_1 ldr r2, =0x2000 1: ldrb r3, [r0], #1 str r3, [r1], #4 subs r2, r2, #1 bne 1b @ Set GPIO 40 & 45 to PWM ldr r0, =GPIO_FSEL4 ldr r1, [r0] ldr r2, =0x00038007 bic r1, r1, r2 ldr r2, =0x00020004 orr r1, r1, r2 str r1, [r0] @ Setup clock ldr r0, =CM_PWMDIV ldr r1, =0x5A002000 str r1, [r0] ldr r0, =CM_PWMCTL ldr r1, =0x5A000016 str r1, [r0] @ Setup PWM ldr r1, =0x00002C48 ldr r0, =PWM_RNG1 str r1, [r0] ldr r0, =PWM_RNG2 str r1, [r0] ldr r0, =PWM_CTL ldr r1, =0x00002161 str r1, [r0] @ Setup PWM to use DMA ldr r0, =PWM_DMAC ldr r1, =0x80000001 str r1, [r0] @ Enable DMA0 ldr r0, =DMA_ENABLE ldr r1, =0x00000001 str r1, [r0] @ Set DMA0 control block ldr r0, =DMA0_CONBLK adr r1, DMA_CTRL_1 str r1, [r0] @ Start DMA0 ldr r0, =DMA0_CS ldr r1, =0x00000001 str r1, [r0] mov pc, lr @ ------------------------------------------------------------------------------ @ Should be called when DMA triggers an interrupt, but unfortunately the @ hardware seems incapable of triggering it. Fortunately, we can poll for the @ interrupt flag in the DMA interrupt status register and call the function @ ourselves @ @ Arguments: @ none @ Clobbers: @ none @ Returns: @ none @ ------------------------------------------------------------------------------ update_sound: stmfd sp!, {r0 - r10, lr} ldr r0, =DMA_INT_STATUS ldr r1, [r0] tst r1, r1 ldmeqfd sp!, {r0 - r10, pc} ldr r0, =DMA0_CS ldr r1, =0x00000005 str r1, [r0] @ Swap buffers ldr r1, =buffer_index ldr r0, [r1] add r0, r0, #1 and r0, r0, #1 str r0, [r1] @ Find target buffer tst r0, r0 ldrne r0, =dma_buffer_0 ldreq r0, =dma_buffer_1 @ Copy background sound ldr r1, =corneria_start ldr r2, =corneria_ptr ldr r3, [r2] ldr r4, =corneria_end sub r4, r4, #0x2000 add r3, r3, #0x2000 cmp r3, r4 movge r3, r1 str r3, [r2] ldr r4, =0x2000 mov r2, r0 1: ldrb r5, [r3], #1 lsl r5, r5, #3 str r5, [r2], #4 subs r4, r4, #1 bne 1b @ Play sounds ldr r9, =sounds mov r10, #9 1: ldr r5, [r9] tst r5, r5 beq 3f ldr r5, [r9, #4] ldr r3, =0x2000 mov r7, r0 2: ldrb r6, [r5], #1 sub r6, r6, #0x7F ldr r8, [r7] add r8, r8, r6, lsl #3 str r8, [r7], #4 subs r3, r3, #1 bne 2b ldr r3, [r9, #8] ldr r4, [r9, #12] cmp r5, r4 movge r5, r3 str r5, [r9, #4] movge r5, #0 strge r5, [r9] 3: add r9, #56 subs r10, r10, #1 bne 1b ldmfd sp!, {r0 - r10, pc} .ltorg .section .text @ ------------------------------------------------------------------------------ @ DMA control structures - chained after each other @ ------------------------------------------------------------------------------ .align 5 DMA_CTRL_0: .long 0x00050141 @ Attributes .long dma_buffer_0 @ Source address .long 0x7E20C018 @ Destination Address .long 0x8000 @ Transfer length .long 0 .long DMA_CTRL_1 .align 5 DMA_CTRL_1: .long 0x00050141 @ Attributes .long dma_buffer_1 @ Source address .long 0x7E20C018 @ Destination Address .long 0x8000 @ Transfer length .long 0 .long DMA_CTRL_0 .align 4 @ ------------------------------------------------------------------------------ @ DMA buffers @ ------------------------------------------------------------------------------ dma_buffer_0: .space 0x8000, 0 dma_buffer_1: .space 0x8000, 0 .align 2 @ ------------------------------------------------------------------------------ @ Sound effect states @ ------------------------------------------------------------------------------ buffer_index: .long 1 sounds: sound bullet sound roll sound rock sound crash sound fail sound boost sound rocket sound cantlet sound pickup .section .data @ ------------------------------------------------------------------------------ @ Background music @ ------------------------------------------------------------------------------ corneria_start: .incbin "assets/corneria.bin" corneria_end: corneria_ptr: .long corneria_start @ ------------------------------------------------------------------------------ @ Short sounds effects @ ------------------------------------------------------------------------------ bullet_start: .incbin "assets/laser.bin" bullet_end: roll_start: .incbin "assets/roll.bin" roll_end: rock_start: .incbin "assets/rocknroll.bin" rock_end: crash_start: .incbin "assets/crash.bin" crash_end: fail_start: .incbin "assets/fail.bin" fail_end: boost_start: .incbin "assets/boost.bin" boost_end: rocket_start: .incbin "assets/rocketsound.bin" rocket_end: cantlet_start: .incbin "assets/cantletyou.bin" cantlet_end: pickup_start: .incbin "assets/pickup.bin" pickup_end: ================================================ FILE: test.s ================================================ @ This file is part of the Team 28 Project @ Licensing information can be found in the LICENSE file @ (C) 2014 The Team 28 Authors. All rights reserved. .global run_tests .section .data @------------------------------------------------------------------------------- @ Sin and Cos test cases @------------------------------------------------------------------------------- angle_input: .float -777.0, -10.0, -6.283, -3.6, -3.1415, -3.0, -2.8, -2.5, -2.2, -2.0 .float -1.8, -1.57075, -1.047197, -0.785375, -0.5 .float 0.0 .float 777.0, 10.0, 6.283, 3.6, 3.1415, 3.0, 2.8, 2.5, 2.2, 2.0 .float 1.8, 1.57075, 1.047197, 0.785375, 0.5 @------------------------------------------------------------------------------- @ Sin output destination @------------------------------------------------------------------------------- sin_output: .float 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 .float 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 .float 2.0, 2.0, 2.0, 2.0 @------------------------------------------------------------------------------- @ Cos output destination @------------------------------------------------------------------------------- cos_output: .float 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 .float 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 .float 2.0, 2.0, 2.0, 2.0 .section .text @------------------------------------------------------------------------------- @ Runs test functions @ Arguments: @ None @ Returns: @ None @ Clobbers: @ None @------------------------------------------------------------------------------- run_tests: stmfd sp!, {r0 - r2, lr} @ test sin ldr r0, =angle_input mov r1, #30 ldr r2, =sin_output bl sin_test @ test cos ldr r0, =angle_input mov r1, #30 ldr r2, =cos_output bl cos_test ldmfd sp!, {r0 - r2, pc} @ ------------------------------------------------------------------------------ @ Sin function test @ Arguments: @ r0 - address of inputs @ r1 - number of inputs @ r2 - destination for outputs @ Returns: @ None @ Clobbers: @ None @ ------------------------------------------------------------------------------ sin_test: stmfd sp!, {r0 - r4, lr} vstmdb sp!, {s0 - s1} mov r3, #0 1: cmp r3, r1 bge 2f ldr r4, [r0] vmov.f32 s0, r4 bl sin vstm.f32 r2, {s1} add r0, r0, #4 add r2, r2, #4 add r3, r3, #1 b 1b 2: vldmia.f32 sp!, {s0 - s1} ldmfd sp!, {r0 - r4, pc} @ ------------------------------------------------------------------------------ @ Cos function test @ Arguments: @ r0 - address of inputs @ r1 - number of inputs @ r2 - destination for outputs @ Returns: @ None @ Clobbers: @ None @ ------------------------------------------------------------------------------ cos_test: stmfd sp!, {r0 - r4, lr} vstmdb sp!, {s0 - s1} mov r3, #0 1: cmp r3, r1 bge 2f ldr r4, [r0] vmov.f32 s0, r4 bl cos vstm.f32 r2, {s1} add r0, r0, #4 add r2, r2, #4 add r3, r3, #1 b 1b 2: vldmia.f32 sp!, {s0 - s1} ldmfd sp!, {r0 - r4, pc} ================================================ FILE: toolchains/arm-none-eabi.cmake ================================================ # Copyright (c) 2013, Brian Sidebotham # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # A CMake toolchain file so we can cross-compile for the Rapsberry-Pi bare-metal # usage # cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-arm-none-eabi.cmake ../ include( CMakeForceCompiler ) # The Generic system name is used for embedded targets (targets without OS) in # CMake set( CMAKE_SYSTEM_NAME Generic ) set( CMAKE_SYSTEM_PROCESSOR BCM2385 ) # Set a toolchain path. You only need to set this if the toolchain isn't in # your system path. Don't forget a trailing path separator! set( TC_PATH "" ) # The toolchain prefix for all toolchain executables set( CROSS_COMPILE arm-none-eabi- ) # specify the cross compiler. Force the compiler so it doesn't perform checks. # We don't want to attempt to test the compiler when we're using a custom # linker script for example, or we're not linking against a c library as it'll # fail. See: http://www.cmake.org/Wiki/CMake_Cross_Compiling cmake_force_c_compiler( ${TC_PATH}${CROSS_COMPILE}gcc GNU ) cmake_force_cxx_compiler( ${TC_PATH}${CROSS_COMPILE}g++ GNU ) # We must set the OBJCOPY setting into cache so that it's available to the # whole project. Otherwise, this does not get set into the CACHE and therefore # the build doesn't know what the OBJCOPY filepath is set( CMAKE_OBJCOPY ${TC_PATH}${CROSS_COMPILE}objcopy CACHE FILEPATH "The toolchain objcopy command " FORCE )