Skip to content

Commit d660a22

Browse files
committed
asset, rdpq, toolchain: initial picolibc support
1 parent 7d39b09 commit d660a22

5 files changed

Lines changed: 112 additions & 17 deletions

File tree

src/asset.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ static fpos_t seekfn_none(void *c, fpos_t pos, int whence)
227227
return -1;
228228
}
229229

230+
#if defined(__PICOLIBC__)
231+
static int readfn_none(void *c, char *buf, size_t sz)
232+
#else
230233
static int readfn_none(void *c, char *buf, int sz)
234+
#endif
231235
{
232236
cookie_none_t *cookie = c;
233237
assertf(!cookie->seeked, "Cannot seek in file opened via asset_fopen (it might be compressed)");
@@ -251,7 +255,11 @@ typedef struct {
251255
uint8_t state[] alignas(8);
252256
} cookie_cmp_t;
253257

258+
#if defined(__PICOLIBC__)
259+
static int readfn_cmp(void *c, char *buf, size_t sz)
260+
#else
254261
static int readfn_cmp(void *c, char *buf, int sz)
262+
#endif
255263
{
256264
cookie_cmp_t *cookie = (cookie_cmp_t*)c;
257265
assertf(!cookie->seeked, "Cannot seek in file opened via asset_fopen (it might be compressed)");
@@ -334,7 +342,11 @@ FILE *asset_fopen(const char *fn, int *sz)
334342
cookie->pos = 0;
335343
cookie->seeked = false;
336344
if (sz) *sz = header.orig_size;
345+
#if defined(__PICOLIBC__) && defined(TINY_STDIO)
346+
assertf(0, "assets: opening compressed assets not yet supported on picolibc");
347+
#else
337348
return funopen(cookie, readfn_cmp, NULL, seekfn_cmp, closefn_cmp);
349+
#endif
338350
}
339351

340352
// Not compressed. Return a wrapped FILE* without the seeking capability,
@@ -344,10 +356,14 @@ FILE *asset_fopen(const char *fn, int *sz)
344356
*sz = ftell(f);
345357
}
346358
fseek(f, 0, SEEK_SET);
359+
#if defined(__PICOLIBC__) && defined(TINY_STDIO)
360+
return f;
361+
#else
347362
cookie_none_t *cookie = malloc(sizeof(cookie_none_t));
348363
cookie->fp = f;
349364
cookie->seeked = false;
350365
return funopen(cookie, readfn_none, NULL, seekfn_none, closefn_none);
366+
#endif
351367
}
352368

353369
#endif /* N64 */

src/rdpq/rdpq_text.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ int rdpq_text_printn(const rdpq_textparms_t *parms, uint8_t initial_font_id, flo
3838
int rdpq_text_printf(const rdpq_textparms_t *parms, uint8_t font_id, float x0, float y0,
3939
const char *utf8_fmt, ...)
4040
{
41+
#if defined(__PICOLIBC__) && defined(TINY_STDIO)
42+
char *buf;
43+
44+
va_list va;
45+
va_start(va, utf8_fmt);
46+
size_t n = vasprintf(&buf, utf8_fmt, va);
47+
va_end(va);
48+
49+
int nbytes = rdpq_text_printn(parms, font_id, x0, y0, buf, n);
50+
free(buf);
51+
#else
4152
char buf[512];
4253
size_t n = sizeof(buf);
4354

@@ -48,6 +59,7 @@ int rdpq_text_printf(const rdpq_textparms_t *parms, uint8_t font_id, float x0, f
4859

4960
int nbytes = rdpq_text_printn(parms, font_id, x0, y0, buf2, n);
5061
if (buf2 != buf) free(buf2);
62+
#endif
5163
return nbytes;
5264
}
5365

src/system.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <fcntl.h>
1111
#include <sys/types.h>
1212
#include <sys/stat.h>
13+
#include <sys/time.h>
1314
#include <sys/times.h>
1415
#include <stdarg.h>
1516
#include <stdint.h>

tools/build-toolchain.sh

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ N64_BUILD=${N64_BUILD:-""}
2222
N64_HOST=${N64_HOST:-""}
2323
N64_TARGET=${N64_TARGET:-mips64-elf}
2424

25+
# Toolchain configuration options.
26+
N64_USE_PICOLIBC=${N64_USE_PICOLIBC:-"false"}
27+
N64_USE_PICOLIBC_TINYSTDIO=${N64_USE_PICOLIBC_TINYSTDIO:-"false"}
28+
2529
# Set N64_INST before calling the script to change the default installation directory path
2630
INSTALL_PATH="${N64_INST}"
2731
# Set PATH for newlib to compile using GCC for MIPS N64 (pass 1)
@@ -38,8 +42,9 @@ GCC_CONFIGURE_ARGS=()
3842
BINUTILS_V=2.42
3943
GCC_V=13.2.0
4044
NEWLIB_V=4.4.0.20231231
41-
GMP_V=6.3.0
42-
MPC_V=1.3.1
45+
PICOLIBC_V=1.8.6
46+
GMP_V=6.3.0
47+
MPC_V=1.3.1
4348
MPFR_V=4.2.1
4449
MAKE_V=${MAKE_V:-""}
4550

@@ -104,8 +109,13 @@ test -d "binutils-$BINUTILS_V" || tar -xzf "binutils-$BINUTILS_V.tar.gz"
104109
test -f "gcc-$GCC_V.tar.gz" || download "https://ftp.gnu.org/gnu/gcc/gcc-$GCC_V/gcc-$GCC_V.tar.gz"
105110
test -d "gcc-$GCC_V" || tar -xzf "gcc-$GCC_V.tar.gz"
106111

107-
test -f "newlib-$NEWLIB_V.tar.gz" || download "https://sourceware.org/pub/newlib/newlib-$NEWLIB_V.tar.gz"
108-
test -d "newlib-$NEWLIB_V" || tar -xzf "newlib-$NEWLIB_V.tar.gz"
112+
if [ "$N64_USE_PICOLIBC" == "true" ]; then
113+
test -f "picolibc-$PICOLIBC_V.tar.xz" || download "https://github.com/picolibc/picolibc/releases/download/$PICOLIBC_V/picolibc-$PICOLIBC_V.tar.xz"
114+
test -d "picolibc-$PICOLIBC_V" || tar -xf "picolibc-$PICOLIBC_V.tar.xz"
115+
else
116+
test -f "newlib-$NEWLIB_V.tar.gz" || download "https://sourceware.org/pub/newlib/newlib-$NEWLIB_V.tar.gz"
117+
test -d "newlib-$NEWLIB_V" || tar -xzf "newlib-$NEWLIB_V.tar.gz"
118+
fi
109119

110120
if [ "$GMP_V" != "" ]; then
111121
test -f "gmp-$GMP_V.tar.bz2" || download "https://ftp.gnu.org/gnu/gmp/gmp-$GMP_V.tar.bz2"
@@ -221,19 +231,56 @@ make all-target-libgcc -j "$JOBS"
221231
make install-target-libgcc || sudo make install-target-libgcc || su -c "make install-target-libgcc"
222232
popd
223233

224-
# Compile newlib for target.
225-
mkdir -p newlib_compile_target
226-
pushd newlib_compile_target
227-
CFLAGS_FOR_TARGET="-DHAVE_ASSERT_FUNC -O2" ../"newlib-$NEWLIB_V"/configure \
228-
--prefix="$CROSS_PREFIX" \
229-
--target="$N64_TARGET" \
230-
--with-cpu=mips64vr4300 \
231-
--disable-threads \
232-
--disable-libssp \
233-
--disable-werror
234-
make -j "$JOBS"
235-
make install || sudo env PATH="$PATH" make install || su -c "env PATH=\"$PATH\" make install"
236-
popd
234+
if [ "$N64_USE_PICOLIBC" == "true" ]; then
235+
# Compile picolibc for target.
236+
mkdir -p picolibc_compile_target
237+
pushd picolibc_compile_target
238+
meson setup \
239+
--cross-file=../../meson-cross.txt \
240+
-Dmultilib=false \
241+
-Dpicocrt=false \
242+
-Dpicolib=false \
243+
-Dsemihost=false \
244+
-Dspecsdir=none \
245+
-Dtests=false \
246+
-Dtinystdio="$N64_USE_PICOLIBC_TINYSTDIO" \
247+
-Dfast-bufio=true \
248+
-Dio-long-long=true \
249+
-Dio-pos-args="$N64_USE_PICOLIBC_TINYSTDIO" \
250+
-Dio-percent-b=true \
251+
-Dposix-console=true \
252+
-Dformat-default=double \
253+
-Dnewlib-fseek-optimization=true \
254+
-Dnewlib-fvwrite-in-streamio=true \
255+
-Dnewlib-io-float=true \
256+
-Dnewlib-stdio64=false \
257+
-Dnewlib-unbuf-stream-opt=true \
258+
-Dnewlib-nano-malloc=false \
259+
-Dnewlib-multithread=false \
260+
-Dnewlib-retargetable-locking=false \
261+
-Dthread-local-storage=false \
262+
-Dprefix="$CROSS_PREFIX" \
263+
-Dlibdir=mips64-elf/lib \
264+
-Dincludedir=mips64-elf/include \
265+
../"picolibc-$PICOLIBC_V"
266+
ninja -j "$JOBS"
267+
ninja install || sudo env PATH="$PATH" ninja install || su -c "env PATH=\"$PATH\" ninja install"
268+
popd
269+
else
270+
# Compile newlib for target.
271+
mkdir -p newlib_compile_target
272+
pushd newlib_compile_target
273+
CFLAGS_FOR_TARGET="-DHAVE_ASSERT_FUNC -O2" ../"newlib-$NEWLIB_V"/configure \
274+
--prefix="$CROSS_PREFIX" \
275+
--target="$N64_TARGET" \
276+
--with-cpu=mips64vr4300 \
277+
--disable-threads \
278+
--disable-libssp \
279+
--disable-werror
280+
make -j "$JOBS"
281+
make install || sudo env PATH="$PATH" make install || su -c "env PATH=\"$PATH\" make install"
282+
popd
283+
fi
237284

238285
# For a standard cross-compiler, the only thing left is to finish compiling the target libraries
239286
# like libstd++. We can continue on the previous GCC build target.

tools/meson-cross.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[binaries]
2+
# Meson 0.53.2 doesn't use any cflags when doing basic compiler tests,
3+
# so we have to add -nostdlib to the compiler configuration itself or
4+
# early compiler tests will fail. This can be removed when picolibc
5+
# requires at least version 0.54.2 of meson.
6+
c = ['mips64-elf-gcc', '-nostdlib']
7+
ar = 'mips64-elf-ar'
8+
as = 'mips64-elf-as'
9+
nm = 'mips64-elf-nm'
10+
strip = 'mips64-elf-strip'
11+
12+
[host_machine]
13+
system = 'none'
14+
cpu_family = 'mips64'
15+
cpu = 'mips64vr4300'
16+
endian = 'big'
17+
18+
[properties]
19+
skip_sanity_check = true

0 commit comments

Comments
 (0)