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 DEBUG
|
||||||
#define BUF g_outputBuf
|
#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