forked from len0rd/rockbox
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
129 lines
4.1 KiB
ArmAsm
129 lines
4.1 KiB
ArmAsm
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2019 Franklin Wei
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
***************************************************************************/
|
|
|
|
/** Sound mixing code for ARM. **/
|
|
/* Takes 8-bit mono audio and outputs stereo 16-bit samples.
|
|
* stereo volumes are passed as arguments.
|
|
*
|
|
* Bear with me. This is my first ARM assembly, ever.
|
|
*/
|
|
|
|
.text
|
|
.align 2
|
|
.global SND_PaintChannelFrom8
|
|
.type SND_PaintChannelFrom8, %function
|
|
|
|
#if defined(__ARM_ARCH_5TEJ__)
|
|
SND_PaintChannelFrom8:
|
|
// r0: int true_lvol
|
|
// r1: int true_rvol
|
|
// r2: char *sfx
|
|
// r3: int count
|
|
|
|
stmfd sp!, {r4, r5, r6, r7, r8, sl}
|
|
|
|
ldr ip, =paintbuffer
|
|
ldr ip, [ip]
|
|
|
|
mov r0, r0, asl #16 // pre-scale both volumes by 2^16
|
|
mov r1, r1, asl #16
|
|
|
|
sub r3, r3, #1 // we'll count backwards
|
|
// sl = 0xffff0000
|
|
ldrh sl, =0xffff
|
|
|
|
.loop:
|
|
ldrsb r4, [r2, r3] // load *sfx[i] -> r4
|
|
|
|
// keep endianness in mind here
|
|
// buffer looks like [left_0, left_1, right_0, right_1] in memory
|
|
// but it is loaded as [right1, right0, left1, left0] to registers
|
|
ldr r8, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
|
|
|
|
// handle high half (right channel) first
|
|
mul r5, r4, r1 // SCALEDRIGHT = SFXI * (true_rvol << 16) -- bottom half is zero
|
|
|
|
// r7 holds right channel in high half (dirty bottom half)
|
|
qadd r7, r5, r8 // RIGHTCHANORIG = SCALEDRIGHT + RIGHTCHANORIG (high half)
|
|
|
|
bic r7, r7, sl // zero bottom bits of r7
|
|
|
|
// trash r5, r6 and handle left channel
|
|
mul r5, r4, r0 // SCALEDLEFT = SFXI * (true_rvol << 16)
|
|
|
|
mov r8, r8, lsl #16 // extract original left channel from paintbuffer
|
|
|
|
// r8 holds left channel in high half with zero bottom half
|
|
qadd r8, r5, r8
|
|
|
|
// combine the two 16-bit samples in r7 as 32-bit [left:right]
|
|
// (use lsr to not sign-extend the lower half)
|
|
orr r7, r7, r8, lsr #16
|
|
|
|
str r7, [ip, r3, lsl #2] // write 32-bit to paintbuffer
|
|
subs r3, r3, #1
|
|
bgt .loop // must use instead of bne because of the corner case count=1
|
|
|
|
|
|
|
|
ldmfd sp!, {r4, r5, r6, r7, r8, sl}
|
|
|
|
bx lr
|
|
|
|
#elif defined(__ARM_ARCH_6__) // ARMv6 with QADD16 (disabled)
|
|
SND_PaintChannelFrom8:
|
|
// r0: int true_lvol
|
|
// r1: int true_rvol
|
|
// r2: char *sfx
|
|
// r3: int count
|
|
|
|
stmfd sp!, {r4, r5, r6, r7}
|
|
|
|
ldr ip, =paintbuffer
|
|
ldr ip, [ip]
|
|
sub r3, r3, #1 // we'll count backwards
|
|
.loop:
|
|
ldrsb r4, [r2, r3] // load *sfx[i] -> r4
|
|
|
|
// keep endianness in mind here
|
|
// buffer looks like [left_0, left_1, right_0, right_1] in memory
|
|
// but it is loaded as [right1, right0, left1, left0] to registers
|
|
ldr r7, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
|
|
|
|
// handle high half (right channel) first
|
|
mul r5, r4, r1 // SCALEDRIGHT = SFXI * true_rvol
|
|
mul r6, r4, r0 // SCALEDLEFT = SFXI * true_rvol
|
|
|
|
orr r6, r6, r5, lsl #16
|
|
|
|
qadd16 r6, r6, r7
|
|
|
|
str r6, [ip, r3, lsl #2] // write 32-bit to paintbuffer
|
|
|
|
subs r3, r3, #1
|
|
bne .loop
|
|
|
|
ldmfd sp!, {r4, r5, r6, r7}
|
|
|
|
bx lr
|
|
#else
|
|
#error ARMv5/6 only
|
|
#endif
|