initial upload
commit
c815dc1360
@ -0,0 +1,12 @@
|
|||||||
|
build/*
|
||||||
|
local/*
|
||||||
|
*.exe
|
||||||
|
*.pdb
|
||||||
|
*.exp
|
||||||
|
*.lib
|
||||||
|
*.obj
|
||||||
|
*.dll
|
||||||
|
*.ilk
|
||||||
|
*.d
|
||||||
|
*.swp
|
||||||
|
*.rdbg
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
cd /D "%~dp0"
|
||||||
|
|
||||||
|
:: --- Unpack Arguments -------------------------------------------------------
|
||||||
|
for %%a in (%*) do set "%%a=1"
|
||||||
|
if not "%msvc%"=="1" if not "%clang%"=="1" set msvc=1
|
||||||
|
if not "%release%"=="1" set debug=1
|
||||||
|
if "%debug%"=="1" set release=0 && echo [debug]
|
||||||
|
if "%release%"=="1" set debug=0 && echo [release]
|
||||||
|
if "%msvc%"=="1" set clang=0 && echo [msvc]
|
||||||
|
if "%clang%"=="1" set msvc=0 && echo [clang]
|
||||||
|
if "%deploy%"=="1" echo [deploy]
|
||||||
|
|
||||||
|
:: --- Unpack Command Line Build Mix-ins --------------------------------------
|
||||||
|
set auto_compile_flags=
|
||||||
|
set auto_link_flags=
|
||||||
|
if "%telemetry%"=="1" set auto_compile_flags=%auto_compile_flags% -DBUILD_TELEMETRY=1 && echo [telemetry]
|
||||||
|
if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan]
|
||||||
|
|
||||||
|
:: --- Mix Git Commit ID ------------------------------------------------------
|
||||||
|
git rev-parse --is-inside-work-tree >nul 2>&1 && set in_git_tree=1
|
||||||
|
if "%in_git_tree%"=="1" (
|
||||||
|
for /f %%i in ('call git describe --always --dirty') do set auto_compile_flags=%auto_compile_flags% -DBUILD_GIT_HASH=\"%%i\"
|
||||||
|
for /f %%i in ('call git rev-parse HEAD') do set auto_compile_flags=%auto_compile_flags% -DBUILD_GIT_HASH_FULL=\"%%i\"
|
||||||
|
)
|
||||||
|
|
||||||
|
:: --- [MSVC] Compile/Link Line Definitions -----------------------------------
|
||||||
|
set cl_common= /I..\code\ /I..\local\ /nologo /FC /Z7
|
||||||
|
set cl_debug= call cl /Od /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags%
|
||||||
|
set cl_release= call cl /O2 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags%
|
||||||
|
set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%% %auto_link_flags%
|
||||||
|
set cl_out= /out:
|
||||||
|
|
||||||
|
:: --- [Clang] Compile/Link Line Definitions ----------------------------------
|
||||||
|
set clang_common= -g -I..\code\ -I..\local\ -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-unused-parameter -Wno-writable-strings -Wno-missing-field-initializers -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -ferror-limit=10000
|
||||||
|
set clang_common_n64= --target=mips-unknown-elf -mcpu=mips3 -mabi=32 -EB -mno-abicalls -fno-pic -ffreestanding -nostdlib -fno-builtin -G 0 -fno-unroll-loops -DN64=1
|
||||||
|
set clang_debug= call clang -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags%
|
||||||
|
set clang_release= call clang -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags%
|
||||||
|
set clang_debug_n64= call clang -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% %clang_common_n64% -c
|
||||||
|
set clang_release_n64= call clang -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% %clang_common_n64% -c
|
||||||
|
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% %auto_link_flags%
|
||||||
|
set clang_out= -o
|
||||||
|
|
||||||
|
:: --- [LLD] Link Line Definitions
|
||||||
|
set lld_link_common=
|
||||||
|
set lld_link_common_n64= -T "../code/n64/n64.ld"
|
||||||
|
set lld_link= call ld.lld %lld_link_common% %auto_link_flags%
|
||||||
|
set lld_link_n64= call ld.lld %lld_link_common% %lld_link_common_n64% %auto_link_flags%
|
||||||
|
|
||||||
|
:: --- Choose Compile/Link Lines ----------------------------------------------
|
||||||
|
if "%msvc%"=="1" set compile_debug=%cl_debug%
|
||||||
|
if "%msvc%"=="1" set compile_release=%cl_release%
|
||||||
|
if "%msvc%"=="1" set compile_link=%cl_link%
|
||||||
|
if "%msvc%"=="1" set out=%cl_out%
|
||||||
|
if "%clang%"=="1" set compile_debug=%clang_debug%
|
||||||
|
if "%clang%"=="1" set compile_release=%clang_release%
|
||||||
|
if "%clang%"=="1" set compile_link=%clang_link%
|
||||||
|
if "%clang%"=="1" set out=%clang_out%
|
||||||
|
if "%debug%"=="1" set compile=%compile_debug%
|
||||||
|
if "%release%"=="1" set compile=%compile_release%
|
||||||
|
if "%debug%"=="1" set compile_n64=%clang_debug_n64%
|
||||||
|
if "%release%"=="1" set compile_n64=%clang_release_n64%
|
||||||
|
set link_n64= %lld_link_n64%
|
||||||
|
set out_n64= %clang_out%
|
||||||
|
set romify_n64= n64tool -t "^!n64_rom_name^!" -o "^!n64_rom_name^!.z64" --align 256 "^!n64_rom_name^!.elf"
|
||||||
|
|
||||||
|
:: --- Per-Build Settings -----------------------------------------------------
|
||||||
|
set link_dll=-DLL
|
||||||
|
if "%msvc%"=="1" set only_compile=-c
|
||||||
|
if "%clang%"=="1" set only_compile=/c
|
||||||
|
if "%msvc%"=="1" set EHsc=/EHsc
|
||||||
|
if "%clang%"=="1" set EHsc=
|
||||||
|
if "%msvc%"=="1" set no_aslr=/DYNAMICBASE:NO
|
||||||
|
if "%clang%"=="1" set no_aslr=-Wl,/DYNAMICBASE:NO
|
||||||
|
if "%msvc%"=="1" set rc=call rc
|
||||||
|
if "%clang%"=="1" set rc=call llvm-rc
|
||||||
|
|
||||||
|
:: --- Prep Directories -------------------------------------------------------
|
||||||
|
if not exist build mkdir build
|
||||||
|
if not exist local mkdir local
|
||||||
|
|
||||||
|
:: --- Build n64tool ----------------------------------------------------------
|
||||||
|
pushd build
|
||||||
|
if "%n64tool%"=="1" if exist n64tool.exe del n64tool.exe
|
||||||
|
if not exist n64tool.exe (
|
||||||
|
%clang_debug% ..\code\third_party\n64tool\n64tool.c %clang_link% %clang_out% n64tool.exe
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
|
||||||
|
:: --- Build Targets ----------------------------------------------------------
|
||||||
|
pushd build
|
||||||
|
if "%n64_test%"=="1" (
|
||||||
|
set didbuild=1
|
||||||
|
set "n64_rom_name=n64_test"
|
||||||
|
%compile_n64% ..\code\n64_test\n64_test.c
|
||||||
|
%link_n64% n64_test.o %out_n64% !n64_rom_name!.elf
|
||||||
|
%romify_n64%
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
|
||||||
|
:: --- Deploy To N64 ----------------------------------------------------------
|
||||||
|
if "%deploy%"=="1" if not "%n64_rom_name%"=="" (
|
||||||
|
pushd build
|
||||||
|
..\tools\sc64deployer upload %n64_rom_name%.z64
|
||||||
|
popd
|
||||||
|
)
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,676 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef BASE_H
|
||||||
|
#define BASE_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Context Cracking
|
||||||
|
|
||||||
|
//- rjf: MSVC Extraction
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
# define COMPILER_MSVC 1
|
||||||
|
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# define PLATFORM_WINDOWS 1
|
||||||
|
# else
|
||||||
|
# error _MSC_VER is defined, but _WIN32 is not. This setup is not supported.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(_M_AMD64)
|
||||||
|
# define ARCH_X64 1
|
||||||
|
# elif defined(_M_IX86)
|
||||||
|
# define ARCH_X86 1
|
||||||
|
# elif defined(_M_ARM64)
|
||||||
|
# define ARCH_ARM64 1
|
||||||
|
# elif defined(_M_ARM)
|
||||||
|
# define ARCH_ARM32 1
|
||||||
|
# else
|
||||||
|
# error Target architecture is not supported. _MSC_VER is defined, but one of {_M_AMD64, _M_IX86, _M_ARM64, _M_ARM} is not.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1920
|
||||||
|
# define COMPILER_MSVC_YEAR 2019
|
||||||
|
#elif _MSC_VER >= 1910
|
||||||
|
# define COMPILER_MSVC_YEAR 2017
|
||||||
|
#elif _MSC_VER >= 1900
|
||||||
|
# define COMPILER_MSVC_YEAR 2015
|
||||||
|
#elif _MSC_VER >= 1800
|
||||||
|
# define COMPILER_MSVC_YEAR 2013
|
||||||
|
#elif _MSC_VER >= 1700
|
||||||
|
# define COMPILER_MSVC_YEAR 2012
|
||||||
|
#elif _MSC_VER >= 1600
|
||||||
|
# define COMPILER_MSVC_YEAR 2010
|
||||||
|
#elif _MSC_VER >= 1500
|
||||||
|
# define COMPILER_MSVC_YEAR 2008
|
||||||
|
#elif _MSC_VER >= 1400
|
||||||
|
# define COMPILER_MSVC_YEAR 2005
|
||||||
|
#else
|
||||||
|
# define COMPILER_MSVC_YEAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//- rjf: Clang Extraction
|
||||||
|
|
||||||
|
#elif defined(__clang__)
|
||||||
|
|
||||||
|
# define COMPILER_CLANG 1
|
||||||
|
|
||||||
|
# if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
# define PLATFORM_MAC 1
|
||||||
|
# elif defined(__gnu_linux__)
|
||||||
|
# define PLATFORM_LINUX 1
|
||||||
|
# elif defined(N64)
|
||||||
|
# define PLATFORM_N64 1
|
||||||
|
# else
|
||||||
|
# error __clang__ is defined, but one of {__APPLE__, __gnu_linux__, N64} is not. This setup is not supported.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
|
# define ARCH_X64 1
|
||||||
|
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
||||||
|
# define ARCH_X86 1
|
||||||
|
# elif defined(__aarch64__)
|
||||||
|
# define ARCH_ARM64 1
|
||||||
|
# elif defined(__arm__)
|
||||||
|
# define ARCH_ARM32 1
|
||||||
|
# elif defined(__mips) && defined(__mips64)
|
||||||
|
# define ARCH_MIPS64 1
|
||||||
|
# elif defined(__mips) && !defined(__mips64)
|
||||||
|
# define ARCH_MIPS32 1
|
||||||
|
# else
|
||||||
|
# error Target architecture is not supported. __clang__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__, __mips} is not.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
//- rjf: GCC Extraction
|
||||||
|
|
||||||
|
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
|
||||||
|
# define COMPILER_GCC 1
|
||||||
|
|
||||||
|
# if defined(__gnu_linux__)
|
||||||
|
# define PLATFORM_LINUX 1
|
||||||
|
# else
|
||||||
|
# error __GNUC__ or __GNUG__ is defined, but __gnu_linux__ is not. This setup is not supported.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
|
# define ARCH_X64 1
|
||||||
|
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
||||||
|
# define ARCH_X86 1
|
||||||
|
# elif defined(__aarch64__)
|
||||||
|
# define ARCH_ARM64 1
|
||||||
|
# elif defined(__arm__)
|
||||||
|
# define ARCH_ARM32 1
|
||||||
|
# else
|
||||||
|
# error Target architecture is not supported. __GNU_C__ or __GNUG__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error Compiler is not supported. _MSC_VER, __clang__, __GNUC__, or __GNUG__ must be defined.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARCH_X64 || ARCH_ARM64 || ARCH_MIPS64
|
||||||
|
# define ARCH_64BIT 1
|
||||||
|
#elif ARCH_X86 || ARCH_ARM32 || ARCH_MIPS32
|
||||||
|
# define ARCH_32BIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
# define LITTLE_ENDIAN 0
|
||||||
|
# define BIG_ENDIAN 1
|
||||||
|
#else
|
||||||
|
# define LITTLE_ENDIAN 1
|
||||||
|
# define BIG_ENDIAN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Variadic Arguments
|
||||||
|
|
||||||
|
#define VariadicS64(args) va_arg(args, S64)
|
||||||
|
#define VariadicU64(args) va_arg(args, U64)
|
||||||
|
#if ARCH_X64 || ARCH_ARM64
|
||||||
|
# define VariadicS32(args) va_arg(args, S32)
|
||||||
|
# define VariadicU32(args) va_arg(args, U32)
|
||||||
|
# define VariadicInt(args) va_arg(args, int)
|
||||||
|
# define VariadicAddr(args) va_arg(args, UAddr)
|
||||||
|
#elif ARCH_MIPS32 || ARCH_MIPS64
|
||||||
|
# define VariadicS32(args) (S32)(va_arg(args, U64) & 0xffffffff)
|
||||||
|
# define VariadicU32(args) (U64)(va_arg(args, U64) & 0xffffffff)
|
||||||
|
# define VariadicInt(args) (int)(va_arg(args, U64) & 0xffffffff)
|
||||||
|
# define VariadicAddr(args) (UAddr)(va_arg(args, U64) & 0xffffffff)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Keywords
|
||||||
|
|
||||||
|
#define function static
|
||||||
|
#define global static
|
||||||
|
#define local_persist static
|
||||||
|
#define align(n) __attribute__((aligned(n)))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Preprocessor Operations
|
||||||
|
|
||||||
|
#define Glue_(A, B) A##B
|
||||||
|
#define Glue(A, B) Glue_(A, B)
|
||||||
|
#define Stringify_(S) #S
|
||||||
|
#define Stringify(S) Stringify_(S)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Static Assertions
|
||||||
|
|
||||||
|
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Clamps, Mins, Maxes
|
||||||
|
|
||||||
|
#define Min(a, b) (((a)<(b)) ? (a) : (b))
|
||||||
|
#define Max(a, b) (((a)>(b)) ? (a) : (b))
|
||||||
|
#define ClampTop(x, a) Min(x,a)
|
||||||
|
#define ClampBot(a, x) Max(a,x)
|
||||||
|
#define Clamp(a, x, b) (((a)>(x))?(a):((b)<(x))?(b):(x))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Swaps
|
||||||
|
|
||||||
|
#define Swap(T, a, b) do{T c = (a); (a) = (b); (b) = c;}while(0)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Array Counts
|
||||||
|
|
||||||
|
#define ArrayCount(a) ((sizeof(a)) / sizeof((a)[0]))
|
||||||
|
#define ArrayAndCount(a) (a), ArrayCount(a)
|
||||||
|
#define CountAndArray(a) ArrayCount(a), (a)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Loop Helpers
|
||||||
|
|
||||||
|
#define EachIndex(idx, count) (UAddr idx = 0; idx < (count); idx += 1)
|
||||||
|
#define EachElement(idx, array) (UAddr idx = 0; idx < ArrayCount(array); idx += 1)
|
||||||
|
|
||||||
|
#define DeferLoop(start, end) for(int _i_ = ((start), 0); _i_ == 0; (_i_ += 1, (end)))
|
||||||
|
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Bit Arrays
|
||||||
|
|
||||||
|
#define BitArrayDecl(type, name, count) type name[(count + sizeof(type)*8-1) / sizeof(type)*8]
|
||||||
|
#define BitArrayAdd(arr, bit) ((arr)[(bit) / (sizeof((arr)[0])*8)] |= (((U64)1) << ((bit) % (sizeof((arr)[0])*8))))
|
||||||
|
#define BitArrayRemove(arr, bit) ((arr)[(bit) / (sizeof((arr)[0])*8)] &= ~(((U64)1) << ((bit) % (sizeof((arr)[0])*8))))
|
||||||
|
#define BitArrayGet(arr, bit) (!!((arr)[(bit) / (sizeof((arr)[0])*8)] & (((U64)1) << ((bit) % (sizeof((arr)[0])*8)))))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Masks
|
||||||
|
|
||||||
|
#define Lower16(x) (((x)&0x0000ffff) >> 0)
|
||||||
|
#define Upper16(x) (((x)&0xffff0000) >> 16)
|
||||||
|
#define Lower32(x) (((x)&0x00000000ffffffffull) >> 0)
|
||||||
|
#define Upper32(x) (((x)&0xffffffff00000000ull) >> 32)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Units
|
||||||
|
|
||||||
|
#define KiB(x) ((x)*1024)
|
||||||
|
#define MiB(x) (KiB(x)*1024)
|
||||||
|
#define GiB(x) (MiB(x)*1024)
|
||||||
|
#define TiB(x) (GiB(x)*1024)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Structure Packing Marker Macros
|
||||||
|
|
||||||
|
#define pack_begin _Pragma("pack(push, 1)")
|
||||||
|
#define pack_end _Pragma("pack(pop)")
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Type -> Alignment
|
||||||
|
|
||||||
|
#if COMPILER_MSVC
|
||||||
|
# define AlignOf(T) __alignof(T)
|
||||||
|
#elif COMPILER_CLANG
|
||||||
|
# define AlignOf(T) __alignof(T)
|
||||||
|
#elif COMPILER_GCC
|
||||||
|
# define AlignOf(T) __alignof__(T)
|
||||||
|
#else
|
||||||
|
# error AlignOf not defined for this compiler.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Basic Types
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef int8_t S8;
|
||||||
|
typedef int16_t S16;
|
||||||
|
typedef int32_t S32;
|
||||||
|
typedef int64_t S64;
|
||||||
|
typedef uint8_t U8;
|
||||||
|
typedef uint16_t U16;
|
||||||
|
typedef uint32_t U32;
|
||||||
|
typedef uint64_t U64;
|
||||||
|
typedef S8 B8;
|
||||||
|
typedef S16 B16;
|
||||||
|
typedef S32 B32;
|
||||||
|
typedef S64 B64;
|
||||||
|
typedef float F32;
|
||||||
|
typedef double F64;
|
||||||
|
typedef void VoidFunction(void);
|
||||||
|
|
||||||
|
#if ARCH_32BIT
|
||||||
|
typedef S32 SAddr;
|
||||||
|
typedef U32 UAddr;
|
||||||
|
#elif ARCH_64BIT
|
||||||
|
typedef S64 SAddr;
|
||||||
|
typedef U64 UAddr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: C Runtime Implementations
|
||||||
|
|
||||||
|
void *memset(void *buffer, int c, UAddr n);
|
||||||
|
void *memcpy(void *dest, void *src, UAddr n);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Memory Operations
|
||||||
|
|
||||||
|
#define MemoryZero(ptr, size) memset((ptr), 0, (size))
|
||||||
|
#define MemoryZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
|
||||||
|
#define MemoryCopy(dst, src, size) memcpy((dst), (src), (size))
|
||||||
|
#define MemoryCopyStruct(dst, src) memcpy((dst), (src), Min(sizeof(*(dst)), sizeof(*(src))))
|
||||||
|
|
||||||
|
function inline void
|
||||||
|
WriteAndInc(void *buffer, void *src, UAddr size, UAddr *cursor)
|
||||||
|
{
|
||||||
|
MemoryCopy((U8 *)buffer + *cursor, src, size);
|
||||||
|
*cursor += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline void
|
||||||
|
ReadAndInc(void *buffer, void *dst, UAddr size, UAddr *cursor)
|
||||||
|
{
|
||||||
|
MemoryCopy(dst, (U8 *)buffer + *cursor, size);
|
||||||
|
*cursor += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WriteStructAndInc(buffer, ptr, cursor_ptr) WriteAndInc((buffer), (ptr), sizeof(*(ptr)), (cursor_ptr))
|
||||||
|
#define ReadStructAndInc(buffer, ptr, cursor_ptr) ReadAndInc((buffer), (ptr), sizeof(*(ptr)), (cursor_ptr))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Float Operations
|
||||||
|
|
||||||
|
function inline F32
|
||||||
|
TruncF32(F32 f)
|
||||||
|
{
|
||||||
|
#if ARCH_MIPS32
|
||||||
|
F32 result_int;
|
||||||
|
F32 result;
|
||||||
|
__asm("trunc.w.s %0,%1" : "=f"(result_int) : "f"(f));
|
||||||
|
__asm("cvt.s.w %0,%1" : "=f"(result) : "f"(result_int));
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
# error TruncF32 not implemented for this architecture.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline F32
|
||||||
|
FloorF32(F32 f)
|
||||||
|
{
|
||||||
|
#if ARCH_MIPS32
|
||||||
|
F32 result_int;
|
||||||
|
F32 result;
|
||||||
|
__asm("floor.w.s %0,%1" : "=f"(result_int) : "f"(f));
|
||||||
|
__asm("cvt.s.w %0,%1" : "=f"(result) : "f"(result_int));
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
# error FloorF32 not implemented for this architecture.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline F32
|
||||||
|
ModF32(F32 f, F32 d)
|
||||||
|
{
|
||||||
|
F32 result = f - TruncF32(f/d)*d;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline S32
|
||||||
|
Fixed112FromF32(F32 f)
|
||||||
|
{
|
||||||
|
S32 result = (S32)(f*4.f);
|
||||||
|
result = Clamp(-4096*4, result, +4095*4);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline S32
|
||||||
|
Fixed1616FromF32(F32 f)
|
||||||
|
{
|
||||||
|
S32 result;
|
||||||
|
if(f >= 32768.f)
|
||||||
|
{
|
||||||
|
result = 0x7fffffff;
|
||||||
|
}
|
||||||
|
else if(f < -32768.f)
|
||||||
|
{
|
||||||
|
result = 0x80000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = (S32)FloorF32(f*65536.f);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Scalar Math Functions
|
||||||
|
|
||||||
|
function F32 inline
|
||||||
|
SquareRootF32(F32 v)
|
||||||
|
{
|
||||||
|
#if ARCH_MIPS32
|
||||||
|
F32 result;
|
||||||
|
__asm("sqrt.s %0,%1" : "=f"(result) : "f"(v));
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
# error SquareRootF32 not implemented for this architecture.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
function F32 SinF32(F32 turns);
|
||||||
|
|
||||||
|
function F32 inline
|
||||||
|
CosF32(F32 turns)
|
||||||
|
{
|
||||||
|
F32 result = SinF32(turns + 0.25f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function F32 inline
|
||||||
|
TanF32(F32 turns)
|
||||||
|
{
|
||||||
|
F32 result = SinF32(turns) / CosF32(turns);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Vector / Matrix Types
|
||||||
|
|
||||||
|
typedef union Vec2U32 Vec2U32;
|
||||||
|
union Vec2U32
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
U32 x;
|
||||||
|
U32 y;
|
||||||
|
};
|
||||||
|
U32 v[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union Vec2F32 Vec2F32;
|
||||||
|
union Vec2F32
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
F32 x;
|
||||||
|
F32 y;
|
||||||
|
};
|
||||||
|
F32 v[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union Vec3F32 Vec3F32;
|
||||||
|
union Vec3F32
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
F32 x;
|
||||||
|
F32 y;
|
||||||
|
F32 z;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vec2F32 xy;
|
||||||
|
F32 z_;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
F32 x_;
|
||||||
|
Vec2F32 yz;
|
||||||
|
};
|
||||||
|
F32 v[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union Vec4F32 Vec4F32;
|
||||||
|
union Vec4F32
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
F32 x;
|
||||||
|
F32 y;
|
||||||
|
F32 z;
|
||||||
|
F32 w;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vec2F32 xy;
|
||||||
|
Vec2F32 zw;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vec3F32 xyz;
|
||||||
|
F32 w_;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
F32 x_;
|
||||||
|
Vec3F32 yzw;
|
||||||
|
};
|
||||||
|
F32 v[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Mat3x3F32 Mat3x3F32;
|
||||||
|
struct Mat3x3F32
|
||||||
|
{
|
||||||
|
F32 v[3][3];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Mat4x4F32 Mat4x4F32;
|
||||||
|
struct Mat4x4F32
|
||||||
|
{
|
||||||
|
F32 v[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Vector Functions
|
||||||
|
|
||||||
|
//- rjf: constructors
|
||||||
|
function Vec2U32 V2U32(U32 x, U32 y);
|
||||||
|
function Vec2F32 V2F32(F32 x, F32 y);
|
||||||
|
function Vec3F32 V3F32(F32 x, F32 y, F32 z);
|
||||||
|
function Vec4F32 V4F32(F32 x, F32 y, F32 z, F32 w);
|
||||||
|
|
||||||
|
//- rjf: 2-vector ops
|
||||||
|
function Vec2F32 Add2F32(Vec2F32 l, Vec2F32 r);
|
||||||
|
function Vec2F32 Sub2F32(Vec2F32 l, Vec2F32 r);
|
||||||
|
function Vec2F32 Mul2F32(Vec2F32 l, Vec2F32 r);
|
||||||
|
function Vec2F32 Div2F32(Vec2F32 l, Vec2F32 r);
|
||||||
|
function F32 LengthSquared2F32(Vec2F32 v);
|
||||||
|
function F32 Length2F32(Vec2F32 v);
|
||||||
|
function Vec2F32 Scale2F32(Vec2F32 v, F32 s);
|
||||||
|
function Vec2F32 Normalize2F32(Vec2F32 v);
|
||||||
|
function F32 Dot2F32(Vec2F32 l, Vec2F32 r);
|
||||||
|
|
||||||
|
//- rjf: 3-vector ops
|
||||||
|
function Vec3F32 Add3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
function Vec3F32 Sub3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
function Vec3F32 Mul3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
function Vec3F32 Div3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
function F32 LengthSquared3F32(Vec3F32 v);
|
||||||
|
function F32 Length3F32(Vec3F32 v);
|
||||||
|
function Vec3F32 Scale3F32(Vec3F32 v, F32 s);
|
||||||
|
function Vec3F32 Normalize3F32(Vec3F32 v);
|
||||||
|
function F32 Dot3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
function Vec3F32 Cross3F32(Vec3F32 l, Vec3F32 r);
|
||||||
|
|
||||||
|
//- rjf: 4-vector ops
|
||||||
|
function Vec4F32 Add4F32(Vec4F32 l, Vec4F32 r);
|
||||||
|
function Vec4F32 Sub4F32(Vec4F32 l, Vec4F32 r);
|
||||||
|
function Vec4F32 Mul4F32(Vec4F32 l, Vec4F32 r);
|
||||||
|
function Vec4F32 Div4F32(Vec4F32 l, Vec4F32 r);
|
||||||
|
function F32 LengthSquared4F32(Vec4F32 v);
|
||||||
|
function F32 Length4F32(Vec4F32 v);
|
||||||
|
function Vec4F32 Scale4F32(Vec4F32 v, F32 s);
|
||||||
|
function Vec4F32 Normalize4F32(Vec4F32 v);
|
||||||
|
function F32 Dot4F32(Vec4F32 l, Vec4F32 r);
|
||||||
|
function Vec4F32 XForm4F32(Mat4x4F32 m, Vec4F32 v);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Matrix Functions
|
||||||
|
|
||||||
|
//- rjf: constructors
|
||||||
|
function Mat3x3F32 MakeMat3x3F32(F32 d);
|
||||||
|
function Mat3x3F32 MakeTranslate3x3F32(Vec2F32 translation);
|
||||||
|
function Mat3x3F32 MakeScale3x3F32(Vec2F32 scale);
|
||||||
|
function Mat3x3F32 MakeRotate3x3F32(F32 turns);
|
||||||
|
function Mat4x4F32 MakeMat4x4F32(F32 d);
|
||||||
|
function Mat4x4F32 MakeTranslate4x4F32(Vec3F32 translation);
|
||||||
|
function Mat4x4F32 MakeScale4x4F32(Vec3F32 scale);
|
||||||
|
function Mat4x4F32 MakePerspective4x4F32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z);
|
||||||
|
function Mat4x4F32 MakeOrthographic4x4F32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z);
|
||||||
|
function Mat4x4F32 MakeLookAt4x4F32(Vec3F32 eye, Vec3F32 center, Vec3F32 up);
|
||||||
|
function Mat4x4F32 MakeRotate4x4F32(Vec3F32 axis, F32 turns);
|
||||||
|
|
||||||
|
//- rjf: ops
|
||||||
|
function Mat3x3F32 Mul3x3F32(Mat3x3F32 a, Mat3x3F32 b);
|
||||||
|
function Mat3x3F32 Scale3x3F32(Mat3x3F32 m, F32 scale);
|
||||||
|
function Mat4x4F32 Mul4x4F32(Mat4x4F32 a, Mat4x4F32 b);
|
||||||
|
function Mat4x4F32 Scale4x4F32(Mat4x4F32 m, F32 scale);
|
||||||
|
function Mat4x4F32 Inverse4x4F32(Mat4x4F32 m);
|
||||||
|
function Mat4x4F32 RemoveRotation4x4F32(Mat4x4F32 mat);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Arenas
|
||||||
|
|
||||||
|
typedef struct Arena Arena;
|
||||||
|
struct Arena
|
||||||
|
{
|
||||||
|
UAddr pos;
|
||||||
|
UAddr cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Arena *ArenaMakeStatic(U8 *buffer, UAddr buffer_size);
|
||||||
|
function void *ArenaPush(Arena *arena, UAddr size, UAddr align);
|
||||||
|
function UAddr ArenaPos(Arena *arena);
|
||||||
|
function void ArenaPopTo(Arena *arena, UAddr pos);
|
||||||
|
function void ArenaClear(Arena *arena);
|
||||||
|
function void ArenaPop(Arena *arena, UAddr amt);
|
||||||
|
#define PushArrayNoZeroAligned(a, T, c, align) (T *)ArenaPush((a), sizeof(T)*(c), (align))
|
||||||
|
#define PushArrayAligned(a, T, c, align) (T *)MemoryZero(PushArrayNoZeroAligned(a, T, c, align), sizeof(T)*(c))
|
||||||
|
#define PushArrayNoZero(a, T, c) PushArrayNoZeroAligned(a, T, c, AlignOf(T))
|
||||||
|
#define PushArray(a, T, c) PushArrayAligned(a, T, c, AlignOf(T))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Arena Temporary Scopes
|
||||||
|
|
||||||
|
typedef struct Temp Temp;
|
||||||
|
struct Temp
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
UAddr pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Temp TempBegin(Arena *arena);
|
||||||
|
function void TempEnd(Temp temp);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Thread Context
|
||||||
|
|
||||||
|
typedef struct ThreadCtx ThreadCtx;
|
||||||
|
struct ThreadCtx
|
||||||
|
{
|
||||||
|
Arena *scratch_arenas[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
//- rjf: @per_platform Thread Context Functions
|
||||||
|
function ThreadCtx *GetThreadCtx(void);
|
||||||
|
|
||||||
|
//- rjf: Thread Context Helpers
|
||||||
|
function Arena *GetScratch(Arena *conflict);
|
||||||
|
#define ScratchBegin(result_arena) TempBegin(GetScratch(result_arena))
|
||||||
|
#define ScratchEnd(temp) TempEnd(temp)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Strings
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef struct String8 String8;
|
||||||
|
struct String8
|
||||||
|
{
|
||||||
|
U8 *str;
|
||||||
|
UAddr size;
|
||||||
|
};
|
||||||
|
|
||||||
|
function UAddr CStr8Size(char *cstr);
|
||||||
|
function String8 Str8(U8 *str, UAddr size);
|
||||||
|
#define Str8Lit(s) Str8((U8 *)(s), sizeof(s)-1)
|
||||||
|
#define Str8LitComp(s) {(U8 *)(s), sizeof(s)-1}
|
||||||
|
#define S(s) Str8Lit(s)
|
||||||
|
function String8 Str8FV(Arena *arena, char *fmt, va_list args);
|
||||||
|
function String8 Str8F(Arena *arena, char *fmt, ...);
|
||||||
|
#define SF(...) Str8F(scratch.arena, __VA_ARGS__)
|
||||||
|
function String8 ByteStringFromData(Arena *arena, String8 data);
|
||||||
|
|
||||||
|
global U8 dec_chars[] = "0123456789";
|
||||||
|
global U8 hex_chars_lower[] = "0123456789abcdef";
|
||||||
|
global U8 hex_chars_upper[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Colors
|
||||||
|
|
||||||
|
function U16 RGBA5551From4F32(Vec4F32 rgba);
|
||||||
|
function U32 RGBA32From4F32(Vec4F32 rgba);
|
||||||
|
function Vec4F32 RGBA4F32From32(U32 rgba);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Game Pads
|
||||||
|
|
||||||
|
typedef enum GamePadButtonKind
|
||||||
|
{
|
||||||
|
GamePadButtonKind_Null,
|
||||||
|
GamePadButtonKind_A,
|
||||||
|
GamePadButtonKind_B,
|
||||||
|
GamePadButtonKind_CLeft,
|
||||||
|
GamePadButtonKind_CUp,
|
||||||
|
GamePadButtonKind_CRight,
|
||||||
|
GamePadButtonKind_CDown,
|
||||||
|
GamePadButtonKind_Start,
|
||||||
|
GamePadButtonKind_DLeft,
|
||||||
|
GamePadButtonKind_DUp,
|
||||||
|
GamePadButtonKind_DRight,
|
||||||
|
GamePadButtonKind_DDown,
|
||||||
|
GamePadButtonKind_Z,
|
||||||
|
GamePadButtonKind_LeftBumper,
|
||||||
|
GamePadButtonKind_RightBumper,
|
||||||
|
GamePadButtonKind_COUNT
|
||||||
|
}
|
||||||
|
GamePadButtonKind;
|
||||||
|
|
||||||
|
typedef struct GamePad GamePad;
|
||||||
|
struct GamePad
|
||||||
|
{
|
||||||
|
U32 connect_gen; // incremented on every connection change
|
||||||
|
BitArrayDecl(U32, last_buttons, GamePadButtonKind_COUNT);
|
||||||
|
BitArrayDecl(U32, buttons, GamePadButtonKind_COUNT);
|
||||||
|
F32 left_trigger;
|
||||||
|
F32 right_trigger;
|
||||||
|
Vec2F32 sticks[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GAME_PAD_SLOT_COUNT 4
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Program Tick Entry Point
|
||||||
|
|
||||||
|
function B32 Run(U64 tick_idx, Arena *permanent_arena, GamePad game_pads[GAME_PAD_SLOT_COUNT]);
|
||||||
|
|
||||||
|
#endif // BASE_H
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#include "base.c"
|
||||||
|
#if PLATFORM_N64
|
||||||
|
# include "n64/base/n64_base.c"
|
||||||
|
#else
|
||||||
|
# error Platform-defined implementations for base layer not defined for this platform.
|
||||||
|
#endif
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef BASE_INC_H
|
||||||
|
#define BASE_INC_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
#if PLATFORM_N64
|
||||||
|
# include "n64/base/n64_base.h"
|
||||||
|
#else
|
||||||
|
# error Platform-defined implementations for base layer not defined for this platform.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BASE_INC_H
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
function ThreadCtx *
|
||||||
|
GetThreadCtx(void)
|
||||||
|
{
|
||||||
|
return &n64_tctx;
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef N64_BASE_H
|
||||||
|
#define N64_BASE_H
|
||||||
|
|
||||||
|
#endif // N64_BASE_H
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-bigmips")
|
||||||
|
OUTPUT_ARCH(mips)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
irq PT_LOAD AT (0x80000000);
|
||||||
|
text PT_LOAD AT (0x80000400);
|
||||||
|
data PT_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.intvectors 0x80000000 :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
KEEP(*(.intvectors))
|
||||||
|
__intvectors_end = .;
|
||||||
|
}:irq
|
||||||
|
|
||||||
|
.text 0x80000400 :
|
||||||
|
{
|
||||||
|
*(.text.boot)
|
||||||
|
*(.text*)
|
||||||
|
*(.rodata*)
|
||||||
|
}:text
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data*)
|
||||||
|
n64_static_data_end = .;
|
||||||
|
}:data
|
||||||
|
|
||||||
|
.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
__bss_start = .;
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.eh_frame*)
|
||||||
|
*(.comment)
|
||||||
|
*(.note*)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,333 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Resources @per_platform
|
||||||
|
|
||||||
|
function R_BufferHandle
|
||||||
|
R_BufferHandleFromData(void *data, UAddr element_count, UAddr element_size)
|
||||||
|
{
|
||||||
|
R_BufferHandle result = {0};
|
||||||
|
if(n64_r_state.buffers_count < ArrayCount(n64_r_state.buffers))
|
||||||
|
{
|
||||||
|
N64_R_Buffer *buffer = &n64_r_state.buffers[n64_r_state.buffers_count];
|
||||||
|
buffer->data = data;
|
||||||
|
buffer->element_count = element_count;
|
||||||
|
buffer->element_size = element_size;
|
||||||
|
n64_r_state.buffers_count += 1;
|
||||||
|
result.uaddr[0] = n64_r_state.buffers_count;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function R_SubModelHandle
|
||||||
|
R_SubModelHandleFromBuffers(R_BufferHandle vtx_buffer, R_BufferHandle idx_buffer)
|
||||||
|
{
|
||||||
|
R_SubModelHandle result = {0};
|
||||||
|
if(n64_r_state.sub_models_count < ArrayCount(n64_r_state.sub_models))
|
||||||
|
{
|
||||||
|
N64_R_SubModel *sub_model= &n64_r_state.sub_models[n64_r_state.sub_models_count];
|
||||||
|
sub_model->vtx_buffer_num = (U16)vtx_buffer.uaddr[0];
|
||||||
|
sub_model->idx_buffer_num = (U16)idx_buffer.uaddr[0];
|
||||||
|
n64_r_state.sub_models_count += 1;
|
||||||
|
result.uaddr[0] = n64_r_state.sub_models_count;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Commands @per_platform
|
||||||
|
|
||||||
|
function void
|
||||||
|
R_Pass(R_PassParams *params)
|
||||||
|
{
|
||||||
|
MemoryCopyStruct(&n64_r_state.pass_params, params);
|
||||||
|
n64_r_state.pass_view_projection = Mul4x4F32(params->projection, params->view);
|
||||||
|
n64_r_state.buffers_count = 0;
|
||||||
|
n64_r_state.sub_models_count = 0;
|
||||||
|
|
||||||
|
//- rjf: draw sky
|
||||||
|
{
|
||||||
|
// rjf: sync pipe
|
||||||
|
{
|
||||||
|
N64_DP_Cmd_Stub cmd = {0};
|
||||||
|
cmd.id = N64_DP_CmdID_SyncPipe;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: set other modes
|
||||||
|
{
|
||||||
|
N64_DP_Cmd_SetOtherModes cmd = {0};
|
||||||
|
cmd.id = N64_DP_CmdID_SetOtherModes;
|
||||||
|
cmd.atomic_prim = 1;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: draw full-screen triangle for sky
|
||||||
|
{
|
||||||
|
N64_DP_Cmd_FillTriangleBase cmd = {0};
|
||||||
|
cmd.id = N64_DP_CmdID_FillTriangleS;
|
||||||
|
cmd.flags = N64_DP_Cmd_FillTriangleFlag_LeftMajor;
|
||||||
|
cmd.yl = Fixed112FromF32(N64_FB_HEIGHT);
|
||||||
|
cmd.ym = Fixed112FromF32(N64_FB_HEIGHT);
|
||||||
|
cmd.yh = 0;
|
||||||
|
cmd.xl = Fixed1616FromF32(N64_FB_WIDTH);
|
||||||
|
cmd.dxldy = 0;
|
||||||
|
cmd.xh = 0;
|
||||||
|
cmd.dxhdy = 0;
|
||||||
|
cmd.xm = Fixed1616FromF32(N64_FB_WIDTH);
|
||||||
|
cmd.dxmdy = 0;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
{
|
||||||
|
F32 pitch = 0.1f;
|
||||||
|
Vec4F32 top_color_4f32 = V4F32(0.02f, 0.2f - 0.1f*(0.75f + pitch/0.25f), 0.05f - 0.02f*(0.75f + pitch/0.25f), 1.f);
|
||||||
|
// top_color_4f32 = V4F32(0.02f, 0.15f - 0.1f*(0.75f + pitch/0.25f), 0.3f - 0.02f*(0.75f + pitch/0.25f), 1.f);
|
||||||
|
S32 top_color_x_s32 = Fixed1616FromF32(top_color_4f32.x*255.f);
|
||||||
|
S32 top_color_y_s32 = Fixed1616FromF32(top_color_4f32.y*255.f);
|
||||||
|
S32 top_color_z_s32 = Fixed1616FromF32(top_color_4f32.z*255.f);
|
||||||
|
S32 top_color_w_s32 = Fixed1616FromF32(top_color_4f32.w*255.f);
|
||||||
|
S32 dcdy = Fixed1616FromF32(-0.1f);
|
||||||
|
S32 dcpdy = Fixed1616FromF32(+0.01f);
|
||||||
|
N64_DP_CmdExt_FillTriangleShading ext = {0};
|
||||||
|
ext.r_i = Upper16(top_color_x_s32);
|
||||||
|
ext.g_i = Upper16(top_color_y_s32);
|
||||||
|
ext.b_i = Upper16(top_color_z_s32);
|
||||||
|
ext.a_i = Upper16(top_color_w_s32);
|
||||||
|
ext.r_f = Lower16(top_color_x_s32);
|
||||||
|
ext.g_f = Lower16(top_color_y_s32);
|
||||||
|
ext.b_f = Lower16(top_color_z_s32);
|
||||||
|
ext.a_f = Lower16(top_color_w_s32);
|
||||||
|
ext.drde_i = Upper16(dcdy);
|
||||||
|
ext.dgde_i = Upper16(dcdy);
|
||||||
|
ext.dbde_i = Upper16(dcpdy);
|
||||||
|
ext.drde_f = Lower16(dcdy);
|
||||||
|
ext.dgde_f = Lower16(dcdy);
|
||||||
|
ext.dbde_f = Lower16(dcpdy);
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &ext, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: set up depth tested drawing parameters
|
||||||
|
{
|
||||||
|
// rjf: sync pipe
|
||||||
|
{
|
||||||
|
N64_DP_Cmd_Stub cmd = {0};
|
||||||
|
cmd.id = N64_DP_CmdID_SyncPipe;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: set other modes
|
||||||
|
{
|
||||||
|
N64_DP_Cmd_SetOtherModes cmd = {0};
|
||||||
|
cmd.id = N64_DP_CmdID_SetOtherModes;
|
||||||
|
cmd.atomic_prim = 1;
|
||||||
|
cmd.z_update_en = 1;
|
||||||
|
cmd.z_compare_en = 1;
|
||||||
|
cmd.antialias_en = 1;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
R_SubModel(R_SubModelHandle handle, R_Material material, Mat4x4F32 xform)
|
||||||
|
{
|
||||||
|
Mat4x4F32 view_projection = n64_r_state.pass_view_projection;
|
||||||
|
UAddr sub_model_num = handle.uaddr[0];
|
||||||
|
if(0 < sub_model_num && sub_model_num <= n64_r_state.sub_models_count)
|
||||||
|
{
|
||||||
|
N64_R_SubModel *sub_model = &n64_r_state.sub_models[sub_model_num-1];
|
||||||
|
if(0 < sub_model->vtx_buffer_num && sub_model->vtx_buffer_num <= n64_r_state.buffers_count &&
|
||||||
|
0 < sub_model->idx_buffer_num && sub_model->idx_buffer_num <= n64_r_state.buffers_count)
|
||||||
|
{
|
||||||
|
N64_R_Buffer *vtx_buffer = &n64_r_state.buffers[sub_model->vtx_buffer_num-1];
|
||||||
|
N64_R_Buffer *idx_buffer = &n64_r_state.buffers[sub_model->idx_buffer_num-1];
|
||||||
|
Vec3F32 material_rgb = material.color.xyz;
|
||||||
|
if(vtx_buffer->element_size == sizeof(Vec3F32) &&
|
||||||
|
(idx_buffer->element_size == 2 || idx_buffer->element_size == 4))
|
||||||
|
{
|
||||||
|
UAddr tri_count = idx_buffer->element_count/3;
|
||||||
|
Vec3F32 *vtx = (Vec3F32 *)vtx_buffer->data;
|
||||||
|
UAddr vtx_count = vtx_buffer->element_count;
|
||||||
|
UAddr command_bytes_per_tri = sizeof(N64_DP_Cmd_FillTriangleBase) + sizeof(N64_DP_CmdExt_FillTriangleShading) + sizeof(N64_DP_CmdExt_FillTriangleDepth);
|
||||||
|
UAddr command_bytes_left = ArrayCount(n64_r_state.rdp_command_buffer) - n64_r_state.rdp_command_buffer_write_pos;
|
||||||
|
UAddr tri_count_max = command_bytes_left / command_bytes_per_tri;
|
||||||
|
UAddr tri_count_actual = Min(tri_count_max, tri_count);
|
||||||
|
for EachIndex(tri_idx, tri_count_actual)
|
||||||
|
{
|
||||||
|
// rjf: get face nums for this triangle
|
||||||
|
UAddr face_nums[3];
|
||||||
|
switch(idx_buffer->element_size)
|
||||||
|
{
|
||||||
|
default:{MemoryZero(face_nums, sizeof(face_nums));}break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
face_nums[0] = ((U16 *)idx_buffer->data)[tri_idx*3+0];
|
||||||
|
face_nums[1] = ((U16 *)idx_buffer->data)[tri_idx*3+1];
|
||||||
|
face_nums[2] = ((U16 *)idx_buffer->data)[tri_idx*3+2];
|
||||||
|
}break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
face_nums[0] = ((U32 *)idx_buffer->data)[tri_idx*3+0];
|
||||||
|
face_nums[1] = ((U32 *)idx_buffer->data)[tri_idx*3+1];
|
||||||
|
face_nums[2] = ((U32 *)idx_buffer->data)[tri_idx*3+2];
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: unpack world-space vertices
|
||||||
|
Vec4F32 world_v[3] =
|
||||||
|
{
|
||||||
|
V4F32(vtx[face_nums[0]-1].x, vtx[face_nums[0]-1].y, vtx[face_nums[0]-1].z, 1.f),
|
||||||
|
V4F32(vtx[face_nums[1]-1].x, vtx[face_nums[1]-1].y, vtx[face_nums[1]-1].z, 1.f),
|
||||||
|
V4F32(vtx[face_nums[2]-1].x, vtx[face_nums[2]-1].y, vtx[face_nums[2]-1].z, 1.f),
|
||||||
|
};
|
||||||
|
|
||||||
|
// rjf: world -> clip
|
||||||
|
Vec4F32 clip_v[] =
|
||||||
|
{
|
||||||
|
XForm4F32(view_projection, world_v[0]),
|
||||||
|
XForm4F32(view_projection, world_v[1]),
|
||||||
|
XForm4F32(view_projection, world_v[2]),
|
||||||
|
};
|
||||||
|
|
||||||
|
// rjf: clip -> ndc
|
||||||
|
Vec3F32 ndc_v[] =
|
||||||
|
{
|
||||||
|
Scale3F32(clip_v[0].xyz, 1.f/clip_v[0].w),
|
||||||
|
Scale3F32(clip_v[1].xyz, 1.f/clip_v[1].w),
|
||||||
|
Scale3F32(clip_v[2].xyz, 1.f/clip_v[2].w),
|
||||||
|
};
|
||||||
|
|
||||||
|
// rjf: early discard of back-facing triangles
|
||||||
|
{
|
||||||
|
Vec3F32 normal = Cross3F32(Sub3F32(ndc_v[1], ndc_v[0]), Sub3F32(ndc_v[2], ndc_v[0]));
|
||||||
|
Vec3F32 eye = V3F32(0, 0, 1);
|
||||||
|
F32 dot = Dot3F32(normal, eye);
|
||||||
|
if(dot > 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: ndc -> screen
|
||||||
|
Vec3F32 ndc2screen_v = V3F32(N64_FB_WIDTH/2.f, N64_FB_HEIGHT/2.f, 0x7FFF/2.f);
|
||||||
|
Vec3F32 screen_v[] =
|
||||||
|
{
|
||||||
|
Mul3F32(Add3F32(Mul3F32(ndc_v[0], V3F32(-1, -1, 1)), V3F32(1, 1, 1)), ndc2screen_v),
|
||||||
|
Mul3F32(Add3F32(Mul3F32(ndc_v[1], V3F32(-1, -1, 1)), V3F32(1, 1, 1)), ndc2screen_v),
|
||||||
|
Mul3F32(Add3F32(Mul3F32(ndc_v[2], V3F32(-1, -1, 1)), V3F32(1, 1, 1)), ndc2screen_v),
|
||||||
|
};
|
||||||
|
|
||||||
|
// rjf: screen -> snapped; ensures joining edges of triangles, otherwise triangles
|
||||||
|
// disagree on edges in projected space, causing seams.
|
||||||
|
for EachElement(idx, screen_v)
|
||||||
|
{
|
||||||
|
for EachIndex(axis, 3)
|
||||||
|
{
|
||||||
|
screen_v[idx].v[axis] = FloorF32(screen_v[idx].v[axis]*4.f)/4.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: sort vertices into top/mid/bot
|
||||||
|
Vec3F32 top = screen_v[0];
|
||||||
|
Vec3F32 mid = screen_v[1];
|
||||||
|
Vec3F32 bot = screen_v[2];
|
||||||
|
U8 world_idxs[] =
|
||||||
|
{
|
||||||
|
0, 1, 2
|
||||||
|
};
|
||||||
|
if(mid.y > bot.y)
|
||||||
|
{
|
||||||
|
Swap(Vec3F32, mid, bot);
|
||||||
|
}
|
||||||
|
if(top.y > mid.y)
|
||||||
|
{
|
||||||
|
Swap(Vec3F32, top, mid);
|
||||||
|
}
|
||||||
|
if(mid.y > bot.y)
|
||||||
|
{
|
||||||
|
Swap(Vec3F32, mid, bot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: unpack triangle edges
|
||||||
|
//
|
||||||
|
// *
|
||||||
|
// |\ "M":top2mid
|
||||||
|
// | \
|
||||||
|
// "H":top2bot | *
|
||||||
|
// | /
|
||||||
|
// |/ "L":mid2bot
|
||||||
|
// *
|
||||||
|
//
|
||||||
|
Vec3F32 top2mid = Sub3F32(mid, top);
|
||||||
|
Vec3F32 top2bot = Sub3F32(bot, top);
|
||||||
|
Vec3F32 mid2bot = Sub3F32(bot, mid);
|
||||||
|
F32 top2bot_invslope = (top2bot.y != 0) ? (top2bot.x / top2bot.y) : 0;
|
||||||
|
F32 top2mid_invslope = (top2mid.y != 0) ? (top2mid.x / top2mid.y) : 0;
|
||||||
|
F32 mid2bot_invslope = (mid2bot.y != 0) ? (mid2bot.x / mid2bot.y) : 0;
|
||||||
|
F32 fy = FloorF32(top.y) - top.y;
|
||||||
|
F32 nz = top2bot.x*top2mid.y - top2bot.y*top2mid.x;
|
||||||
|
F32 inv_n = (nz != 0.f) ? (-1.f / nz) : 0.f;
|
||||||
|
|
||||||
|
// rjf: fill command
|
||||||
|
N64_DP_Cmd_FillTriangleBase cmd = {0};
|
||||||
|
F32 x_h_at_mid = top.x + (mid.y - top.y) * top2bot_invslope;
|
||||||
|
B32 left_major = (mid.x >= x_h_at_mid);
|
||||||
|
cmd.id = N64_DP_CmdID_FillTriangleSZ;
|
||||||
|
cmd.flags = left_major ? N64_DP_Cmd_FillTriangleFlag_LeftMajor : 0;
|
||||||
|
cmd.yl = Fixed112FromF32(bot.y);
|
||||||
|
cmd.ym = Fixed112FromF32(mid.y);
|
||||||
|
cmd.yh = Fixed112FromF32(top.y);
|
||||||
|
cmd.xl = Fixed1616FromF32(mid.x);
|
||||||
|
cmd.dxldy = Fixed1616FromF32(mid2bot_invslope);
|
||||||
|
cmd.xh = Fixed1616FromF32(top.x + fy*top2bot_invslope);
|
||||||
|
cmd.dxhdy = Fixed1616FromF32(top2bot_invslope);
|
||||||
|
cmd.xm = Fixed1616FromF32(top.x + fy*top2mid_invslope);
|
||||||
|
cmd.dxmdy = Fixed1616FromF32(top2mid_invslope);
|
||||||
|
|
||||||
|
// rjf: push
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &cmd, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
|
||||||
|
// rjf: unpack lighting
|
||||||
|
Vec3F32 normal = Cross3F32(Sub3F32(world_v[2].xyz, world_v[0].xyz), Sub3F32(world_v[1].xyz, world_v[0].xyz));
|
||||||
|
Vec3F32 keylight_dir = n64_r_state.pass_params.keylight_dir;
|
||||||
|
F32 normal_dot_keylight_dir = Dot3F32(Normalize3F32(keylight_dir), Normalize3F32(normal));
|
||||||
|
F32 light_factor_unclamped = 1 - Clamp(0, -normal_dot_keylight_dir, 1);
|
||||||
|
F32 light_factor = Clamp(0.2f, light_factor_unclamped, 1.f);
|
||||||
|
|
||||||
|
// rjf: unpack vertex colors
|
||||||
|
Vec3F32 rgb_v[] =
|
||||||
|
{
|
||||||
|
Scale3F32(material_rgb, light_factor),
|
||||||
|
Scale3F32(material_rgb, light_factor),
|
||||||
|
Scale3F32(material_rgb, light_factor),
|
||||||
|
};
|
||||||
|
|
||||||
|
// rjf: extend w/ shading
|
||||||
|
{
|
||||||
|
N64_DP_CmdExt_FillTriangleShading ext = {0};
|
||||||
|
ext.r_i = 255*rgb_v[0].x;
|
||||||
|
ext.g_i = 255*rgb_v[0].y;
|
||||||
|
ext.b_i = 255*rgb_v[0].z;
|
||||||
|
ext.a_i = 255;
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &ext, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: extend w/ depth
|
||||||
|
{
|
||||||
|
F32 dzdx = (top2bot.y*top2mid.z - top2mid.y*top2bot.z) * inv_n;
|
||||||
|
F32 dzdy = (top2mid.x*top2bot.z - top2bot.x*top2mid.z) * inv_n;
|
||||||
|
F32 dzde = dzdy + dzdx*top2bot_invslope;
|
||||||
|
N64_DP_CmdExt_FillTriangleDepth ext = {0};
|
||||||
|
ext.z = Fixed1616FromF32(top.z + fy * dzde);
|
||||||
|
ext.dzdx = Fixed1616FromF32(dzdx);
|
||||||
|
ext.dzdy = Fixed1616FromF32(dzdy);
|
||||||
|
ext.dzde = Fixed1616FromF32(dzde);
|
||||||
|
WriteStructAndInc(n64_r_state.rdp_command_buffer, &ext, &n64_r_state.rdp_command_buffer_write_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef N64_RENDER_H
|
||||||
|
#define N64_RENDER_H
|
||||||
|
|
||||||
|
typedef struct N64_R_Buffer N64_R_Buffer;
|
||||||
|
struct N64_R_Buffer
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
UAddr element_count;
|
||||||
|
UAddr element_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N64_R_SubModel N64_R_SubModel;
|
||||||
|
struct N64_R_SubModel
|
||||||
|
{
|
||||||
|
U16 vtx_buffer_num;
|
||||||
|
U16 idx_buffer_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N64_R_State N64_R_State;
|
||||||
|
struct N64_R_State
|
||||||
|
{
|
||||||
|
U8 align(64) rdp_command_buffer[KiB(256)];
|
||||||
|
UAddr rdp_command_buffer_write_pos;
|
||||||
|
R_PassParams pass_params;
|
||||||
|
Mat4x4F32 pass_view_projection;
|
||||||
|
N64_R_Buffer buffers[1024];
|
||||||
|
UAddr buffers_count;
|
||||||
|
N64_R_SubModel sub_models[1024];
|
||||||
|
UAddr sub_models_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
global N64_R_State n64_r_state = {0};
|
||||||
|
|
||||||
|
#endif // N64_RENDER_H
|
||||||
@ -0,0 +1,475 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#include "base/base_inc.h"
|
||||||
|
#include "n64/n64.h"
|
||||||
|
#include "render/render_inc.h"
|
||||||
|
|
||||||
|
#include "base/base_inc.c"
|
||||||
|
#include "n64/n64.c"
|
||||||
|
#include "render/render_inc.c"
|
||||||
|
|
||||||
|
typedef struct SubModel SubModel;
|
||||||
|
struct SubModel
|
||||||
|
{
|
||||||
|
U16 material_num;
|
||||||
|
U16 *idxs;
|
||||||
|
UAddr idxs_count;
|
||||||
|
U64 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Model Model;
|
||||||
|
struct Model
|
||||||
|
{
|
||||||
|
Vec3F32 *vtx;
|
||||||
|
UAddr vtx_count;
|
||||||
|
SubModel *sub_models;
|
||||||
|
UAddr sub_models_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
R_Material materials[] =
|
||||||
|
{
|
||||||
|
{{1, 0.5f, 0, 1}}, // yellow
|
||||||
|
{{0, 1, 0, 1}}, // green
|
||||||
|
{{1, 0, 0, 1}}, // red
|
||||||
|
{{0, 0, 1, 1}}, // blue
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Model n64_logo_model;
|
||||||
|
extern Model dg_logo_model;
|
||||||
|
|
||||||
|
function B32
|
||||||
|
Run(U64 tick_idx, Arena *permanent_arena, GamePad game_pads[GAME_PAD_SLOT_COUNT])
|
||||||
|
{
|
||||||
|
B32 keep_running = 1;
|
||||||
|
|
||||||
|
//- rjf: get/update camera state
|
||||||
|
local_persist F32 yaw = 0.125f;
|
||||||
|
local_persist F32 pitch = 0.125f;
|
||||||
|
local_persist F32 zoom = 5.f;
|
||||||
|
{
|
||||||
|
// rjf: stick -> adjust yaw/pitch
|
||||||
|
yaw += 0.1f * game_pads[0].sticks[0].x;
|
||||||
|
pitch += 0.1f * game_pads[0].sticks[0].y;
|
||||||
|
pitch = Clamp(-0.24f, pitch, +0.24f);
|
||||||
|
|
||||||
|
// rjf: z -> zoom in
|
||||||
|
if(BitArrayGet(game_pads[0].buttons, GamePadButtonKind_Z))
|
||||||
|
{
|
||||||
|
zoom -= 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: r -> zoom out
|
||||||
|
else if(BitArrayGet(game_pads[0].buttons, GamePadButtonKind_RightBumper))
|
||||||
|
{
|
||||||
|
zoom += 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: camera state -> view projection
|
||||||
|
F32 cos_pitch = CosF32(pitch);
|
||||||
|
F32 cos_pitch_zoom = cos_pitch*zoom;
|
||||||
|
Vec3F32 eye = V3F32(cos_pitch_zoom*CosF32(yaw),
|
||||||
|
cos_pitch_zoom*SinF32(yaw),
|
||||||
|
zoom*SinF32(pitch));
|
||||||
|
Mat4x4F32 view = MakeLookAt4x4F32(eye, V3F32(0, 0, 0), V3F32(0, 0, 1));
|
||||||
|
Mat4x4F32 projection = MakePerspective4x4F32(0.25f, (F32)N64_FB_WIDTH/N64_FB_HEIGHT, 0.01f, 50.f);
|
||||||
|
|
||||||
|
//- rjf: get/update selected model
|
||||||
|
local_persist S32 model_num = 0;
|
||||||
|
if(BitArrayGet(n64_state.game_pads[0].buttons, GamePadButtonKind_CRight) && !BitArrayGet(n64_state.game_pads[0].last_buttons, GamePadButtonKind_CRight))
|
||||||
|
{
|
||||||
|
model_num += 1;
|
||||||
|
if(model_num > 2)
|
||||||
|
{
|
||||||
|
model_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(BitArrayGet(n64_state.game_pads[0].buttons, GamePadButtonKind_CLeft) && !BitArrayGet(n64_state.game_pads[0].last_buttons, GamePadButtonKind_CLeft))
|
||||||
|
{
|
||||||
|
model_num -= 1;
|
||||||
|
if(model_num < 0)
|
||||||
|
{
|
||||||
|
model_num = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Model *model = &n64_logo_model;
|
||||||
|
switch(model_num)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
|
{}break;
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
model = &dg_logo_model;
|
||||||
|
}break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// model = &n64_controller_model;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: set up render pass
|
||||||
|
R_PassParams pass_params =
|
||||||
|
{
|
||||||
|
view,
|
||||||
|
projection,
|
||||||
|
V3F32(+0.5f, +0.1f, -1),
|
||||||
|
};
|
||||||
|
R_Pass(&pass_params);
|
||||||
|
|
||||||
|
//- rjf: draw model
|
||||||
|
R_BufferHandle vtx_buffer = R_BufferHandleFromData(model->vtx, model->vtx_count, sizeof(model->vtx[0]));
|
||||||
|
for EachIndex(sub_model_idx, model->sub_models_count)
|
||||||
|
{
|
||||||
|
SubModel *sub_model = &model->sub_models[sub_model_idx];
|
||||||
|
R_Material material = materials[sub_model->material_num-1];
|
||||||
|
R_BufferHandle idx_buffer = R_BufferHandleFromData(sub_model->idxs, sub_model->idxs_count, sizeof(sub_model->idxs[0]));
|
||||||
|
R_SubModelHandle handle = R_SubModelHandleFromBuffers(vtx_buffer, idx_buffer);
|
||||||
|
R_SubModel(handle, material, MakeMat4x4F32(1.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: gradient test
|
||||||
|
#if 0
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
U16 *p = N64_Framebuffer();
|
||||||
|
int midpoint = N64_FB_WIDTH - (tick_idx%N64_FB_WIDTH);
|
||||||
|
for(int i = 0; i < N64_FB_WIDTH*N64_FB_HEIGHT; i += 1)
|
||||||
|
{
|
||||||
|
// NOTE(rjf): RGBA5551 (R5 G5 B5 A1)
|
||||||
|
//
|
||||||
|
// - 0xF801 = bright red
|
||||||
|
// - 0x07C1 = bright green
|
||||||
|
// - 0x003F = bright blue
|
||||||
|
// - 0xFFFF = white
|
||||||
|
// - 0x0001 = black (with alpha)
|
||||||
|
//
|
||||||
|
F32 pct = (F32)(i%N64_FB_WIDTH) / N64_FB_WIDTH;
|
||||||
|
U16 red = (U16)(pct * 0x1f);
|
||||||
|
U16 color = 0x0001 | (red<<11);
|
||||||
|
if((i%N64_FB_WIDTH) > midpoint)
|
||||||
|
{
|
||||||
|
F32 pct = (F32)(N64_FB_WIDTH - (i%N64_FB_WIDTH)) / N64_FB_WIDTH;
|
||||||
|
U16 green = (U16)(pct * 0x1f);
|
||||||
|
color |= (green<<6);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
F32 pct = ((F32)(i / N64_FB_WIDTH) / N64_FB_HEIGHT);
|
||||||
|
U16 blue = (U16)(pct * 0x1f);
|
||||||
|
color |= (blue<<1);
|
||||||
|
}
|
||||||
|
p[i] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
U16 *p = N64_Framebuffer();
|
||||||
|
for(int i = 0; i < N64_FB_WIDTH*N64_FB_HEIGHT; i += 1)
|
||||||
|
{
|
||||||
|
if(i%N64_FB_WIDTH > tick_idx%N64_FB_WIDTH)
|
||||||
|
{
|
||||||
|
p[i] = 0xf801;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p[i] = 0x0001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Temp scratch = ScratchBegin(0);
|
||||||
|
#if 0
|
||||||
|
Vec2F32 text_pos = {150, 64 + 32.f};
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), SF("DP status_flags: %ib", N64_DP_REGS->status_flags)).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), SF("MI_VERSION: %ix", *N64_MI_VERSION)).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), S("ABCDEFGHIJKLMNOPQRSTUVWXYZ")).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), S("abcdefghijklmnopqrstuvwxyz")).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), S("0123456789")).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), S("`~!@#$%^&*()-_=+[]{};:'\"|\\.,<>?/")).y;
|
||||||
|
text_pos.y += 4;
|
||||||
|
text_pos.y += N64_DrawDebugString(1, text_pos, V4F32(1, 0.8f, 0, 1), S("Hello, N64!")).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 1, 1, 1), SF("Memory Size = %i", N64_BOOT_INFO->memory_size)).y;
|
||||||
|
text_pos.y += N64_DrawDebugString(0, text_pos, V4F32(1, 0, 0, 1), SF("DP STATUS = %ib", N64_DP_REGS->status_flags)).y;
|
||||||
|
N64_DrawMonochromeBitmap(V2F32(320 - 32, 240 - 48), V4F32(1, 1, 0, 1), n64_dgtlgrove_logo_32x48, 32, 48);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Vec2F32 button_pos = {16, 48};
|
||||||
|
for(U64 idx = 0; idx < 4; idx += 1)
|
||||||
|
{
|
||||||
|
B32 controller_is_connected = (n64_state.joybus_port_states[idx].id == N64_JoyBus_ID_N64Controller);
|
||||||
|
Vec4F32 color = controller_is_connected ? V4F32(1, 1, 1, 1) : V4F32(1, 0, 0, 1);
|
||||||
|
N64_DrawMonochromeBitmap(V2F32(16 + 32*idx, 16), color, n64_controller_icon_32x32, 32, 32);
|
||||||
|
if(controller_is_connected)
|
||||||
|
{
|
||||||
|
N64_DrawDebugString(0,
|
||||||
|
V2F32(16 + 32*idx + 16 - N64_SMALL_DEFAULT_FONT_GLYPH_WIDTH/2 + 8*game_pads[idx].sticks[0].x,
|
||||||
|
16 + 16 - N64_SMALL_DEFAULT_FONT_GLYPH_HEIGHT/2 + -8*game_pads[idx].sticks[0].y),
|
||||||
|
V4F32(1, 1, 0, 1), S("*"));
|
||||||
|
}
|
||||||
|
if(controller_is_connected)
|
||||||
|
{
|
||||||
|
// button_pos.y += N64_DrawDebugString(0, button_pos, V4F32(1, 1, 1, 1), SF("Stick")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_A))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0, 0, 1, 1), S("A")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_B))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0, 1, 0, 1), S("B")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_Start))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(1, 0, 0, 1), S("Start")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_CLeft))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(1, 1, 0, 1), S("C<")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_CUp))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(1, 1, 0, 1), S("C^")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_CRight))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(1, 1, 0, 1), S("C>")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_CDown))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(1, 1, 0, 1), S("Cv")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_DLeft))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("D<")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_DUp))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("D^")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_DRight))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("D>")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_DDown))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("Dv")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_Z))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("Z")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_LeftBumper))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("L")).y;
|
||||||
|
}
|
||||||
|
if(BitArrayGet(game_pads[idx].buttons, GamePadButtonKind_RightBumper))
|
||||||
|
{
|
||||||
|
button_pos.y += N64_DrawDebugString(1, button_pos, V4F32(0.5f, 0.5f, 0.5f, 1), S("R")).y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScratchEnd(scratch);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//- rjf: digital grove splash test
|
||||||
|
#if 0
|
||||||
|
F32 t_pct = (F32)tick_idx / 80.f;
|
||||||
|
if(t_pct > 1.f)
|
||||||
|
{
|
||||||
|
t_pct = 1.f;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
U16 *p = N64_Framebuffer();
|
||||||
|
U8 bayer[16] =
|
||||||
|
{
|
||||||
|
0, 8, 2, 10,
|
||||||
|
12, 4, 14, 6,
|
||||||
|
3, 11, 1, 9,
|
||||||
|
15, 7, 13, 5
|
||||||
|
};
|
||||||
|
F32 dither_step = 1.f / 31.f;
|
||||||
|
for(U32 off = 0; off < N64_FB_WIDTH*N64_FB_HEIGHT; off += 1)
|
||||||
|
{
|
||||||
|
U32 x = off%N64_FB_WIDTH;
|
||||||
|
U32 y = off/N64_FB_WIDTH;
|
||||||
|
F32 x_pct = (F32)x/N64_FB_WIDTH;
|
||||||
|
F32 y_pct = (F32)y/N64_FB_HEIGHT;
|
||||||
|
Vec4F32 color = V4F32(t_pct * (0.04f + 0.08f*x_pct - 0.03f*y_pct),
|
||||||
|
t_pct * (0.15f - 0.04f*y_pct),
|
||||||
|
t_pct * (0.03f + 0.04f*y_pct),
|
||||||
|
1.f);
|
||||||
|
U32 x_bayer = x%4;
|
||||||
|
U32 y_bayer = y%4;
|
||||||
|
F32 bayer_f = (bayer[y_bayer*4 + x_bayer] / 16.f);
|
||||||
|
Vec4F32 color_dithered = color;
|
||||||
|
color_dithered.x += (bayer_f - 0.5f) * dither_step;
|
||||||
|
color_dithered.y += (bayer_f - 0.5f) * dither_step;
|
||||||
|
color_dithered.z += (bayer_f - 0.5f) * dither_step;
|
||||||
|
p[off] = RGBA5551From4F32(color_dithered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Vec4F32 logo_color = V4F32(1*t_pct, 0.8f*t_pct, 0, 1);
|
||||||
|
// N64_DrawMonochromeBitmap(V2F32(160 - 16, 120 - 24 + 32*(1-t_pct)), logo_color, n64_dgtlgrove_logo_32x48, 32, 48);
|
||||||
|
// N64_DrawDebugString(1, V2F32(160 - 6.5f*N64_BIG_DEFAULT_FONT_GLYPH_WIDTH, 120+30 + 32*(1-t_pct)), logo_color, S("Digital Grove 64"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return keep_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
global Vec3F32 n64_logo_model_vtx[] =
|
||||||
|
{
|
||||||
|
{ -0.319213, -0.322617, 0.083041 }, { -0.319213, -0.671946, 0.719425 }, { -0.319213, 0.332592, -0.051930 }, { -0.691264, 0.339679, -0.737678 },
|
||||||
|
{ -0.691264, -0.321049, -0.737678 }, { -0.691264, -0.319959, 0.719425 }, { -0.691264, 0.689761, 0.087923 }, { -0.319213, 0.339679, -0.737678 },
|
||||||
|
{ -0.691264, -0.322617, 0.083041 }, { -0.319213, -0.321049, -0.737678 }, { -0.691264, -0.671946, -0.737678 }, { -0.319213, -0.671946, -0.737678 },
|
||||||
|
{ -0.691264, -0.671946, 0.719425 }, { -0.319213, -0.319959, 0.719425 }, { -0.691264, 0.332592, -0.051930 }, { -0.691264, 0.332592, 0.087923 },
|
||||||
|
{ -0.319213, 0.332592, 0.087923 }, { -0.319213, 0.689761, 0.087923 }, { -0.691264, 0.689761, -0.737678 }, { -0.319213, 0.689761, -0.737678 },
|
||||||
|
{ -0.319213, -0.671946, 0.086702 }, { -0.691264, 0.689761, -0.049576 }, { -0.319213, 0.689761, -0.051523 }, { -0.691264, 0.689761, 0.726424 },
|
||||||
|
{ -0.691264, 0.332592, 0.726424 }, { -0.319213, 0.332592, 0.726424 }, { -0.319213, 0.689761, 0.726424 }, { 0.328262, 0.332592, -0.731953 },
|
||||||
|
{ 0.328262, 0.689761, -0.731953 }, { 0.328262, 0.332592, -0.040641 }, { 0.328262, 0.689761, -0.040641 }, { 0.663334, 0.332592, -0.731953 },
|
||||||
|
{ 0.663334, 0.689761, -0.731953 }, { 0.663334, 0.332592, -0.040641 }, { 0.663334, 0.689761, -0.040641 }, { 0.328262, 0.332592, 0.089613 },
|
||||||
|
{ 0.328262, 0.689761, 0.089613 }, { 0.663334, 0.332592, 0.089613 }, { 0.663334, 0.689761, 0.089613 }, { 0.328262, 0.332592, 0.726182 },
|
||||||
|
{ 0.328262, 0.689761, 0.726182 }, { 0.663334, 0.332592, 0.726182 }, { 0.663334, 0.689761, 0.726182 }, { 0.663334, -0.324375, -0.734938 },
|
||||||
|
{ 0.328262, -0.324375, -0.734938 }, { 0.663333, -0.324375, -0.039661 }, { 0.328262, -0.324375, -0.039662 }, { 0.663334, -0.677543, -0.734938 },
|
||||||
|
{ 0.328262, -0.677543, -0.734938 }, { 0.663333, -0.677543, -0.039661 }, { 0.328262, -0.677543, -0.039662 }, { 0.663333, -0.324375, 0.099964 },
|
||||||
|
{ 0.328262, -0.324375, 0.099964 }, { 0.663333, -0.677543, 0.099964 }, { 0.328262, -0.677543, 0.099964 }, { 0.663333, -0.324375, 0.720610 },
|
||||||
|
{ 0.328261, -0.324375, 0.720610 }, { 0.663333, -0.677543, 0.720610 }, { 0.328261, -0.677543, 0.720610 }, { -0.691264, -0.671946, 0.086713 },
|
||||||
|
{ -0.691264, -0.671946, -0.042679 }, { -0.319213, -0.671946, -0.040508 }, { -0.319213, -0.322617, -0.040018 }, { -0.691264, -0.322617, -0.044321 },
|
||||||
|
};
|
||||||
|
|
||||||
|
global U16 n64_logo_model_tri_faces__yellow[] =
|
||||||
|
{
|
||||||
|
14, 13, 2, 27, 25, 26, 40, 43, 41, 57, 58, 56,
|
||||||
|
14, 6, 13, 27, 24, 25, 40, 42, 43, 57, 59, 58,
|
||||||
|
};
|
||||||
|
global U16 n64_logo_model_tri_faces__green[] =
|
||||||
|
{
|
||||||
|
15, 8, 3, 9, 14, 1, 63, 9, 1, 12, 5, 10,
|
||||||
|
12, 61, 11, 3, 16, 15, 7, 27, 18, 18, 22, 7,
|
||||||
|
8, 19, 20, 47, 1, 14, 23, 19, 22, 25, 63, 26,
|
||||||
|
29, 32, 28, 37, 8, 20, 23, 37, 20, 31, 33, 29,
|
||||||
|
34, 36, 30, 31, 39, 35, 36, 3, 8, 37, 43, 39,
|
||||||
|
46, 53, 52, 48, 51, 49, 44, 49, 45, 50, 55, 51,
|
||||||
|
55, 58, 59, 57, 34, 30, 60, 2, 13, 62, 60, 61,
|
||||||
|
21, 51, 2, 1, 49, 21, 47, 44, 45, 38, 40, 36,
|
||||||
|
15, 4, 8, 9, 6, 14, 63, 64, 9, 12, 11, 5,
|
||||||
|
12, 62, 61, 3, 17, 16, 7, 24, 27, 18, 23, 22,
|
||||||
|
8, 4, 19, 47, 45, 1, 23, 20, 19, 25, 64, 63,
|
||||||
|
29, 33, 32, 37, 36, 8, 23, 41, 37, 31, 35, 33,
|
||||||
|
34, 38, 36, 31, 37, 39, 36, 40, 3, 37, 41, 43,
|
||||||
|
46, 47, 53, 48, 50, 51, 44, 48, 49, 50, 54, 55,
|
||||||
|
55, 54, 58, 57, 56, 34, 60, 21, 2, 62, 21, 60,
|
||||||
|
21, 49, 51, 1, 45, 49, 47, 46, 44, 38, 42, 40,
|
||||||
|
};
|
||||||
|
global U16 n64_logo_model_tri_faces__red[] =
|
||||||
|
{
|
||||||
|
10, 16, 17, 40, 23, 3, 2, 47, 14, 52, 28, 32,
|
||||||
|
10, 5, 16, 40, 41, 23, 2, 51, 47, 52, 53, 28,
|
||||||
|
};
|
||||||
|
global U16 n64_logo_model_tri_faces__blue[] =
|
||||||
|
{
|
||||||
|
17, 23, 18, 11, 64, 5, 22, 4, 15, 1, 62, 63,
|
||||||
|
63, 17, 26, 22, 16, 7, 12, 63, 62, 16, 24, 7,
|
||||||
|
27, 17, 18, 33, 34, 32, 34, 52, 32, 35, 38, 34,
|
||||||
|
30, 37, 31, 39, 42, 38, 46, 48, 44, 52, 58, 54,
|
||||||
|
51, 53, 47, 46, 54, 50, 59, 53, 55, 60, 6, 9,
|
||||||
|
28, 31, 29, 16, 64, 25, 61, 9, 64, 53, 30, 28,
|
||||||
|
17, 3, 23, 11, 61, 64, 22, 19, 4, 1, 21, 62,
|
||||||
|
63, 10, 17, 22, 15, 16, 12, 10, 63, 16, 25, 24,
|
||||||
|
27, 26, 17, 33, 35, 34, 34, 56, 52, 35, 39, 38,
|
||||||
|
30, 36, 37, 39, 43, 42, 46, 50, 48, 52, 56, 58,
|
||||||
|
51, 55, 53, 46, 52, 54, 59, 57, 53, 60, 13, 6,
|
||||||
|
28, 30, 31, 16, 5, 64, 61, 60, 9, 53, 57, 30,
|
||||||
|
};
|
||||||
|
|
||||||
|
SubModel n64_logo_submodels[] =
|
||||||
|
{
|
||||||
|
{1, ArrayAndCount(n64_logo_model_tri_faces__yellow)},
|
||||||
|
{2, ArrayAndCount(n64_logo_model_tri_faces__green)},
|
||||||
|
{3, ArrayAndCount(n64_logo_model_tri_faces__red)},
|
||||||
|
{4, ArrayAndCount(n64_logo_model_tri_faces__blue)},
|
||||||
|
};
|
||||||
|
|
||||||
|
Model n64_logo_model =
|
||||||
|
{
|
||||||
|
ArrayAndCount(n64_logo_model_vtx),
|
||||||
|
ArrayAndCount(n64_logo_submodels),
|
||||||
|
};
|
||||||
|
|
||||||
|
global Vec3F32 dg_logo_model_vtx[] =
|
||||||
|
{
|
||||||
|
{ 0.085057, 0.094957, -2.584146 }, { 0.084919, -0.027923, -2.658362 }, { 0.083808, -0.171746, -2.550864 }, { 0.083306, -0.107028, -2.394031 },
|
||||||
|
{ 0.084125, 0.080334, -2.405339 }, { 0.086326, 0.278994, -2.690513 }, { 0.086225, 0.063105, -2.850055 }, { 0.084853, -0.226452, -2.810704 },
|
||||||
|
{ 0.083159, -0.367724, -2.581724 }, { 0.082095, -0.334552, -2.335907 }, { 0.082196, -0.118662, -2.176362 }, { 0.083569, 0.170893, -2.215714 },
|
||||||
|
{ 0.085262, 0.312166, -2.444695 }, { 0.082318, -0.135191, -2.215159 }, { 0.075256, -0.133749, -0.766794 }, { 0.068438, -0.894210, -0.004996 },
|
||||||
|
{ 0.060581, -0.892605, 1.606462 }, { 0.059976, -0.130628, 2.366775 }, { 0.056730, -0.025024, 3.120139 }, { 0.061291, 0.084822, 2.277215 },
|
||||||
|
{ 0.062657, -0.607715, 1.418925 }, { 0.068886, -0.608987, 0.141494 }, { 0.075700, 0.081880, -0.677655 }, { 0.083340, 0.080320, -2.244440 },
|
||||||
|
{ 0.064875, -0.875355, 0.740968 }, { 0.057463, -1.609634, 1.646470 }, { 0.065358, -0.664627, 0.818029 }, { 0.078421, 0.011302, -1.294146 },
|
||||||
|
{ 0.077959, 0.627437, -0.684809 }, { 0.068811, 0.750083, 1.292086 }, { 0.071499, 0.844370, 0.820083 }, { 0.079242, 0.843008, -0.767747 },
|
||||||
|
{ 0.079871, 0.049410, -1.559573 }, { 0.074583, 0.687116, 0.056670 }, { 0.074556, 1.285580, 0.562082 }, { 0.075410, 0.757468, -0.054058 },
|
||||||
|
{ 0.056820, -0.262075, 2.903636 }, { 0.056290, -0.354120, 2.935505 }, { 0.054757, -0.443627, 3.174871 }, { 0.056529, -0.201492, 3.013897 },
|
||||||
|
{ 0.071368, 0.941992, 0.928360 }, { 0.070890, 0.941275, 1.025741 }, { 0.070886, 1.137012, 1.190092 }, { 0.071973, 1.066184, 0.908125 },
|
||||||
|
{ -0.027071, 0.095414, -2.584693 }, { -0.027210, -0.027466, -2.658910 }, { -0.028321, -0.171288, -2.551411 }, { -0.028822, -0.106571, -2.394578 },
|
||||||
|
{ -0.028003, 0.080791, -2.405887 }, { -0.025802, 0.279451, -2.691060 }, { -0.025903, 0.063562, -2.850603 }, { -0.027276, -0.225994, -2.811251 },
|
||||||
|
{ -0.028969, -0.367267, -2.582272 }, { -0.030033, -0.334095, -2.336454 }, { -0.029932, -0.118205, -2.176909 }, { -0.028560, 0.171350, -2.216261 },
|
||||||
|
{ -0.026866, 0.312623, -2.445242 }, { -0.029810, -0.134734, -2.215707 }, { -0.036872, -0.133292, -0.767341 }, { -0.043690, -0.893753, -0.005543 },
|
||||||
|
{ -0.051548, -0.892148, 1.605915 }, { -0.052152, -0.130171, 2.366227 }, { -0.055398, -0.024567, 3.119591 }, { -0.050837, 0.085279, 2.276668 },
|
||||||
|
{ -0.049471, -0.607258, 1.418378 }, { -0.043242, -0.608530, 0.140947 }, { -0.036429, 0.082337, -0.678202 }, { -0.028789, 0.080777, -2.244987 },
|
||||||
|
{ -0.047254, -0.874897, 0.740421 }, { -0.054666, -1.609177, 1.645923 }, { -0.046771, -0.664170, 0.817482 }, { -0.033708, 0.011759, -1.294693 },
|
||||||
|
{ -0.034170, 0.627894, -0.685356 }, { -0.043318, 0.750540, 1.291539 }, { -0.040630, 0.844827, 0.819536 }, { -0.032886, 0.843465, -0.768294 },
|
||||||
|
{ -0.032257, 0.049867, -1.560121 }, { -0.037545, 0.687573, 0.056123 }, { -0.037572, 1.286037, 0.561534 }, { -0.036718, 0.757925, -0.054605 },
|
||||||
|
{ -0.055308, -0.261618, 2.903088 }, { -0.055839, -0.353663, 2.934958 }, { -0.057372, -0.443170, 3.174324 }, { -0.055599, -0.201035, 3.013350 },
|
||||||
|
{ -0.040760, 0.942449, 0.927813 }, { -0.041238, 0.941732, 1.025193 }, { -0.041243, 1.137469, 1.189545 }, { -0.040155, 1.066641, 0.907578 },
|
||||||
|
};
|
||||||
|
|
||||||
|
global U16 dg_logo_model_tri_faces[] =
|
||||||
|
{
|
||||||
|
1, 13, 5, 2, 6, 1, 18, 20, 19, 17, 20, 18,
|
||||||
|
17, 21, 20, 16, 21, 17, 16, 22, 21, 16, 23, 22,
|
||||||
|
15, 23, 16, 15, 24, 23, 14, 24, 15, 1, 6, 13,
|
||||||
|
3, 4, 10, 2, 3, 8, 5, 13, 12, 4, 11, 10,
|
||||||
|
3, 9, 8, 2, 7, 6, 4, 5, 11, 5, 12, 11,
|
||||||
|
3, 10, 9, 2, 8, 7, 45, 49, 57, 46, 45, 50,
|
||||||
|
62, 63, 64, 61, 62, 64, 61, 64, 65, 60, 61, 65,
|
||||||
|
60, 65, 66, 60, 66, 67, 59, 60, 67, 59, 67, 68,
|
||||||
|
58, 59, 68, 45, 57, 50, 47, 54, 48, 46, 52, 47,
|
||||||
|
49, 56, 57, 48, 54, 55, 47, 52, 53, 46, 50, 51,
|
||||||
|
48, 55, 49, 49, 55, 56, 47, 53, 54, 46, 51, 52,
|
||||||
|
53, 8, 9, 54, 9, 10, 67, 22, 23, 55, 10, 11,
|
||||||
|
60, 15, 16, 63, 18, 19, 56, 11, 12, 57, 12, 13,
|
||||||
|
68, 23, 24, 64, 19, 20, 49, 1, 5, 62, 17, 18,
|
||||||
|
59, 14, 15, 45, 2, 1, 58, 24, 14, 46, 3, 2,
|
||||||
|
47, 4, 3, 65, 20, 21, 48, 5, 4, 61, 16, 17,
|
||||||
|
50, 13, 6, 51, 6, 7, 52, 7, 8, 66, 21, 22,
|
||||||
|
53, 52, 8, 54, 53, 9, 67, 66, 22, 55, 54, 10,
|
||||||
|
60, 59, 15, 63, 62, 18, 56, 55, 11, 57, 56, 12,
|
||||||
|
68, 67, 23, 64, 63, 19, 49, 45, 1, 62, 61, 17,
|
||||||
|
59, 58, 14, 45, 46, 2, 58, 68, 24, 46, 47, 3,
|
||||||
|
47, 48, 4, 65, 64, 20, 48, 49, 5, 61, 60, 16,
|
||||||
|
50, 57, 13, 51, 50, 6, 52, 51, 7, 66, 65, 21,
|
||||||
|
25, 27, 26, 69, 70, 71, 70, 25, 26, 71, 26, 27,
|
||||||
|
69, 27, 25, 70, 69, 25, 71, 70, 26, 69, 71, 27,
|
||||||
|
29, 31, 30, 29, 32, 31, 29, 33, 32, 28, 33, 29,
|
||||||
|
73, 74, 75, 73, 75, 76, 73, 76, 77, 72, 73, 77,
|
||||||
|
76, 31, 32, 77, 32, 33, 73, 28, 29, 72, 33, 28,
|
||||||
|
75, 30, 31, 74, 29, 30, 76, 75, 31, 77, 76, 32,
|
||||||
|
73, 72, 28, 72, 77, 33, 75, 74, 30, 74, 73, 29,
|
||||||
|
34, 36, 35, 78, 79, 80, 80, 35, 36, 79, 34, 35,
|
||||||
|
78, 36, 34, 80, 79, 35, 79, 78, 34, 78, 80, 36,
|
||||||
|
38, 40, 39, 38, 37, 40, 82, 83, 84, 82, 84, 81,
|
||||||
|
82, 37, 38, 84, 39, 40, 83, 38, 39, 81, 40, 37,
|
||||||
|
82, 81, 37, 84, 83, 39, 83, 82, 38, 81, 84, 40,
|
||||||
|
42, 44, 43, 41, 44, 42, 86, 87, 88, 85, 86, 88,
|
||||||
|
88, 43, 44, 87, 42, 43, 86, 41, 42, 85, 44, 41,
|
||||||
|
88, 87, 43, 87, 86, 42, 86, 85, 41, 85, 88, 44,
|
||||||
|
};
|
||||||
|
|
||||||
|
SubModel dg_logo_submodels[] =
|
||||||
|
{
|
||||||
|
{1, ArrayAndCount(dg_logo_model_tri_faces)},
|
||||||
|
};
|
||||||
|
|
||||||
|
Model dg_logo_model =
|
||||||
|
{
|
||||||
|
ArrayAndCount(dg_logo_model_vtx),
|
||||||
|
ArrayAndCount(dg_logo_submodels),
|
||||||
|
};
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef RENDER_H
|
||||||
|
#define RENDER_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Pass Parameters
|
||||||
|
|
||||||
|
typedef struct R_PassParams R_PassParams;
|
||||||
|
struct R_PassParams
|
||||||
|
{
|
||||||
|
Mat4x4F32 view;
|
||||||
|
Mat4x4F32 projection;
|
||||||
|
Vec3F32 keylight_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Resource Types
|
||||||
|
|
||||||
|
typedef struct R_Material R_Material;
|
||||||
|
struct R_Material
|
||||||
|
{
|
||||||
|
Vec4F32 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct R_TriFace R_TriFace;
|
||||||
|
struct R_TriFace
|
||||||
|
{
|
||||||
|
U16 idx[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Handles
|
||||||
|
|
||||||
|
typedef struct R_BufferHandle R_BufferHandle;
|
||||||
|
struct R_BufferHandle
|
||||||
|
{
|
||||||
|
UAddr uaddr[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct R_SubModelHandle R_SubModelHandle;
|
||||||
|
struct R_SubModelHandle
|
||||||
|
{
|
||||||
|
UAddr uaddr[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Resources @per_platform
|
||||||
|
|
||||||
|
function R_BufferHandle R_BufferHandleFromData(void *data, UAddr element_count, UAddr element_size);
|
||||||
|
function R_SubModelHandle R_SubModelHandleFromBuffers(R_BufferHandle vtx_buffer, R_BufferHandle idx_buffer);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Render Commands @per_platform
|
||||||
|
|
||||||
|
function void R_Pass(R_PassParams *params);
|
||||||
|
function void R_SubModel(R_SubModelHandle handle, R_Material material, Mat4x4F32 xform);
|
||||||
|
|
||||||
|
#endif // RENDER_H
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#include "render.c"
|
||||||
|
#if PLATFORM_N64
|
||||||
|
# include "n64/render/n64_render.c"
|
||||||
|
#else
|
||||||
|
# error Platform-defined implementations for render layer not defined for this platform.
|
||||||
|
#endif
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
// The Digital Grove Codebase
|
||||||
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
||||||
|
|
||||||
|
#ifndef RENDER_INC_H
|
||||||
|
#define RENDER_INC_H
|
||||||
|
|
||||||
|
#include "render.h"
|
||||||
|
#if PLATFORM_N64
|
||||||
|
# include "n64/render/n64_render.h"
|
||||||
|
#else
|
||||||
|
# error Platform-defined implementations for render layer not defined for this platform.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RENDER_INC_H
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
static const unsigned int crc_table[256] = {
|
||||||
|
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||||
|
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||||
|
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||||
|
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||||
|
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||||
|
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||||
|
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||||
|
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||||
|
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||||
|
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||||
|
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||||
|
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||||
|
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||||
|
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||||
|
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||||
|
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||||
|
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||||
|
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||||
|
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||||
|
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||||
|
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||||
|
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||||
|
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||||
|
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||||
|
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||||
|
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||||
|
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||||
|
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||||
|
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||||
|
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||||
|
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||||
|
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||||
|
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||||
|
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||||
|
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||||
|
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||||
|
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||||
|
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||||
|
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||||
|
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||||
|
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||||
|
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||||
|
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||||
|
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||||
|
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||||
|
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||||
|
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||||
|
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||||
|
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||||
|
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||||
|
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||||
|
0x2d02ef8dL
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int crc32_update(unsigned int crc, const unsigned char *buffer, unsigned int len)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int crc32(const unsigned char *buffer, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int crc = 0xffffffffL;
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||||
|
}
|
||||||
|
return crc ^ 0xffffffffL;
|
||||||
|
}
|
||||||
@ -0,0 +1,540 @@
|
|||||||
|
unsigned char default_ipl3[] = {
|
||||||
|
0x80, 0x37, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x69, 0x62, 0x64,
|
||||||
|
0x72, 0x61, 0x67, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x30, 0x44, 0xd2, 0x36, 0x3c, 0x1d, 0xa4, 0x00,
|
||||||
|
0x37, 0xbd, 0x0f, 0xf0, 0x27, 0xbd, 0xff, 0xe0, 0x00, 0x00, 0xd8, 0x25,
|
||||||
|
0xaf, 0xbf, 0x00, 0x1c, 0xaf, 0xb1, 0x00, 0x18, 0xaf, 0xb0, 0x00, 0x14,
|
||||||
|
0x04, 0x11, 0x02, 0x64, 0x40, 0x04, 0x48, 0x00, 0x3c, 0x02, 0xa4, 0x10,
|
||||||
|
0x04, 0x11, 0x02, 0x61, 0x8c, 0x44, 0x00, 0x10, 0x00, 0x00, 0x10, 0x25,
|
||||||
|
0x40, 0x82, 0x68, 0x00, 0x40, 0x82, 0x48, 0x00, 0x40, 0x82, 0x58, 0x00,
|
||||||
|
0x40, 0x82, 0x90, 0x00, 0x3c, 0x02, 0xa4, 0x30, 0x8c, 0x51, 0x00, 0x04,
|
||||||
|
0x24, 0x02, 0x00, 0xb0, 0x32, 0x31, 0x00, 0xf0, 0x12, 0x22, 0x00, 0x58,
|
||||||
|
0x3c, 0x02, 0xa4, 0x70, 0x8c, 0x42, 0x00, 0x0c, 0x10, 0x40, 0x00, 0x11,
|
||||||
|
0x00, 0x00, 0x80, 0x25, 0x3c, 0x02, 0x12, 0x34, 0x3c, 0x06, 0xa0, 0x00,
|
||||||
|
0x24, 0x42, 0x56, 0x78, 0x3c, 0x05, 0x00, 0x20, 0x3c, 0x04, 0x00, 0x80,
|
||||||
|
0x02, 0x06, 0x18, 0x21, 0xac, 0x60, 0x00, 0x00, 0xac, 0x62, 0x00, 0x00,
|
||||||
|
0x8c, 0x63, 0x00, 0x00, 0x54, 0x62, 0x00, 0x69, 0x24, 0x02, 0x00, 0x01,
|
||||||
|
0x02, 0x05, 0x80, 0x21, 0x16, 0x04, 0xff, 0xf9, 0x02, 0x06, 0x18, 0x21,
|
||||||
|
0x10, 0x00, 0x00, 0x64, 0x24, 0x02, 0x00, 0x01, 0x3c, 0x04, 0xa4, 0x00,
|
||||||
|
0x04, 0x11, 0x01, 0x3d, 0x24, 0x84, 0x03, 0xb4, 0x00, 0x40, 0x80, 0x25,
|
||||||
|
0x3c, 0x03, 0xb0, 0x00, 0x24, 0x66, 0x10, 0x40, 0x3c, 0x05, 0xa4, 0x60,
|
||||||
|
0x8c, 0xa2, 0x00, 0x10, 0x30, 0x42, 0x00, 0x03, 0x14, 0x40, 0xff, 0xfd,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x8c, 0x62, 0x10, 0x40, 0x3c, 0x07, 0x60, 0x00,
|
||||||
|
0x02, 0x02, 0x20, 0x23, 0x3c, 0x03, 0x80, 0x00, 0x24, 0xe7, 0x00, 0x08,
|
||||||
|
0x00, 0xc7, 0x30, 0x21, 0x00, 0x83, 0x18, 0x21, 0xac, 0xa3, 0x00, 0x00,
|
||||||
|
0xac, 0xa6, 0x00, 0x04, 0x3c, 0x06, 0xa4, 0x04, 0x8c, 0xc5, 0x00, 0x18,
|
||||||
|
0x14, 0xa0, 0xff, 0xfe, 0x3c, 0x05, 0xa4, 0x60, 0x24, 0x42, 0xff, 0xff,
|
||||||
|
0xac, 0xa2, 0x00, 0x0c, 0x40, 0x80, 0xe0, 0x00, 0x40, 0x80, 0xe8, 0x00,
|
||||||
|
0x3c, 0x02, 0x80, 0x00, 0x24, 0x45, 0x20, 0x00, 0xbc, 0x49, 0x00, 0x00,
|
||||||
|
0xbc, 0x49, 0x00, 0x10, 0xbc, 0x49, 0x00, 0x20, 0xbc, 0x49, 0x00, 0x30,
|
||||||
|
0x24, 0x42, 0x00, 0x40, 0x14, 0x45, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3c, 0x02, 0x80, 0x00, 0x24, 0x45, 0x40, 0x00, 0xbc, 0x48, 0x00, 0x00,
|
||||||
|
0xbc, 0x48, 0x00, 0x20, 0xbc, 0x48, 0x00, 0x40, 0xbc, 0x48, 0x00, 0x60,
|
||||||
|
0x24, 0x42, 0x00, 0x80, 0x14, 0x45, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x14, 0x34, 0x00, 0x00, 0x13, 0x16, 0x00, 0x00, 0x46, 0x10, 0x25,
|
||||||
|
0x3a, 0x31, 0x00, 0xb0, 0x00, 0x15, 0x32, 0x00, 0x00, 0x46, 0x10, 0x25,
|
||||||
|
0x2e, 0x31, 0x00, 0x01, 0x3c, 0x05, 0xa4, 0x00, 0x00, 0x51, 0x10, 0x25,
|
||||||
|
0xac, 0xb0, 0x00, 0x00, 0xac, 0xa2, 0x00, 0x08, 0xac, 0xa0, 0x00, 0x0c,
|
||||||
|
0x3c, 0x05, 0xa4, 0x60, 0x8c, 0xa2, 0x00, 0x10, 0x30, 0x42, 0x00, 0x01,
|
||||||
|
0x14, 0x40, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x7f, 0xff,
|
||||||
|
0x34, 0x42, 0xff, 0xf0, 0x00, 0x82, 0x20, 0x21, 0x00, 0x60, 0x00, 0x08,
|
||||||
|
0x00, 0x80, 0xe8, 0x25, 0x3c, 0x02, 0xa0, 0x00, 0x8c, 0x50, 0x03, 0x18,
|
||||||
|
0x8c, 0x54, 0x03, 0x00, 0x8c, 0x55, 0x03, 0x0c, 0x3c, 0x02, 0x00, 0x80,
|
||||||
|
0x12, 0x02, 0x00, 0x33, 0x3c, 0x02, 0x00, 0x40, 0x16, 0x02, 0x00, 0x0c,
|
||||||
|
0x24, 0x02, 0x00, 0x20, 0x3c, 0x03, 0xa4, 0x60, 0x8c, 0x62, 0x00, 0x10,
|
||||||
|
0x30, 0x42, 0x00, 0x03, 0x14, 0x40, 0xff, 0xfd, 0x3c, 0x02, 0xb0, 0x00,
|
||||||
|
0x8c, 0x42, 0x00, 0x08, 0x3c, 0x03, 0x80, 0x40, 0x00, 0x43, 0x10, 0x2b,
|
||||||
|
0x50, 0x40, 0x00, 0x01, 0x3c, 0x10, 0x00, 0x80, 0x24, 0x02, 0x00, 0x20,
|
||||||
|
0x00, 0x00, 0x20, 0x25, 0x3c, 0x05, 0xa4, 0x30, 0x8c, 0xa3, 0x00, 0x2c,
|
||||||
|
0x00, 0x04, 0x20, 0x40, 0x30, 0x63, 0x00, 0x01, 0x24, 0x42, 0xff, 0xff,
|
||||||
|
0x14, 0x40, 0xff, 0xfb, 0x00, 0x64, 0x20, 0x25, 0x04, 0x11, 0x01, 0xe1,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x01, 0x16, 0xa2, 0x00, 0x05,
|
||||||
|
0x3c, 0x02, 0xa4, 0x04, 0x3c, 0x02, 0x80, 0x00, 0x04, 0x11, 0x01, 0xdb,
|
||||||
|
0x8c, 0x44, 0x01, 0xa4, 0x3c, 0x02, 0xa4, 0x04, 0x8c, 0x43, 0x00, 0x18,
|
||||||
|
0x14, 0x60, 0xff, 0xfe, 0x24, 0x03, 0x00, 0xb0, 0x52, 0x23, 0x00, 0x12,
|
||||||
|
0x3c, 0x02, 0xa4, 0x00, 0x24, 0x03, 0x10, 0x00, 0xac, 0x43, 0x00, 0x00,
|
||||||
|
0x3c, 0x03, 0x00, 0x80, 0x24, 0x63, 0x20, 0x00, 0xac, 0x43, 0x00, 0x04,
|
||||||
|
0x24, 0x03, 0x0f, 0xff, 0xac, 0x43, 0x00, 0x08, 0x3c, 0x05, 0xff, 0xff,
|
||||||
|
0x24, 0xa5, 0x7c, 0x00, 0x3c, 0x04, 0xa0, 0x00, 0x02, 0x05, 0x28, 0x21,
|
||||||
|
0x04, 0x11, 0x00, 0x17, 0x24, 0x84, 0x04, 0x00, 0x10, 0x00, 0xff, 0x89,
|
||||||
|
0x3c, 0x03, 0xb0, 0x00, 0x10, 0x00, 0xff, 0xd9, 0x3c, 0x10, 0x00, 0x7c,
|
||||||
|
0x24, 0x43, 0x10, 0x00, 0x24, 0x42, 0x20, 0x00, 0xac, 0x60, 0x00, 0x00,
|
||||||
|
0x24, 0x63, 0x00, 0x04, 0x54, 0x62, 0xff, 0xfe, 0xac, 0x60, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0xff, 0xf0, 0x3c, 0x05, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x20, 0x4c, 0x69, 0x62, 0x64, 0x72, 0x61, 0x67,
|
||||||
|
0x6f, 0x6e, 0x20, 0x49, 0x50, 0x4c, 0x33, 0x20, 0x20, 0x43, 0x6f, 0x64,
|
||||||
|
0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x52, 0x61, 0x73, 0x6b, 0x79, 0x20,
|
||||||
|
0x3c, 0x02, 0xa0, 0x00, 0x00, 0x82, 0x20, 0x25, 0xb0, 0x80, 0x00, 0x00,
|
||||||
|
0xb4, 0x80, 0x00, 0x07, 0x28, 0xa2, 0x00, 0x09, 0x14, 0x40, 0x00, 0x19,
|
||||||
|
0x24, 0xa5, 0xff, 0xf8, 0x00, 0xa4, 0x10, 0x21, 0xb0, 0x40, 0x00, 0x00,
|
||||||
|
0xb4, 0x40, 0x00, 0x07, 0x3c, 0x09, 0x00, 0x10, 0x24, 0x84, 0x00, 0x08,
|
||||||
|
0x24, 0x0a, 0xf0, 0x00, 0x3c, 0x03, 0xa4, 0x04, 0x24, 0x08, 0x10, 0x00,
|
||||||
|
0x00, 0xa9, 0x30, 0x2a, 0x10, 0xc0, 0x00, 0x05, 0x3c, 0x02, 0x00, 0x10,
|
||||||
|
0x28, 0xa6, 0x10, 0x00, 0x14, 0xc0, 0x00, 0x02, 0x00, 0xa0, 0x10, 0x25,
|
||||||
|
0x00, 0xaa, 0x10, 0x24, 0x8c, 0x67, 0x00, 0x14, 0x14, 0xe0, 0xff, 0xfe,
|
||||||
|
0x24, 0x47, 0xff, 0xff, 0x00, 0xa2, 0x28, 0x23, 0xac, 0x68, 0x00, 0x00,
|
||||||
|
0xac, 0x64, 0x00, 0x04, 0xac, 0x67, 0x00, 0x0c, 0x1c, 0xa0, 0xff, 0xf1,
|
||||||
|
0x00, 0x82, 0x20, 0x21, 0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x02, 0xff, 0xff, 0x14, 0x82, 0x00, 0x0c, 0x3c, 0x02, 0xa4, 0x04,
|
||||||
|
0x8c, 0x43, 0x00, 0x18, 0x14, 0x60, 0xff, 0xfe, 0x24, 0x03, 0x10, 0x00,
|
||||||
|
0xac, 0x43, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x80, 0x24, 0x63, 0x20, 0x00,
|
||||||
|
0xac, 0x43, 0x00, 0x04, 0x24, 0x03, 0x0f, 0xff, 0xac, 0x43, 0x00, 0x08,
|
||||||
|
0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x14, 0xa0, 0x00, 0x04,
|
||||||
|
0x00, 0x04, 0x25, 0x00, 0x3c, 0x05, 0x00, 0x20, 0x10, 0x00, 0xff, 0xcd,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3c, 0x05, 0x00, 0x1f, 0x10, 0x00, 0xff, 0xfc,
|
||||||
|
0x34, 0xa5, 0x80, 0x00, 0x30, 0xa6, 0x00, 0x01, 0x50, 0xc0, 0x00, 0x05,
|
||||||
|
0x03, 0x44, 0x20, 0x04, 0x3c, 0x02, 0xa4, 0x30, 0x24, 0x03, 0x20, 0x00,
|
||||||
|
0xac, 0x43, 0x00, 0x00, 0x03, 0x44, 0x20, 0x04, 0x00, 0x85, 0x28, 0x21,
|
||||||
|
0x00, 0x05, 0x28, 0x80, 0x3c, 0x02, 0xa3, 0xf0, 0x00, 0x45, 0x10, 0x21,
|
||||||
|
0x8c, 0x43, 0x00, 0x00, 0x10, 0xc0, 0x00, 0x03, 0x24, 0x04, 0x10, 0x00,
|
||||||
|
0x3c, 0x02, 0xa4, 0x30, 0xac, 0x44, 0x00, 0x00, 0x00, 0x03, 0x26, 0x00,
|
||||||
|
0x00, 0x03, 0x16, 0x02, 0x00, 0x44, 0x10, 0x25, 0x00, 0x03, 0x22, 0x02,
|
||||||
|
0x30, 0x84, 0xff, 0x00, 0x00, 0x44, 0x10, 0x25, 0x00, 0x03, 0x1a, 0x00,
|
||||||
|
0x3c, 0x04, 0x00, 0xff, 0x00, 0x64, 0x18, 0x24, 0x03, 0xe0, 0x00, 0x08,
|
||||||
|
0x00, 0x62, 0x10, 0x25, 0x24, 0x02, 0x01, 0x00, 0x24, 0x42, 0xff, 0xff,
|
||||||
|
0x14, 0x40, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x08,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1e, 0x00, 0x00, 0x06, 0x16, 0x02,
|
||||||
|
0x00, 0x43, 0x10, 0x25, 0x00, 0x06, 0x1a, 0x02, 0x30, 0x63, 0xff, 0x00,
|
||||||
|
0x00, 0x43, 0x10, 0x25, 0x00, 0x06, 0x32, 0x00, 0x3c, 0x03, 0x00, 0xff,
|
||||||
|
0x00, 0xc3, 0x30, 0x24, 0x00, 0xc2, 0x30, 0x25, 0x24, 0x02, 0xff, 0xff,
|
||||||
|
0x54, 0x82, 0x00, 0x07, 0x03, 0x44, 0x20, 0x04, 0x00, 0x05, 0x28, 0x80,
|
||||||
|
0x3c, 0x02, 0xa3, 0xf8, 0x00, 0x45, 0x10, 0x21, 0xac, 0x46, 0x00, 0x00,
|
||||||
|
0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x28, 0x21,
|
||||||
|
0x00, 0x05, 0x28, 0x80, 0x10, 0x00, 0xff, 0xf9, 0x3c, 0x02, 0xa3, 0xf0,
|
||||||
|
0x27, 0xbd, 0xff, 0xe8, 0x38, 0xc7, 0x00, 0x3f, 0x00, 0x80, 0x40, 0x25,
|
||||||
|
0xaf, 0xbf, 0x00, 0x14, 0x00, 0xa0, 0x48, 0x25, 0x10, 0xa0, 0x00, 0x02,
|
||||||
|
0x24, 0x06, 0x00, 0x46, 0x24, 0x06, 0x00, 0xc6, 0x3c, 0x03, 0x40, 0x00,
|
||||||
|
0x00, 0x07, 0x17, 0x80, 0x00, 0x43, 0x10, 0x24, 0x00, 0x07, 0x18, 0xc2,
|
||||||
|
0x00, 0x03, 0x1f, 0xc0, 0x00, 0x43, 0x10, 0x25, 0x3c, 0x04, 0x00, 0x40,
|
||||||
|
0x00, 0x07, 0x1d, 0x40, 0x00, 0x64, 0x18, 0x24, 0x00, 0x43, 0x10, 0x25,
|
||||||
|
0x00, 0x07, 0x1b, 0x00, 0x30, 0x63, 0x40, 0x00, 0x00, 0x43, 0x10, 0x25,
|
||||||
|
0x3c, 0x04, 0x00, 0x80, 0x00, 0x07, 0x1c, 0xc0, 0x00, 0x64, 0x18, 0x24,
|
||||||
|
0x00, 0x43, 0x10, 0x25, 0x00, 0x07, 0x1a, 0x80, 0x30, 0x63, 0x80, 0x00,
|
||||||
|
0x00, 0x43, 0x10, 0x25, 0x00, 0x46, 0x30, 0x25, 0x24, 0x05, 0x00, 0x03,
|
||||||
|
0x04, 0x11, 0xff, 0xca, 0x01, 0x00, 0x20, 0x25, 0x11, 0x20, 0x00, 0x1b,
|
||||||
|
0x8f, 0xbf, 0x00, 0x14, 0x24, 0x05, 0x00, 0x03, 0x04, 0x11, 0xff, 0xbf,
|
||||||
|
0x01, 0x00, 0x20, 0x25, 0x04, 0x11, 0xff, 0xa2, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x05, 0x00, 0x03, 0x04, 0x11, 0xff, 0x9f, 0x01, 0x00, 0x20, 0x25,
|
||||||
|
0x00, 0x02, 0x3f, 0x82, 0x00, 0x02, 0x1d, 0x42, 0x30, 0x63, 0x00, 0x02,
|
||||||
|
0x30, 0xe7, 0x00, 0x01, 0x00, 0xe3, 0x38, 0x25, 0x00, 0x02, 0x1b, 0x02,
|
||||||
|
0x30, 0x63, 0x00, 0x04, 0x00, 0xe3, 0x38, 0x25, 0x00, 0x02, 0x1f, 0x02,
|
||||||
|
0x30, 0x63, 0x00, 0x08, 0x00, 0xe3, 0x38, 0x25, 0x00, 0x02, 0x1c, 0xc2,
|
||||||
|
0x30, 0x63, 0x00, 0x10, 0x00, 0x02, 0x12, 0x82, 0x00, 0xe3, 0x38, 0x25,
|
||||||
|
0x30, 0x42, 0x00, 0x20, 0x00, 0xe2, 0x38, 0x25, 0x8f, 0xbf, 0x00, 0x14,
|
||||||
|
0x00, 0xe0, 0x10, 0x25, 0x03, 0xe0, 0x00, 0x08, 0x27, 0xbd, 0x00, 0x18,
|
||||||
|
0x27, 0xbd, 0xff, 0xb0, 0x3c, 0x03, 0xa4, 0x70, 0x24, 0x02, 0x00, 0x20,
|
||||||
|
0xaf, 0xbf, 0x00, 0x34, 0xaf, 0xb4, 0x00, 0x2c, 0xaf, 0xb3, 0x00, 0x28,
|
||||||
|
0xaf, 0xb2, 0x00, 0x24, 0xaf, 0xb0, 0x00, 0x1c, 0xe7, 0xb7, 0x00, 0x44,
|
||||||
|
0xaf, 0xb5, 0x00, 0x30, 0xaf, 0xb1, 0x00, 0x20, 0xe7, 0xb9, 0x00, 0x4c,
|
||||||
|
0xe7, 0xb8, 0x00, 0x48, 0xe7, 0xb6, 0x00, 0x40, 0xe7, 0xb5, 0x00, 0x3c,
|
||||||
|
0xe7, 0xb4, 0x00, 0x38, 0xac, 0x62, 0x00, 0x04, 0x04, 0x11, 0xff, 0x92,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x14, 0xac, 0x60, 0x00, 0x08,
|
||||||
|
0xac, 0x62, 0x00, 0x0c, 0xac, 0x60, 0x00, 0x00, 0x04, 0x11, 0xff, 0x8c,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x0e, 0xac, 0x62, 0x00, 0x00,
|
||||||
|
0x04, 0x11, 0xff, 0x88, 0x24, 0x03, 0x01, 0x0f, 0x3c, 0x02, 0xa4, 0x30,
|
||||||
|
0xac, 0x43, 0x00, 0x00, 0x3c, 0x02, 0x18, 0x08, 0x3c, 0x10, 0xa3, 0xf8,
|
||||||
|
0x24, 0x42, 0x28, 0x38, 0xae, 0x02, 0x00, 0x08, 0x00, 0x80, 0x98, 0x25,
|
||||||
|
0x00, 0x00, 0x28, 0x25, 0x24, 0x04, 0xff, 0xff, 0x02, 0x60, 0xf8, 0x09,
|
||||||
|
0x24, 0x1a, 0x00, 0x08, 0x3c, 0x06, 0x00, 0x03, 0x34, 0xc6, 0x80, 0xfc,
|
||||||
|
0x24, 0x05, 0x00, 0x01, 0x24, 0x04, 0xff, 0xff, 0x04, 0x11, 0xff, 0x7d,
|
||||||
|
0x3c, 0x14, 0xa4, 0x00, 0x3c, 0x02, 0x44, 0x00, 0xc6, 0x97, 0x09, 0xe4,
|
||||||
|
0xae, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x90, 0x25, 0xae, 0x00, 0x00, 0x14,
|
||||||
|
0x00, 0x00, 0x80, 0x25, 0x00, 0x10, 0x30, 0x80, 0x24, 0x05, 0x00, 0x01,
|
||||||
|
0x04, 0x11, 0xff, 0x73, 0x24, 0x04, 0x01, 0xff, 0x24, 0x06, 0x00, 0x46,
|
||||||
|
0x24, 0x05, 0x00, 0x03, 0x04, 0x11, 0xff, 0x6f, 0x02, 0x00, 0x20, 0x25,
|
||||||
|
0x24, 0x05, 0x00, 0x03, 0x04, 0x11, 0xff, 0x4b, 0x02, 0x00, 0x20, 0x25,
|
||||||
|
0x30, 0x42, 0x00, 0x02, 0x14, 0x40, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x52, 0x00, 0x00, 0x05, 0x00, 0x10, 0x80, 0x43, 0x24, 0x05, 0x00, 0x01,
|
||||||
|
0x02, 0x60, 0xf8, 0x09, 0x26, 0x04, 0xff, 0xfe, 0x00, 0x10, 0x80, 0x43,
|
||||||
|
0x24, 0x02, 0x00, 0x01, 0x02, 0x02, 0x10, 0x04, 0x24, 0x42, 0xff, 0xff,
|
||||||
|
0x3c, 0x03, 0x00, 0x06, 0x24, 0x63, 0x36, 0x34, 0x00, 0x02, 0x14, 0xc0,
|
||||||
|
0x00, 0x43, 0x10, 0x25, 0x8f, 0xbf, 0x00, 0x34, 0x3c, 0x03, 0xa4, 0x70,
|
||||||
|
0xac, 0x62, 0x00, 0x10, 0x8c, 0x62, 0x00, 0x10, 0x8f, 0xb5, 0x00, 0x30,
|
||||||
|
0x8f, 0xb4, 0x00, 0x2c, 0x8f, 0xb3, 0x00, 0x28, 0x8f, 0xb1, 0x00, 0x20,
|
||||||
|
0x8f, 0xb0, 0x00, 0x1c, 0xc7, 0xb9, 0x00, 0x4c, 0xc7, 0xb8, 0x00, 0x48,
|
||||||
|
0xc7, 0xb7, 0x00, 0x44, 0xc7, 0xb6, 0x00, 0x40, 0xc7, 0xb5, 0x00, 0x3c,
|
||||||
|
0xc7, 0xb4, 0x00, 0x38, 0x02, 0x40, 0x10, 0x25, 0x8f, 0xb2, 0x00, 0x24,
|
||||||
|
0x03, 0xe0, 0x00, 0x08, 0x27, 0xbd, 0x00, 0x50, 0x16, 0x00, 0x00, 0x44,
|
||||||
|
0x00, 0x00, 0x28, 0x25, 0x44, 0x80, 0xa0, 0x00, 0x3c, 0x02, 0xa4, 0x00,
|
||||||
|
0x3c, 0x11, 0xa0, 0x00, 0xc4, 0x59, 0x09, 0xe8, 0x02, 0x51, 0x88, 0x21,
|
||||||
|
0x46, 0x00, 0xa5, 0x86, 0x00, 0x00, 0xa8, 0x25, 0x46, 0x00, 0xa6, 0x06,
|
||||||
|
0x02, 0x00, 0x20, 0x25, 0x32, 0xa6, 0x00, 0xff, 0x44, 0x80, 0xa8, 0x00,
|
||||||
|
0x04, 0x11, 0xff, 0x51, 0x00, 0x00, 0x28, 0x25, 0x24, 0x03, 0x00, 0x0a,
|
||||||
|
0x24, 0x04, 0xff, 0xff, 0xae, 0x24, 0x00, 0x00, 0xae, 0x24, 0x00, 0x04,
|
||||||
|
0x92, 0x22, 0x00, 0x05, 0x30, 0x42, 0x00, 0xff, 0xa3, 0xa2, 0x00, 0x10,
|
||||||
|
0x93, 0xa2, 0x00, 0x10, 0x30, 0x42, 0x00, 0xff, 0x14, 0x40, 0x00, 0x33,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x24, 0x63, 0xff, 0xff, 0x14, 0x60, 0xff, 0xf5,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x46, 0x15, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x45, 0x02, 0x00, 0x05, 0x46, 0x19, 0xad, 0x42, 0x8e, 0x24, 0x00, 0x04,
|
||||||
|
0x04, 0x11, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x46, 0x19, 0xad, 0x42,
|
||||||
|
0x44, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x80, 0x00, 0x20,
|
||||||
|
0x46, 0x16, 0xad, 0x81, 0x46, 0x00, 0xb5, 0x82, 0xc6, 0x80, 0x09, 0xe4,
|
||||||
|
0x46, 0x15, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x05,
|
||||||
|
0x46, 0x16, 0xa5, 0x00, 0x26, 0xb5, 0x00, 0x01, 0x24, 0x02, 0x00, 0x40,
|
||||||
|
0x56, 0xa2, 0xff, 0xd8, 0x46, 0x00, 0xad, 0x86, 0x3c, 0x02, 0xa4, 0x00,
|
||||||
|
0xc4, 0x40, 0x09, 0xec, 0x3c, 0x02, 0xa4, 0x00, 0x46, 0x00, 0xa5, 0x02,
|
||||||
|
0xc4, 0x40, 0x09, 0xf0, 0x46, 0x00, 0xa5, 0x00, 0x46, 0x00, 0xa0, 0x0d,
|
||||||
|
0x44, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x00, 0x17,
|
||||||
|
0x00, 0x00, 0x60, 0x25, 0x3c, 0x06, 0x00, 0x03, 0x34, 0xc6, 0x80, 0xf4,
|
||||||
|
0x24, 0x05, 0x00, 0x01, 0x04, 0x11, 0xff, 0x06, 0x02, 0x00, 0x20, 0x25,
|
||||||
|
0x10, 0x00, 0xff, 0xa2, 0x00, 0x10, 0x80, 0x43, 0x02, 0x60, 0xf8, 0x09,
|
||||||
|
0x26, 0x04, 0xff, 0xfe, 0x24, 0x02, 0x00, 0x08, 0x16, 0x02, 0xff, 0xb9,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xff, 0x9b, 0x00, 0x10, 0x80, 0x43,
|
||||||
|
0x93, 0xa2, 0x00, 0x10, 0x30, 0x42, 0x00, 0x01, 0x54, 0x40, 0x00, 0x01,
|
||||||
|
0x46, 0x17, 0xad, 0x40, 0x93, 0xa2, 0x00, 0x10, 0x30, 0x42, 0x00, 0xff,
|
||||||
|
0x10, 0x00, 0xff, 0xc2, 0x00, 0x02, 0x10, 0x42, 0x00, 0x00, 0x68, 0x25,
|
||||||
|
0x00, 0x00, 0x58, 0x25, 0x24, 0x0e, 0x00, 0x40, 0x02, 0x00, 0x20, 0x25,
|
||||||
|
0x31, 0x66, 0x00, 0xff, 0x04, 0x11, 0xff, 0x05, 0x24, 0x05, 0x00, 0x01,
|
||||||
|
0x00, 0x4a, 0x18, 0x23, 0x00, 0x03, 0x27, 0xc3, 0x00, 0x83, 0x18, 0x26,
|
||||||
|
0x11, 0x60, 0x00, 0x3a, 0x00, 0x64, 0x18, 0x23, 0x00, 0x6d, 0x20, 0x2a,
|
||||||
|
0x54, 0x80, 0x00, 0x02, 0x01, 0x60, 0x60, 0x25, 0x01, 0xa0, 0x18, 0x25,
|
||||||
|
0x01, 0x42, 0x10, 0x2a, 0x14, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x25, 0x6b, 0x00, 0x01, 0x15, 0x6e, 0xff, 0xee, 0x00, 0x60, 0x68, 0x25,
|
||||||
|
0x11, 0x80, 0xff, 0xd3, 0x31, 0x86, 0x00, 0xff, 0x24, 0x05, 0x00, 0x01,
|
||||||
|
0x04, 0x11, 0xfe, 0xf1, 0x02, 0x00, 0x20, 0x25, 0x00, 0x00, 0x28, 0x25,
|
||||||
|
0x04, 0x11, 0xfe, 0xb6, 0x02, 0x00, 0x20, 0x25, 0x00, 0x40, 0x38, 0x25,
|
||||||
|
0x30, 0x43, 0xf0, 0x00, 0x24, 0x02, 0x10, 0x00, 0x14, 0x62, 0xff, 0xc8,
|
||||||
|
0x30, 0xe2, 0x0f, 0x00, 0x24, 0x03, 0x09, 0x00, 0x14, 0x43, 0xff, 0xc5,
|
||||||
|
0x30, 0xe2, 0x00, 0xf0, 0x24, 0x03, 0x00, 0xb0, 0x14, 0x43, 0xff, 0xc2,
|
||||||
|
0x30, 0xe2, 0x00, 0x04, 0x10, 0x40, 0xff, 0xc0, 0x24, 0x05, 0x00, 0x09,
|
||||||
|
0x04, 0x11, 0xfe, 0xa7, 0x02, 0x00, 0x20, 0x25, 0x00, 0x02, 0x14, 0x02,
|
||||||
|
0x24, 0x03, 0x00, 0x05, 0x10, 0x43, 0x00, 0x17, 0x3c, 0x06, 0x04, 0x0a,
|
||||||
|
0x30, 0xe7, 0x00, 0x01, 0x14, 0xe0, 0x00, 0x03, 0x24, 0xc6, 0x1c, 0x10,
|
||||||
|
0x3c, 0x06, 0x04, 0x12, 0x24, 0xc6, 0x0c, 0x08, 0x24, 0x05, 0x00, 0x06,
|
||||||
|
0x04, 0x11, 0xfe, 0xbc, 0x02, 0x00, 0x20, 0x25, 0x3c, 0x02, 0xa0, 0x20,
|
||||||
|
0x3c, 0x03, 0x00, 0x08, 0x02, 0x42, 0x10, 0x21, 0x8e, 0x24, 0x00, 0x00,
|
||||||
|
0x8e, 0x24, 0x00, 0x04, 0x02, 0x23, 0x88, 0x21, 0x14, 0x51, 0xff, 0xfc,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x20, 0x26, 0x10, 0x00, 0x02,
|
||||||
|
0x10, 0x00, 0xff, 0x3a, 0x02, 0x42, 0x90, 0x21, 0x10, 0x00, 0xff, 0xca,
|
||||||
|
0x00, 0x00, 0x60, 0x25, 0x10, 0x00, 0xff, 0xee, 0x24, 0xc6, 0x1c, 0x10,
|
||||||
|
0x3f, 0x80, 0x00, 0x00, 0x3c, 0x4c, 0xcc, 0xcd, 0x40, 0x0c, 0xcc, 0xcd,
|
||||||
|
0x3f, 0x00, 0x00, 0x00, 0x3c, 0x02, 0xcc, 0x9e, 0x24, 0x42, 0x2d, 0x51,
|
||||||
|
0x00, 0x82, 0x00, 0x18, 0x00, 0x00, 0x10, 0x12, 0x00, 0x02, 0x1c, 0x42,
|
||||||
|
0x00, 0x02, 0x13, 0xc0, 0x00, 0x43, 0x10, 0x25, 0x3c, 0x03, 0x1b, 0x87,
|
||||||
|
0x24, 0x63, 0x35, 0x93, 0x00, 0x43, 0x00, 0x18, 0x00, 0x00, 0x10, 0x12,
|
||||||
|
0x00, 0x5b, 0x10, 0x26, 0x00, 0x02, 0x1c, 0xc2, 0x00, 0x02, 0x13, 0x40,
|
||||||
|
0x00, 0x62, 0x10, 0x25, 0x00, 0x02, 0x18, 0x80, 0x00, 0x62, 0x18, 0x21,
|
||||||
|
0x3c, 0x02, 0xe6, 0x54, 0x24, 0x42, 0x6b, 0x64, 0x03, 0xe0, 0x00, 0x08,
|
||||||
|
0x00, 0x62, 0xd8, 0x21, 0x00, 0x1b, 0x1c, 0x02, 0x3c, 0x02, 0x85, 0xeb,
|
||||||
|
0x00, 0x7b, 0x18, 0x26, 0x34, 0x42, 0xca, 0x6b, 0x00, 0x62, 0x00, 0x18,
|
||||||
|
0x00, 0x00, 0x10, 0x12, 0x00, 0x02, 0x1b, 0x42, 0x00, 0x62, 0x18, 0x26,
|
||||||
|
0x3c, 0x02, 0xc2, 0xb2, 0x34, 0x42, 0xae, 0x35, 0x00, 0x62, 0x00, 0x18,
|
||||||
|
0x00, 0x00, 0x10, 0x12, 0x00, 0x02, 0x1c, 0x02, 0x03, 0xe0, 0x00, 0x08,
|
||||||
|
0x00, 0x62, 0x10, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x17,
|
||||||
|
0xc4, 0x1d, 0x1c, 0xf5, 0x3c, 0x0a, 0xb0, 0x00, 0x3c, 0x09, 0xa4, 0x00,
|
||||||
|
0x25, 0x4b, 0x0f, 0xc0, 0x25, 0x3d, 0x1f, 0xf0, 0x8d, 0x5f, 0x00, 0x40,
|
||||||
|
0xad, 0x3f, 0x00, 0x40, 0x25, 0x4a, 0x00, 0x04, 0x15, 0x4b, 0xff, 0xfc,
|
||||||
|
0x25, 0x29, 0x00, 0x04, 0x00, 0x00, 0x48, 0x25, 0x24, 0x0a, 0x00, 0x40,
|
||||||
|
0x27, 0xab, 0xe0, 0x50, 0x01, 0x60, 0x00, 0x08, 0x27, 0xbf, 0xf5, 0x60,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe8,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x27, 0xbd, 0xff, 0xa0, 0x3c, 0x07, 0x10, 0x00,
|
||||||
|
0x3c, 0x03, 0x7f, 0x45, 0x3c, 0x02, 0x14, 0x00, 0x3c, 0x04, 0xa0, 0x00,
|
||||||
|
0xaf, 0xbe, 0x00, 0x58, 0xaf, 0xb3, 0x00, 0x44, 0xaf, 0xbf, 0x00, 0x5c,
|
||||||
|
0xaf, 0xb7, 0x00, 0x54, 0xaf, 0xb6, 0x00, 0x50, 0xaf, 0xb5, 0x00, 0x4c,
|
||||||
|
0xaf, 0xb4, 0x00, 0x48, 0xaf, 0xb2, 0x00, 0x40, 0xaf, 0xb1, 0x00, 0x3c,
|
||||||
|
0xaf, 0xb0, 0x00, 0x38, 0x03, 0xa0, 0xf0, 0x25, 0x24, 0xf3, 0x10, 0x00,
|
||||||
|
0x24, 0x63, 0x4c, 0x46, 0x24, 0x42, 0x10, 0x00, 0x02, 0x64, 0x28, 0x25,
|
||||||
|
0x8c, 0xa5, 0x00, 0x00, 0x50, 0xa3, 0x00, 0xfa, 0x00, 0x13, 0x12, 0x00,
|
||||||
|
0x26, 0x73, 0x01, 0x00, 0x16, 0x62, 0xff, 0xfb, 0x02, 0x64, 0x28, 0x25,
|
||||||
|
0x3c, 0x04, 0xb0, 0x00, 0x10, 0x00, 0x01, 0x01, 0x24, 0x84, 0x17, 0x55,
|
||||||
|
0x16, 0x22, 0x00, 0x7c, 0x24, 0x14, 0x00, 0x20, 0x24, 0x14, 0x00, 0x38,
|
||||||
|
0x24, 0x02, 0x00, 0x24, 0x3c, 0x04, 0xa0, 0x00, 0x00, 0x53, 0x10, 0x21,
|
||||||
|
0x00, 0x44, 0x10, 0x25, 0x24, 0x04, 0x00, 0x02, 0x8c, 0x48, 0x00, 0x00,
|
||||||
|
0x16, 0x24, 0x00, 0x02, 0x24, 0x02, 0x00, 0x2c, 0x24, 0x02, 0x00, 0x38,
|
||||||
|
0x3c, 0x04, 0xa0, 0x00, 0x00, 0x53, 0x10, 0x21, 0x00, 0x44, 0x10, 0x25,
|
||||||
|
0x8c, 0x42, 0x00, 0x00, 0x24, 0x04, 0x00, 0x02, 0x00, 0x02, 0x14, 0x02,
|
||||||
|
0xaf, 0xc2, 0x00, 0x10, 0x16, 0x24, 0x00, 0x02, 0x24, 0x02, 0x00, 0x18,
|
||||||
|
0x24, 0x02, 0x00, 0x1c, 0x3c, 0x04, 0xa4, 0x00, 0x8c, 0x83, 0x00, 0x00,
|
||||||
|
0x00, 0x53, 0x10, 0x21, 0x3c, 0x04, 0xa0, 0x00, 0x00, 0x44, 0x10, 0x25,
|
||||||
|
0x8c, 0x42, 0x00, 0x00, 0xaf, 0xc3, 0x00, 0x28, 0xaf, 0xc2, 0x00, 0x2c,
|
||||||
|
0x8f, 0xc2, 0x00, 0x10, 0x01, 0x13, 0x40, 0x21, 0x00, 0x54, 0x00, 0x18,
|
||||||
|
0x00, 0x00, 0x30, 0x12, 0x24, 0xc2, 0x00, 0x10, 0x03, 0xa2, 0xe8, 0x23,
|
||||||
|
0x27, 0xb0, 0x00, 0x10, 0x00, 0x10, 0x10, 0x23, 0x30, 0x42, 0x00, 0x0f,
|
||||||
|
0x02, 0x02, 0x80, 0x21, 0x00, 0xc0, 0x28, 0x25, 0x04, 0x11, 0x00, 0xd8,
|
||||||
|
0x02, 0x00, 0x20, 0x25, 0x3c, 0x02, 0xa4, 0x60, 0x8c, 0x44, 0x00, 0x10,
|
||||||
|
0x30, 0x84, 0x00, 0x03, 0x14, 0x80, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0xc6, 0xff, 0xff, 0xac, 0x50, 0x00, 0x00, 0xac, 0x48, 0x00, 0x04,
|
||||||
|
0xac, 0x46, 0x00, 0x0c, 0x04, 0x11, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x03, 0x00, 0x04, 0x3a, 0x22, 0x00, 0x02, 0x14, 0x40, 0x00, 0x03,
|
||||||
|
0xaf, 0xc3, 0x00, 0x14, 0x24, 0x03, 0x00, 0x0c, 0xaf, 0xc3, 0x00, 0x14,
|
||||||
|
0x24, 0x03, 0x00, 0x08, 0x14, 0x40, 0x00, 0x03, 0xaf, 0xc3, 0x00, 0x18,
|
||||||
|
0x24, 0x03, 0x00, 0x14, 0xaf, 0xc3, 0x00, 0x18, 0x24, 0x03, 0x00, 0x0c,
|
||||||
|
0x14, 0x40, 0x00, 0x03, 0xaf, 0xc3, 0x00, 0x1c, 0x24, 0x03, 0x00, 0x1c,
|
||||||
|
0xaf, 0xc3, 0x00, 0x1c, 0x24, 0x03, 0x00, 0x10, 0x14, 0x40, 0x00, 0x03,
|
||||||
|
0xaf, 0xc3, 0x00, 0x20, 0x24, 0x03, 0x00, 0x24, 0xaf, 0xc3, 0x00, 0x20,
|
||||||
|
0x24, 0x03, 0x00, 0x14, 0x14, 0x40, 0x00, 0x03, 0xaf, 0xc3, 0x00, 0x24,
|
||||||
|
0x24, 0x03, 0x00, 0x2c, 0xaf, 0xc3, 0x00, 0x24, 0x14, 0x40, 0x00, 0x02,
|
||||||
|
0x24, 0x17, 0x00, 0x18, 0x24, 0x17, 0x00, 0x04, 0x3c, 0x02, 0xa4, 0x00,
|
||||||
|
0x24, 0x42, 0x03, 0x30, 0x00, 0x00, 0x90, 0x25, 0x00, 0x00, 0x88, 0x25,
|
||||||
|
0xaf, 0xc2, 0x00, 0x30, 0xaf, 0xd4, 0x00, 0x34, 0x8f, 0xc2, 0x00, 0x10,
|
||||||
|
0x02, 0x42, 0x10, 0x2a, 0x54, 0x40, 0x00, 0x23, 0x8f, 0xc2, 0x00, 0x14,
|
||||||
|
0x3c, 0x02, 0x00, 0xaa, 0x3c, 0x03, 0xa4, 0x04, 0x34, 0x42, 0xaa, 0x0e,
|
||||||
|
0xac, 0x62, 0x00, 0x10, 0x3c, 0x02, 0xa4, 0x08, 0xac, 0x40, 0x00, 0x00,
|
||||||
|
0xac, 0x60, 0x00, 0x1c, 0x3c, 0x02, 0xa4, 0x30, 0x24, 0x03, 0x05, 0x55,
|
||||||
|
0xac, 0x43, 0x00, 0x0c, 0x24, 0x04, 0x00, 0x02, 0xac, 0x43, 0x00, 0x08,
|
||||||
|
0x3c, 0x03, 0xa4, 0x60, 0xac, 0x64, 0x00, 0x10, 0x3c, 0x03, 0xa4, 0x80,
|
||||||
|
0xac, 0x60, 0x00, 0x18, 0x3c, 0x03, 0xa4, 0x50, 0xac, 0x60, 0x00, 0x0c,
|
||||||
|
0x24, 0x03, 0x08, 0x00, 0xac, 0x43, 0x00, 0x00, 0x3c, 0x02, 0xa4, 0x00,
|
||||||
|
0x24, 0x42, 0x0a, 0x48, 0x00, 0x40, 0xf8, 0x09, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3c, 0x03, 0xa4, 0x00, 0xac, 0x62, 0x00, 0x04, 0x3c, 0x03, 0x80, 0x00,
|
||||||
|
0xac, 0x62, 0x01, 0xa4, 0x3c, 0x02, 0xb0, 0x00, 0x24, 0x42, 0x18, 0x28,
|
||||||
|
0x00, 0x40, 0xf8, 0x09, 0x8f, 0xc4, 0x00, 0x2c, 0x10, 0x00, 0xff, 0x86,
|
||||||
|
0x24, 0x02, 0x00, 0x1c, 0x3c, 0x03, 0x64, 0xe3, 0x02, 0x02, 0x10, 0x21,
|
||||||
|
0x8c, 0x49, 0x00, 0x00, 0x8f, 0xc2, 0x00, 0x18, 0x24, 0x64, 0x63, 0x41,
|
||||||
|
0x02, 0x02, 0x10, 0x21, 0x8c, 0x54, 0x00, 0x00, 0x8f, 0xc2, 0x00, 0x1c,
|
||||||
|
0x02, 0x02, 0x10, 0x21, 0x8c, 0x55, 0x00, 0x00, 0x8f, 0xc2, 0x00, 0x20,
|
||||||
|
0x02, 0x02, 0x10, 0x21, 0x8c, 0x56, 0x00, 0x00, 0x8f, 0xc2, 0x00, 0x24,
|
||||||
|
0x02, 0x02, 0x10, 0x21, 0x8c, 0x4a, 0x00, 0x00, 0x02, 0x17, 0x10, 0x21,
|
||||||
|
0x8c, 0x4b, 0x00, 0x00, 0x8e, 0x02, 0x00, 0x00, 0x14, 0x44, 0x00, 0x14,
|
||||||
|
0x24, 0x04, 0x00, 0x01, 0x16, 0x80, 0x00, 0x14, 0x02, 0x80, 0x88, 0x25,
|
||||||
|
0x26, 0xc2, 0x00, 0x17, 0x00, 0x02, 0x10, 0xc2, 0x00, 0x02, 0x10, 0xc0,
|
||||||
|
0x03, 0xa2, 0xe8, 0x23, 0x27, 0xb1, 0x00, 0x10, 0x00, 0x11, 0x10, 0x23,
|
||||||
|
0x30, 0x42, 0x00, 0x0f, 0x02, 0x22, 0x88, 0x21, 0x02, 0xc0, 0x28, 0x25,
|
||||||
|
0x04, 0x11, 0x00, 0x62, 0x02, 0x20, 0x20, 0x25, 0x16, 0xc0, 0x00, 0x0e,
|
||||||
|
0x02, 0x20, 0xa0, 0x25, 0x8f, 0xc2, 0x00, 0x34, 0x26, 0x52, 0x00, 0x01,
|
||||||
|
0x10, 0x00, 0xff, 0xb3, 0x02, 0x02, 0x80, 0x21, 0x14, 0x44, 0xff, 0xfc,
|
||||||
|
0x8f, 0xc2, 0x00, 0x34, 0x12, 0xc0, 0xff, 0xf9, 0x32, 0x82, 0x00, 0x07,
|
||||||
|
0x10, 0x40, 0x00, 0x05, 0x31, 0x22, 0x00, 0x01, 0x3c, 0x04, 0xb0, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x51, 0x24, 0x84, 0x17, 0x18, 0x31, 0x22, 0x00, 0x01,
|
||||||
|
0x50, 0x40, 0x00, 0x04, 0x31, 0x64, 0x10, 0x00, 0x3c, 0x04, 0xb0, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x4b, 0x24, 0x84, 0x16, 0xfa, 0x10, 0x80, 0x00, 0x02,
|
||||||
|
0x02, 0x80, 0x10, 0x25, 0x02, 0xa0, 0x10, 0x25, 0x8f, 0xc3, 0x00, 0x28,
|
||||||
|
0x3c, 0x05, 0x80, 0x00, 0x00, 0x4a, 0x10, 0x21, 0x00, 0x65, 0x28, 0x21,
|
||||||
|
0x00, 0xa2, 0x10, 0x2b, 0x10, 0x40, 0x00, 0x04, 0x24, 0x05, 0xff, 0xfe,
|
||||||
|
0x3c, 0x04, 0xb0, 0x00, 0x10, 0x00, 0x00, 0x3e, 0x24, 0x84, 0x16, 0xe4,
|
||||||
|
0x26, 0xc2, 0x00, 0x01, 0x00, 0x45, 0x10, 0x24, 0x01, 0x33, 0x48, 0x21,
|
||||||
|
0x3c, 0x05, 0xa4, 0x60, 0x8c, 0xaa, 0x00, 0x10, 0x31, 0x4a, 0x00, 0x03,
|
||||||
|
0x15, 0x40, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0xff,
|
||||||
|
0xac, 0xb4, 0x00, 0x00, 0xac, 0xa9, 0x00, 0x04, 0xac, 0xa2, 0x00, 0x0c,
|
||||||
|
0x10, 0x80, 0x00, 0x16, 0x02, 0xc0, 0x28, 0x25, 0x02, 0x80, 0x20, 0x25,
|
||||||
|
0x02, 0x20, 0xf8, 0x09, 0x02, 0xa0, 0x30, 0x25, 0x00, 0x40, 0x28, 0x25,
|
||||||
|
0x02, 0xa0, 0x20, 0x25, 0x04, 0x11, 0x00, 0x2b, 0x00, 0x40, 0x48, 0x25,
|
||||||
|
0x02, 0x95, 0x10, 0x2b, 0x10, 0x40, 0x00, 0x10, 0x02, 0xd4, 0x18, 0x21,
|
||||||
|
0x02, 0xa3, 0x10, 0x2b, 0x54, 0x40, 0x00, 0x01, 0x02, 0xa0, 0x18, 0x25,
|
||||||
|
0x00, 0x74, 0x30, 0x23, 0x00, 0xc0, 0x28, 0x25, 0x04, 0x11, 0x00, 0x21,
|
||||||
|
0x02, 0x80, 0x20, 0x25, 0x8f, 0xc2, 0x00, 0x30, 0x00, 0xc0, 0x28, 0x25,
|
||||||
|
0x00, 0x40, 0xf8, 0x09, 0x02, 0x80, 0x20, 0x25, 0x04, 0x11, 0x00, 0x84,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xff, 0xbb, 0x8f, 0xc2, 0x00, 0x34,
|
||||||
|
0x01, 0x35, 0x10, 0x21, 0x00, 0x43, 0x20, 0x2b, 0x10, 0x80, 0xff, 0xf9,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x20, 0x2b, 0x54, 0x80, 0xff, 0xee,
|
||||||
|
0x00, 0x40, 0xa0, 0x25, 0x10, 0x00, 0xff, 0xed, 0x00, 0x74, 0x30, 0x23,
|
||||||
|
0x3c, 0x03, 0xa4, 0x00, 0xac, 0x62, 0x00, 0x0c, 0x26, 0x62, 0x00, 0x04,
|
||||||
|
0x00, 0x44, 0x10, 0x25, 0x8c, 0x42, 0x00, 0x00, 0x3c, 0x03, 0x00, 0xff,
|
||||||
|
0x00, 0x02, 0x8e, 0x02, 0x00, 0x43, 0x10, 0x24, 0x3c, 0x03, 0x00, 0x01,
|
||||||
|
0x14, 0x43, 0xff, 0x03, 0x24, 0x02, 0x00, 0x02, 0x3c, 0x04, 0xb0, 0x00,
|
||||||
|
0x24, 0x84, 0x17, 0x35, 0x04, 0x11, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x03, 0xff, 0xf0, 0x00, 0x83, 0x18, 0x24, 0x00, 0x83, 0x20, 0x23,
|
||||||
|
0x00, 0x85, 0x20, 0x21, 0x00, 0x00, 0x10, 0x25, 0x00, 0x44, 0x28, 0x2a,
|
||||||
|
0x14, 0xa0, 0x00, 0x03, 0x00, 0x43, 0x28, 0x21, 0x03, 0xe0, 0x00, 0x08,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xbc, 0xb5, 0x00, 0x00, 0x10, 0x00, 0xff, 0xf9,
|
||||||
|
0x24, 0x42, 0x00, 0x10, 0x24, 0x02, 0xff, 0xfc, 0x00, 0x82, 0x10, 0x24,
|
||||||
|
0x3c, 0x03, 0xa0, 0x00, 0x00, 0x43, 0x10, 0x25, 0x8c, 0x42, 0x00, 0x00,
|
||||||
|
0x00, 0x04, 0x20, 0x27, 0x00, 0x04, 0x20, 0xc0, 0x00, 0x82, 0x10, 0x06,
|
||||||
|
0x03, 0xe0, 0x00, 0x08, 0x30, 0x42, 0x00, 0xff, 0x27, 0xbd, 0xff, 0xe8,
|
||||||
|
0x3c, 0x02, 0xa4, 0x40, 0x3c, 0x03, 0xa0, 0x10, 0xaf, 0xbf, 0x00, 0x14,
|
||||||
|
0xac, 0x43, 0x00, 0x04, 0x3c, 0x03, 0xa0, 0x12, 0x00, 0x80, 0x38, 0x25,
|
||||||
|
0x3c, 0x02, 0xa0, 0x10, 0x24, 0x04, 0xc9, 0x50, 0x24, 0x63, 0x58, 0x00,
|
||||||
|
0xa4, 0x44, 0x00, 0x00, 0x24, 0x42, 0x00, 0x02, 0x54, 0x43, 0xff, 0xfe,
|
||||||
|
0xa4, 0x44, 0x00, 0x00, 0x3c, 0x02, 0xa4, 0x40, 0x24, 0x03, 0x01, 0x40,
|
||||||
|
0xac, 0x43, 0x00, 0x08, 0x24, 0x03, 0x02, 0x00, 0xac, 0x43, 0x00, 0x30,
|
||||||
|
0x3c, 0x06, 0xa0, 0x10, 0x24, 0x03, 0x04, 0x00, 0x3c, 0x08, 0xb0, 0x00,
|
||||||
|
0xac, 0x43, 0x00, 0x34, 0x24, 0xc6, 0x64, 0x50, 0x25, 0x08, 0x17, 0x6c,
|
||||||
|
0x24, 0x0b, 0xf7, 0xb2, 0x04, 0x11, 0xff, 0xdb, 0x00, 0xe0, 0x20, 0x25,
|
||||||
|
0x00, 0x02, 0x1e, 0x00, 0x00, 0x03, 0x1e, 0x03, 0x10, 0x40, 0x00, 0x18,
|
||||||
|
0x24, 0xe7, 0x00, 0x01, 0x24, 0x62, 0xff, 0xff, 0x00, 0x02, 0x28, 0x80,
|
||||||
|
0x00, 0xa2, 0x28, 0x21, 0x01, 0x05, 0x28, 0x21, 0x24, 0xac, 0x00, 0x05,
|
||||||
|
0x00, 0xc0, 0x48, 0x25, 0x24, 0x0d, 0x00, 0x08, 0x04, 0x11, 0xff, 0xce,
|
||||||
|
0x00, 0xa0, 0x20, 0x25, 0x01, 0x20, 0x20, 0x25, 0x00, 0x00, 0x18, 0x25,
|
||||||
|
0x00, 0x62, 0x50, 0x07, 0x31, 0x4a, 0x00, 0x01, 0x55, 0x40, 0x00, 0x01,
|
||||||
|
0xa4, 0x8b, 0x00, 0x00, 0x24, 0x63, 0x00, 0x01, 0x14, 0x6d, 0xff, 0xfa,
|
||||||
|
0x24, 0x84, 0x02, 0x80, 0x24, 0xa5, 0x00, 0x01, 0x14, 0xac, 0xff, 0xf3,
|
||||||
|
0x25, 0x29, 0x00, 0x02, 0x10, 0x00, 0xff, 0xe4, 0x24, 0xc6, 0x00, 0x0e,
|
||||||
|
0x3c, 0x06, 0xa4, 0x00, 0x04, 0x11, 0xff, 0xbd, 0x24, 0xc4, 0x00, 0x09,
|
||||||
|
0x00, 0x40, 0x28, 0x25, 0x04, 0x11, 0xff, 0xba, 0x24, 0xc4, 0x00, 0x0b,
|
||||||
|
0x00, 0x05, 0x20, 0xc0, 0x00, 0x85, 0x20, 0x23, 0x3c, 0x03, 0xb0, 0x00,
|
||||||
|
0x00, 0x04, 0x20, 0x80, 0x24, 0x63, 0x16, 0x90, 0x00, 0x64, 0x18, 0x21,
|
||||||
|
0x3c, 0x04, 0xa4, 0x40, 0x24, 0x85, 0x00, 0x14, 0x24, 0x84, 0x00, 0x30,
|
||||||
|
0x8c, 0x66, 0x00, 0x00, 0x24, 0xa5, 0x00, 0x04, 0xac, 0xa6, 0xff, 0xfc,
|
||||||
|
0x14, 0xa4, 0xff, 0xfc, 0x24, 0x63, 0x00, 0x04, 0x10, 0x40, 0x00, 0x02,
|
||||||
|
0x24, 0x03, 0x32, 0x02, 0x24, 0x03, 0x12, 0x02, 0x3c, 0x02, 0xa4, 0x40,
|
||||||
|
0xac, 0x43, 0x00, 0x00, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3c, 0x03, 0xa4, 0x60, 0x8c, 0x62, 0x00, 0x10, 0x30, 0x42, 0x00, 0x03,
|
||||||
|
0x14, 0x40, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x48, 0x00,
|
||||||
|
0x3c, 0x19, 0xa4, 0x00, 0x27, 0x39, 0x09, 0xf4, 0x03, 0x20, 0x00, 0x08,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x23, 0x3a, 0x00, 0x00, 0x02, 0x71,
|
||||||
|
0x00, 0x15, 0x0c, 0x69, 0x0c, 0x6f, 0x0c, 0x6e, 0x00, 0x80, 0x03, 0x00,
|
||||||
|
0x00, 0x5f, 0x02, 0x39, 0x00, 0x09, 0x02, 0x6b, 0x03, 0xe5, 0x22, 0x39,
|
||||||
|
0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x0c, 0x15, 0x0c, 0x15, 0x0c, 0x15,
|
||||||
|
0x00, 0x6c, 0x02, 0xec, 0x00, 0x25, 0x01, 0xff, 0x00, 0x0e, 0x02, 0x04,
|
||||||
|
0x04, 0x65, 0x1e, 0x39, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x04, 0x0c, 0x11,
|
||||||
|
0x0c, 0x19, 0x0c, 0x1a, 0x00, 0x6c, 0x02, 0xec, 0x00, 0x25, 0x01, 0xff,
|
||||||
|
0x00, 0x0e, 0x02, 0x04, 0x10, 0x17, 0x11, 0x01, 0x1e, 0x10, 0x12, 0x18,
|
||||||
|
0x10, 0x19, 0x1f, 0x01, 0x1f, 0x1a, 0x1a, 0x01, 0x17, 0x0c, 0x1d, 0x12,
|
||||||
|
0x10, 0x00, 0x10, 0x17, 0x11, 0x01, 0x1a, 0x11, 0x11, 0x1e, 0x10, 0x1f,
|
||||||
|
0x01, 0x19, 0x1a, 0x1f, 0x01, 0x04, 0x01, 0x0d, 0x24, 0x1f, 0x10, 0x01,
|
||||||
|
0x0c, 0x17, 0x14, 0x12, 0x19, 0x10, 0x0f, 0x00, 0x10, 0x17, 0x11, 0x01,
|
||||||
|
0x21, 0x0c, 0x0f, 0x0f, 0x1d, 0x01, 0x19, 0x1a, 0x1f, 0x01, 0x0a, 0x01,
|
||||||
|
0x0d, 0x24, 0x1f, 0x10, 0x01, 0x0c, 0x17, 0x14, 0x12, 0x19, 0x10, 0x0f,
|
||||||
|
0x00, 0x10, 0x17, 0x11, 0x01, 0x17, 0x14, 0x1f, 0x1f, 0x17, 0x10, 0x01,
|
||||||
|
0x10, 0x19, 0x0f, 0x14, 0x0c, 0x19, 0x01, 0x19, 0x1a, 0x1f, 0x01, 0x1e,
|
||||||
|
0x20, 0x1b, 0x1b, 0x1a, 0x1d, 0x1f, 0x10, 0x0f, 0x00, 0x10, 0x17, 0x11,
|
||||||
|
0x01, 0x13, 0x10, 0x0c, 0x0f, 0x10, 0x1d, 0x01, 0x19, 0x1a, 0x1f, 0x01,
|
||||||
|
0x11, 0x1a, 0x20, 0x19, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x7e, 0xa1, 0x99, 0x85, 0x7e, 0x84, 0x82, 0xff, 0x80, 0x80, 0xc1,
|
||||||
|
0xa1, 0x91, 0x89, 0x86, 0x89, 0x89, 0x89, 0x89, 0x76, 0x18, 0x14, 0x12,
|
||||||
|
0xff, 0x10, 0x8f, 0x89, 0x89, 0x89, 0x71, 0x7e, 0x89, 0x89, 0x89, 0x72,
|
||||||
|
0x01, 0x81, 0x61, 0x19, 0x07, 0x62, 0x95, 0x89, 0x95, 0x62, 0x4e, 0x91,
|
||||||
|
0x91, 0x91, 0x7e, 0xfe, 0x11, 0x11, 0x11, 0xfe, 0xff, 0x89, 0x89, 0x89,
|
||||||
|
0x76, 0x7e, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x7e, 0xff,
|
||||||
|
0x89, 0x89, 0x89, 0x89, 0xff, 0x09, 0x09, 0x09, 0x09, 0x7e, 0x81, 0x91,
|
||||||
|
0x51, 0xf1, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x81, 0xff, 0x81, 0x00,
|
||||||
|
0x40, 0x80, 0x80, 0x80, 0x7f, 0xff, 0x08, 0x14, 0x22, 0xc1, 0xff, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0xff, 0x02, 0x04, 0x02, 0xff, 0xff, 0x06, 0x18, 0x60,
|
||||||
|
0xff, 0x7e, 0x81, 0x81, 0x81, 0x7e, 0xff, 0x11, 0x11, 0x11, 0x0e, 0x7e,
|
||||||
|
0x81, 0xa1, 0xc1, 0xfe, 0xff, 0x11, 0x11, 0x11, 0xee, 0x86, 0x89, 0x89,
|
||||||
|
0x89, 0x71, 0x01, 0x01, 0xff, 0x01, 0x01, 0x7f, 0x80, 0x80, 0x80, 0x7f,
|
||||||
|
0x1f, 0x60, 0x80, 0x60, 0x1f, 0xff, 0x40, 0x20, 0x40, 0xff, 0xc7, 0x28,
|
||||||
|
0x10, 0x28, 0xc7, 0x07, 0x08, 0xf0, 0x08, 0x07, 0xc1, 0xa1, 0x99, 0x85,
|
||||||
|
0x83, 0x00, 0x00, 0x00, 0x3c, 0x03, 0xa4, 0x80, 0x8c, 0x62, 0x00, 0x18,
|
||||||
|
0x30, 0x42, 0x00, 0x03, 0x14, 0x40, 0xff, 0xfd, 0x3c, 0x02, 0xbf, 0xc0,
|
||||||
|
0x24, 0x03, 0x00, 0x08, 0xac, 0x43, 0x07, 0xfc, 0x3c, 0x02, 0xa4, 0x00,
|
||||||
|
0x8c, 0x43, 0x00, 0x00, 0x40, 0x80, 0xe0, 0x00, 0x40, 0x80, 0xe8, 0x00,
|
||||||
|
0x3c, 0x02, 0x80, 0x00, 0x24, 0x45, 0x20, 0x00, 0xbc, 0x49, 0x00, 0x00,
|
||||||
|
0xbc, 0x49, 0x00, 0x10, 0xbc, 0x49, 0x00, 0x20, 0xbc, 0x49, 0x00, 0x30,
|
||||||
|
0x24, 0x42, 0x00, 0x40, 0x14, 0x45, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3c, 0x02, 0x80, 0x00, 0x24, 0x45, 0x40, 0x00, 0xbc, 0x48, 0x00, 0x00,
|
||||||
|
0xbc, 0x48, 0x00, 0x20, 0xbc, 0x48, 0x00, 0x40, 0xbc, 0x48, 0x00, 0x60,
|
||||||
|
0x24, 0x42, 0x00, 0x80, 0x14, 0x45, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3c, 0x02, 0xa4, 0x04, 0x8c, 0x45, 0x00, 0x14, 0x14, 0xa0, 0xff, 0xfe,
|
||||||
|
0x3c, 0x05, 0xa4, 0x00, 0x24, 0xa5, 0x10, 0x00, 0xac, 0x45, 0x00, 0x00,
|
||||||
|
0x24, 0x65, 0x80, 0x00, 0xac, 0x45, 0x00, 0x04, 0x3c, 0x05, 0x00, 0x01,
|
||||||
|
0x34, 0xa5, 0xf3, 0xff, 0xac, 0x45, 0x00, 0x0c, 0x3c, 0x02, 0xa4, 0x04,
|
||||||
|
0x8c, 0x45, 0x00, 0x14, 0x14, 0xa0, 0xff, 0xfe, 0x3c, 0x05, 0x00, 0x80,
|
||||||
|
0x24, 0xa5, 0x20, 0x00, 0xac, 0x45, 0x00, 0x04, 0x3c, 0x05, 0xa4, 0x00,
|
||||||
|
0x24, 0xa5, 0x00, 0x10, 0xac, 0x45, 0x00, 0x00, 0x24, 0x05, 0x0f, 0xef,
|
||||||
|
0xac, 0x45, 0x00, 0x08, 0x3c, 0x05, 0xa4, 0x80, 0x8c, 0xa2, 0x00, 0x18,
|
||||||
|
0x30, 0x42, 0x00, 0x03, 0x14, 0x40, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xac, 0xa0, 0x00, 0x18, 0x3c, 0x05, 0xa4, 0x04, 0x8c, 0xa2, 0x00, 0x18,
|
||||||
|
0x14, 0x40, 0xff, 0xfe, 0x3c, 0x02, 0x7f, 0xff, 0x34, 0x42, 0xff, 0xf0,
|
||||||
|
0x00, 0x62, 0x18, 0x21, 0x00, 0x80, 0x00, 0x08, 0x00, 0x60, 0xe8, 0x25
|
||||||
|
};
|
||||||
|
unsigned int default_ipl3_len = 6444;
|
||||||
@ -0,0 +1,842 @@
|
|||||||
|
/*
|
||||||
|
n64tool V1.0, a program used to append an n64 header to an arbitrary
|
||||||
|
sized Nintendo64 binary.
|
||||||
|
Copyright (C) 2009 DragonMinded (dragonminded@dragonminded.com)
|
||||||
|
|
||||||
|
This tool is part of the Libdragon SDK.
|
||||||
|
|
||||||
|
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 program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "polyfill.h"
|
||||||
|
#include "crc32.c"
|
||||||
|
|
||||||
|
typedef intptr_t ssize_t;
|
||||||
|
|
||||||
|
// Default header to use if none is specified
|
||||||
|
#include "ipl3.h"
|
||||||
|
|
||||||
|
#define ROUND_UP(n, d) ({ \
|
||||||
|
typeof(n) _n = n; typeof(d) _d = d; \
|
||||||
|
(((_n) + (_d) - 1) / (_d) * (_d)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
// strlcpy() is not available on all platforms, so we provide a simple implementation
|
||||||
|
#ifndef strlcpy
|
||||||
|
size_t __strlcpy(char * restrict dst, const char * restrict src, size_t dstsize)
|
||||||
|
{
|
||||||
|
strncpy(dst, src, dstsize - 1);
|
||||||
|
dst[dstsize - 1] = '\0';
|
||||||
|
return strlen(dst);
|
||||||
|
}
|
||||||
|
#define strlcpy __strlcpy
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Minimum ROM size alignment, used by default. We currently know of two constraints:
|
||||||
|
// * 64drive firmware has a bug and can only transfer chunks of 512 bytes. Some
|
||||||
|
// tools like UNFloader and g64drive work around this bug by padding ROMs,
|
||||||
|
// but others (like the official one) don't. So it's better in general to
|
||||||
|
// pad to 512 bytes.
|
||||||
|
// * EverDrive64 also requires ROMs to be transferred in blocks of 512 bytes,
|
||||||
|
// which means that the ROM has to be padded.
|
||||||
|
// * iQue player only allows loading ROMs which are multiple of 16 KiB in size.
|
||||||
|
//
|
||||||
|
// To allow the maximum compatibility, we pad to 16 KiB by default. Users can still
|
||||||
|
// force a specific length with --size, if they need to.
|
||||||
|
// We also allow changing the padding alignment with --padding.
|
||||||
|
int pad_align = 16384;
|
||||||
|
|
||||||
|
#define WRITE_SIZE (1024 * 1024)
|
||||||
|
|
||||||
|
#define TITLE_OFFSET 0x20
|
||||||
|
#define TITLE_SIZE 20
|
||||||
|
|
||||||
|
#define CATEGORY_OFFSET 0x3B
|
||||||
|
#define REGION_OFFSET 0x3E
|
||||||
|
|
||||||
|
#define IQUE_ENTRYPOINT_OFFSET 0x8
|
||||||
|
|
||||||
|
#define STATUS_OK 0
|
||||||
|
#define STATUS_ERROR 1
|
||||||
|
#define STATUS_BADUSAGE 2
|
||||||
|
|
||||||
|
#define TOC_SIZE 1024
|
||||||
|
#define TOC_ALIGN 16
|
||||||
|
#define TOC_ENTRY_SIZE 64
|
||||||
|
#define TOC_MAX_ENTRIES ((TOC_SIZE - 16) / 64)
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define SWAPLONG(i) (i)
|
||||||
|
#define SWAPSHORT(i) (i)
|
||||||
|
#else
|
||||||
|
#define SWAPLONG(i) (((uint32_t)((i) & 0xFF000000) >> 24) | ((uint32_t)((i) & 0x00FF0000) >> 8) | ((uint32_t)((i) & 0x0000FF00) << 8) | ((uint32_t)((i) & 0x000000FF) << 24))
|
||||||
|
#define SWAPSHORT(i) (((uint16_t)((i) & 0xFF00) >> 8) | ((uint16_t)((i) & 0x00FF) << 8))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const unsigned char zero[1024] = {0};
|
||||||
|
static char * tmp_output = NULL;
|
||||||
|
static uint32_t elf_loadpoint = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
// The TOC cookie could be just a 32-bit random number; its goal is just to
|
||||||
|
// differentiate different ROMs, to detect if a ROM was "swapped" by a flashcart
|
||||||
|
// during runtime.
|
||||||
|
// However we don't want to use a random number as we want ROMs to be reproducible,
|
||||||
|
// so we will instead hash the various file contents to generate a fixed-but-random
|
||||||
|
// cookie.
|
||||||
|
static uint32_t toc_cookie = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
struct toc_s {
|
||||||
|
char magic_version[4];
|
||||||
|
uint32_t cookie;
|
||||||
|
uint32_t toc_size;
|
||||||
|
uint16_t entry_size;
|
||||||
|
uint16_t num_entries;
|
||||||
|
struct {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
char name[TOC_ENTRY_SIZE - 8];
|
||||||
|
} files[TOC_MAX_ENTRIES];
|
||||||
|
} toc = {
|
||||||
|
.magic_version = "TOC0",
|
||||||
|
.toc_size = TOC_SIZE,
|
||||||
|
.entry_size = TOC_ENTRY_SIZE,
|
||||||
|
.num_entries = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
_Static_assert(sizeof(toc) <= TOC_SIZE, "invalid table size");
|
||||||
|
|
||||||
|
int print_usage(const char * prog_name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [flags] [file-flags] <file> [[file-flags] <file> ...]\n\n", prog_name);
|
||||||
|
fprintf(stderr, "This program creates an N64 ROM from a header and a list of files,\n");
|
||||||
|
fprintf(stderr, "the first being an Nintendo 64 binary and the rest arbitrary data.\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "General flags (to be used before any file):\n");
|
||||||
|
fprintf(stderr, "\t-t, --title <title> Title of ROM (max %d characters).\n", TITLE_SIZE);
|
||||||
|
fprintf(stderr, "\t-l, --size <size> Force ROM output file size to <size> (min 1 mebibyte).\n");
|
||||||
|
fprintf(stderr, "\t-P, --padding <size> Padding alignment for the final ROM (default: 16 KiB).\n");
|
||||||
|
fprintf(stderr, "\t-h, --header <file> Use <file> as IPL3 header (default: use libdragon IPL3).\n");
|
||||||
|
fprintf(stderr, "\t-o, --output <file> Save output ROM to <file>.\n");
|
||||||
|
fprintf(stderr, "\t-C, --category <cat> N64 Media Category Code (default: 'N' - N64 Game Pak).\n");
|
||||||
|
fprintf(stderr, "\t-R, --region <reg> Specify ROM region (default: 'E' - North America).\n");
|
||||||
|
fprintf(stderr, "\t-T, --toc Create a table of contents in the ROM.\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "File flags (to be used before each file):\n");
|
||||||
|
fprintf(stderr, "\t-a, --align <align> Next file is aligned at <align> bytes from top of memory (default: 16).\n");
|
||||||
|
fprintf(stderr, "\t-s, --offset <offset> Next file starts at <offset> from top of memory. Offset must be 4-byte aligned.\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "Binary byte size/offset suffix notation:\n");
|
||||||
|
fprintf(stderr, "\tB for bytes.\n");
|
||||||
|
fprintf(stderr, "\tK for kibibytes (KiB) [1024 bytes].\n");
|
||||||
|
fprintf(stderr, "\tM for mebibytes (MiB) [1024 kibibytes].\n");
|
||||||
|
return STATUS_BADUSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_flag(const char * arg, const char * shortFlag, const char * longFlag)
|
||||||
|
{
|
||||||
|
return !strcmp(arg, shortFlag) || !strcmp(arg, longFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_file_size(FILE * fp)
|
||||||
|
{
|
||||||
|
size_t restore = ftell(fp);
|
||||||
|
size_t end = 0;
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
end = ftell(fp);
|
||||||
|
fseek(fp, restore, SEEK_SET);
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t copy_file(FILE * dest, const char * file)
|
||||||
|
{
|
||||||
|
FILE *read_file = fopen(file, "rb");
|
||||||
|
uint8_t *buffer;
|
||||||
|
|
||||||
|
if(!read_file)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Cannot open %s for reading!\n", file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t fsize = get_file_size(read_file);
|
||||||
|
ssize_t rsize = fsize;
|
||||||
|
|
||||||
|
/* Should probably make this read in increments, but whatever */
|
||||||
|
buffer = malloc(WRITE_SIZE);
|
||||||
|
|
||||||
|
if(!buffer)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Out of memory!\n");
|
||||||
|
|
||||||
|
fclose(read_file);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Weird Windows bug fix, plus this is the right way to do things */
|
||||||
|
while(fsize > 0)
|
||||||
|
{
|
||||||
|
/* Max 1K chunk */
|
||||||
|
ssize_t write_size = (fsize > WRITE_SIZE) ? WRITE_SIZE : fsize;
|
||||||
|
fsize -= write_size;
|
||||||
|
|
||||||
|
fread(buffer, 1, write_size, read_file);
|
||||||
|
fwrite(buffer, 1, write_size, dest);
|
||||||
|
|
||||||
|
/* Update the TOC cookie with file contents. */
|
||||||
|
toc_cookie = crc32_update(toc_cookie, buffer, write_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
fclose(read_file);
|
||||||
|
|
||||||
|
return rsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t output_zeros(FILE * dest, ssize_t amount)
|
||||||
|
{
|
||||||
|
if(amount < 0)
|
||||||
|
{
|
||||||
|
/* Can't backward seek */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (amount > 0) {
|
||||||
|
int sz = amount;
|
||||||
|
if (sz > sizeof(zero))
|
||||||
|
sz = sizeof(zero);
|
||||||
|
fwrite(zero, 1, sz, dest);
|
||||||
|
toc_cookie = crc32_update(toc_cookie, zero, sz);
|
||||||
|
amount -= sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t parse_bytes(const char * arg)
|
||||||
|
{
|
||||||
|
size_t arg_len = strlen(arg);
|
||||||
|
|
||||||
|
if(arg_len < 2)
|
||||||
|
{
|
||||||
|
/* Need at least 2 characters to parse */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * suffix;
|
||||||
|
size_t size = strtol(arg, &suffix, 10);
|
||||||
|
|
||||||
|
/* Multiply by the suffix magnitude */
|
||||||
|
switch(suffix[0])
|
||||||
|
{
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
size *= 1024;
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
size *= 1024;
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
default:
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_tmp_file(void)
|
||||||
|
{
|
||||||
|
if(tmp_output)
|
||||||
|
remove(tmp_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t fread32be_at(FILE *fp, int offset)
|
||||||
|
{
|
||||||
|
uint8_t buf[4];
|
||||||
|
fseek(fp, offset, SEEK_SET);
|
||||||
|
fread(buf, 1, 4, fp);
|
||||||
|
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t fread16be_at(FILE *fp, int offset)
|
||||||
|
{
|
||||||
|
uint8_t buf[2];
|
||||||
|
fseek(fp, offset, SEEK_SET);
|
||||||
|
fread(buf, 1, 2, fp);
|
||||||
|
return (buf[0] << 8) | buf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_elf_loadpoint(const char *elf_fn, uint32_t *loadpoint)
|
||||||
|
{
|
||||||
|
FILE *elf = fopen(elf_fn, "rb");
|
||||||
|
|
||||||
|
if(!elf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Cannot open %s for reading!\n", elf_fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char id[4];
|
||||||
|
fread(id, 1, 4, elf);
|
||||||
|
if (memcmp(id, "\x7F" "ELF", 4) != 0) {
|
||||||
|
fprintf(stderr, "WARNING: %s is not an ELF file, boot may fail\n", elf_fn);
|
||||||
|
fclose(elf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool elf64 = fgetc(elf) == 2;
|
||||||
|
if (fgetc(elf) == 1) {
|
||||||
|
fprintf(stderr, "WARNING: %s is a little-endian ELF file, boot may fail\n", elf_fn);
|
||||||
|
fclose(elf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int phoff = fread32be_at(elf, (elf64 ? 0x20+4 : 0x1C));
|
||||||
|
int phnum = fread16be_at(elf, (elf64 ? 0x38 : 0x2C));
|
||||||
|
|
||||||
|
enum { PF_N64_COMPRESSED = 0x1000 };
|
||||||
|
enum { PT_LOAD = 0x1 };
|
||||||
|
|
||||||
|
bool found_loadpoint = false;
|
||||||
|
for (int i=0; i<phnum; i++) {
|
||||||
|
uint32_t type = fread32be_at(elf, phoff + 0);
|
||||||
|
uint32_t vaddr = fread32be_at(elf, phoff + (elf64 ? 5 : 2)*4);
|
||||||
|
uint32_t paddr = fread32be_at(elf, phoff + (elf64 ? 7 : 3)*4);
|
||||||
|
uint32_t flags = fread32be_at(elf, phoff + (elf64 ? 1 : 6)*4);
|
||||||
|
|
||||||
|
if (flags & PF_N64_COMPRESSED)
|
||||||
|
vaddr = paddr;
|
||||||
|
|
||||||
|
if (type == PT_LOAD && !(vaddr >= 0x80000000 && vaddr < 0x80000400)) {
|
||||||
|
*loadpoint = vaddr;
|
||||||
|
found_loadpoint = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
phoff += elf64 ? 0x38 : 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_loadpoint) {
|
||||||
|
fprintf(stderr, "WARNING: No suitable loading point found in %s, boot may fail on iQue\n", elf_fn);
|
||||||
|
fclose(elf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(elf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
winconsole_utf8();
|
||||||
|
FILE * write_file = NULL;
|
||||||
|
const char * header = NULL;
|
||||||
|
const char * output = NULL;
|
||||||
|
size_t declared_size = 0;
|
||||||
|
size_t total_bytes_written = 0;
|
||||||
|
char title[TITLE_SIZE + 1] = { 0, };
|
||||||
|
bool create_toc = false;
|
||||||
|
size_t toc_offset = 0;
|
||||||
|
int header_size = 0;
|
||||||
|
int align_next = 16;
|
||||||
|
|
||||||
|
char category = 'N';
|
||||||
|
// Some flashcarts (at least Everdrive X7) seem to automatically set the TV type based on the region field.
|
||||||
|
// As a result, some users might not be able to play the ROM because their TV or capture device doesn't
|
||||||
|
// support either PAL or NTSC. If the field is 0, the flashcart seems to not overwrite the console's region,
|
||||||
|
// so we use it as default.
|
||||||
|
char region = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if(argc <= 1)
|
||||||
|
{
|
||||||
|
/* No way we can have just one argument or less */
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
const char * arg;
|
||||||
|
|
||||||
|
while(i < argc)
|
||||||
|
{
|
||||||
|
arg = argv[i++];
|
||||||
|
if(check_flag(arg, "-b", "--byteswap"))
|
||||||
|
{
|
||||||
|
/* Invalid usage */
|
||||||
|
fprintf(stderr, "ERROR: The byteswap option is no longer supported. ");
|
||||||
|
fprintf(stderr, "Use another tool to convert the output of this program.\n");
|
||||||
|
fprintf(stderr, " For example: dd conv=swab if=rom.z64 of=rom.v64\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-h", "--header"))
|
||||||
|
{
|
||||||
|
if(header)
|
||||||
|
{
|
||||||
|
/* Invalid usage */
|
||||||
|
fprintf(stderr, "ERROR: The header can only be set once\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Invalid usage */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to header flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
header = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-o", "--output"))
|
||||||
|
{
|
||||||
|
if(output)
|
||||||
|
{
|
||||||
|
/* Invalid usage */
|
||||||
|
fprintf(stderr, "ERROR: The output can only be set once\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Invalid usage */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to output flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
output = argv[i++];
|
||||||
|
unsigned int needed_size = snprintf(0, 0, "%s.tmp", output) + 1;
|
||||||
|
tmp_output = calloc(needed_size, 1);
|
||||||
|
snprintf(tmp_output, needed_size, "%s.tmp", output);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-l", "--size"))
|
||||||
|
{
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to size flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t size = parse_bytes(argv[i++]);
|
||||||
|
|
||||||
|
if (size % 4 != 0)
|
||||||
|
{
|
||||||
|
/* Invalid size */
|
||||||
|
fprintf(stderr, "ERROR: Invalid size argument; must be a multiple of 4 bytes\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
if (size % 512 != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "WARNING: Sizes which are not multiple of 512 bytes might have problems being loaded with a 64drive\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
declared_size = size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-P", "--padding"))
|
||||||
|
{
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to padding flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t size = parse_bytes(argv[i++]);
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
{
|
||||||
|
/* Invalid size */
|
||||||
|
fprintf(stderr, "ERROR: Invalid padding argument; must be positive\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pad_align = size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-T", "--toc"))
|
||||||
|
{
|
||||||
|
if(total_bytes_written)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: -T / --toc must be specified before any input file\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
create_toc = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-s", "--offset"))
|
||||||
|
{
|
||||||
|
if(!output)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Need output flag before offset\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!total_bytes_written)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: The first file cannot have an offset\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to offset flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t offset = parse_bytes(argv[i++]);
|
||||||
|
|
||||||
|
if(offset <= 0)
|
||||||
|
{
|
||||||
|
/* Invalid offset */
|
||||||
|
fprintf(stderr, "ERROR: Invalid offset argument\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
if((offset % 4) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Invalid offset argument (must be multiple of 4)\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out needed number of zeros */
|
||||||
|
ssize_t num_zeros = offset - total_bytes_written;
|
||||||
|
|
||||||
|
if(output_zeros(write_file, num_zeros))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Invalid offset %zd to seek to in %s!\n", offset, output);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Same as total_bytes_written = offset */
|
||||||
|
total_bytes_written += num_zeros;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-a", "--align"))
|
||||||
|
{
|
||||||
|
if(!output)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Need output flag before alignment\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to align flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int align = atoi(argv[i++]);
|
||||||
|
if (align < 4)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Minimum alignment is 4 bytes\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
align_next = align;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-t", "--title"))
|
||||||
|
{
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to title flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * title_arg = argv[i++];
|
||||||
|
size_t title_len = strlen(title_arg);
|
||||||
|
|
||||||
|
if(title_len > TITLE_SIZE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "WARNING: Title will be truncated to %d characters\n", TITLE_SIZE);
|
||||||
|
title_len = TITLE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(title, title_arg, title_len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-C", "--category"))
|
||||||
|
{
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to category flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * category_arg = argv[i++];
|
||||||
|
if(strlen(category_arg) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Category must be a single character\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
category = category_arg[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(check_flag(arg, "-R", "--region"))
|
||||||
|
{
|
||||||
|
if(i >= argc)
|
||||||
|
{
|
||||||
|
/* Expected another argument */
|
||||||
|
fprintf(stderr, "ERROR: Expected an argument to region flag\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * region_arg = argv[i++];
|
||||||
|
if (strlen(region_arg) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Region must be a single character\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
region = region_arg[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Argument is not a flag; treat it as an input file */
|
||||||
|
|
||||||
|
/* Can't copy input file unless header and output set */
|
||||||
|
if(!output)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Need output flag before first file\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is the first input file, open the output file and write the header */
|
||||||
|
if(!write_file)
|
||||||
|
{
|
||||||
|
/* Create or completely overwrite the output file */
|
||||||
|
write_file = fopen(tmp_output, "wb");
|
||||||
|
|
||||||
|
if(!write_file)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Cannot open '%s' for writing\n", output);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to clean up the temporary file if we exit */
|
||||||
|
atexit(remove_tmp_file);
|
||||||
|
|
||||||
|
/* Copy over the ROM header */
|
||||||
|
if (header)
|
||||||
|
{
|
||||||
|
header_size = copy_file(write_file, header);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
header_size = sizeof(default_ipl3);
|
||||||
|
fwrite(default_ipl3, 1, header_size, write_file);
|
||||||
|
if (parse_elf_loadpoint(arg, &elf_loadpoint) < 0)
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header_size < 0x100)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Header file '%s' is too small (minimum is 4096 bytes)\n", header);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HACK. Unfortunately, n64tool handles both --align and --offset with respect
|
||||||
|
to file positions/sizes *excluding* the header. The header used to be of
|
||||||
|
fixed size (4096 bytes), but that's now just a minimum. For full backward
|
||||||
|
compatibility, we still consider the header to always be 4096 bytes, and
|
||||||
|
just offset from there. */
|
||||||
|
total_bytes_written += header_size - 4096;
|
||||||
|
header_size = 4096;
|
||||||
|
|
||||||
|
/* Leave space for the table, if asked to do so. */
|
||||||
|
if(create_toc && !toc_offset)
|
||||||
|
{
|
||||||
|
if (total_bytes_written % TOC_ALIGN)
|
||||||
|
{
|
||||||
|
ssize_t num_zeros = TOC_ALIGN - (total_bytes_written % TOC_ALIGN);
|
||||||
|
output_zeros(write_file, num_zeros);
|
||||||
|
total_bytes_written += num_zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
toc_offset = ftell(write_file);
|
||||||
|
output_zeros(write_file, TOC_SIZE);
|
||||||
|
total_bytes_written += TOC_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (align_next)
|
||||||
|
{
|
||||||
|
if (total_bytes_written % align_next)
|
||||||
|
{
|
||||||
|
ssize_t num_zeros = align_next - (total_bytes_written % align_next);
|
||||||
|
|
||||||
|
if(output_zeros(write_file, num_zeros))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Invalid alignment %d to seek to in %s!\n", align_next, output);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_bytes_written += num_zeros;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset to 16 for next file (default) */
|
||||||
|
align_next = 16;
|
||||||
|
|
||||||
|
size_t offset = ftell(write_file);
|
||||||
|
|
||||||
|
/* Copy the input file into the output file */
|
||||||
|
ssize_t bytes_copied = copy_file(write_file, arg);
|
||||||
|
|
||||||
|
if(bytes_copied < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Unable to copy file from '%s' to '%s'\n", arg, output);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toc.num_entries < TOC_MAX_ENTRIES)
|
||||||
|
{
|
||||||
|
/* Add the file to the toc */
|
||||||
|
toc.files[toc.num_entries].offset = offset;
|
||||||
|
toc.files[toc.num_entries].size = bytes_copied;
|
||||||
|
|
||||||
|
const char *basename = strrchr(arg, '/');
|
||||||
|
if (!basename) basename = strrchr(arg, '\\');
|
||||||
|
if (!basename) basename = arg;
|
||||||
|
if (basename[0] == '/' || basename[0] == '\\') basename++;
|
||||||
|
strlcpy(toc.files[toc.num_entries].name, basename, sizeof(toc.files[toc.num_entries].name));
|
||||||
|
toc.num_entries++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (create_toc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Too many files to add to table.\n");
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Keep track to be sure we align properly when they request a memory alignment */
|
||||||
|
total_bytes_written += bytes_copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!total_bytes_written)
|
||||||
|
{
|
||||||
|
/* Didn't write anything! */
|
||||||
|
printf("ERROR: No input files, nothing written\n\n");
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the declared size is too small, error out */
|
||||||
|
if(declared_size && declared_size < total_bytes_written)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Couldn't fit ROM in %zu bytes as requested.\n", declared_size);
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad the output file to the declared size (not including the IPL3 header) */
|
||||||
|
if(!declared_size) {
|
||||||
|
/* If the user didn't specify a size, initialize this to the minimum
|
||||||
|
size that is padded to the correct alignment. Notice that this variable
|
||||||
|
declares the size WITHOUT header, but the padding refers to the final
|
||||||
|
ROM and so it must be calculated with the header. */
|
||||||
|
if (pad_align)
|
||||||
|
declared_size = ROUND_UP(header_size, pad_align)-header_size;
|
||||||
|
}
|
||||||
|
if(declared_size > total_bytes_written)
|
||||||
|
{
|
||||||
|
ssize_t num_zeros = declared_size - total_bytes_written;
|
||||||
|
|
||||||
|
if(output_zeros(write_file, num_zeros))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Couldn't pad %zu bytes to %zu bytes.\n", total_bytes_written, declared_size);
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(pad_align && ((total_bytes_written+header_size) % pad_align) != 0)
|
||||||
|
{
|
||||||
|
/* Pad size as required. */
|
||||||
|
ssize_t num_zeros = pad_align - ((total_bytes_written+header_size) % pad_align);
|
||||||
|
if(output_zeros(write_file, num_zeros))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Couldn't pad %zu bytes to %zu bytes.\n", total_bytes_written, total_bytes_written+num_zeros);
|
||||||
|
return print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set title in header */
|
||||||
|
fseek(write_file, TITLE_OFFSET, SEEK_SET);
|
||||||
|
fwrite(title, 1, TITLE_SIZE, write_file);
|
||||||
|
|
||||||
|
/* Set category in header */
|
||||||
|
fseek(write_file, CATEGORY_OFFSET, SEEK_SET);
|
||||||
|
fwrite(&category, 1, 1, write_file);
|
||||||
|
|
||||||
|
/* Set region in header */
|
||||||
|
fseek(write_file, REGION_OFFSET, SEEK_SET);
|
||||||
|
fwrite(®ion, 1, 1, write_file);
|
||||||
|
|
||||||
|
/* If we are using libdragon's IPL3, set the entrypoint in the header
|
||||||
|
for iQue to match the first valid loadpoint found in the ELF. This make
|
||||||
|
sure that the iQue OS, in its initial flat-binary loading, will use
|
||||||
|
the same memory region as the ELF. */
|
||||||
|
if (elf_loadpoint != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
elf_loadpoint = SWAPLONG(elf_loadpoint);
|
||||||
|
fseek(write_file, IQUE_ENTRYPOINT_OFFSET, SEEK_SET);
|
||||||
|
fwrite(&elf_loadpoint, 1, 4, write_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write table of contents */
|
||||||
|
if(create_toc)
|
||||||
|
{
|
||||||
|
for (int i=0; i<toc.num_entries; i++) {
|
||||||
|
toc.files[i].offset = SWAPLONG(toc.files[i].offset);
|
||||||
|
toc.files[i].size = SWAPLONG(toc.files[i].size);
|
||||||
|
}
|
||||||
|
toc.toc_size = SWAPLONG(toc.toc_size);
|
||||||
|
toc.num_entries = SWAPSHORT(toc.num_entries);
|
||||||
|
toc.entry_size = SWAPSHORT(toc.entry_size);
|
||||||
|
|
||||||
|
toc_cookie = ~crc32_update(toc_cookie, (uint8_t *)&toc, sizeof(toc));
|
||||||
|
toc.cookie = SWAPLONG(toc_cookie);
|
||||||
|
|
||||||
|
fseek(write_file, toc_offset, SEEK_SET);
|
||||||
|
fwrite(&toc, 1, sizeof(toc), write_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sync and close the output file */
|
||||||
|
fclose(write_file);
|
||||||
|
|
||||||
|
/* Rename to the final name */
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Windows doesn't support atomic renames, so we have to delete the old file first */
|
||||||
|
remove(output);
|
||||||
|
#endif
|
||||||
|
if(rename(tmp_output, output) != 0) {
|
||||||
|
fprintf(stderr, "Couldn't rename temporary output file '%s' to '%s': %s", tmp_output, output, strerror(errno));
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
@ -0,0 +1,412 @@
|
|||||||
|
/*
|
||||||
|
polyfill: mingw32 polyfills for missing C/POSIX functions
|
||||||
|
Written by Giovanni Bajo <giovannibajo@gmail.com>
|
||||||
|
|
||||||
|
This tool is part of the Libdragon SDK.
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
|
#ifndef LIBDRAGON_TOOLS_POLYFILL_H
|
||||||
|
#define LIBDRAGON_TOOLS_POLYFILL_H
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
|
||||||
|
// NOTE: we include both stdio.h and cstdio because both of them will undef
|
||||||
|
// tmpfile and redefine it to something else. Since we want to provide our
|
||||||
|
// own implementation, we need to make sure both are included first, so that
|
||||||
|
// we don't run the risk either of them is included after this file.
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <cstdio>
|
||||||
|
#endif
|
||||||
|
// NOTE: include both assert.h and cassert because we need to make sure
|
||||||
|
// _assert and _wassert are declared properly before we mess with them later.
|
||||||
|
#include <assert.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <cassert>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <share.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if typedef doesn't exist (msvc, blah)
|
||||||
|
typedef intptr_t ssize_t;
|
||||||
|
|
||||||
|
/* Implementation of 'getline' fetched from: https://stackoverflow.com/a/47229318 */
|
||||||
|
/* The original code is public domain -- Will Hartung 4/9/09 */
|
||||||
|
/* Modifications, public domain as well, by Antti Haapala, 11/10/17
|
||||||
|
- Switched to getc on 5/23/19 */
|
||||||
|
__attribute__((used))
|
||||||
|
static ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
|
||||||
|
size_t pos;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (lineptr == NULL || stream == NULL || n == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = getc(stream);
|
||||||
|
if (c == EOF) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*lineptr == NULL) {
|
||||||
|
*lineptr = (char*)malloc(128);
|
||||||
|
if (*lineptr == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*n = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while(c != EOF) {
|
||||||
|
if (pos + 1 >= *n) {
|
||||||
|
size_t new_size = *n + (*n >> 2);
|
||||||
|
if (new_size < 128) {
|
||||||
|
new_size = 128;
|
||||||
|
}
|
||||||
|
char *new_ptr = (char*)realloc(*lineptr, new_size);
|
||||||
|
if (new_ptr == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*n = new_size;
|
||||||
|
*lineptr = new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
((unsigned char *)(*lineptr))[pos ++] = c;
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = getc(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*lineptr)[pos] = '\0';
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide implementation of strndup for MSYS2 environments that are missing it (before April 13 2026).
|
||||||
|
#if defined(MSYS2_RUNTIME_PACMAN_AGE) && MSYS2_RUNTIME_PACMAN_AGE <= 20260413
|
||||||
|
__attribute__((used))
|
||||||
|
static char *msys2_fallback_strndup(const char *s, size_t n)
|
||||||
|
{
|
||||||
|
size_t len = strnlen(s, n);
|
||||||
|
char *ret = (char*)malloc(len + 1);
|
||||||
|
if (!ret) return NULL;
|
||||||
|
memcpy(ret, s, len);
|
||||||
|
ret[len] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef strndup
|
||||||
|
#undef strndup
|
||||||
|
#endif
|
||||||
|
#define strndup msys2_fallback_strndup
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Replace 'assert' so that it has 'noreturn' behaviour on Windows.
|
||||||
|
// (soft reverts this MSYS2 commit: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/ecf2328a328d11dec7044b40b2b5e93b5b2b9d9e/)
|
||||||
|
#if defined(MSYS2_RUNTIME_PACMAN_AGE) && MSYS2_RUNTIME_PACMAN_AGE >= 20260611 && !defined(NDEBUG)
|
||||||
|
|
||||||
|
#if defined(_UNICODE) || defined(UNICODE)
|
||||||
|
|
||||||
|
__attribute__((used)) __attribute__((noreturn))
|
||||||
|
static void msys2_wassert_fix(const wchar_t* _Message, const wchar_t* _File, unsigned _Line)
|
||||||
|
{
|
||||||
|
_wassert(_Message, _File, _Line);
|
||||||
|
abort();
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _wassert(a,b,c) msys2_wassert_fix(a,b,c)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
__attribute__((used)) __attribute__((noreturn))
|
||||||
|
static void msys2_assert_fix(const char* _Message, const char* _File, unsigned _Line)
|
||||||
|
{
|
||||||
|
_assert(_Message, _File, _Line);
|
||||||
|
abort();
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _assert(a,b,c) msys2_assert_fix(a,b,c)
|
||||||
|
|
||||||
|
#endif // defined(_UNICODE) || defined(UNICODE)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ >= 0xE00
|
||||||
|
// UCRT is being used so we can use runtime-provided tmpfile() implementation
|
||||||
|
#else
|
||||||
|
// tmpfile() in MINGW64 is broken for use (it uses MSVCRT that tries to
|
||||||
|
// create a file in C:\, which is non-writable nowadays)
|
||||||
|
#ifdef tmpfile
|
||||||
|
#undef tmpfile
|
||||||
|
#endif
|
||||||
|
#define tmpfile() mingw_tmpfile()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void* HANDLE;
|
||||||
|
typedef const char* LPCSTR;
|
||||||
|
typedef int BOOL;
|
||||||
|
#define INVALID_HANDLE_VALUE ((HANDLE)(long)-1)
|
||||||
|
struct _SECURITY_ATTRIBUTES;
|
||||||
|
|
||||||
|
// Access rights
|
||||||
|
#define GENERIC_READ 0x80000000
|
||||||
|
#define GENERIC_WRITE 0x40000000
|
||||||
|
|
||||||
|
// Share modes
|
||||||
|
#define FILE_SHARE_READ 0x00000001
|
||||||
|
#define FILE_SHARE_WRITE 0x00000002
|
||||||
|
#define FILE_SHARE_DELETE 0x00000004
|
||||||
|
|
||||||
|
// Creation disposition
|
||||||
|
#define CREATE_NEW 1
|
||||||
|
|
||||||
|
// Flags and attributes
|
||||||
|
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
|
||||||
|
#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
|
||||||
|
|
||||||
|
__declspec(dllimport) HANDLE __stdcall CreateFileA(
|
||||||
|
LPCSTR lpFileName,
|
||||||
|
unsigned long dwDesiredAccess,
|
||||||
|
unsigned long dwShareMode,
|
||||||
|
struct _SECURITY_ATTRIBUTES* lpSecurityAttributes,
|
||||||
|
unsigned long dwCreationDisposition,
|
||||||
|
unsigned long dwFlagsAndAttributes,
|
||||||
|
HANDLE hTemplateFile
|
||||||
|
);
|
||||||
|
__declspec(dllimport) int __stdcall CloseHandle(HANDLE);
|
||||||
|
__declspec(dllimport) unsigned long __stdcall GetLastError(void);
|
||||||
|
__declspec(dllimport) unsigned long __stdcall GetTickCount(void);
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static FILE *mingw_tmpfile(void) {
|
||||||
|
static int counter = 0;
|
||||||
|
char path[260];
|
||||||
|
|
||||||
|
for (int i = 0; i < 4096; i++) {
|
||||||
|
// Generate a random filename. Notice we *purposedly* not make this
|
||||||
|
// very random with PID, timestamp, etc. because this is the third
|
||||||
|
// iteration of mingw_tmpfile(): the previous ones were misbehaving
|
||||||
|
// in various ways on various CRTs, Windows versions, etc.
|
||||||
|
// We want this code to be exercised often so that it is robust.
|
||||||
|
snprintf(path, sizeof(path), "mksprite-%04x.tmp", counter++);
|
||||||
|
|
||||||
|
HANDLE h = CreateFileA(
|
||||||
|
path,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
NULL,
|
||||||
|
CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
|
int fd = _open_osfhandle((intptr_t)h, _O_RDWR | _O_BINARY);
|
||||||
|
if (fd == -1) {
|
||||||
|
CloseHandle(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return fdopen(fd, "w+b");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 80 = ERROR_FILE_EXISTS
|
||||||
|
if (GetLastError() != 80)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static char* strcasestr(const char* haystack, const char* needle)
|
||||||
|
{
|
||||||
|
size_t needle_len = strlen(needle);
|
||||||
|
size_t haystack_len = strlen(haystack);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (needle_len > haystack_len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i <= haystack_len - needle_len; i++)
|
||||||
|
{
|
||||||
|
if (strncasecmp(haystack + i, needle, needle_len) == 0)
|
||||||
|
return (char*)(haystack + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation from FreeBSD
|
||||||
|
__attribute__((used))
|
||||||
|
static void *memmem(const void *l, size_t l_len, const void *s, size_t s_len)
|
||||||
|
{
|
||||||
|
char *cur, *last;
|
||||||
|
const char *cl = (const char *)l;
|
||||||
|
const char *cs = (const char *)s;
|
||||||
|
|
||||||
|
/* we need something to compare */
|
||||||
|
if (l_len == 0 || s_len == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* "s" must be smaller or equal to "l" */
|
||||||
|
if (l_len < s_len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* special case where s_len == 1 */
|
||||||
|
if (s_len == 1)
|
||||||
|
return memchr(l, (int)*cs, l_len);
|
||||||
|
|
||||||
|
/* the last position where its possible to find "s" in "l" */
|
||||||
|
last = (char *)cl + l_len - s_len;
|
||||||
|
|
||||||
|
for (cur = (char *)cl; cur <= last; cur++)
|
||||||
|
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
|
||||||
|
return cur;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rename() that ovewrites the destination file
|
||||||
|
#define rename(a,b) mingw_rename(a,b)
|
||||||
|
|
||||||
|
#define MOVEFILE_REPLACE_EXISTING 0x00000001
|
||||||
|
#define MOVEFILE_WRITE_THROUGH 0x00000008
|
||||||
|
|
||||||
|
__declspec(dllimport) int __stdcall MoveFileExA(const char *lpExistingFileName,
|
||||||
|
const char *lpNewFileName,
|
||||||
|
unsigned long dwFlags);
|
||||||
|
__declspec(dllimport) unsigned long __stdcall GetLastError(void);
|
||||||
|
|
||||||
|
static void map_windows_error_to_errno(unsigned long err) {
|
||||||
|
switch (err) {
|
||||||
|
case 2: errno = ENOENT; break; // ERROR_FILE_NOT_FOUND
|
||||||
|
case 3: errno = ENOENT; break; // ERROR_PATH_NOT_FOUND
|
||||||
|
case 5: errno = EACCES; break; // ERROR_ACCESS_DENIED
|
||||||
|
case 32: errno = EBUSY; break; // ERROR_SHARING_VIOLATION
|
||||||
|
case 80: errno = EEXIST; break; // ERROR_FILE_EXISTS
|
||||||
|
case 183: errno = EEXIST; break; // ERROR_ALREADY_EXISTS
|
||||||
|
default: errno = EIO; break; // Generic error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static int mingw_rename(const char *oldpath, const char *newpath) {
|
||||||
|
if (MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
map_windows_error_to_errno(GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POISX mkdir has a mode argument, but mingw's mkdir doesn't
|
||||||
|
#define mkdir(path, mode) mkdir(path)
|
||||||
|
|
||||||
|
typedef struct _PROCESS_BASIC_INFORMATION_MIN {
|
||||||
|
void* Reserved1;
|
||||||
|
void* PebBaseAddress;
|
||||||
|
void* Reserved2[2];
|
||||||
|
void* UniqueProcessId;
|
||||||
|
void* InheritedFromUniqueProcessId;
|
||||||
|
} PROCESS_BASIC_INFORMATION_MIN;
|
||||||
|
|
||||||
|
#define CURRENT_PROCESS ((HANDLE)(intptr_t)-1)
|
||||||
|
|
||||||
|
__declspec(dllimport) long __stdcall NtQueryInformationProcess(
|
||||||
|
HANDLE ProcessHandle, unsigned long ProcessInformationClass,
|
||||||
|
void* ProcessInformation, unsigned long ProcessInformationLength,
|
||||||
|
unsigned long *ReturnLength);
|
||||||
|
|
||||||
|
// Enable long path support in the current process.
|
||||||
|
// This is a hacky workaround for a limitation in Windows where
|
||||||
|
// file paths longer than 260 characters are not supported.
|
||||||
|
// The documented ways involve also setting a registry key, and thus
|
||||||
|
// is not suitable for a tool like this.
|
||||||
|
// This same approach is used by the Go runtime on Windows, so it is
|
||||||
|
// reasonably safe to use it here as well.
|
||||||
|
__attribute__((used))
|
||||||
|
static void enable_peb_long_path_unsafe(void)
|
||||||
|
{
|
||||||
|
PROCESS_BASIC_INFORMATION_MIN pbi; unsigned long retlen;
|
||||||
|
if (NtQueryInformationProcess(CURRENT_PROCESS, 0, &pbi, sizeof(pbi), &retlen) < 0)
|
||||||
|
return;
|
||||||
|
volatile uint8_t *peb = (volatile uint8_t*)pbi.PebBaseAddress;
|
||||||
|
enum { PEB_BITFIELD_OFFSET = 3, IS_LONG_PATH_AWARE_MASK = 0x80 };
|
||||||
|
peb[PEB_BITFIELD_OFFSET] |= (uint8_t)IS_LONG_PATH_AWARE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it was defined, undefine it as there's no limit on path length after the hack above
|
||||||
|
#undef MAX_PATH
|
||||||
|
|
||||||
|
__declspec(dllimport) int __stdcall SetConsoleOutputCP(unsigned int);
|
||||||
|
__declspec(dllimport) int __stdcall SetConsoleCP(unsigned int);
|
||||||
|
__declspec(dllimport) unsigned int __stdcall GetConsoleOutputCP(void);
|
||||||
|
__declspec(dllimport) unsigned int __stdcall GetConsoleCP(void);
|
||||||
|
#define CP_UTF8 65001
|
||||||
|
|
||||||
|
static int old_out_cp = 0;
|
||||||
|
static int old_in_cp = 0;
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static void winconsole_restore(void) {
|
||||||
|
if (old_out_cp)
|
||||||
|
SetConsoleOutputCP(old_out_cp);
|
||||||
|
if (old_in_cp)
|
||||||
|
SetConsoleCP(old_in_cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static void winconsole_utf8(void) {
|
||||||
|
// Enable long path support in the current process
|
||||||
|
enable_peb_long_path_unsafe();
|
||||||
|
|
||||||
|
// Save the current code page
|
||||||
|
old_out_cp = GetConsoleOutputCP();
|
||||||
|
old_in_cp = GetConsoleCP();
|
||||||
|
|
||||||
|
// Enable UTF-8 in the console
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
SetConsoleCP(CP_UTF8);
|
||||||
|
|
||||||
|
atexit(winconsole_restore);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else /* __MINGW32__ */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__((used))
|
||||||
|
static void winconsole_utf8(void) {}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __MINGW32__ */
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
version(2);
|
||||||
|
project_name = "DIGITAL GROVE 64";
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Indentation
|
||||||
|
|
||||||
|
indent_width = "1";
|
||||||
|
default_tab_width = "1";
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Code File Extensions
|
||||||
|
|
||||||
|
patterns =
|
||||||
|
{
|
||||||
|
"*.c",
|
||||||
|
"*.cpp",
|
||||||
|
"*.h",
|
||||||
|
"*.inc",
|
||||||
|
"*.hpp",
|
||||||
|
"*.bat",
|
||||||
|
"*.sh",
|
||||||
|
"*.4coder",
|
||||||
|
"*.glsl",
|
||||||
|
"*.bfs",
|
||||||
|
"*.html",
|
||||||
|
"*.txt",
|
||||||
|
"*.ds",
|
||||||
|
"*.mdesk",
|
||||||
|
"*.asm",
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Omit Patterns
|
||||||
|
|
||||||
|
blacklist_patterns =
|
||||||
|
{
|
||||||
|
".*",
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Load Paths
|
||||||
|
|
||||||
|
paths =
|
||||||
|
{
|
||||||
|
{ .path = ".", .recursive = false, .relative = true, },
|
||||||
|
{ .path = "code", .recursive = true , .relative = true, },
|
||||||
|
{ .path = "notes", .recursive = true , .relative = true, },
|
||||||
|
};
|
||||||
|
|
||||||
|
load_paths =
|
||||||
|
{
|
||||||
|
.win = paths,
|
||||||
|
.linux = paths,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Commands
|
||||||
|
|
||||||
|
commands =
|
||||||
|
{
|
||||||
|
.build_g0_n64 = { .win = "build n64_test clang deploy release", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Default F-Keys
|
||||||
|
|
||||||
|
fkey_command =
|
||||||
|
{
|
||||||
|
.F1 = "build_g0_n64",
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Username Overridden F-Keys
|
||||||
|
|
||||||
|
fkey_command_override =
|
||||||
|
{
|
||||||
|
.rjf =
|
||||||
|
{
|
||||||
|
.F1 = "build_g0_n64",
|
||||||
|
},
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue