DONT USE THIS LIBRARY IF YOU DON'T KNOW HOW TO USE
This commit is contained in:
parent
82cf7d95fe
commit
6c76004761
21
.vscode/c_cpp_properties.json
vendored
Normal file
21
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "3ds",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
//"C:/devkitpro/libnx/include/**",
|
||||
"C:/devkitpro/libctru/include/**",
|
||||
"/opt/devkitpro/libctru/include/**",
|
||||
//"C:/devkitpro/portlibs/switch/include/**",
|
||||
"/opt/devkitpro/portlibs/3ds/include/**",
|
||||
"C:/devkitpro/portlibs/3ds/include/**"
|
||||
],
|
||||
"defines": [],
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
20
3ds.cmake
Normal file
20
3ds.cmake
Normal file
@ -0,0 +1,20 @@
|
||||
#########################################################################################
|
||||
set(DEVKITPRO $ENV{DEVKITPRO})
|
||||
|
||||
set(CMAKE_SYSTEM_NAME "Nintendo 3ds")
|
||||
set(CMAKE_C_COMPILER "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gcc")
|
||||
set(CMAKE_CXX_COMPILER "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-g++")
|
||||
set(CMAKE_AR "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gcc-ar" CACHE STRING "")
|
||||
set(CMAKE_RANLIB "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gcc-ranlib" CACHE STRING "")
|
||||
set(CMAKE_ASM_COMPILER "${DEVKITPRO}/devkitARM/bin/arm-none-eabi-gcc")
|
||||
|
||||
set(ARCH "-march=armv6k -mtune=mpcore -mfloat-abi=hard -mfpu=vfp -mtp=soft -D__3DS__")
|
||||
set(CMAKE_C_FLAGS "${ARCH} -Wall -mword-relocations -O3 -fomit-frame-pointer -ffunction-sections -fdata-sections" CACHE STRING "C flags")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -std=gnu++20" CACHE STRING "C++ flags")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_FIND_ROOT_PATH ${DEVKITPRO}/devkitARM ${DEVKITPRO}/libctru ${DEVKITARM}/portlibs/3ds)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Shared libs not available")
|
||||
|
||||
link_directories(${DEVKITPRO}/libcrtu/lib ${DEVKITPRO}/portlibs/3ds/lib)
|
||||
#########################################################################################
|
14
CMakeLists.txt
Normal file
14
CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(picasso)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-L${DEVKITPRO}/libctru/lib -L${DEVKITPRO}/picaGL/lib -L${DEVKITPRO}/portlibs/3ds/lib -specs=3dsx.specs -Wl,--gc-sections")
|
||||
|
||||
include_directories(${DEVKITPRO}/libctru/include ${DEVKITPRO}/picaGL/include ${DEVKITPRO}/portlibs/3ds/include)
|
||||
add_definitions("-D__3DS__")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC source/picasso_assembler.cpp source/picasso_library.cpp)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include)
|
348
compile
Executable file
348
compile
Executable file
@ -0,0 +1,348 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# 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, 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, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN* | MSYS*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/* | msys/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
43
example/CMakeLists.txt
Normal file
43
example/CMakeLists.txt
Normal file
@ -0,0 +1,43 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(linpicasso_sample)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-L${DEVKITPRO}/libctru/lib -L${DEVKITPRO}/picaGL/lib -L${DEVKITPRO}/portlibs/3ds/lib -specs=3dsx.specs -Wl,--gc-sections")
|
||||
|
||||
include_directories(${DEVKITPRO}/libctru/include ${DEVKITPRO}/picaGL/include ${DEVKITPRO}/portlibs/3ds/include)
|
||||
add_definitions("-D__3DS__")
|
||||
|
||||
|
||||
set(APP_TITLE "${PROJECT_NAME}")
|
||||
set(APP_DESCRIPTION "Example of Lib Picasso")
|
||||
set(APP_AUTHOR "Tobi-D7, tobid7vx")
|
||||
|
||||
#set(APP_ICON "${PROJECT_SOURCE_DIR}/app/icon.png")
|
||||
#set(APP_ROMFS "${PROJECT_SOURCE_DIR}/romfs")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
set(BASE_CTR ON CACHE BOOL "Enable 3ds")
|
||||
add_subdirectory(../ picasso)
|
||||
|
||||
add_executable(${PROJECT_NAME}.elf src/main.cpp)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}.elf PRIVATE src ../include)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}.elf citro2d citro3d ctru m picasso)
|
||||
#"${APP_ICON}"
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.smdh
|
||||
COMMAND smdhtool --create "${APP_TITLE}" "${APP_DESCRIPTION}" "${APP_AUTHOR}" "/opt/devkitpro/libctru/default_icon.png" ${PROJECT_NAME}.smdh
|
||||
DEPENDS ${PROJECT_NAME}.elf
|
||||
)
|
||||
#--romfs=${APP_ROMFS}
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.3dsx
|
||||
COMMAND 3dsxtool ${PROJECT_NAME}.elf ${PROJECT_NAME}.3dsx --smdh=${PROJECT_NAME}.smdh
|
||||
DEPENDS ${PROJECT_NAME}.elf
|
||||
)
|
||||
|
||||
add_custom_target( 3ds ALL
|
||||
DEPENDS ${PROJECT_NAME}.smdh ${PROJECT_NAME}.3dsx
|
||||
)
|
172
example/src/main.cpp
Normal file
172
example/src/main.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
#include <3ds.h>
|
||||
#include <citro3d.h>
|
||||
|
||||
#include <picasso.hpp>
|
||||
|
||||
static const char *const vertShader = R"text(
|
||||
; Example PICA200 vertex shader
|
||||
|
||||
; Uniforms
|
||||
.fvec projection[4]
|
||||
|
||||
; Constants
|
||||
.constf myconst(0.0, 1.0, -1.0, 0.1)
|
||||
.constf myconst2(0.3, 0.0, 0.0, 0.0)
|
||||
.alias zeros myconst.xxxx ; Vector full of zeros
|
||||
.alias ones myconst.yyyy ; Vector full of ones
|
||||
|
||||
; Outputs
|
||||
.out outpos position
|
||||
.out outclr color
|
||||
|
||||
; Inputs (defined as aliases for convenience)
|
||||
.alias inpos v0
|
||||
.alias inclr v1
|
||||
|
||||
.proc main
|
||||
; Force the w component of inpos to be 1.0
|
||||
mov r0.xyz, inpos
|
||||
mov r0.w, ones
|
||||
|
||||
; outpos = projectionMatrix * inpos
|
||||
dp4 outpos.x, projection[0], r0
|
||||
dp4 outpos.y, projection[1], r0
|
||||
dp4 outpos.z, projection[2], r0
|
||||
dp4 outpos.w, projection[3], r0
|
||||
|
||||
; outclr = inclr
|
||||
mov outclr, inclr
|
||||
|
||||
; We're finished
|
||||
end
|
||||
.end
|
||||
)text";
|
||||
|
||||
#define CLEAR_COLOR 0x68B0D8FF
|
||||
|
||||
#define DISPLAY_TRANSFER_FLAGS \
|
||||
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
|
||||
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
|
||||
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
|
||||
|
||||
typedef struct { float x, y, z; } vertex;
|
||||
|
||||
static const vertex vertex_list[] =
|
||||
{
|
||||
{ 200.0f, 200.0f, 0.5f },
|
||||
{ 100.0f, 40.0f, 0.5f },
|
||||
{ 300.0f, 40.0f, 0.5f },
|
||||
};
|
||||
|
||||
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0]))
|
||||
|
||||
static DVLB_s* vshader_dvlb;
|
||||
static shaderProgram_s program;
|
||||
static int uLoc_projection;
|
||||
static C3D_Mtx projection;
|
||||
|
||||
|
||||
static char* vshader_shbin;
|
||||
static int vshader_shbin_size;
|
||||
|
||||
static void* vbo_data;
|
||||
|
||||
static void sceneInit(void)
|
||||
{
|
||||
// Load the vertex shader, create a shader program and bind it
|
||||
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
|
||||
shaderProgramInit(&program);
|
||||
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
|
||||
C3D_BindProgram(&program);
|
||||
|
||||
// Get the location of the uniforms
|
||||
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
|
||||
|
||||
// Configure attributes for use with the vertex shader
|
||||
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
|
||||
AttrInfo_Init(attrInfo);
|
||||
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
|
||||
AttrInfo_AddFixed(attrInfo, 1); // v1=color
|
||||
|
||||
// Set the fixed attribute (color) to solid white
|
||||
C3D_FixedAttribSet(1, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
// Compute the projection matrix
|
||||
Mtx_OrthoTilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0, true);
|
||||
|
||||
// Create the VBO (vertex buffer object)
|
||||
vbo_data = linearAlloc(sizeof(vertex_list));
|
||||
memcpy(vbo_data, vertex_list, sizeof(vertex_list));
|
||||
|
||||
// Configure buffers
|
||||
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
|
||||
BufInfo_Init(bufInfo);
|
||||
BufInfo_Add(bufInfo, vbo_data, sizeof(vertex), 1, 0x0);
|
||||
|
||||
// Configure the first fragment shading substage to just pass through the vertex color
|
||||
// See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0, (GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
|
||||
}
|
||||
|
||||
static void sceneRender(void)
|
||||
{
|
||||
// Update the uniforms
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection);
|
||||
|
||||
// Draw the VBO
|
||||
C3D_DrawArrays(GPU_TRIANGLES, 0, vertex_list_count);
|
||||
}
|
||||
|
||||
static void sceneExit(void)
|
||||
{
|
||||
// Free the VBO
|
||||
linearFree(vbo_data);
|
||||
|
||||
// Free the shader program
|
||||
shaderProgramFree(&program);
|
||||
DVLB_Free(vshader_dvlb);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize graphics
|
||||
gfxInitDefault();
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
vshader_shbin = Pica::AssembleCode(vertShader, vshader_shbin_size);
|
||||
|
||||
// Initialize the render target
|
||||
C3D_RenderTarget* target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
|
||||
// Initialize the scene
|
||||
sceneInit();
|
||||
|
||||
// Main loop
|
||||
while (aptMainLoop())
|
||||
{
|
||||
hidScanInput();
|
||||
|
||||
// Respond to user input
|
||||
u32 kDown = hidKeysDown();
|
||||
if (kDown & KEY_START)
|
||||
break; // break in order to return to hbmenu
|
||||
|
||||
// Render the scene
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
C3D_RenderTargetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0);
|
||||
C3D_FrameDrawOn(target);
|
||||
sceneRender();
|
||||
C3D_FrameEnd(0);
|
||||
}
|
||||
|
||||
// Deinitialize the scene
|
||||
sceneExit();
|
||||
|
||||
// Deinitialize graphics
|
||||
C3D_Fini();
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
9
include/picasso.hpp
Normal file
9
include/picasso.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
//#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace Pica
|
||||
{
|
||||
void InstallErrorCallback(void(*ErrorHandler)(const char* top, const char* message));
|
||||
char* AssembleCode(const char* vertex, int &res_size);
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
|
||||
class FileClass
|
||||
{
|
||||
FILE* f;
|
||||
bool LittleEndian, own;
|
||||
int filePos;
|
||||
|
||||
size_t _RawRead(void* buffer, size_t size)
|
||||
{
|
||||
size_t x = fread(buffer, 1, size, f);
|
||||
filePos += x;
|
||||
return x;
|
||||
}
|
||||
|
||||
size_t _RawWrite(const void* buffer, size_t size)
|
||||
{
|
||||
size_t x = fwrite(buffer, 1, size, f);
|
||||
filePos += x;
|
||||
return x;
|
||||
}
|
||||
|
||||
public:
|
||||
FileClass(const char* file, const char* mode) : LittleEndian(true), own(true), filePos(0)
|
||||
{
|
||||
f = fopen(file, mode);
|
||||
}
|
||||
FileClass(FILE* inf) : f(inf), LittleEndian(true), own(false), filePos(0) { }
|
||||
~FileClass()
|
||||
{
|
||||
if (f && own) fclose(f);
|
||||
}
|
||||
|
||||
void SetLittleEndian() { LittleEndian = true; }
|
||||
void SetBigEndian() { LittleEndian = false; }
|
||||
|
||||
FILE* get_ptr() { return f; }
|
||||
bool openerror() { return f == NULL; }
|
||||
|
||||
dword_t ReadDword()
|
||||
{
|
||||
dword_t value;
|
||||
_RawRead(&value, sizeof(dword_t));
|
||||
return LittleEndian ? le_dword(value) : be_dword(value);
|
||||
}
|
||||
|
||||
void WriteDword(dword_t value)
|
||||
{
|
||||
value = LittleEndian ? le_dword(value) : be_dword(value);
|
||||
_RawWrite(&value, sizeof(dword_t));
|
||||
}
|
||||
|
||||
word_t ReadWord()
|
||||
{
|
||||
word_t value;
|
||||
_RawRead(&value, sizeof(word_t));
|
||||
return LittleEndian ? le_word(value) : be_word(value);
|
||||
}
|
||||
|
||||
void WriteWord(word_t value)
|
||||
{
|
||||
value = LittleEndian ? le_word(value) : be_word(value);
|
||||
_RawWrite(&value, sizeof(word_t));
|
||||
}
|
||||
|
||||
hword_t ReadHword()
|
||||
{
|
||||
hword_t value;
|
||||
_RawRead(&value, sizeof(hword_t));
|
||||
return LittleEndian ? le_hword(value) : be_hword(value);
|
||||
}
|
||||
|
||||
void WriteHword(hword_t value)
|
||||
{
|
||||
value = LittleEndian ? le_hword(value) : be_hword(value);
|
||||
_RawWrite(&value, sizeof(hword_t));
|
||||
}
|
||||
|
||||
byte_t ReadByte()
|
||||
{
|
||||
byte_t value;
|
||||
_RawRead(&value, sizeof(byte_t));
|
||||
return value;
|
||||
}
|
||||
|
||||
void WriteByte(byte_t value)
|
||||
{
|
||||
_RawWrite(&value, sizeof(byte_t));
|
||||
}
|
||||
|
||||
float ReadFloat()
|
||||
{
|
||||
union { word_t w; float f; } t;
|
||||
t.w = ReadWord();
|
||||
return t.f;
|
||||
}
|
||||
|
||||
void WriteFloat(float value)
|
||||
{
|
||||
union { word_t w; float f; } t;
|
||||
t.f = value;
|
||||
WriteWord(t.w);
|
||||
}
|
||||
|
||||
bool ReadRaw(void* buffer, size_t size) { return _RawRead(buffer, size) == size; }
|
||||
bool WriteRaw(const void* buffer, size_t size) { return _RawWrite(buffer, size) == size; }
|
||||
|
||||
void Seek(int pos, int mode) { fseek(f, pos, mode); }
|
||||
int Tell() { return filePos /*ftell(f)*/; }
|
||||
void Flush() { fflush(f); }
|
||||
};
|
||||
|
||||
static inline char* StringFromFile(const char* filename)
|
||||
{
|
||||
FILE* f = fopen(filename, "rb");
|
||||
if (!f) return NULL;
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
rewind(f);
|
||||
char* buf = (char*)malloc(size+1);
|
||||
if (!buf)
|
||||
{
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
fread(buf, 1, size, f);
|
||||
buf[size] = 0;
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
enum
|
||||
{
|
||||
MAESTRO_ADD = 0x00,
|
||||
MAESTRO_DP3,
|
||||
MAESTRO_DP4,
|
||||
MAESTRO_DPH,
|
||||
MAESTRO_DST,
|
||||
MAESTRO_EX2,
|
||||
MAESTRO_LG2,
|
||||
MAESTRO_LITP,
|
||||
MAESTRO_MUL,
|
||||
MAESTRO_SGE,
|
||||
MAESTRO_SLT,
|
||||
MAESTRO_FLR,
|
||||
MAESTRO_MAX,
|
||||
MAESTRO_MIN,
|
||||
MAESTRO_RCP,
|
||||
MAESTRO_RSQ,
|
||||
|
||||
MAESTRO_unk10,
|
||||
MAESTRO_unk11,
|
||||
MAESTRO_MOVA,
|
||||
MAESTRO_MOV,
|
||||
MAESTRO_unk14,
|
||||
MAESTRO_unk15,
|
||||
MAESTRO_unk16,
|
||||
MAESTRO_unk17,
|
||||
MAESTRO_DPHI,
|
||||
MAESTRO_DSTI,
|
||||
MAESTRO_SGEI,
|
||||
MAESTRO_SLTI,
|
||||
MAESTRO_unk1C,
|
||||
MAESTRO_unk1D,
|
||||
MAESTRO_unk1E,
|
||||
MAESTRO_unk1F,
|
||||
|
||||
MAESTRO_BREAK,
|
||||
MAESTRO_NOP,
|
||||
MAESTRO_END,
|
||||
MAESTRO_BREAKC,
|
||||
MAESTRO_CALL,
|
||||
MAESTRO_CALLC,
|
||||
MAESTRO_CALLU,
|
||||
MAESTRO_IFU,
|
||||
MAESTRO_IFC,
|
||||
MAESTRO_FOR,
|
||||
MAESTRO_EMIT, // Geometry shader related
|
||||
MAESTRO_SETEMIT, // Geometry shader related
|
||||
MAESTRO_JMPC,
|
||||
MAESTRO_JMPU,
|
||||
MAESTRO_CMP, // only the upper 5 bits are used for the opcode
|
||||
|
||||
// Only the upper 3 bits are used for the following opcodes
|
||||
MAESTRO_MADI = 0x30,
|
||||
MAESTRO_MAD = 0x38,
|
||||
};
|
256
source/picasso.h
256
source/picasso.h
@ -1,256 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <getopt.h>
|
||||
#ifdef WIN32
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "types.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "FileClass.h"
|
||||
|
||||
#include "maestro_opcodes.h"
|
||||
|
||||
#if !defined(WIN32) && !defined(stricmp)
|
||||
#define stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
COMP_X = 0,
|
||||
COMP_Y,
|
||||
COMP_Z,
|
||||
COMP_W,
|
||||
};
|
||||
|
||||
#define SWIZZLE_COMP(n,v) ((v) << (6-(n)*2))
|
||||
#define OPSRC_MAKE(neg, sw) ((neg) | ((sw) << 1))
|
||||
#define OPDESC_MAKE(out, src1, src2, src3) ((out) | ((src1) << 4) | ((src2) << (4+9)) | ((src3) << (4+9*2)))
|
||||
#define FMT_OPCODE(n) ((n)<<26)
|
||||
#define OUTPUT_MAKE(i, reg, mask) ((i) | ((reg)<<16) | ((u64)(mask)<<32))
|
||||
|
||||
#define DEFAULT_SWIZZLE (SWIZZLE_COMP(0,COMP_X) | SWIZZLE_COMP(1,COMP_Y) | SWIZZLE_COMP(2,COMP_Z) | SWIZZLE_COMP(3,COMP_W))
|
||||
#define DEFAULT_OPSRC OPSRC_MAKE(0, DEFAULT_SWIZZLE)
|
||||
|
||||
#define OPDESC_MASK_D123 OPDESC_MAKE(0xF, 0x1FF, 0x1FF, 0x1FF)
|
||||
#define OPDESC_MASK_D12 OPDESC_MAKE(0xF, 0x1FF, 0x1FF, 0)
|
||||
#define OPDESC_MASK_D1 OPDESC_MAKE(0xF, 0x1FF, 0, 0)
|
||||
#define OPDESC_MASK_1 OPDESC_MAKE(0, 0x1FF, 0, 0)
|
||||
#define OPDESC_MASK_12 OPDESC_MAKE(0, 0x1FF, 0x1FF, 0)
|
||||
|
||||
enum
|
||||
{
|
||||
COND_EQ = 0,
|
||||
COND_NE,
|
||||
COND_LT,
|
||||
COND_LE,
|
||||
COND_GT,
|
||||
COND_GE,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Global data
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Output buffer
|
||||
#define MAX_VSH_SIZE 512
|
||||
typedef std::vector<u32> outputBufType;
|
||||
typedef outputBufType::iterator outputBufIter;
|
||||
extern outputBufType g_outputBuf;
|
||||
|
||||
enum
|
||||
{
|
||||
SE_PROC,
|
||||
SE_FOR,
|
||||
SE_IF,
|
||||
SE_ARRAY,
|
||||
};
|
||||
|
||||
struct StackEntry
|
||||
{
|
||||
int type;
|
||||
size_t pos;
|
||||
union
|
||||
{
|
||||
const char* strExtra;
|
||||
size_t uExtra;
|
||||
};
|
||||
};
|
||||
|
||||
// Stack used to keep track of stuff.
|
||||
#define MAX_STACK 32
|
||||
extern StackEntry g_stack[MAX_STACK];
|
||||
extern int g_stackPos;
|
||||
|
||||
// Operand descriptor stuff.
|
||||
#define MAX_OPDESC 128
|
||||
extern int g_opdescTable[MAX_OPDESC];
|
||||
extern int g_opdeskMasks[MAX_OPDESC]; // used to keep track of used bits
|
||||
extern int g_opdescCount;
|
||||
|
||||
enum
|
||||
{
|
||||
UTYPE_BOOL = 0,
|
||||
UTYPE_IVEC,
|
||||
UTYPE_FVEC,
|
||||
};
|
||||
|
||||
struct Uniform
|
||||
{
|
||||
std::string name;
|
||||
int pos, size;
|
||||
int type;
|
||||
|
||||
inline bool operator <(const Uniform& rhs) const
|
||||
{
|
||||
return pos < rhs.pos;
|
||||
}
|
||||
|
||||
void init(const char* name, int pos, int size, int type)
|
||||
{
|
||||
this->name = name;
|
||||
this->pos = pos;
|
||||
this->size = size;
|
||||
this->type = type;
|
||||
}
|
||||
};
|
||||
|
||||
// List of uniforms
|
||||
#define MAX_UNIFORM 0x60
|
||||
extern Uniform g_uniformTable[MAX_UNIFORM];
|
||||
extern int g_uniformCount;
|
||||
|
||||
struct DVLEData; // Forward declaration
|
||||
|
||||
typedef std::pair<size_t, size_t> procedure; // position, size
|
||||
typedef std::pair<size_t, std::string> relocation; // position, name
|
||||
|
||||
typedef std::map<std::string, procedure> procTableType;
|
||||
typedef std::map<std::string, size_t> labelTableType;
|
||||
typedef std::map<std::string, int> aliasTableType;
|
||||
typedef std::vector<relocation> relocTableType;
|
||||
typedef std::list<DVLEData> dvleTableType;
|
||||
|
||||
typedef procTableType::iterator procTableIter;
|
||||
typedef labelTableType::iterator labelTableIter;
|
||||
typedef aliasTableType::iterator aliasTableIter;
|
||||
typedef relocTableType::iterator relocTableIter;
|
||||
typedef dvleTableType::iterator dvleTableIter;
|
||||
|
||||
extern procTableType g_procTable;
|
||||
extern dvleTableType g_dvleTable;
|
||||
extern relocTableType g_procRelocTable;
|
||||
extern int g_totalDvleCount;
|
||||
|
||||
// The following are cleared before each file is processed
|
||||
extern labelTableType g_labels;
|
||||
extern relocTableType g_labelRelocTable;
|
||||
extern aliasTableType g_aliases;
|
||||
|
||||
extern bool g_autoNop;
|
||||
|
||||
int AssembleString(char* str, const char* initialFilename);
|
||||
int RelocateProduct(void);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local data
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
OUTTYPE_POS = 0,
|
||||
OUTTYPE_NQUAT = 1,
|
||||
OUTTYPE_CLR = 2,
|
||||
OUTTYPE_TCOORD0 = 3,
|
||||
OUTTYPE_TCOORD0W = 4,
|
||||
OUTTYPE_TCOORD1 = 5,
|
||||
OUTTYPE_TCOORD2 = 6,
|
||||
OUTTYPE_VIEW = 8,
|
||||
OUTTYPE_DUMMY = 9,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GSHTYPE_POINT = 0,
|
||||
GSHTYPE_VARIABLE = 1,
|
||||
GSHTYPE_FIXED = 2,
|
||||
};
|
||||
|
||||
struct Constant
|
||||
{
|
||||
int regId;
|
||||
int type;
|
||||
union
|
||||
{
|
||||
float fparam[4];
|
||||
u8 iparam[4];
|
||||
bool bparam;
|
||||
};
|
||||
};
|
||||
|
||||
struct DVLEData
|
||||
{
|
||||
// General config
|
||||
std::string filename;
|
||||
std::string entrypoint;
|
||||
size_t entryStart, entryEnd;
|
||||
bool nodvle, isGeoShader, isCompatGeoShader, isMerge;
|
||||
u16 inputMask, outputMask;
|
||||
u8 geoShaderType;
|
||||
u8 geoShaderFixedStart;
|
||||
u8 geoShaderVariableNum;
|
||||
u8 geoShaderFixedNum;
|
||||
|
||||
// Uniforms
|
||||
Uniform uniformTable[MAX_UNIFORM];
|
||||
int uniformCount;
|
||||
size_t symbolSize;
|
||||
|
||||
// Constants
|
||||
#define MAX_CONSTANT 0x60
|
||||
Constant constantTable[MAX_CONSTANT];
|
||||
int constantCount;
|
||||
|
||||
// Outputs
|
||||
#define MAX_OUTPUT 16
|
||||
u64 outputTable[MAX_OUTPUT];
|
||||
u32 outputUsedReg;
|
||||
int outputCount;
|
||||
|
||||
bool usesGshSpace() const { return isGeoShader && !isCompatGeoShader; }
|
||||
int findFreeOutput() const
|
||||
{
|
||||
for (int i = 0; i < maxOutputReg(); i ++)
|
||||
if (!(outputMask & BIT(i)))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int findFreeInput() const
|
||||
{
|
||||
for (int i = 0; i < 16; i ++)
|
||||
if (!(inputMask & BIT(i)))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int maxOutputReg() const
|
||||
{
|
||||
return isGeoShader ? 0x07 : 0x10;
|
||||
}
|
||||
|
||||
DVLEData(const char* filename) :
|
||||
filename(filename), entrypoint("main"),
|
||||
nodvle(false), isGeoShader(false), isCompatGeoShader(false), isMerge(false),
|
||||
inputMask(0), outputMask(0), geoShaderType(0), geoShaderFixedStart(0), geoShaderVariableNum(0), geoShaderFixedNum(0),
|
||||
uniformCount(0), symbolSize(0), constantCount(0), outputUsedReg(0), outputCount(0) { }
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
#include "picasso.h"
|
||||
#include <picasso/picasso.h>
|
||||
|
||||
//#define DEBUG
|
||||
#define BUF g_outputBuf
|
||||
|
192
source/picasso_library.cpp
Normal file
192
source/picasso_library.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
#include <picasso.hpp>
|
||||
#include <picasso/picasso.h>
|
||||
// f24 has:
|
||||
// - 1 sign bit
|
||||
// - 7 exponent bits
|
||||
// - 16 mantissa bits
|
||||
uint32_t f32tof24(float f) {
|
||||
uint32_t i;
|
||||
memcpy(&i, &f, sizeof(f));
|
||||
|
||||
uint32_t mantissa = (i << 9) >> 9;
|
||||
int32_t exponent = (i << 1) >> 24;
|
||||
uint32_t sign = (i << 0) >> 31;
|
||||
|
||||
// Truncate mantissa
|
||||
mantissa >>= 7;
|
||||
|
||||
// Re-bias exponent
|
||||
exponent = exponent - 127 + 63;
|
||||
if (exponent < 0) {
|
||||
// Underflow: flush to zero
|
||||
return sign << 23;
|
||||
} else if (exponent > 0x7F) {
|
||||
// Overflow: saturate to infinity
|
||||
return (sign << 23) | (0x7F << 16);
|
||||
}
|
||||
|
||||
return (sign << 23) | (exponent << 16) | mantissa;
|
||||
}
|
||||
|
||||
void BasicHandler(const char *top, const char *message)
|
||||
{
|
||||
std::cout << top << std::endl << message << std::endl;
|
||||
}
|
||||
|
||||
static void (*EHND)(const char *top, const char *message) = BasicHandler;
|
||||
|
||||
namespace Pica {
|
||||
|
||||
void InstallErrorCallback(void (*ErrorHandler)(const char *top,
|
||||
const char *message)) {
|
||||
EHND = ErrorHandler;
|
||||
}
|
||||
|
||||
char *AssembleCode(const char *vertex, int &res_size) {
|
||||
int rc = 0;
|
||||
rc = AssembleString((char *)vertex, "llc_npi");
|
||||
if (rc) {
|
||||
EHND("Error when Assembling Code", vertex);
|
||||
}
|
||||
|
||||
rc = RelocateProduct();
|
||||
if (rc) {
|
||||
EHND("Error when Relocating Product", "0");
|
||||
}
|
||||
FileClass f("Dont Care", "wb");
|
||||
|
||||
u32 progSize = g_outputBuf.size();
|
||||
u32 dvlpSize = 10 * 4 + progSize * 4 + g_opdescCount * 8;
|
||||
|
||||
// Write DVLB header
|
||||
f.WriteWord(0x424C5644); // DVLB
|
||||
f.WriteWord(g_totalDvleCount); // Number of DVLEs
|
||||
|
||||
// Calculate and write DVLE offsets
|
||||
u32 curOff = 2 * 4 + g_totalDvleCount * 4 + dvlpSize;
|
||||
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end();
|
||||
++dvle) {
|
||||
if (dvle->nodvle)
|
||||
continue;
|
||||
f.WriteWord(curOff);
|
||||
curOff += 16 * 4; // Header
|
||||
curOff += dvle->constantCount * 20;
|
||||
curOff += dvle->outputCount * 8;
|
||||
curOff += dvle->uniformCount * 8;
|
||||
curOff += dvle->symbolSize;
|
||||
curOff = (curOff + 3) & ~3; // Word alignment
|
||||
}
|
||||
|
||||
// Write DVLP header
|
||||
f.WriteWord(0x504C5644); // DVLP
|
||||
f.WriteWord(0); // version
|
||||
f.WriteWord(10 * 4); // offset to shader binary blob
|
||||
f.WriteWord(progSize); // size of shader binary blob
|
||||
f.WriteWord(10 * 4 + progSize * 4); // offset to opdesc table
|
||||
f.WriteWord(g_opdescCount); // number of opdescs
|
||||
f.WriteWord(dvlpSize); // offset to symtable (TODO)
|
||||
f.WriteWord(0); // ????
|
||||
f.WriteWord(0); // ????
|
||||
f.WriteWord(0); // ????
|
||||
|
||||
// Write program
|
||||
for (outputBufIter it = g_outputBuf.begin(); it != g_outputBuf.end(); ++it)
|
||||
f.WriteWord(*it);
|
||||
|
||||
// Write opdescs
|
||||
for (int i = 0; i < g_opdescCount; i++)
|
||||
f.WriteDword(g_opdescTable[i]);
|
||||
|
||||
// Write DVLEs
|
||||
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end();
|
||||
++dvle) {
|
||||
if (dvle->nodvle)
|
||||
continue;
|
||||
curOff = 16 * 4;
|
||||
|
||||
f.WriteWord(0x454C5644); // DVLE
|
||||
f.WriteHword(0x1002); // maybe version?
|
||||
f.WriteByte(dvle->isGeoShader ? 1 : 0); // Shader type
|
||||
f.WriteByte(dvle->isMerge ? 1 : 0);
|
||||
f.WriteWord(dvle->entryStart); // offset to main
|
||||
f.WriteWord(dvle->entryEnd); // offset to end of main
|
||||
f.WriteHword(dvle->inputMask);
|
||||
f.WriteHword(dvle->outputMask);
|
||||
f.WriteByte(dvle->geoShaderType);
|
||||
f.WriteByte(dvle->geoShaderFixedStart);
|
||||
f.WriteByte(dvle->geoShaderVariableNum);
|
||||
f.WriteByte(dvle->geoShaderFixedNum);
|
||||
f.WriteWord(curOff); // offset to constant table
|
||||
f.WriteWord(dvle->constantCount); // size of constant table
|
||||
curOff += dvle->constantCount * 5 * 4;
|
||||
f.WriteWord(curOff); // offset to label table (TODO)
|
||||
f.WriteWord(0); // size of label table (TODO)
|
||||
f.WriteWord(curOff); // offset to output table
|
||||
f.WriteWord(dvle->outputCount); // size of output table
|
||||
curOff += dvle->outputCount * 8;
|
||||
f.WriteWord(curOff); // offset to uniform table
|
||||
f.WriteWord(dvle->uniformCount); // size of uniform table
|
||||
curOff += dvle->uniformCount * 8;
|
||||
f.WriteWord(curOff); // offset to symbol table
|
||||
f.WriteWord(dvle->symbolSize); // size of symbol table
|
||||
|
||||
// Sort uniforms by position
|
||||
std::sort(dvle->uniformTable, dvle->uniformTable + dvle->uniformCount);
|
||||
|
||||
// Write constants
|
||||
for (int i = 0; i < dvle->constantCount; i++) {
|
||||
Constant &ct = dvle->constantTable[i];
|
||||
f.WriteHword(ct.type);
|
||||
if (ct.type == UTYPE_FVEC) {
|
||||
f.WriteHword(ct.regId - 0x20);
|
||||
for (int j = 0; j < 4; j++)
|
||||
f.WriteWord(f32tof24(ct.fparam[j]));
|
||||
} else if (ct.type == UTYPE_IVEC) {
|
||||
f.WriteHword(ct.regId - 0x80);
|
||||
for (int j = 0; j < 4; j++)
|
||||
f.WriteByte(ct.iparam[j]);
|
||||
} else if (ct.type == UTYPE_BOOL) {
|
||||
f.WriteHword(ct.regId - 0x88);
|
||||
f.WriteWord(ct.bparam ? 1 : 0);
|
||||
}
|
||||
if (ct.type != UTYPE_FVEC)
|
||||
for (int j = 0; j < 3; j++)
|
||||
f.WriteWord(0); // Padding
|
||||
}
|
||||
|
||||
// Write outputs
|
||||
for (int i = 0; i < dvle->outputCount; i++)
|
||||
f.WriteDword(dvle->outputTable[i]);
|
||||
|
||||
// Write uniforms
|
||||
size_t sp = 0;
|
||||
for (int i = 0; i < dvle->uniformCount; i++) {
|
||||
Uniform &u = dvle->uniformTable[i];
|
||||
size_t l = u.name.length() + 1;
|
||||
f.WriteWord(sp);
|
||||
sp += l;
|
||||
int pos = u.pos;
|
||||
if (pos >= 0x20)
|
||||
pos -= 0x10;
|
||||
f.WriteHword(pos);
|
||||
f.WriteHword(pos + u.size - 1);
|
||||
}
|
||||
|
||||
// Write symbols
|
||||
for (int i = 0; i < dvle->uniformCount; i++) {
|
||||
std::string u(dvle->uniformTable[i].name);
|
||||
std::replace(u.begin(), u.end(), '$', '.');
|
||||
size_t l = u.length() + 1;
|
||||
f.WriteRaw(u.c_str(), l);
|
||||
}
|
||||
|
||||
// Word alignment
|
||||
int pos = f.Tell();
|
||||
int pad = ((pos + 3) & ~3) - pos;
|
||||
for (int i = 0; i < pad; i++)
|
||||
f.WriteByte(0);
|
||||
}
|
||||
res_size = f.Tell();
|
||||
return (char *)f.get_ptr()->str().c_str();
|
||||
}
|
||||
} // namespace Pica
|
@ -1,68 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t dword_t;
|
||||
typedef uint32_t word_t;
|
||||
typedef uint16_t hword_t;
|
||||
typedef uint8_t byte_t;
|
||||
typedef int64_t dlong_t;
|
||||
typedef int32_t long_t;
|
||||
typedef int16_t short_t;
|
||||
typedef int8_t char_t;
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint8_t u8;
|
||||
|
||||
#define BIT(n) (1U << (n))
|
||||
|
||||
#ifndef __BYTE_ORDER__
|
||||
#include <sys/param.h>
|
||||
#define __BYTE_ORDER__ BYTE_ORDER
|
||||
#define __ORDER_LITTLE_ENDIAN__ LITTLE_ENDIAN
|
||||
#define __ORDER_BIG_ENDIAN__ BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifndef __llvm__
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
|
||||
|
||||
static inline uint16_t __builtin_bswap16(uint16_t x)
|
||||
{
|
||||
return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
|
||||
static inline uint32_t __builtin_bswap32(uint32_t x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000) |
|
||||
((x << 8) & 0x00ff0000) |
|
||||
((x >> 8) & 0x0000ff00) |
|
||||
((x >> 24) & 0x000000ff);
|
||||
}
|
||||
|
||||
static inline uint64_t __builtin_bswap64(uint64_t x)
|
||||
{
|
||||
return (uint64_t)__builtin_bswap32(x>>32) |
|
||||
((uint64_t)__builtin_bswap32(x&0xFFFFFFFF) << 32);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define be_dword(a) __builtin_bswap64(a)
|
||||
#define be_word(a) __builtin_bswap32(a)
|
||||
#define be_hword(a) __builtin_bswap16(a)
|
||||
#define le_dword(a) (a)
|
||||
#define le_word(a) (a)
|
||||
#define le_hword(a) (a)
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define be_dword(a) (a)
|
||||
#define be_word(a) (a)
|
||||
#define be_hword(a) (a)
|
||||
#define le_dword(a) __builtin_bswap64(a)
|
||||
#define le_word(a) __builtin_bswap32(a)
|
||||
#define le_hword(a) __builtin_bswap16(a)
|
||||
#else
|
||||
#error "What's the endianness of the platform you're targeting?"
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user