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 |


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('<II', height, width))
# Write data
for y in xrange(height):
for x in xrange(width):
r, g, b, a = image.getpixel((x, y))
assert 0 <= r < 256
assert 0 <= g < 256
assert 0 <= b < 256
assert 0 <= a < 256
f.write(struct.pack('<BBBB', r, g, b, a))
if args.add_depth:
f.write(struct.pack('<f', 0x38f00000))
f.flush()
f.close()
if __name__ == '__main__':
main()
================================================
FILE: input.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_input
.global update_input
.global button_pressed
.global button_clicked
.global button_dclicked
.include "ports.s"
@ ------------------------------------------------------------------------------
@ Macros used to wait for a while
@ ------------------------------------------------------------------------------
.macro wait reg, x
mov \reg, \x
9:
subs \reg, \reg, #1
bne 9b
.endm
@ ------------------------------------------------------------------------------
@ Global variable storing the state of buttons
@ ------------------------------------------------------------------------------
.section .data
button_pressed: .long 0 @ button is held down
button_clicked: .long 0 @ button pressed during frame
button_hclicked: .long 0 @ button pressed during last 30 frames
button_dclicked: .long 0 @ button pressed twice
button_lclicked: .long 0 @ Last time button was clicked
.section .text
@ ------------------------------------------------------------------------------
@ Initialises the input module
@ ------------------------------------------------------------------------------
setup_input:
stmfd sp!, {r0 - r2}
@ Setup GPIO ports 10 and 11 as outputs
ldr r0, =GPIO_FSEL1
ldr r1, [r0]
ldr r2, =0xFFFFFFC0
and r1, r1, r2
mov r2, #0x00000009
orr r1, r1, r2
str r1, [r0]
ldmfd sp!, {r0 - r2}
mov pc, lr
@ ------------------------------------------------------------------------------
@ Updates the state machine on receipt of an interrupt
@ GPIO 4 - data in
@ GPIO 10 - pulse
@ GPIO 11 - latch
@ ------------------------------------------------------------------------------
update_input:
stmfd sp!, {r0 - r9, lr}
ldr r0, =GPIO_SET0
ldr r1, =GPIO_CLR0
ldr r2, =GPIO_LEV0
ldr r3, =button_pressed
ldr r3, [r3]
ldr r4, =button_hclicked
ldr r4, [r4]
ldr r5, =button_lclicked
ldr r6, [r5]
tst r4, r4
moveq r6, #0
addne r6, r6, #1
cmp r6, #15
movge r6, #0
movge r7, r4
movlt r7, #0
movge r4, #0
str r6, [r5]
ldr r5, =button_clicked
str r7, [r5]
ldr r5, =button_dclicked
ldr r5, [r5]
mov r5, #0
@ Latch
mov r6, #0x800
str r6, [r0]
wait r12, #128
str r6, [r1]
wait r12, #128
mov r7, #0
mov r8, #8
mov r9, #1
1:
@ Read button state
ldr r6, [r2]
tst r6, #0x10
bne 3f
orr r7, r7, r9
tst r3, r9
bne 3f
tst r4, r9
orreq r4, r4, r9 @ Click: up -> 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 )
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
SYMBOL INDEX (1 symbols across 1 files) FILE: imager.py function main (line 16) | def main():
Condensed preview — 28 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (187K chars).
[
{
"path": ".gitignore",
"chars": 194,
"preview": "# CMake\nbuild/\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Libraries\n*.lib\n*.a\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*"
},
{
"path": "CMakeLists.txt",
"chars": 2042,
"preview": "# This file is part of the Team 28 Project\n# Licensing information can be found in the LICENSE file\n# (C) 2014 The Team "
},
{
"path": "LICENSE",
"chars": 1542,
"preview": "Copyright (c) 2014, Licker Nandor, Ilija Radosavovic, David Avedissian, Nic Prettejohn\nAll rights reserved.\n\nRedistribut"
},
{
"path": "README.md",
"chars": 2664,
"preview": "PiFox\n=====\n\nVideo of the game in action: https://www.youtube.com/watch?v=-5n9IxSQH1M\n\nDeveloped as an extension to a fi"
},
{
"path": "assets/enemy.s",
"chars": 1600,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "assets/pillar.s",
"chars": 1509,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "assets/rock.s",
"chars": 3257,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "assets/rocket.s",
"chars": 2622,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "assets/ship.s",
"chars": 1954,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "bullets.s",
"chars": 4713,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "enemies.s",
"chars": 12140,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "game.s",
"chars": 12944,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "gfx.s",
"chars": 31023,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "imager.py",
"chars": 1433,
"preview": "#!/usr/bin/python2\n\n\"\"\"\nThis file is part of the Team 28 Project\nLicensing information can be found in the LICENSE file\n"
},
{
"path": "input.s",
"chars": 3376,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "kernel.ld",
"chars": 1812,
"preview": "SECTIONS\n{\n /**\n * Start address of the kernel.\n *\n * In QEMU, this is hardcoded to 0x100000 (64Kb).\n * On the "
},
{
"path": "kernel.s",
"chars": 4932,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "math.s",
"chars": 23436,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "mbox.s",
"chars": 1878,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "objects.s",
"chars": 9797,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "pillars.s",
"chars": 3831,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "player.s",
"chars": 19212,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "ports.s",
"chars": 4975,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "printf.s",
"chars": 5027,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "rockets.s",
"chars": 7246,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "sound.s",
"chars": 7175,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "test.s",
"chars": 3392,
"preview": "@ This file is part of the Team 28 Project\n@ Licensing information can be found in the LICENSE file\n@ (C) 2014 The Team "
},
{
"path": "toolchains/arm-none-eabi.cmake",
"chars": 2738,
"preview": "# Copyright (c) 2013, Brian Sidebotham\n# All rights reserved.\n\n# Redistribution and use in source and binary forms"
}
]
About this extraction
This page contains the full source code of the ICTeam28/PiFox GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 28 files (174.3 KB), approximately 66.8k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.