mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
Added missing dependicies
This commit is contained in:
parent
03baa21c10
commit
ebcd9f00ed
47 changed files with 18405 additions and 0 deletions
6
libs/3ds_portlibs/.gitignore
vendored
Normal file
6
libs/3ds_portlibs/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
freetype-*
|
||||
libexif-*
|
||||
libjpeg-*
|
||||
libpng-*
|
||||
sqlite-*
|
||||
zlib-*
|
||||
150
libs/3ds_portlibs/Makefile
Normal file
150
libs/3ds_portlibs/Makefile
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
FREETYPE := freetype
|
||||
FREETYPE_VERSION := $(FREETYPE)-2.6
|
||||
FREETYPE_SRC := $(FREETYPE_VERSION).tar.bz2
|
||||
FREETYPE_DOWNLOAD := "http://download.savannah.gnu.org/releases/freetype/freetype-2.6.tar.bz2"
|
||||
|
||||
LIBEXIF := libexif
|
||||
LIBEXIF_VERSION := $(LIBEXIF)-0.6.21
|
||||
LIBEXIF_SRC := $(LIBEXIF_VERSION).tar.bz2
|
||||
LIBEXIF_DOWNLOAD := "http://sourceforge.net/projects/libexif/files/libexif/0.6.21/libexif-0.6.21.tar.bz2"
|
||||
|
||||
LIBJPEGTURBO := libjpeg-turbo
|
||||
LIBJPEGTURBO_VERSION := $(LIBJPEGTURBO)-1.4.1
|
||||
LIBJPEGTURBO_SRC := $(LIBJPEGTURBO_VERSION).tar.gz
|
||||
LIBJPEGTURBO_DOWNLOAD := "http://sourceforge.net/projects/libjpeg-turbo/files/1.4.1/libjpeg-turbo-1.4.1.tar.gz"
|
||||
|
||||
LIBPNG := libpng
|
||||
LIBPNG_VERSION := $(LIBPNG)-1.6.17
|
||||
LIBPNG_SRC := $(LIBPNG_VERSION).tar.xz
|
||||
LIBPNG_DOWNLOAD := "http://prdownloads.sourceforge.net/libpng/libpng-1.6.17.tar.xz"
|
||||
|
||||
SQLITE := sqlite
|
||||
SQLITE_VERSION := $(SQLITE)-autoconf-3081002
|
||||
SQLITE_SRC := $(SQLITE_VERSION).tar.gz
|
||||
SQLITE_DOWNLOAD := "http://www.sqlite.org/2015/sqlite-autoconf-3081002.tar.gz"
|
||||
|
||||
ZLIB := zlib
|
||||
ZLIB_VERSION := $(ZLIB)-1.2.8
|
||||
ZLIB_SRC := $(ZLIB_VERSION).tar.gz
|
||||
ZLIB_DOWNLOAD := "http://prdownloads.sourceforge.net/libpng/zlib-1.2.8.tar.gz"
|
||||
|
||||
export PORTLIBS := $(CURDIR)/build
|
||||
export PATH := $(DEVKITARM)/bin:$(PATH)
|
||||
export PKG_CONFIG_PATH := $(PORTLIBS)/lib/pkgconfig
|
||||
export CFLAGS := -march=armv6k -mtune=mpcore -mfloat-abi=hard -O3 \
|
||||
-mword-relocations -fomit-frame-pointer -ffast-math
|
||||
export CPPFLAGS := -I$(PORTLIBS)/include
|
||||
export LDFLAGS := -L$(PORTLIBS)/lib
|
||||
|
||||
.PHONY: all old_all install install-zlib clean \
|
||||
$(FREETYPE) \
|
||||
$(LIBEXIF) \
|
||||
$(LIBJPEGTURBO) \
|
||||
$(LIBPNG) \
|
||||
$(SQLITE) \
|
||||
$(ZLIB)
|
||||
all: zlib install-zlib freetype libexif libjpeg-turbo libpng sqlite install
|
||||
@echo "Finished!"
|
||||
|
||||
create_build_dir:
|
||||
@[ -d $(CURDIR)/build ] || mkdir -p $(CURDIR)/build
|
||||
@[ -d $(CURDIR)/build/include ] || mkdir -p $(CURDIR)/build/include
|
||||
@[ -d $(CURDIR)/build/lib ] || mkdir -p $(CURDIR)/build/lib
|
||||
|
||||
old_all:
|
||||
@echo "Please choose one of the following targets:"
|
||||
@echo " $(FREETYPE) (requires zlib to be installed)"
|
||||
@echo " $(LIBEXIF)"
|
||||
@echo " $(LIBJPEGTURBO)"
|
||||
@echo " $(LIBPNG) (requires zlib to be installed)"
|
||||
@echo " $(SQLITE)"
|
||||
@echo " $(ZLIB)"
|
||||
|
||||
$(FREETYPE): $(FREETYPE_SRC)
|
||||
@[ -d $(FREETYPE_VERSION) ] || tar -xf $<
|
||||
@cd $(FREETYPE_VERSION) && \
|
||||
./configure --prefix=$(PORTLIBS) --host=arm-none-eabi --disable-shared --enable-static --without-harfbuzz
|
||||
@$(MAKE) -C $(FREETYPE_VERSION)
|
||||
@make create_build_dir
|
||||
@cp -srf $(CURDIR)/freetype-2.6/include/. $(CURDIR)/build/include
|
||||
@cp -sf $(CURDIR)/freetype-2.6/objs/.libs/libfreetype.a $(CURDIR)/build/lib/libfreetype.a
|
||||
|
||||
$(LIBEXIF): $(LIBEXIF_SRC)
|
||||
@[ -d $(LIBEXIF_VERSION) ] || tar -xf $<
|
||||
@cd $(LIBEXIF_VERSION) && \
|
||||
./configure --prefix=$(PORTLIBS) --host=arm-none-eabi --disable-shared --enable-static
|
||||
@$(MAKE) -C $(LIBEXIF_VERSION)
|
||||
|
||||
$(LIBJPEGTURBO): $(LIBJPEGTURBO_SRC)
|
||||
@[ -d $(LIBJPEGTURBO_VERSION) ] || tar -xf $<
|
||||
@cd $(LIBJPEGTURBO_VERSION) && \
|
||||
./configure --prefix=$(PORTLIBS) --host=arm-none-eabi --disable-shared --enable-static
|
||||
@$(MAKE) CFLAGS+="\"-Drandom()=rand()\"" -C $(LIBJPEGTURBO_VERSION)
|
||||
@make create_build_dir
|
||||
@cp -sf $(CURDIR)/libjpeg-turbo-*/*.h $(CURDIR)/build/include
|
||||
@cp -sf $(CURDIR)/libjpeg-turbo-*/.libs/libjpeg.a $(CURDIR)/build/lib/libjpeg.a
|
||||
|
||||
$(LIBPNG): $(LIBPNG_SRC)
|
||||
@[ -d $(LIBPNG_VERSION) ] || tar -xf $<
|
||||
@cd $(LIBPNG_VERSION) && \
|
||||
./configure --prefix=$(PORTLIBS) --host=arm-none-eabi --disable-shared --enable-static
|
||||
@$(MAKE) -C $(LIBPNG_VERSION)
|
||||
@make create_build_dir
|
||||
@cp -sf $(CURDIR)/libpng-*/*.h $(CURDIR)/build/include
|
||||
@cp -sf $(CURDIR)/libpng-*/.libs/*.a $(CURDIR)/build/lib/libpng.a
|
||||
|
||||
# sqlite won't work with -ffast-math
|
||||
$(SQLITE): $(SQLITE_SRC)
|
||||
@[ -d $(SQLITE_VERSION) ] || tar -xf $<
|
||||
@cd $(SQLITE_VERSION) && \
|
||||
CFLAGS="$(filter-out -ffast-math,$(CFLAGS)) -DSQLITE_OS_OTHER=1" ./configure --disable-shared --disable-threadsafe --disable-dynamic-extensions --host=arm-none-eabi --prefix=$(PORTLIBS)
|
||||
# avoid building sqlite3 shell
|
||||
@$(MAKE) -C $(SQLITE_VERSION) libsqlite3.la
|
||||
|
||||
$(ZLIB): $(ZLIB_SRC)
|
||||
@[ -d $(ZLIB_VERSION) ] || tar -xf $<
|
||||
@cd $(ZLIB_VERSION) && \
|
||||
CHOST=arm-none-eabi ./configure --static --prefix=$(PORTLIBS)
|
||||
@$(MAKE) -C $(ZLIB_VERSION)
|
||||
@make create_build_dir
|
||||
@cp -sf $(CURDIR)/zlib-*/*.h $(CURDIR)/build/include
|
||||
@cp -sf $(CURDIR)/zlib-*/libz.a $(CURDIR)/build/lib/libz.a
|
||||
|
||||
# Downloads
|
||||
$(ZLIB_SRC):
|
||||
wget -O $@ $(ZLIB_DOWNLOAD)
|
||||
|
||||
$(FREETYPE_SRC):
|
||||
wget -O $@ $(FREETYPE_DOWNLOAD)
|
||||
|
||||
$(LIBEXIF_SRC):
|
||||
wget -O $@ $(LIBEXIF_DOWNLOAD)
|
||||
|
||||
$(LIBJPEGTURBO_SRC):
|
||||
wget -O $@ $(LIBJPEGTURBO_DOWNLOAD)
|
||||
|
||||
$(LIBPNG_SRC):
|
||||
wget -O $@ $(LIBPNG_DOWNLOAD)
|
||||
|
||||
$(SQLITE_SRC):
|
||||
wget -O $@ $(SQLITE_DOWNLOAD)
|
||||
|
||||
install-zlib:
|
||||
@$(MAKE) -C $(ZLIB_VERSION) install
|
||||
|
||||
install:
|
||||
@[ ! -d $(FREETYPE_VERSION) ] || $(MAKE) -C $(FREETYPE_VERSION) install
|
||||
@[ ! -d $(LIBEXIF_VERSION) ] || $(MAKE) -C $(LIBEXIF_VERSION) install
|
||||
@[ ! -d $(LIBJPEGTURBO_VERSION) ] || $(MAKE) -C $(LIBJPEGTURBO_VERSION) install
|
||||
@[ ! -d $(LIBPNG_VERSION) ] || $(MAKE) -C $(LIBPNG_VERSION) install
|
||||
@[ ! -d $(SQLITE_VERSION) ] || $(MAKE) -C $(SQLITE_VERSION) install-libLTLIBRARIES install-data
|
||||
|
||||
clean:
|
||||
@$(RM) -r $(FREETYPE_VERSION)
|
||||
@$(RM) -r $(LIBEXIF_VERSION)
|
||||
@$(RM) -r $(LIBJPEGTURBO_VERSION)
|
||||
@$(RM) -r $(LIBPNG_VERSION)
|
||||
@$(RM) -r $(SQLITE_VERSION)
|
||||
@$(RM) -r $(ZLIB_VERSION)
|
||||
@rm -rf $(CURDIR)/build
|
||||
@rm -f $(CURDIR)/*.tar.*
|
||||
42
libs/3ds_portlibs/README.md
Normal file
42
libs/3ds_portlibs/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
3DS Portlibs
|
||||
============
|
||||
|
||||
Here is a Makefile for building various portlibs for 3DS.
|
||||
|
||||
Type:
|
||||
|
||||
$ make
|
||||
or:
|
||||
|
||||
$ make all
|
||||
|
||||
to download and install all the libraries at once.
|
||||
|
||||
You can build and install the libraries separately:
|
||||
|
||||
$ make zlib
|
||||
$ make install-zlib
|
||||
$ make <targets>
|
||||
$ make install
|
||||
|
||||
This will install the portlibs to `$DEVKITPRO/portlibs/armv6k`. If this is a
|
||||
privileged location, you will need to `sudo make install-zlib` and `sudo make
|
||||
install` in order for the portlibs to be installed.
|
||||
|
||||
Currently supports the following portlibs:
|
||||
|
||||
* freetype (requires zlib)
|
||||
* libexif
|
||||
* libjpeg-turbo
|
||||
* libpng (requires zlib)
|
||||
* sqlite
|
||||
* zlib
|
||||
|
||||
Download links:
|
||||
|
||||
* [freetype-2.5.5.tar.bz2] (http://download.savannah.gnu.org/releases/freetype/freetype-2.5.5.tar.bz2)
|
||||
* [libexif-0.6.21.tar.bz2] (http://sourceforge.net/projects/libexif/files/libexif/0.6.21/libexif-0.6.21.tar.bz2/download)
|
||||
* [libjpeg-turbo-1.4.0.tar.gz] (http://sourceforge.net/projects/libjpeg-turbo/files/1.4.0/libjpeg-turbo-1.4.0.tar.gz/download)
|
||||
* [libpng-1.6.17.tar.xz] (http://prdownloads.sourceforge.net/libpng/libpng-1.6.17.tar.xz?download)
|
||||
* [sqlite-autoconf-3081002.tar.gz] (http://www.sqlite.org/2015/sqlite-autoconf-3081002.tar.gz)
|
||||
* [zlib-1.2.8.tar.gz] (http://prdownloads.sourceforge.net/libpng/zlib-1.2.8.tar.gz?download)
|
||||
17
libs/3ds_portlibs/TODO.md
Normal file
17
libs/3ds_portlibs/TODO.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
TODO
|
||||
====
|
||||
|
||||
List of things to get done.
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
* Change `-mfloat-abi=softfp` to `-mfloat-abi=hard` when new devkitARM is
|
||||
released.
|
||||
|
||||
SQLite
|
||||
------
|
||||
|
||||
* Implement `sqlite3_os_init` and `sqlite3_os_end`, or replace
|
||||
`-DSQLITE_OS_OTHER=1` with `-DSQLITE_OS_UNIX=1`?
|
||||
* Remove `--disable-threadsafe` and implement locking mechanism.
|
||||
27
libs/aemstro/README.md
Normal file
27
libs/aemstro/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
aemstro
|
||||
=======
|
||||
|
||||
''THE ORIGINAL'' pica200 shader (dis)assembly toolkit !
|
||||
|
||||
set of tools used to disassemble and assemble shader code for DMP's MAESTRO shader extension used in the 3DS's PICA200 GPU
|
||||
see http://3dbrew.org/wiki/Shader_Instruction_Set for more information
|
||||
|
||||
it is meant for rapid iteration and experimentation as I reverse engineer the instruction set. as such, the code is dirty and ugly and poorly organized. functionality is also lacking and overall it is not recommended that you use this for your own homebrew projects unless they involve reverse engineering. for more user friendly implementations, see neobrain's nihstro and fincs's picasso.
|
||||
|
||||
requires python 3. sorry !
|
||||
|
||||
please note that the current iteration of aemstro is very experimental as we are still in the process of reverse engineering the instruction set. the current version is a prototype meant to be iterated upon quickly; not a well thought out piece of clean software. so basically don't fret if you think the code looks like shit and could be written in a much more efficient manner; you're not alone.
|
||||
|
||||
aemstro.py :
|
||||
|
||||
- disassembles shbin/bcsdr files
|
||||
- usage : aemstro.py <input.shbin/input.bcsdr>
|
||||
- outputs to stdout
|
||||
|
||||
aemstro_as.py :
|
||||
|
||||
- assembles vertex shaders
|
||||
- usage : aemstro_as.py <input.vsh> <output.shbin>
|
||||
- see test.vsh for sample code
|
||||
- can *not* assemble output from aemstro.py
|
||||
- is currently much less up to date than aemstro.py (mostly the instruction format thing is all wrong)
|
||||
749
libs/aemstro/aemstro.py
Executable file
749
libs/aemstro/aemstro.py
Executable file
|
|
@ -0,0 +1,749 @@
|
|||
import struct
|
||||
import os
|
||||
import sys
|
||||
|
||||
input={}
|
||||
# '''0x0 : "vertex.position",
|
||||
# 0x1 : "vertex.texcoord",
|
||||
# 0x4 : "vertex.color?"}'''
|
||||
|
||||
output={}
|
||||
# {0x0 : "glPosition",
|
||||
# 0x2 : "glTexcoord",
|
||||
# 0x4 : "glTexcoord",
|
||||
# 0x6 : "glColor?",
|
||||
# 0x8 : "glTexcoord?"}
|
||||
|
||||
lineIndentLevel={}
|
||||
|
||||
def indentLine(k):
|
||||
if not(k in lineIndentLevel):
|
||||
lineIndentLevel[k]=0
|
||||
lineIndentLevel[k]+=1
|
||||
|
||||
def unindentLine(k):
|
||||
if not(k in lineIndentLevel):
|
||||
lineIndentLevel[k]=0
|
||||
lineIndentLevel[k]-=1
|
||||
|
||||
def resetIndentLevel():
|
||||
for k in lineIndentLevel:
|
||||
lineIndentLevel[k]=0
|
||||
|
||||
def getWord(b, k, n=4):
|
||||
return sum(list(map(lambda c: b[k+c]<<(c*8),range(n))))
|
||||
|
||||
def convFloat24(f):
|
||||
#seee eeee mmmm mmmm mmmm mmmm
|
||||
if f==0x0:
|
||||
return 0.0
|
||||
s=f>>23
|
||||
e=(f>>16)&0x7F
|
||||
m=f&0xffff
|
||||
x=pow(2.0,e-63)*(1 + m*pow(2.0,-16))
|
||||
if f&0x800000!=0:
|
||||
return -x
|
||||
return x
|
||||
|
||||
# # doesn't quite work, but could be a more accurate approach ?
|
||||
# def convFloat24(val):
|
||||
# if val==0x0:
|
||||
# return 0.0
|
||||
# tmp=((val>>16)&0xFF)+0x40
|
||||
# out=(tmp<<23)|((val&0x800000)<<31)|((val&0xFFFF)<<7)
|
||||
# try:
|
||||
# return (struct.unpack("f",struct.pack("I",out)))[0]
|
||||
# except:
|
||||
# return (val)
|
||||
|
||||
def parseSymbol(b,o):
|
||||
len=0
|
||||
while getWord(b,o+len,1)!=0x00:
|
||||
len+=1
|
||||
return(b[o:o+len].decode("ascii"))
|
||||
|
||||
def parseExtTable(data):
|
||||
l=len(data)
|
||||
out=[]
|
||||
for i in range(0,l,8):
|
||||
out+=[(getWord(data, i), getWord(data, i+0x4))]
|
||||
return out
|
||||
|
||||
def getRegisterNameSRC(v):
|
||||
if v<0x80:
|
||||
return getRegisterNameSRC1(v)
|
||||
elif v<0x88:
|
||||
return "i"+str(v-0x80)
|
||||
else:
|
||||
return "b"+str(v-0x88)
|
||||
|
||||
def getRegisterNameSRC1(v):
|
||||
if v<0x10:
|
||||
return "v"+str(v&0xF)
|
||||
elif v<0x20:
|
||||
return "r"+str(v-0x10)
|
||||
elif v<0x80:
|
||||
return "c"+str(v-0x20)
|
||||
else:
|
||||
return ("r%02X"%(v))
|
||||
|
||||
def getRegisterNameSRC2(v):
|
||||
return getRegisterNameSRC1(v)
|
||||
|
||||
def getRegisterNameDST(v):
|
||||
if v<0x10:
|
||||
return ("o%X"%(v))
|
||||
elif v<0x20:
|
||||
return "r"+str(v-0x10)
|
||||
else:
|
||||
return ("r%02X"%(v))
|
||||
|
||||
def getRegisterName(v):
|
||||
return ("r%02X"%(v))
|
||||
# if v<16:
|
||||
# return "v"+str(v&0xF)
|
||||
# elif v<120:
|
||||
# return "c"+str(v-16)
|
||||
# else:
|
||||
# return "b"+str(v-0x88)
|
||||
|
||||
|
||||
def getInputSymbol(v, vt, ut, idx):
|
||||
src=getRegisterNameSRC(v)
|
||||
return getInputSymbolFromString(src, vt, ut, idx)
|
||||
|
||||
def getInputSymbolFromString(src, vt, ut, idx):
|
||||
idxstr=""
|
||||
|
||||
if idx==1:
|
||||
idxstr="[idx1]"
|
||||
elif idx==2:
|
||||
idxstr="[idx2]"
|
||||
elif idx==3:
|
||||
idxstr="[lcnt]"
|
||||
|
||||
if src in vt:
|
||||
return vt[src]+idxstr
|
||||
if src in ut:
|
||||
return ut[src]+idxstr
|
||||
else:
|
||||
f=src.find(".")
|
||||
if f>=0:
|
||||
src=getInputSymbolFromString(src[:f], vt, ut, idx)+src[f:]
|
||||
idxstr=""
|
||||
return src+idxstr
|
||||
|
||||
def getOutputSymbol(v, ot):
|
||||
dst=getRegisterNameDST(v)
|
||||
return ot[dst] if dst in ot else dst
|
||||
|
||||
def getLabelSymbol(v, t):
|
||||
return t[v][1] if v in t else hex(v)
|
||||
|
||||
def initIndent():
|
||||
global numIdent
|
||||
numIdent=0
|
||||
|
||||
def indentOut():
|
||||
global numIdent
|
||||
numIdent=numIdent+1
|
||||
|
||||
def unindentOut():
|
||||
global numIdent
|
||||
numIdent=numIdent-1
|
||||
|
||||
def iprint(s, e=False):
|
||||
global numIdent
|
||||
if e:
|
||||
print(" "*numIdent+s,end='')
|
||||
else:
|
||||
print(" "*numIdent+s)
|
||||
|
||||
comp=["x", "y", "z", "w"]
|
||||
def parseComponentMask(v):
|
||||
out=""
|
||||
for i in range(4):
|
||||
if v&(1<<(3-i))!=0x0:
|
||||
out+=comp[i]
|
||||
else:
|
||||
out+="_"
|
||||
return out
|
||||
|
||||
def parseExt(v):
|
||||
return {"src1" : (v>>5)&0xFF,
|
||||
"src2" : (v>>14)&0xFF,
|
||||
"src3" : (v>>23)&0xFF,
|
||||
"nsrc1" : (v>>4)&0x1, #negation bit
|
||||
"nsrc2" : (v>>13)&0x1, #negation bit
|
||||
"nsrc3" : (v>>22)&0x1, #negation bit
|
||||
"dst" : (v)&0x1F,
|
||||
"dstcomp" : parseComponentMask(v&0xF),
|
||||
"rest" : (v>>22)}
|
||||
|
||||
def parseComponentSwizzle(v):
|
||||
out=""
|
||||
for i in range(4):
|
||||
out+=comp[(v>>((3-i)*2))&0x3]
|
||||
return out
|
||||
|
||||
def parseInstFormat10(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x1F,
|
||||
"src1" : (v>>12)&0x7F,
|
||||
"idx_1" : (v>>19)&0x3,
|
||||
"idx_2" : 0x0,
|
||||
"cmpY" : (v>>21)&0x7,
|
||||
"cmpX" : (v>>24)&0x7,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat1(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x1F,
|
||||
"src1" : (v>>12)&0x7F,
|
||||
"idx_1" : (v>>19)&0x3,
|
||||
"idx_2" : 0x0,
|
||||
"dst" : (v>>21)&0x1F,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat8(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x7F,
|
||||
"src1" : (v>>14)&0x1F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : (v>>19)&0x3,
|
||||
"dst" : (v>>21)&0x1F,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat9(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"dst" : (v>>24)&0x1F,
|
||||
"src1" : (v>>17)&0x7F,
|
||||
"src2" : (v>>10)&0x7F,
|
||||
"src3" : (v>>5)&0x1F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : 0x0,
|
||||
"extid" : (v)&0x1F}
|
||||
|
||||
def parseInstFormat12(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"dst" : (v>>24)&0x1F,
|
||||
"src1" : (v>>17)&0x7F,
|
||||
"src2" : (v>>12)&0x1F,
|
||||
"src3" : (v>>5)&0x7F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : 0x0,
|
||||
"extid" : (v)&0x1F}
|
||||
|
||||
def parseInstFormat2(k, v, lt={}):
|
||||
ret={"opcode" : v>>26,
|
||||
"addr" : (v>>8)&0x3FFC,
|
||||
"flags" : (v>>22)&0xF,
|
||||
"ret" : (v)&0x3FF}
|
||||
if ret["opcode"]==0x28: #IF?
|
||||
for i in range(k+4,ret["addr"],4):
|
||||
indentLine(i)
|
||||
for i in range(ret["addr"],ret["addr"]+ret["ret"]*4,4):
|
||||
indentLine(i)
|
||||
if ret["ret"]>0:
|
||||
lt[ret["addr"]]=(-1,"ELSE_%X"%(k))
|
||||
return ret
|
||||
|
||||
#?
|
||||
def parseInstFormat3(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>0)&0x1F,
|
||||
"src1" : (v>>7)&0x7F,
|
||||
"dst" : (v>>14)&0x1F}
|
||||
|
||||
#?
|
||||
def parseInstFormat6(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"vtxid" : (v>>24)&0x3,
|
||||
"primid" : (v>>22)&0x3}
|
||||
# MOV?
|
||||
def parseInstFormat4(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src1" : (v>>7)&0x7F,
|
||||
"dst" : (v>>14)&0x1F,
|
||||
"extid" : (v)&0x3F}
|
||||
# CONDJUMP
|
||||
def parseInstFormat5(k, v, lt={}):
|
||||
ret={"opcode" : v>>26,
|
||||
"addr" : (v>>8)&0x3FFC,
|
||||
"bool" : (v>>22)&0xF,
|
||||
"ret" : (v)&0x3FF}
|
||||
if ret["opcode"]==0x27: #IFU
|
||||
for i in range(k+4,ret["addr"],4):
|
||||
indentLine(i)
|
||||
for i in range(ret["addr"],ret["addr"]+ret["ret"]*4,4):
|
||||
indentLine(i)
|
||||
if ret["ret"]>0:
|
||||
lt[ret["addr"]]=(-1,"ELSE_%X"%(k))
|
||||
elif ret["opcode"]==0x29: #LOOP
|
||||
for i in range(k+4,ret["addr"]+4,4):
|
||||
indentLine(i)
|
||||
return ret
|
||||
|
||||
def outputStringList(k, strl, fmtl):
|
||||
l=len(strl)
|
||||
if k in lineIndentLevel and lineIndentLevel[k]>0:
|
||||
out=" "*lineIndentLevel[k]
|
||||
else:
|
||||
out=""
|
||||
if l==len(fmtl):
|
||||
for i in range(l):
|
||||
str=strl[i]
|
||||
fmt=fmtl[i]
|
||||
if fmt:
|
||||
v=len(str)
|
||||
if v<fmt:
|
||||
str+=" "*(fmt-v)
|
||||
out+=str
|
||||
iprint(out)
|
||||
|
||||
|
||||
def printInstFormat1(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" , ",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" ("+hex(inst["extid"])+" "+hex(extd["rest"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
cmpOp={0x0 : "EQ", 0x1 : "NE", 0x2 : "LT", 0x3 : "LE", 0x4 : "GT", 0x5 : "GE", 0x6 : "??", 0x7 : "??"}
|
||||
|
||||
def printInstFormat10(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
"("+cmpOp[inst["cmpX"]]+", "+cmpOp[inst["cmpY"]]+")",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, 12, 32, None])
|
||||
|
||||
def printInstFormat9(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
nsrc3="-" if extd["nsrc3"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" , ",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" , ",
|
||||
nsrc3+getInputSymbol(inst["src3"], vt, ut, 0)+"."+(parseComponentSwizzle(extd["src3"])),
|
||||
" ("+hex(extd["rest"])+")"],
|
||||
[8, 32, None, 16, None, 16, None, 16, None])
|
||||
|
||||
def printInstFormat4(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" ", "",
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
def printInstFormat7(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
"idx.xy__",
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" ", "",
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
def printInstFormat6(k, n, inst, e, lt, vt, ut, ot):
|
||||
outputStringList(k, [n,
|
||||
"vtx%02X," % inst["vtxid"],
|
||||
"PRIM_EMIT" if inst["primid"]&2==2 else "",
|
||||
"UNK_FLAG" if inst["primid"]&1==1 else ""],
|
||||
[8, 8, 12, 16])
|
||||
|
||||
def printInstFormat2(k, n, inst, e, lt, vt, ut, ot):
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" ("+str(inst["ret"])+ " words, flags: "+bin(inst['flags'])+")"],
|
||||
[8, 32, 32])
|
||||
|
||||
# CONDJUMP (uniform)
|
||||
def printInstFormat5(k, n, inst, e, lt, vt, ut, ot):
|
||||
if inst["opcode"]==0x29: #LOOP
|
||||
reg=getRegisterNameSRC((inst['bool']&0xF)+0x80)
|
||||
start=getInputSymbolFromString(reg+".y", vt, ut, 0)
|
||||
end=start+"+"+getInputSymbolFromString(reg+".x", vt, ut, 0)
|
||||
stride=getInputSymbolFromString(reg+".z", vt, ut, 0)
|
||||
outputStringList(k, [n,
|
||||
"(lcnt = "+start+"; lcnt <= "+end+"; lcnt += "+stride+")",
|
||||
" (adr "+getLabelSymbol(inst["addr"], lt)+", "+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, 16])
|
||||
elif inst["opcode"]==0x27: #IFU
|
||||
outputStringList(k, [n,
|
||||
"("+getInputSymbol((inst['bool']&0xF)+0x88, vt, ut, 0)+")",
|
||||
" ("+getLabelSymbol(inst["addr"], lt)+", "+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, 16])
|
||||
elif inst["opcode"]==0x2d: #JMPU
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
("!" if inst["ret"]==1 else "")+getInputSymbol((inst['bool']&0xF)+0x88, vt, ut, 0),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
else:
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
getInputSymbol((inst['bool']&0xF)+(0x80 if inst["opcode"]==0x29 else 0x88), vt, ut, 0),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
# CONDJUMP (dynamic)
|
||||
def printInstFormat11(k, n, inst, e, lt, vt, ut, ot):
|
||||
cond=""
|
||||
if inst["flags"]&0x3==0x0: #OR
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"+" || "+("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
elif inst["flags"]&0x3==0x1: #AND
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"+" && "+("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
elif inst["flags"]&0x3==0x2: #X
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"
|
||||
elif inst["flags"]&0x3==0x3: #Y
|
||||
cond=("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
|
||||
if inst["opcode"]==0x23: #BREAK
|
||||
outputStringList(k, [n,
|
||||
"("+cond+")",
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None])
|
||||
elif inst["opcode"]==0x28: #IF
|
||||
outputStringList(k, [n,
|
||||
"("+cond+")",
|
||||
" , ",
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
else:
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
"("+cond+")",
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
instList={}
|
||||
fmtList=[(parseInstFormat1, printInstFormat1), (parseInstFormat2, printInstFormat2), (parseInstFormat2, printInstFormat2), (parseInstFormat1, printInstFormat4), (parseInstFormat5, printInstFormat5), (parseInstFormat6, printInstFormat6), (parseInstFormat1, printInstFormat7), (parseInstFormat8, printInstFormat1), (parseInstFormat9, printInstFormat9), (parseInstFormat10, printInstFormat10), (parseInstFormat2, printInstFormat11), (parseInstFormat12, printInstFormat9)]
|
||||
|
||||
instList[0x00]={"name" : "ADD", "format" : 0} #really SUB ?
|
||||
instList[0x01]={"name" : "DP3", "format" : 0}
|
||||
instList[0x02]={"name" : "DP4", "format" : 0}
|
||||
instList[0x03]={"name" : "DPH", "format" : 0} #tested, definitely
|
||||
instList[0x05]={"name" : "EX2", "format" : 3} #tested, definitely
|
||||
instList[0x06]={"name" : "LG2", "format" : 3} #tested, definitely
|
||||
instList[0x08]={"name" : "MUL", "format" : 0}
|
||||
instList[0x09]={"name" : "SGE", "format" : 0}
|
||||
instList[0x0A]={"name" : "SLT", "format" : 0}
|
||||
instList[0x0B]={"name" : "FLR", "format" : 3} #tested, definitely FLR and not FRC
|
||||
instList[0x0C]={"name" : "MAX", "format" : 0} #definitely
|
||||
instList[0x0D]={"name" : "MIN", "format" : 0} #definitely
|
||||
instList[0x0E]={"name" : "RCP", "format" : 3} #1/op1
|
||||
instList[0x0F]={"name" : "RSQ", "format" : 3} #1/sqrt(op1)
|
||||
instList[0x12]={"name" : "SETIDX", "format" : 6}
|
||||
instList[0x13]={"name" : "MOV", "format" : 3}
|
||||
instList[0x18]={"name" : "DPHI", "format" : 7}
|
||||
instList[0x1A]={"name" : "SGEI", "format" : 7}
|
||||
instList[0x1B]={"name" : "SLTI", "format" : 7}
|
||||
instList[0x23]={"name" : "BREAKC", "format" : 10} #conditional break
|
||||
instList[0x24]={"name" : "CALL", "format" : 1} #unconditional call
|
||||
instList[0x25]={"name" : "CALLC", "format" : 10} #conditional call
|
||||
instList[0x26]={"name" : "CALLU", "format" : 4} #conditional call (uniform bool)
|
||||
instList[0x27]={"name" : "IFU", "format" : 4} #if/else statement (uniform bool)
|
||||
instList[0x28]={"name" : "IFC", "format" : 10}
|
||||
instList[0x29]={"name" : "LOOP", "format" : 4}
|
||||
instList[0x2b]={"name" : "SETEMIT", "format" : 5}
|
||||
instList[0x2c]={"name" : "JMPC", "format" : 10} #conditional jump
|
||||
instList[0x2d]={"name" : "JMPU", "format" : 4} #conditional jump (uniform bool)
|
||||
for i in range(0x2):
|
||||
instList[0x2e+i]={"name" : "CMP", "format" : 9}
|
||||
for i in range(0x8):
|
||||
instList[0x30+i]={"name" : "MADI", "format" : 11}
|
||||
for i in range(0x8):
|
||||
instList[0x38+i]={"name" : "MAD", "format" : 8}
|
||||
|
||||
def parseCode(data, e, lt, vt, ut, ot):
|
||||
l=len(data)
|
||||
for k in range(0,l,4):
|
||||
v=getWord(data,k)
|
||||
opcode=v>>26
|
||||
|
||||
if k in lt:
|
||||
iprint("%08x [--------] "%(k), True)
|
||||
unindentLine(k)
|
||||
outputStringList(k, [lt[k][1]+":"], [8])
|
||||
indentLine(k)
|
||||
|
||||
iprint("%08x [%08x] "%(k,v), True)
|
||||
|
||||
if opcode in instList:
|
||||
fmt=instList[opcode]["format"]
|
||||
inst=fmtList[fmt][0](k, v, lt)
|
||||
fmtList[fmt][1](k, instList[opcode]["name"], inst, e, lt, vt, ut, ot)
|
||||
elif opcode==0x21:
|
||||
# outputStringList(k,["END"],[8])
|
||||
outputStringList(k,["NOP"],[8])
|
||||
elif opcode==0x22:
|
||||
outputStringList(k,["END"],[8])
|
||||
elif opcode==0x2A:
|
||||
inst=parseInstFormat1(k, v)
|
||||
outputStringList(k,["EMITVERTEX"],[10])
|
||||
else:
|
||||
inst=parseInstFormat1(k, v)
|
||||
if inst["extid"] < len(e):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
printInstFormat1(k, "???%02X"%(inst["opcode"]), inst, e, lt, vt, ut, ot)
|
||||
else:
|
||||
inst=parseInstFormat3(k, v)
|
||||
outputStringList(k,["???%02X"%(inst["opcode"]),
|
||||
getOutputSymbol(inst["dst"], ot),
|
||||
" <- ",
|
||||
getInputSymbol(inst["src1"], vt, ut, 0),
|
||||
" , ",
|
||||
getInputSymbol(inst["src2"], vt, ut, 0),
|
||||
"(invalid extension id)"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
k+=0x4
|
||||
|
||||
def parseDVLP(data, lt, vt, ut, ot, k):
|
||||
l=len(data)
|
||||
extOffset=getWord(data, 0x10)
|
||||
fnOffset=getWord(data, 0x18)
|
||||
# for i in range(fnOffset, l):
|
||||
# if k==0:
|
||||
# break
|
||||
# elif data[i]==0:
|
||||
# k-=1
|
||||
# print(parseSymbol(data,i))
|
||||
extSize=getWord(data, 0x14)*8
|
||||
ext=parseExtTable(data[extOffset:(extOffset+extSize)])
|
||||
codeOffset=getWord(data, 0x8)
|
||||
codeSize=getWord(data, 0xC)*4
|
||||
parseCode(data[codeOffset:(codeOffset+codeSize)], ext, lt, vt, ut, ot)
|
||||
|
||||
def parseLabelTable(data, sym):
|
||||
l=len(data)
|
||||
out={}
|
||||
for i in range(0,l,0x10):
|
||||
id=getWord(data,i,1)
|
||||
loc=getWord(data,i+0x4)*4
|
||||
off=getWord(data,i+0xC)
|
||||
out[loc]=(id,parseSymbol(sym,off))
|
||||
return out
|
||||
|
||||
def transformRegisterValue(v):
|
||||
if v<16:
|
||||
return (v&0xF)
|
||||
return v+16
|
||||
|
||||
def parseVarTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Uniforms :")
|
||||
indentOut()
|
||||
src={}
|
||||
for i in range(0,l,0x8):
|
||||
off=getWord(data,i)
|
||||
v1=getWord(data,i+4,2)
|
||||
v2=getWord(data,i+6,2)
|
||||
|
||||
base=transformRegisterValue(v1)
|
||||
end=transformRegisterValue(v2)
|
||||
|
||||
# iprint(getRegisterNameSRC(base)+" - "+getRegisterNameSRC(end)+" : "+parseSymbol(sym,off))
|
||||
iprint(getRegisterNameSRC(base)+" - "+getRegisterNameSRC(end)+" : "+parseSymbol(sym,off)+" ("+hex(getWord(data,i))+", "+hex(getWord(data,i+4))+")")
|
||||
if base==end:
|
||||
name=parseSymbol(sym,off)
|
||||
src[getRegisterNameSRC(base)]=name
|
||||
else:
|
||||
for k in range(base, end+1):
|
||||
name=parseSymbol(sym,off)+"["+str(k-base)+"]"
|
||||
src[getRegisterNameSRC(k)]=name
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return src
|
||||
|
||||
def parseConstTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Constants :")
|
||||
indentOut()
|
||||
out={}
|
||||
for i in range(0,l,0x14):
|
||||
type=getWord(data,i,2)
|
||||
r=getWord(data,i+2,2)
|
||||
name=None
|
||||
if type==0x0:
|
||||
#constant bool
|
||||
vec=False if getWord(data,i+4)==0x0 else True
|
||||
r+=0x88
|
||||
name=str(vec)
|
||||
elif type==0x1:
|
||||
#constant integer vec4
|
||||
vec=[hex(getWord(data,i+k,1)) for k in range(4,8,1)]
|
||||
r+=0x80
|
||||
out[getRegisterNameSRC(r)+".x"]=vec[0]
|
||||
out[getRegisterNameSRC(r)+".y"]=vec[1]
|
||||
out[getRegisterNameSRC(r)+".z"]=vec[2]
|
||||
out[getRegisterNameSRC(r)+".w"]=vec[3]
|
||||
else:
|
||||
#constant float24 vec4 (should be type==0x2 but would rather output potential unknowns too)
|
||||
vec=[convFloat24(getWord(data,i+k)) for k in range(4,0x14,4)]
|
||||
r+=0x20
|
||||
name="["+", ".join(["%4.2f"%(v) for v in vec])+"]"
|
||||
# iprint(getRegisterNameSRC(r)+" = "+str(vec)+" ("+str([hex(getWord(data,i+k)) for k in range(0,0x14,4)])+")")
|
||||
iprint(getRegisterNameSRC(r)+" = "+str(vec))
|
||||
if name!=None:
|
||||
out[getRegisterNameSRC(r)]=name
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return out
|
||||
|
||||
outputTypes={0x0 : "result.position",
|
||||
0x1 : "result.normalquat", #maybe
|
||||
0x2 : "result.color",
|
||||
0x3 : "result.texcoord0",
|
||||
0x4 : "result.texcoord0w",
|
||||
0x5 : "result.texcoord1",
|
||||
0x6 : "result.texcoord2",
|
||||
# 0x7 : "?", #sets outreg info to 0x1f1f1f1f...
|
||||
0x8 : "result.view", #"result.view" seems to be pre-projmatrix vertex coordinates
|
||||
}
|
||||
|
||||
def parseOutputTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Output :")
|
||||
indentOut()
|
||||
out={}
|
||||
for i in range(0,l,0x8):
|
||||
off=getWord(data,i+4)
|
||||
v1=getWord(data,i,2)
|
||||
v2=getWord(data,i+2,2)
|
||||
|
||||
dst=getRegisterNameDST(v2)
|
||||
|
||||
if v1 in outputTypes:
|
||||
out[dst]=outputTypes[v1]
|
||||
|
||||
iprint("o"+str(v2)+" = "+(outputTypes[v1] if v1 in outputTypes else hex(v1))+" ("+hex(off)+", "+hex(v1)+", "+hex(v2)+")")
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return out
|
||||
|
||||
def parseDVLE(data,dvlp, k):
|
||||
l=len(data)
|
||||
|
||||
iprint("DVLE "+str(k))
|
||||
|
||||
shaderType=getWord(data, 0x6, 1)
|
||||
mainStart=getWord(data, 0x8)*4
|
||||
mainEnd=getWord(data, 0xC)*4
|
||||
|
||||
resetIndentLevel()
|
||||
|
||||
iprint("unkval "+hex(getWord(data, 0x4, 2)))
|
||||
iprint("vertex shader" if shaderType==0x0 else "geometry shader")
|
||||
iprint("main : "+hex(mainStart)+"-"+hex(mainEnd))
|
||||
print("")
|
||||
|
||||
# # temporarily filter out geometry shaders
|
||||
# if shaderType!=0x0:
|
||||
# return
|
||||
|
||||
# # temporarily filter out vertex shaders
|
||||
# if shaderType==0x0:
|
||||
# return
|
||||
|
||||
codeStartOffset=getWord(data, 0x8)
|
||||
codeEndOffset=getWord(data, 0xC)
|
||||
|
||||
unifOffset=getWord(data, 0x18)
|
||||
unifSize=getWord(data, 0x1C)*0x14
|
||||
|
||||
labelOffset=getWord(data, 0x20)
|
||||
labelSize=getWord(data, 0x24)*0x10
|
||||
|
||||
outputOffset=getWord(data, 0x28)
|
||||
outputSize=getWord(data, 0x2C)*0x8
|
||||
|
||||
varOffset=getWord(data, 0x30)
|
||||
varSize=getWord(data, 0x34)*0x8
|
||||
|
||||
symbolOffset=getWord(data, 0x38)
|
||||
symbolSize=getWord(data, 0x3C)
|
||||
|
||||
sym=data[symbolOffset:(symbolOffset+symbolSize)]
|
||||
labelTable=parseLabelTable(data[labelOffset:(labelOffset+labelSize)],sym)
|
||||
varTable=parseVarTable(data[varOffset:(varOffset+varSize)],sym)
|
||||
unifTable=parseConstTable(data[unifOffset:(unifOffset+unifSize)],sym)
|
||||
outputTable=parseOutputTable(data[outputOffset:(outputOffset+outputSize)],sym)
|
||||
|
||||
parseDVLP(dvlp, labelTable, varTable, unifTable, outputTable, k)
|
||||
print("")
|
||||
|
||||
return (labelTable,varTable,unifTable,range(codeStartOffset,codeEndOffset))
|
||||
|
||||
def parseDVLB(data):
|
||||
l=len(data)
|
||||
n=getWord(data, 0x4)
|
||||
dvleTable={}
|
||||
labelTable={}
|
||||
varTable={}
|
||||
unifTable={}
|
||||
dvlp=data[(0x8+0x4*n):l]
|
||||
for i in range(n):
|
||||
offset=getWord(data, 0x8+0x4*i)
|
||||
r=parseDVLE(data[offset:l],dvlp,i)
|
||||
# for k in r[3]:
|
||||
# dvleTable[k*4]=i
|
||||
# labelTable.update(r[0])
|
||||
# varTable[i]=r[1]
|
||||
# unifTable[i]=r[2]
|
||||
# parseDVLP(dvlp,labelTable,varTable,unifTable,dvleTable)
|
||||
|
||||
if len(sys.argv)<2:
|
||||
print("AEMSTRO :")
|
||||
print(" aemstro.py <input.shbin/input.bcsdr>")
|
||||
else:
|
||||
initIndent()
|
||||
src1fn=sys.argv[1]
|
||||
data=bytearray(open(src1fn, "rb").read())
|
||||
l=len(data)
|
||||
|
||||
for i in range(0,l-4,4):
|
||||
if getWord(data, i)==0x424C5644:
|
||||
parseDVLB(data[i:l])
|
||||
682
libs/aemstro/aemstro_as.py
Normal file
682
libs/aemstro/aemstro_as.py
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
import sys
|
||||
import os
|
||||
import re
|
||||
import copy
|
||||
import struct
|
||||
|
||||
#TODO : add parsing checks, handle errors more gracefully
|
||||
|
||||
def toFloat24(f):
|
||||
f=bytearray(struct.pack('f', f))
|
||||
s=f[3]>>7
|
||||
tmp=(((f[3]<<1)|(f[2]>>7))&0xFF)-0x40
|
||||
tmp2=(((f[0])|(f[1]<<8)|(f[2]<<16))>>7)&0xFFFF
|
||||
if tmp>=0:
|
||||
tmp2|=tmp<<16
|
||||
tmp2|=s<<23
|
||||
else:
|
||||
tmp2=s<<23
|
||||
return tmp2
|
||||
|
||||
vshMain=None
|
||||
vshEndmain=None
|
||||
gshMain=None
|
||||
gshEndmain=None
|
||||
|
||||
class DVLE(object):
|
||||
def __init__(self, type):
|
||||
self._main = 0
|
||||
self._endmain = 0
|
||||
self._type = type
|
||||
self._const = []
|
||||
self._label = []
|
||||
self._labelmap = {}
|
||||
self._outmap = []
|
||||
self._inmap = []
|
||||
self._symbol = bytearray()
|
||||
self._symbolnum = 0
|
||||
|
||||
def setMain(self, main):
|
||||
self._main = main
|
||||
|
||||
def setEndmain(self, endmain):
|
||||
self._endmain = endmain
|
||||
|
||||
#binary word tuple
|
||||
def addConstant(self, const):
|
||||
self._const.append(const)
|
||||
|
||||
#(reg, v)
|
||||
def addConstantB(self, const):
|
||||
self._const.append(((const[0]<<16)|(0x0), const[1], 0, 0, 0))
|
||||
|
||||
#(reg, x, y, z, w)
|
||||
def addConstantI(self, const):
|
||||
self._const.append(((const[0]<<16)|(0x1), ((const[1]&0xff)|((const[2]&0xff)<<8)|((const[3]&0xff)<<16)|(const[4]<<24)), (0), (0), (0)))
|
||||
|
||||
#(reg, x, y, z, w)
|
||||
def addConstantF(self, const):
|
||||
self._const.append(((const[0]<<16)|(0x2), toFloat24(const[1]), toFloat24(const[2]), toFloat24(const[3]), toFloat24(const[4])))
|
||||
|
||||
#string
|
||||
def addSymbol(self, s):
|
||||
ret=len(self._symbol)
|
||||
self._symbol+=bytearray(s, "ascii")+bytearray(b"\x00")
|
||||
self._symbolnum+=1
|
||||
return ret
|
||||
|
||||
#(code offset, symbol offset)
|
||||
def addLabel(self, label):
|
||||
self._label.append((label[0],self.addSymbol(label[1])))
|
||||
self._labelmap[label[1]]=label[0]
|
||||
|
||||
def getLabelAddress(self, label):
|
||||
if label in self._labelmap:
|
||||
return self._labelmap[label]
|
||||
else:
|
||||
return 0x0
|
||||
|
||||
#binary word tuple
|
||||
def addOutput(self, out):
|
||||
self._outmap.append(out)
|
||||
|
||||
#(startreg, endreg, symbol offset)
|
||||
def addInput(self, ind):
|
||||
self._inmap.append((ind[0],ind[1],self.addSymbol(ind[2])))
|
||||
|
||||
def toBinary(self):
|
||||
ret=[]
|
||||
|
||||
offsetConst=0x40
|
||||
offsetLabel=offsetConst+len(self._const)*0x14
|
||||
offsetOutmap=offsetLabel+len(self._label)*0x10
|
||||
offsetInmap=offsetOutmap+len(self._outmap)*0x8
|
||||
offsetSymbol=offsetInmap+len(self._inmap)*0x8
|
||||
|
||||
ret.append(0x454C5644) #DVLE magic
|
||||
ret.append((self._type&1)<<16)
|
||||
ret.append(self._main)
|
||||
ret.append(self._endmain)
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(offsetConst)
|
||||
ret.append(len(self._const))
|
||||
ret.append(offsetLabel)
|
||||
ret.append(len(self._label))
|
||||
ret.append(offsetOutmap)
|
||||
ret.append(len(self._outmap))
|
||||
ret.append(offsetInmap)
|
||||
ret.append(len(self._inmap))
|
||||
ret.append(offsetSymbol)
|
||||
ret.append(len(self._symbol))
|
||||
|
||||
for k in self._const:
|
||||
ret.append(k[0])
|
||||
ret.append(k[1])
|
||||
ret.append(k[2])
|
||||
ret.append(k[3])
|
||||
ret.append(k[4])
|
||||
|
||||
i=0
|
||||
for k in self._label:
|
||||
ret.append(i)
|
||||
ret.append(k[0])
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(k[1])
|
||||
i+=1
|
||||
|
||||
for k in self._outmap:
|
||||
ret.append(k[0])
|
||||
ret.append(k[1])
|
||||
|
||||
for k in self._inmap:
|
||||
ret.append(k[2])
|
||||
ret.append(((k[1]&0xFFFF)<<16)|(k[0]&0xFFFF))
|
||||
|
||||
retb=bytearray()
|
||||
for k in ret:
|
||||
retb+=struct.pack("I",k)
|
||||
retb+=self._symbol
|
||||
|
||||
return retb
|
||||
|
||||
|
||||
class DVLP(object):
|
||||
def __init__(self):
|
||||
self._code = []
|
||||
self._opdesc = []
|
||||
|
||||
def clearCode(self):
|
||||
self._code[:] = []
|
||||
|
||||
def addInstruction(self, inst):
|
||||
self._code.append(inst)
|
||||
return len(self._code)
|
||||
|
||||
def addOpdesc(self, opdesc):
|
||||
self._opdesc.append(opdesc)
|
||||
return len(self._opdesc)
|
||||
|
||||
def getCodelength(self):
|
||||
return len(self._code)
|
||||
|
||||
def toBinary(self):
|
||||
ret=[]
|
||||
|
||||
offsetCode=0x28
|
||||
offsetOpdesc=offsetCode+len(self._code)*0x4
|
||||
symbolOffset=offsetOpdesc+len(self._opdesc)*0x8
|
||||
|
||||
ret.append(0x504C5644) #DVLP magic
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(offsetCode)
|
||||
ret.append(len(self._code))
|
||||
ret.append(offsetOpdesc)
|
||||
ret.append(len(self._opdesc))
|
||||
ret.append(symbolOffset)
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(0x00000000) # ?
|
||||
ret.append(0x00000000) # ?
|
||||
|
||||
retb=bytearray()
|
||||
for k in ret:
|
||||
retb+=struct.pack("I",k)
|
||||
for k in self._code:
|
||||
retb+=struct.pack("I",k)
|
||||
for k in self._opdesc:
|
||||
retb+=struct.pack("I",k[0])
|
||||
retb+=struct.pack("I",k[1])
|
||||
|
||||
return retb
|
||||
|
||||
|
||||
class DVLB(object):
|
||||
def __init__(self):
|
||||
self._dvlp = DVLP()
|
||||
self._dvle = []
|
||||
|
||||
def getDVLP(self):
|
||||
return self._dvlp
|
||||
|
||||
def addDVLE(self, dvle):
|
||||
self._dvle.append(dvle)
|
||||
|
||||
def toBinary(self):
|
||||
ret=[]
|
||||
|
||||
ret.append(0x424C5644) #DVLB magic
|
||||
ret.append(len(self._dvle))
|
||||
|
||||
off=len(self._dvle)*0x4+0x8
|
||||
retb=bytearray()
|
||||
retb+=self._dvlp.toBinary()
|
||||
for k in self._dvle:
|
||||
retb+=bytearray([0x00]*(0 if len(retb)%4==0 else 4-(len(retb)%4)))
|
||||
ret.append(off+len(retb))
|
||||
retb+=k.toBinary()
|
||||
|
||||
retb2=bytearray()
|
||||
for k in ret:
|
||||
retb2+=struct.pack("I",k)
|
||||
|
||||
return retb2+retb
|
||||
|
||||
|
||||
def getRegisterFromNameDst(s):
|
||||
if s[0]=="o": # output
|
||||
return int(s[1:])
|
||||
elif s[0]=="v": # attribute
|
||||
print("error : "+s+" cannot be accessed from dst")
|
||||
elif s[0]=="r": # temporary register
|
||||
return int(s[1:])+0x10
|
||||
elif s[0]=="c": # uniform
|
||||
print("error : "+s+" cannot be accessed from dst")
|
||||
elif s[0]=="d": # direct hex; unambiguous
|
||||
return int("0x"+s[1:],0)
|
||||
else:
|
||||
print("error : "+s+" is not a valid register name")
|
||||
|
||||
def getRegisterFromNameSrc1(s):
|
||||
index=0
|
||||
if "[" in s:
|
||||
i=s.index("[")
|
||||
index=s[i+1:-1]
|
||||
s=s[:i]
|
||||
if index=="a0.x":
|
||||
index=1
|
||||
elif index=="a0.y":
|
||||
index=2
|
||||
elif index=="aL":
|
||||
index=3
|
||||
if s[0]=="o": # output
|
||||
print("error : "+s+" cannot be accessed from src1")
|
||||
elif s[0]=="v": # attribute
|
||||
return (int(s[1:]), index)
|
||||
elif s[0]=="r": # temporary register
|
||||
return (int(s[1:])+0x10, index)
|
||||
elif s[0]=="c": # uniform
|
||||
return (int(s[1:])+0x20, index)
|
||||
elif s[0]=="d": # direct hex; unambiguous
|
||||
return (int("0x"+s[1:],0), index)
|
||||
else:
|
||||
print("error : "+s+" is not a valid register name")
|
||||
|
||||
def getRegisterFromNameSrc2(s):
|
||||
if s[0]=="o": # output
|
||||
print("error : "+s+" cannot be accessed from src2")
|
||||
elif s[0]=="v": # attribute
|
||||
return int(s[1:])
|
||||
elif s[0]=="r": # temporary register
|
||||
return int(s[1:])+0x10
|
||||
elif s[0]=="c": # uniform
|
||||
print("error : "+s+" cannot be accessed from src2")
|
||||
elif s[0]=="d": # direct hex; unambiguous
|
||||
return int("0x"+s[1:],0)
|
||||
else:
|
||||
print("error : "+s+" is not a valid register name")
|
||||
|
||||
def assembleFormat11(d):
|
||||
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x7F)<<10)|((d["src3"]&0x1F)<<5)|(d["extid"]&0x1F)
|
||||
|
||||
def parseFormat11(dvle, s):
|
||||
operandFmt="[^\s,]*"
|
||||
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
||||
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
src1 = getRegisterFromNameSrc1(r.group(2))
|
||||
src2 = getRegisterFromNameSrc1(r.group(3))
|
||||
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
||||
"src1" : src1[0],
|
||||
"src2" : src2[0],
|
||||
"src3" : getRegisterFromNameSrc2(r.group(4)),
|
||||
"extid" : int(r.group(5),0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat12(d):
|
||||
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x1F)<<12)|((d["src3"]&0x7F)<<5)|(d["extid"]&0x1F)
|
||||
|
||||
def parseFormat12(dvle, s):
|
||||
operandFmt="[^\s,]*"
|
||||
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
||||
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
src1 = getRegisterFromNameSrc1(r.group(2))
|
||||
src3 = getRegisterFromNameSrc1(r.group(4))
|
||||
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
||||
"src1" : src1[0],
|
||||
"src2" : getRegisterFromNameSrc2(r.group(3)),
|
||||
"src3" : src3[0],
|
||||
"extid" : int(r.group(5),0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat1(d):
|
||||
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["idx"]&0x3)<<19)|((d["src1"]&0x7F)<<12)|((d["src2"]&0x1F)<<7)|(d["extid"]&0x7F)
|
||||
|
||||
def parseFormat1(dvle, s):
|
||||
operandFmt="[^\s,]*"
|
||||
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
||||
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
src1 = getRegisterFromNameSrc1(r.group(2))
|
||||
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
||||
"src1" : src1[0],
|
||||
"idx" : src1[1],
|
||||
"src2" : getRegisterFromNameSrc2(r.group(3)),
|
||||
"extid" : int(r.group(4),0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat2(d):
|
||||
print(d)
|
||||
return (d["opcode"]<<26)|((d["flags"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
||||
|
||||
def parseFormat2(dvle, s):
|
||||
operandFmt1="[^\s,]*"
|
||||
# operandFmt3="0b[01]+"
|
||||
operandFmt3="([!]?)cmp.([xy])"
|
||||
operandFmt3=operandFmt3+"\s*(?:(&&|\|\|)\s*"+operandFmt3+")?"
|
||||
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*"+operandFmt3+"\s*$")
|
||||
# p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*("+operandFmt3+")\s*")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
neg = [0 if r.group(3)=="!" else 1, 0 if r.group(6)=="!" else 1]
|
||||
comp = [2 if r.group(4)=="y" else 3, None if r.group(7)==None else (2 if r.group(7)=="y" else 3)]
|
||||
op = r.group(5)
|
||||
if comp[0]!=comp[1]:
|
||||
flags=0
|
||||
flags|=neg[0]<<comp[0]
|
||||
flags|=neg[1]<<comp[1] if comp[1]!=None else 0
|
||||
flags|=1 if op=="&&" else (0 if op=="||" else (3 if comp[0]==2 else 2))
|
||||
# print(s)
|
||||
# flags=int(r.group(3),0)
|
||||
print(bin(flags))
|
||||
return {"addr" : dvle.getLabelAddress(r.group(2)),
|
||||
"ret" : dvle.getLabelAddress(r.group(1))-dvle.getLabelAddress(r.group(2)),
|
||||
"flags" : flags}
|
||||
else:
|
||||
raise Exception("invalid or redundant condition "+s)
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction "+s)
|
||||
|
||||
def assembleFormat3(d):
|
||||
return (d["opcode"]<<26)
|
||||
|
||||
def parseFormat3(dvle, s):
|
||||
# doesn't check that there are no operands.
|
||||
# (but really if you want to be an idiot and add useless operands to your code, go ahead)
|
||||
return {}
|
||||
|
||||
def assembleFormat4(d):
|
||||
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["idx"]&0x3)<<19)|((d["src1"]&0x7F)<<12)|(d["extid"]&0x7F)
|
||||
|
||||
def parseFormat4(dvle, s):
|
||||
operandFmt="[^\s,]*"
|
||||
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
||||
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
src1 = getRegisterFromNameSrc1(r.group(2))
|
||||
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
||||
"src1" : src1[0],
|
||||
"idx" : src1[1],
|
||||
"extid" : int(r.group(3),0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction "+s)
|
||||
|
||||
def assembleFormat5(d):
|
||||
return (d["opcode"]<<26)|((d["cmpx"]&0x7)<<24)|((d["cmpy"]&0x7)<<21)|((d["src1"]&0x7F)<<12)|((d["src2"]&0x1F)<<7)|(d["extid"]&0x7F)
|
||||
|
||||
cmpOp = {"eq" : 0x0, "ne" : 0x1, "lt" : 0x2, "le" : 0x3, "gt" : 0x4, "ge" : 0x5}
|
||||
|
||||
def parseFormat5(dvle, s):
|
||||
operandFmt="[^\s,]*"
|
||||
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
||||
opFmt="[a-z]+"
|
||||
p=re.compile("^\s*("+operandFmt+"),\s*("+opFmt+"),\s*("+opFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
src1 = getRegisterFromNameSrc1(r.group(1))
|
||||
return {"src1" : src1[0],
|
||||
"idx" : src1[1],
|
||||
"cmpx" : cmpOp[r.group(2)],
|
||||
"cmpy" : cmpOp[r.group(3)],
|
||||
"src2" : getRegisterFromNameSrc2(r.group(4)),
|
||||
"extid" : int(r.group(5),0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction (5)")
|
||||
|
||||
def assembleFormat6(d):
|
||||
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["src2"]&0x7F)<<7)|((d["src1"]&0x1F)<<14)|(d["extid"]&0x7F)
|
||||
|
||||
def parseFormat7(dvle, s):
|
||||
operandFmt1="[^\s,]*"
|
||||
operandFmt3="i[0-9]+"
|
||||
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt3+")")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
return {"addr" : dvle.getLabelAddress(r.group(1))-1,
|
||||
"ret" : 0,
|
||||
"int" : int(r.group(2).strip()[1:],0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat7(d):
|
||||
return (d["opcode"]<<26)|((d["int"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
||||
|
||||
def parseFormat8(dvle, s):
|
||||
operandFmt1="[^\s,]*"
|
||||
operandFmt3="b[0-9]+"
|
||||
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*("+operandFmt3+")")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
return {"addr" : dvle.getLabelAddress(r.group(2)),
|
||||
"ret" : dvle.getLabelAddress(r.group(1))-dvle.getLabelAddress(r.group(2)),
|
||||
"bool" : int(r.group(3).strip()[1:],0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat8(d):
|
||||
return (d["opcode"]<<26)|((d["bool"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
||||
|
||||
def parseFormat9(dvle, s):
|
||||
operandFmt1="true|false"
|
||||
operandFmt3="vtx[0-9]+"
|
||||
p=re.compile("^\s*("+operandFmt3+"),\s*("+operandFmt1+"),\s*("+operandFmt1+")")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
return {"unk" : r.group(3)=="true",
|
||||
"prim" : r.group(2)=="true",
|
||||
"vtx" : int(r.group(1).strip()[3:],0)}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
def assembleFormat9(d):
|
||||
return (d["opcode"]<<26)|((d["vtx"]&0x3)<<24)|((d["unk"]&0x1)<<22)|((d["prim"]&0x1)<<23)
|
||||
|
||||
def parseFormat10(dvle, s):
|
||||
operandFmt1="[^\s,]*"
|
||||
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+")")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
return {"addr" : dvle.getLabelAddress(r.group(1)),
|
||||
"ret" : dvle.getLabelAddress(r.group(2))-dvle.getLabelAddress(r.group(1)),
|
||||
"flags" : 0x0}
|
||||
else:
|
||||
raise Exception("encountered error while parsing instruction")
|
||||
|
||||
instList={}
|
||||
fmtList=[(parseFormat1, assembleFormat1), (parseFormat2, assembleFormat2), (parseFormat3, assembleFormat3), (parseFormat4, assembleFormat4), (parseFormat5, assembleFormat5), (parseFormat1, assembleFormat6), (parseFormat7, assembleFormat7), (parseFormat8, assembleFormat8), (parseFormat9, assembleFormat9), (parseFormat10, assembleFormat2), (parseFormat11, assembleFormat11), (parseFormat12, assembleFormat12)]
|
||||
|
||||
instList["add"]={"opcode" : 0x00, "format" : 0}
|
||||
instList["dp3"]={"opcode" : 0x01, "format" : 0}
|
||||
instList["dp4"]={"opcode" : 0x02, "format" : 0}
|
||||
instList["dph"]={"opcode" : 0x03, "format" : 0}
|
||||
instList["op4"]={"opcode" : 0x04, "format" : 0}
|
||||
instList["ex2"]={"opcode" : 0x05, "format" : 3}
|
||||
instList["lg2"]={"opcode" : 0x06, "format" : 3}
|
||||
instList["op7"]={"opcode" : 0x07, "format" : 3}
|
||||
instList["mul"]={"opcode" : 0x08, "format" : 0}
|
||||
instList["sge"]={"opcode" : 0x09, "format" : 0}
|
||||
instList["slt"]={"opcode" : 0x0a, "format" : 0}
|
||||
instList["flr"]={"opcode" : 0x0B, "format" : 3}
|
||||
instList["max"]={"opcode" : 0x0C, "format" : 0}
|
||||
instList["min"]={"opcode" : 0x0D, "format" : 0}
|
||||
instList["rcp"]={"opcode" : 0x0E, "format" : 3}
|
||||
instList["rsq"]={"opcode" : 0x0F, "format" : 3}
|
||||
instList["mova"]={"opcode" : 0x12, "format" : 3}
|
||||
instList["mov"]={"opcode" : 0x13, "format" : 3}
|
||||
instList["dphi"]={"opcode" : 0x18, "format" : 5}
|
||||
instList["op19"]={"opcode" : 0x19, "format" : 5}
|
||||
instList["sgei"]={"opcode" : 0x1a, "format" : 5}
|
||||
instList["slti"]={"opcode" : 0x1b, "format" : 5}
|
||||
instList["nop"]={"opcode" : 0x21, "format" : 2}
|
||||
instList["end"]={"opcode" : 0x22, "format" : 2}
|
||||
instList["call"] ={"opcode" : 0x24, "format" : 9}
|
||||
instList["ifu"] ={"opcode" : 0x27, "format" : 7}
|
||||
instList["ifc"] ={"opcode" : 0x28, "format" : 1}
|
||||
instList["loop"] ={"opcode" : 0x29, "format" : 6}
|
||||
instList["emit"]={"opcode" : 0x2a, "format" : 2}
|
||||
instList["setemit"]={"opcode" : 0x2b, "format" : 8}
|
||||
instList["cmp"]={"opcode" : 0x2e, "format" : 4}
|
||||
instList["madi"]={"opcode" : 0x30, "format" : 11}
|
||||
instList["mad"]={"opcode" : 0x38, "format" : 10}
|
||||
|
||||
def parseConst(dvlp, dvle, s):
|
||||
s=s.split(",")
|
||||
s[0]=s[0].strip()
|
||||
if s[0][0]=="b":
|
||||
# bool constant
|
||||
dvle.addConstantB((int(s[0][1:],0), int(s[1])))
|
||||
elif s[0][0]=="i":
|
||||
# int vec4 constant
|
||||
dvle.addConstantI((int(s[0][1:],0), int(s[1],0), int(s[2],0), int(s[3],0), int(s[4],0)))
|
||||
elif s[0][0]=="c":
|
||||
# float vec4 constant
|
||||
dvle.addConstantF((int(s[0][1:],0), float(s[1]), float(s[2]), float(s[3]), float(s[4])))
|
||||
|
||||
outputTypes={"result.position" : 0x0,
|
||||
"result.normalquat" : 0x1,
|
||||
"result.color" : 0x2,
|
||||
"result.texcoord0" : 0x3,
|
||||
"result.texcoord0w" : 0x4,
|
||||
"result.texcoord1" : 0x5,
|
||||
"result.texcoord2" : 0x6,
|
||||
"result.view" : 0x8}
|
||||
|
||||
def parseOut(dvlp, dvle, s):
|
||||
s=s.split(",")
|
||||
s[0]=s[0].replace(" ", "")
|
||||
s[1]=s[1].replace(" ", "")
|
||||
s[2]=s[2].replace(" ", "")
|
||||
reg=int(s[0][1:])
|
||||
if s[1] in outputTypes:
|
||||
type=outputTypes[s[1]]
|
||||
mask=int(s[2], 0)
|
||||
dvle.addOutput((type|(reg<<16), mask))
|
||||
|
||||
swizVal={"w":0x3,"z":0x2,"y":0x1,"x":0x0}
|
||||
|
||||
def parseOpdesc(dvlp, dvle, s):
|
||||
s=s.split(",")
|
||||
for k in range(len(s)):
|
||||
s[k]=s[k].replace(" ", "")
|
||||
#dst mask
|
||||
mask=0
|
||||
for k in range(4):
|
||||
if s[0][k]!="_":
|
||||
mask|=1<<(3-k)
|
||||
swiz=[0,0,0]
|
||||
neg=[0,0,0]
|
||||
for i in range(len(s)-1):
|
||||
l=s[1+i]
|
||||
if l[0]=='-':
|
||||
neg[i]=1
|
||||
l=l[1:]
|
||||
for k in range(4):
|
||||
swiz[i]=((swiz[i]<<2)|swizVal[l[k]])
|
||||
dvlp.addOpdesc(((1<<31)|(swiz[2]<<23)|(neg[2]<<22)|(swiz[1]<<14)|(neg[1]<<13)|(swiz[0]<<5)|(neg[0]<<4)|(mask),0x0000000F))
|
||||
|
||||
def parseUniform(dvlp, dvle, s):
|
||||
s=s.split(",")
|
||||
for k in range(len(s)):
|
||||
s[k]=s[k].replace(" ", "")
|
||||
type=s[0][0]
|
||||
if type!=s[1][0]:
|
||||
print("inconsistent uniform register assignment !")
|
||||
return
|
||||
if type=="c":
|
||||
offset=0x10
|
||||
elif type=="i":
|
||||
offset=0x70
|
||||
elif type=="b":
|
||||
offset=0x78
|
||||
dvle.addInput((int(s[0][1:],0)+offset,int(s[1][1:],0)+offset,s[2]))
|
||||
|
||||
def parseVsh(dvlp, dvle, s):
|
||||
global vshMain, vshEndmain
|
||||
s=s.split(",")
|
||||
for k in range(len(s)):
|
||||
s[k]=s[k].replace(" ", "")
|
||||
vshMain, vshEndmain = s[0], s[1]
|
||||
|
||||
def parseGsh(dvlp, dvle, s):
|
||||
global gshMain, gshEndmain
|
||||
s=s.split(",")
|
||||
for k in range(len(s)):
|
||||
s[k]=s[k].replace(" ", "")
|
||||
gshMain, gshEndmain = s[0], s[1]
|
||||
|
||||
dirList={}
|
||||
|
||||
dirList["const"]=(parseConst)
|
||||
dirList["out"]=(parseOut)
|
||||
dirList["opdesc"]=(parseOpdesc)
|
||||
dirList["uniform"]=(parseUniform)
|
||||
dirList["vsh"]=(parseVsh)
|
||||
dirList["gsh"]=(parseGsh)
|
||||
|
||||
def parseInstruction(dvle, s):
|
||||
s=s.lower()
|
||||
p=re.compile("^\s*([^\s]*)(.*)")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
name=r.group(1)
|
||||
if name in instList:
|
||||
fmt=instList[name]["format"]
|
||||
out=fmtList[fmt][0](dvle, r.group(2))
|
||||
out["opcode"]=instList[name]["opcode"]
|
||||
v=fmtList[fmt][1](out)
|
||||
return v
|
||||
else:
|
||||
print(name+" : no such instruction")
|
||||
return None
|
||||
|
||||
def parseLabel(s):
|
||||
s=s.lower()
|
||||
p=re.compile("^\s*([a-z_0-9]*):")
|
||||
r=p.match(s)
|
||||
if r:
|
||||
return r.group(1)
|
||||
return None
|
||||
|
||||
def parseLine(dvlp, dvle, l, mode):
|
||||
l=l.split(";")[0] #remove comments
|
||||
|
||||
k=0
|
||||
while (k<len(l) and (l[k]==" " or l[k]==" ")):
|
||||
k+=1
|
||||
l=l[k:]
|
||||
|
||||
if len(l)>1:
|
||||
if l[0]==".": #directive
|
||||
if not(mode):
|
||||
p=re.compile("^\s*\.([^\s]*)(.*)")
|
||||
r=p.match(l)
|
||||
if r:
|
||||
name=r.group(1)
|
||||
if name in dirList:
|
||||
dirList[name](dvlp, dvle, r.group(2))
|
||||
else:
|
||||
print(name+" : no such directive")
|
||||
else:
|
||||
v=parseLabel(l)
|
||||
if v: #label
|
||||
if not(mode):
|
||||
dvle.addLabel((dvlp.getCodelength(), v))
|
||||
else: #instruction
|
||||
v=parseInstruction(dvle, l)
|
||||
if v:
|
||||
dvlp.addInstruction(v)
|
||||
|
||||
if len(sys.argv)<3:
|
||||
print("AEMSTRO AS :")
|
||||
print(" aemstro_as.py <input.vsh> <output.shbin>")
|
||||
else:
|
||||
dvlb=DVLB()
|
||||
vsh_dvle=DVLE(0x0)
|
||||
|
||||
with open(sys.argv[1], "r") as f:
|
||||
for line in f:
|
||||
parseLine(dvlb.getDVLP(), vsh_dvle, line, False)
|
||||
dvlb.getDVLP().clearCode()
|
||||
with open(sys.argv[1], "r") as f:
|
||||
for line in f:
|
||||
parseLine(dvlb.getDVLP(), vsh_dvle, line, True)
|
||||
|
||||
vsh_dvle.setMain(vsh_dvle.getLabelAddress(vshMain))
|
||||
vsh_dvle.setEndmain(vsh_dvle.getLabelAddress(vshEndmain))
|
||||
dvlb.addDVLE(vsh_dvle)
|
||||
|
||||
if gshMain!=None and gshEndmain!=None:
|
||||
gsh_dvle=copy.deepcopy(vsh_dvle)
|
||||
gsh_dvle._type=0x1
|
||||
gsh_dvle.setMain(gsh_dvle.getLabelAddress(gshMain))
|
||||
gsh_dvle.setEndmain(gsh_dvle.getLabelAddress(gshEndmain))
|
||||
dvlb.addDVLE(gsh_dvle)
|
||||
|
||||
open(sys.argv[2],"wb").write(dvlb.toBinary())
|
||||
43
libs/aemstro/test.vsh
Normal file
43
libs/aemstro/test.vsh
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
; setup constants
|
||||
.const 5, 0.0, 1.0, 2.0, 3.0
|
||||
|
||||
; setup outmap
|
||||
.out o0, result.position
|
||||
.out o1, result.color
|
||||
.out o2, result.texcoord0
|
||||
.out o3, result.texcoord1
|
||||
.out o4, result.texcoord2
|
||||
|
||||
; setup uniform map (not required)
|
||||
.uniform 0x10, 0x13, mdlvMtx
|
||||
.uniform 0x14, 0x17, projMtx
|
||||
|
||||
;code
|
||||
main:
|
||||
; result.pos = mdlvMtx * in.pos
|
||||
dp4 d40, d40, d00 (0x0)
|
||||
dp4 d40, d41, d00 (0x1)
|
||||
dp4 d40, d42, d00 (0x2)
|
||||
mov d40, d25 (0x4)
|
||||
; result.pos = projMtx * in.pos
|
||||
dp4 d00, d44, d40 (0x0)
|
||||
dp4 d00, d45, d40 (0x1)
|
||||
dp4 d00, d46, d40 (0x2)
|
||||
dp4 d00, d47, d40 (0x3)
|
||||
; result.color = in.pos
|
||||
mov d04, d25 (0x5)
|
||||
; result.texcoord = const
|
||||
mov d08, d25 (0x5)
|
||||
mov d0C, d25 (0x5)
|
||||
mov d10, d25 (0x5)
|
||||
flush
|
||||
end
|
||||
endmain:
|
||||
|
||||
;operand descriptors
|
||||
.opdesc x___, xyzw, xyzw ; 0x0
|
||||
.opdesc _y__, xyzw, xyzw ; 0x1
|
||||
.opdesc __z_, xyzw, xyzw ; 0x2
|
||||
.opdesc ___w, xyzw, xyzw ; 0x3
|
||||
.opdesc ___w, yyyy, xyzw ; 0x4
|
||||
.opdesc xyzw, xyzw, xyzw ; 0x5
|
||||
21
libs/sf2dlib/LICENSE
Normal file
21
libs/sf2dlib/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Sergi Granell (xerpi), xerpi.g.12@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
7
libs/sf2dlib/README.md
Normal file
7
libs/sf2dlib/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
## SF2DLIB
|
||||
|
||||
|
||||
Simple and Fast 2D library for the Nintendo 3DS (using ctrulib)
|
||||
|
||||
### Documentation
|
||||
http://xerpi.github.io/sf2dlib/html/sf2d_8h.html
|
||||
2362
libs/sf2dlib/libsf2d/Doxyfile
Normal file
2362
libs/sf2dlib/libsf2d/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
142
libs/sf2dlib/libsf2d/Makefile
Normal file
142
libs/sf2dlib/libsf2d/Makefile
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sf2d
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
$(BUILD): lib
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) lib latex html
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
install: $(BUILD)
|
||||
@cp $(OUTPUT) $(CTRULIB)/lib
|
||||
@cp include/sf2d.h $(CTRULIB)/include
|
||||
@echo "Installed!"
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
docs:
|
||||
@doxygen Doxyfile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%_vsh.h %.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python ../../../aemstro/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
39
libs/sf2dlib/libsf2d/data/shader.vsh
Normal file
39
libs/sf2dlib/libsf2d/data/shader.vsh
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
; setup constants
|
||||
.const c20, 0.0, 0.0, 0.0, 1.0
|
||||
|
||||
; setup outmap
|
||||
.out o0, result.position, 0xF
|
||||
.out o1, result.texcoord0, 0x3
|
||||
.out o2, result.color, 0xF
|
||||
|
||||
; setup uniform map (not required)
|
||||
.uniform c0, c3, projection
|
||||
|
||||
.vsh vmain, end_vmain
|
||||
|
||||
;code
|
||||
vmain:
|
||||
; result.pos = projMtx * in.pos
|
||||
dp4 o0, c0, v0 (0x0)
|
||||
dp4 o0, c1, v0 (0x1)
|
||||
dp4 o0, c2, v0 (0x2)
|
||||
dp4 o0, c3, v0 (0x3)
|
||||
; result.texcoord = in.texcoord
|
||||
mov o1, v1 (0x5)
|
||||
; result.color = in.color
|
||||
mov o2, v1 (0x5)
|
||||
nop
|
||||
end
|
||||
end_vmain:
|
||||
|
||||
;operand descriptors
|
||||
.opdesc x___, xyzw, xyzw ; 0x0
|
||||
.opdesc _y__, xyzw, xyzw ; 0x1
|
||||
.opdesc __z_, xyzw, xyzw ; 0x2
|
||||
.opdesc ___w, xyzw, xyzw ; 0x3
|
||||
.opdesc xyz_, xyzw, xyzw ; 0x4
|
||||
.opdesc xyzw, xyzw, xyzw ; 0x5
|
||||
.opdesc x_zw, xyzw, xyzw ; 0x6
|
||||
.opdesc xyzw, yyyw, xyzw ; 0x7
|
||||
.opdesc xyz_, wwww, wwww ; 0x8
|
||||
.opdesc xyz_, yyyy, xyzw ; 0x9
|
||||
496
libs/sf2dlib/libsf2d/include/sf2d.h
Normal file
496
libs/sf2dlib/libsf2d/include/sf2d.h
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
/**
|
||||
* @file sf2d.h
|
||||
* @author Sergi Granell (xerpi)
|
||||
* @date 22 March 2015
|
||||
* @brief sf2dlib header
|
||||
*/
|
||||
|
||||
#ifndef SF2D_H
|
||||
#define SF2D_H
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Defines
|
||||
|
||||
/**
|
||||
* @brief Creates a new RGBA8 color
|
||||
* @param r the red component of the color to create
|
||||
* @param g the green component of the color to create
|
||||
* @param b the blue component of the color to create
|
||||
* @param a the alpha component of the color to create
|
||||
*/
|
||||
#define RGBA8(r, g, b, a) ((((r)&0xFF)<<24) | (((g)&0xFF)<<16) | (((b)&0xFF)<<8) | (((a)&0xFF)<<0))
|
||||
|
||||
/**
|
||||
* @brief Default size of the GPU commands FIFO buffer
|
||||
*/
|
||||
#define SF2D_GPUCMD_DEFAULT_SIZE 0x80000
|
||||
|
||||
/**
|
||||
* @brief Default size of the temporary memory pool
|
||||
*/
|
||||
#define SF2D_TEMPPOOL_DEFAULT_SIZE 0x80000
|
||||
|
||||
/**
|
||||
* @brief Default depth (Z coordinate) to draw the textures to
|
||||
*/
|
||||
#define SF2D_DEFAULT_DEPTH 0.5f
|
||||
|
||||
// Enums
|
||||
|
||||
/**
|
||||
* @brief Represents a texture format
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
TEXFMT_RGBA8 = 0,
|
||||
TEXFMT_RGB8 = 1,
|
||||
TEXFMT_RGB5A1 = 2,
|
||||
TEXFMT_RGB565 = 3,
|
||||
TEXFMT_RGBA4 = 4,
|
||||
TEXFMT_IA8 = 5,
|
||||
|
||||
TEXFMT_I8 = 7,
|
||||
TEXFMT_A8 = 8,
|
||||
TEXFMT_IA4 = 9,
|
||||
TEXFMT_I4 = 10,
|
||||
TEXFMT_A4 = 11,
|
||||
TEXFMT_ETC1 = 12,
|
||||
TEXFMT_ETC1A4 = 13
|
||||
} sf2d_texfmt;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Data allocated on the RAM or VRAM
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SF2D_PLACE_RAM, /**< RAM allocated */
|
||||
SF2D_PLACE_VRAM, /**< VRAM allocated */
|
||||
SF2D_PLACE_TEMP /**< Temporary memory pool allocated */
|
||||
} sf2d_place;
|
||||
|
||||
// Structs
|
||||
|
||||
/**
|
||||
* @brief Represents a two dimensional float vector
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
float u; /**< First component of the vector */
|
||||
float v; /**< Second component of the vector */
|
||||
} sf2d_vector_2f;
|
||||
|
||||
/**
|
||||
* @brief Represents a three dimensional float vector
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
float x; /**< First component of the vector */
|
||||
float y; /**< Second component of the vector */
|
||||
float z; /**< Third component of the vector */
|
||||
} sf2d_vector_3f;
|
||||
|
||||
/**
|
||||
* @brief Represents a four dimensional float vector
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
float r; /**< Red component of the vector/color */
|
||||
float g; /**< Green component of the vector/color */
|
||||
float b; /**< Blue component of the vector/color */
|
||||
float a; /**< Alpha component of the vector/color */
|
||||
} sf2d_vector_4f;
|
||||
|
||||
/**
|
||||
* @brief Represents a vertex containing position and color attributes
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
sf2d_vector_3f position; /**< Position of the vertex */
|
||||
sf2d_vector_4f color; /**< Color of the vertex */
|
||||
} sf2d_vertex_pos_col;
|
||||
|
||||
/**
|
||||
* @brief Represents a vertex containing position and texture coordinates
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
sf2d_vector_3f position; /**< Position of the vertex */
|
||||
sf2d_vector_2f texcoord; /**< Texture coordinates of the vertex */
|
||||
} sf2d_vertex_pos_tex;
|
||||
|
||||
/**
|
||||
* @brief Represents a texture
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
sf2d_place place; /**< Where the texture data resides, RAM or VRAM */
|
||||
int tiled; /**< Whether the tetxure is tiled or not */
|
||||
sf2d_texfmt pixel_format; /**< Pixel format */
|
||||
int width; /**< Texture width */
|
||||
int height; /**< Texture height */
|
||||
int pow2_w; /**< Nearest power of 2 >= width */
|
||||
int pow2_h; /**< Nearest power of 2 >= height */
|
||||
int data_size; /**< Size of the raw texture data */
|
||||
void *data; /**< Pointer to the data */
|
||||
} sf2d_texture;
|
||||
|
||||
// Basic functions
|
||||
|
||||
/**
|
||||
* @brief Initializates the library
|
||||
* @return Whether the initialization has been successful or not
|
||||
*/
|
||||
int sf2d_init();
|
||||
|
||||
/**
|
||||
* @brief Initializates the library (with advanced settings)
|
||||
* @param gpucmd_size the size of the GPU FIFO
|
||||
* @param temppool_size the size of the temporary pool
|
||||
* @return Whether the initialization has been successful or not
|
||||
*/
|
||||
int sf2d_init_advanced(int gpucmd_size, int temppool_size);
|
||||
|
||||
/**
|
||||
* @brief Finishes the library
|
||||
* @return Whether the finalization has been successful or not
|
||||
*/
|
||||
int sf2d_fini();
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the 3D
|
||||
* @param enable whether to enable or disable the 3D
|
||||
*/
|
||||
void sf2d_set_3D(int enable);
|
||||
|
||||
/**
|
||||
* @brief Starts a frame
|
||||
* @param screen target screen
|
||||
* @param side target eye (only for top screen)
|
||||
*/
|
||||
void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side);
|
||||
|
||||
/**
|
||||
* @brief Ends a frame, should be called on pair with sf2d_start_frame
|
||||
*/
|
||||
void sf2d_end_frame();
|
||||
|
||||
/**
|
||||
* @brief Swaps the framebuffers, should be called once after all the frames have been finished
|
||||
*/
|
||||
void sf2d_swapbuffers();
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the VBlank waiting
|
||||
* @param enable whether to enable or disable the VBlank waiting
|
||||
*/
|
||||
void sf2d_set_vblank_wait(int enable);
|
||||
|
||||
/**
|
||||
* @brief Returns the FPS (frames per second)
|
||||
* @return the current FPS
|
||||
*/
|
||||
float sf2d_get_fps();
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from a temporary pool. The pool will be emptied after a sf2d_swapbuffers call
|
||||
* @param size the number of bytes to allocate
|
||||
*/
|
||||
void *sf2d_pool_malloc(u32 size);
|
||||
|
||||
/**
|
||||
* @brief Allocates aligned memory from a temporary pool. Works as sf2d_pool_malloc
|
||||
* @param size the number of bytes to allocate
|
||||
* @param alignment the alignment to where allocate the memory
|
||||
*/
|
||||
void *sf2d_pool_memalign(u32 size, u32 alignment);
|
||||
|
||||
/**
|
||||
* @brief Returns the temporary pool's free space
|
||||
* @return the temporary pool's free space
|
||||
*/
|
||||
unsigned int sf2d_pool_space_free();
|
||||
|
||||
/**
|
||||
* @brief Empties the temporary pool
|
||||
*/
|
||||
void sf2d_pool_reset();
|
||||
|
||||
/**
|
||||
* @brief Sets the screen clear color
|
||||
* @param color the color
|
||||
*/
|
||||
void sf2d_set_clear_color(u32 color);
|
||||
|
||||
// Draw functions
|
||||
/**
|
||||
* @brief Draws a line
|
||||
* @param x0 x coordinate of the first dot
|
||||
* @param y0 y coordinate of the first dot
|
||||
* @param x1 x coordinate of the second dot
|
||||
* @param y1 y coordinate of the sceond dot
|
||||
* @param color the color to draw the line
|
||||
*/
|
||||
void sf2d_draw_line(int x0, int y0, int x1, int y1, u32 color);
|
||||
|
||||
/**
|
||||
* @brief Draws a rectangle
|
||||
* @param x x coordinate of the top left corner of the rectangle
|
||||
* @param y y coordinate of the top left corner of the rectangle
|
||||
* @param w rectangle width
|
||||
* @param h rectangle height
|
||||
* @param color the color to draw the rectangle
|
||||
*/
|
||||
void sf2d_draw_rectangle(int x, int y, int w, int h, u32 color);
|
||||
|
||||
/**
|
||||
* @brief Draws a rotated rectangle
|
||||
* @param x x coordinate of the top left corner of the rectangle
|
||||
* @param y y coordinate of the top left corner of the rectangle
|
||||
* @param w rectangle width
|
||||
* @param h rectangle height
|
||||
* @param color the color to draw the rectangle
|
||||
* @param rad rotation (in radians) to draw the rectangle
|
||||
*/
|
||||
void sf2d_draw_rectangle_rotate(int x, int y, int w, int h, u32 color, float rad);
|
||||
|
||||
/**
|
||||
* @brief Draws a filled circle
|
||||
* @param x x coordinate of the center of the circle
|
||||
* @param y y coordinate of the center of the circle
|
||||
* @param radius the radius of the circle
|
||||
* @param color the color to draw the circle
|
||||
*/
|
||||
void sf2d_draw_fill_circle(int x, int y, int radius, u32 color);
|
||||
|
||||
// Texture
|
||||
|
||||
/**
|
||||
* @brief Creates an empty texture.
|
||||
* The returned texture has the data allocated,
|
||||
* this means that the raw pixel data can be filled
|
||||
* just after the return.
|
||||
* @param width the width of the texture
|
||||
* @param height the height of the texture
|
||||
* @param pixel_format the pixel_format of the texture
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture
|
||||
*/
|
||||
sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_format, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Frees a texture
|
||||
* @param texture pointer to the texture to freeze
|
||||
*/
|
||||
void sf2d_free_texture(sf2d_texture *texture);
|
||||
|
||||
/**
|
||||
* @brief Fills an already allocated texture from a RGBA8 source
|
||||
* @param dst pointer to the destination texture to fill
|
||||
* @param rgba8 pointer to the RGBA8 data to fill from
|
||||
* @param source_w width (in pixels) of the RGAB8 source
|
||||
* @param source_h height (in pixels) of the RGAB8 source
|
||||
*/
|
||||
void sf2d_fill_texture_from_RGBA8(sf2d_texture *dst, const void *rgba8, int source_w, int source_h);
|
||||
|
||||
/**
|
||||
* @brief Creates a texture and fills it from a RGBA8 memory source.
|
||||
* The returned texture is already tiled.
|
||||
* @param src_buffer pointer to the RGBA8 data to fill from
|
||||
* @param src_w width (in pixels) of the RGAB8 source
|
||||
* @param src_h height (in pixels) of the RGAB8 source
|
||||
* @param pixel_format the pixel_format of the texture to create
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created, filled, and tiled texture
|
||||
*/
|
||||
|
||||
sf2d_texture *sf2d_create_texture_mem_RGBA8(const void *src_buffer, int src_w, int src_h, sf2d_texfmt pixel_format, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Binds a texture to a GPU texture unit
|
||||
* @param texture the texture to bind
|
||||
* @param unit GPU texture unit to bind to
|
||||
*/
|
||||
void sf2d_bind_texture(const sf2d_texture *texture, GPU_TEXUNIT unit);
|
||||
|
||||
/**
|
||||
* @brief Binds a texture to a GPU texture unit with a constant color
|
||||
* @param texture the texture to bind
|
||||
* @param unit GPU texture unit to bind to
|
||||
* @param color the color the bind with the texture
|
||||
*/
|
||||
void sf2d_bind_texture_color(const sf2d_texture *texture, GPU_TEXUNIT unit, u32 color);
|
||||
|
||||
/**
|
||||
* @brief Binds a texture to a GPU texture unit with custom parameters
|
||||
* @param texture the texture to bind
|
||||
* @param unit GPU texture unit to bind to
|
||||
* @param params the parameters the bind with the texture
|
||||
*/
|
||||
void sf2d_bind_texture_parameters(const sf2d_texture *texture, GPU_TEXUNIT unit, unsigned int params);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
*/
|
||||
void sf2d_draw_texture(const sf2d_texture *texture, int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture with rotation
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param rad rotation (in radians) to draw the texture
|
||||
*/
|
||||
void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad);
|
||||
|
||||
/**
|
||||
* @brief Draws a part of a texture
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param tex_x the starting point (x coordinate) where to start drawing
|
||||
* @param tex_y the starting point (y coordinate) where to start drawing
|
||||
* @param tex_w the width to draw from the starting point
|
||||
* @param tex_h the height to draw from the starting point
|
||||
*/
|
||||
void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture with scaling
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param x_scale the x scale
|
||||
* @param y_scale the y scale
|
||||
*/
|
||||
void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale);
|
||||
|
||||
/**
|
||||
* @brief Draws a part of a texture, with rotation and scaling
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param rad rotation (in radians) to draw the texture
|
||||
* @param tex_x the starting point (x coordinate) where to start drawing
|
||||
* @param tex_y the starting point (y coordinate) where to start drawing
|
||||
* @param tex_w the width to draw from the starting point
|
||||
* @param tex_h the height to draw from the starting point
|
||||
* @param x_scale the x scale
|
||||
* @param y_scale the y scale
|
||||
*/
|
||||
void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture blended with a color
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param color the color to blend with the texture
|
||||
*/
|
||||
void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color);
|
||||
|
||||
/**
|
||||
* @brief Draws a part of a texture blended with a color
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param tex_x the starting point (x coordinate) where to start drawing
|
||||
* @param tex_y the starting point (y coordinate) where to start drawing
|
||||
* @param tex_w the width to draw from the starting point
|
||||
* @param tex_h the height to draw from the starting point
|
||||
* @param color the color to blend with the texture
|
||||
*/
|
||||
void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture blended in a certain depth
|
||||
* @param texture the texture to draw
|
||||
* @param x the x coordinate to draw the texture to
|
||||
* @param y the y coordinate to draw the texture to
|
||||
* @param z the depth to draw the texture to
|
||||
* @note The z parameter is a value in the [-32768, +32767] range,
|
||||
* where -32768 is the deepest and +32767 the toppest.
|
||||
* By default, the textures are drawn at z = 0.
|
||||
* Keep in mind that this function won't do
|
||||
* Order-independent transparency (OIT), so you should use fully
|
||||
* opaque textures to get good results.
|
||||
*/
|
||||
void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z);
|
||||
|
||||
/**
|
||||
* @brief Draws a texture using custom texture coordinates and parameters
|
||||
* @param texture the texture to draw
|
||||
* @param left the left coordinate of the texture to start drawing
|
||||
* @param top the top coordinate of the texture to start drawing
|
||||
* @param width the width to draw from the starting left coordinate
|
||||
* @param height the height to draw from the starting top coordinate
|
||||
* @param u0 the U texture coordinate of the left vertices
|
||||
* @param v0 the V texture coordinate of the top vertices
|
||||
* @param u1 the U texture coordinate of the right vertices
|
||||
* @param v1 the V texture coordinate of the bottom vertices
|
||||
* @param params the parameters to draw the texture with
|
||||
*/
|
||||
void sf2d_draw_quad_uv(const sf2d_texture *texture, float left, float top, float right, float bottom,
|
||||
float u0, float v0, float u1, float v1, unsigned int params);
|
||||
|
||||
/**
|
||||
* @brief Changes a pixel of the texture
|
||||
* @param texture the texture to change the pixel
|
||||
* @param x the x coordinate to change the pixel
|
||||
* @param y the y coordinate to change the pixel
|
||||
* @param new_color the new color to set to the pixel at (x, y)
|
||||
*/
|
||||
void sf2d_set_pixel(sf2d_texture *texture, int x, int y, u32 new_color);
|
||||
|
||||
/**
|
||||
* @brief Gets a pixel of the texture
|
||||
* @param texture the texture to get the pixel
|
||||
* @param x the x coordinate to get the pixel
|
||||
* @param y the y coordinate to get the pixel
|
||||
* @return the pixel at (x, y)
|
||||
*/
|
||||
u32 sf2d_get_pixel(sf2d_texture *texture, int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Tiles a texture
|
||||
* @param texture the texture to tile
|
||||
*/
|
||||
void sf2d_texture_tile32(sf2d_texture *texture);
|
||||
|
||||
/**
|
||||
* @brief Sets the scissor test
|
||||
* @param mode the test mode (disable, invert or normal)
|
||||
* @param x the starting x coordinate of the scissor
|
||||
* @param y the starting y coordinate of the scissor
|
||||
* @param w the width of the scissor rectangle
|
||||
* @param h the height of the scissor rectangle
|
||||
* @note This function should be called after sf2d_start_frame.
|
||||
* The scissor will remain active until the sf2d_end_frame call.
|
||||
*/
|
||||
void sf2d_set_scissor_test(GPU_SCISSORMODE mode, u32 x, u32 y, u32 w, u32 h);
|
||||
|
||||
/**
|
||||
* @brief Returns the current screen (latest call to sf2d_start_frame)
|
||||
* @note The returned value can be GFX_TOP or GFX_BOTTOM.
|
||||
*/
|
||||
gfxScreen_t sf2d_get_current_screen();
|
||||
|
||||
/**
|
||||
* @brief Returns the current screen side (latest call to sf2d_start_frame)
|
||||
* @note The returned value can be GFX_LEFT or GFX_RIGHT.
|
||||
*/
|
||||
gfx3dSide_t sf2d_get_current_side();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
29
libs/sf2dlib/libsf2d/include/sf2d_private.h
Normal file
29
libs/sf2dlib/libsf2d/include/sf2d_private.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef SF2D_PRIVATE_H
|
||||
#define SF2D_PRIVATE_H
|
||||
|
||||
#include <3ds.h>
|
||||
#include "sf2d.h"
|
||||
|
||||
|
||||
void GPU_SetDummyTexEnv(u8 num);
|
||||
|
||||
// Vector operations
|
||||
|
||||
void vector_mult_matrix4x4(const float *msrc, const sf2d_vector_3f *vsrc, sf2d_vector_3f *vdst);
|
||||
|
||||
// Matrix operations
|
||||
|
||||
void matrix_copy(float *dst, const float *src);
|
||||
void matrix_identity4x4(float *m);
|
||||
void matrix_mult4x4(const float *src1, const float *src2, float *dst);
|
||||
void matrix_set_z_rotation(float *m, float rad);
|
||||
void matrix_rotate_z(float *m, float rad);
|
||||
void matrix_set_scaling(float *m, float x_scale, float y_scale, float z_scale);
|
||||
void matrix_swap_xy(float *m);
|
||||
|
||||
void matrix_init_orthographic(float *m, float left, float right, float bottom, float top, float near, float far);
|
||||
void matrix_gpu_set_uniform(const float *m, u32 startreg);
|
||||
|
||||
unsigned int next_pow2(unsigned int v);
|
||||
|
||||
#endif
|
||||
303
libs/sf2dlib/libsf2d/source/sf2d.c
Normal file
303
libs/sf2dlib/libsf2d/source/sf2d.c
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
#include "sf2d.h"
|
||||
#include "sf2d_private.h"
|
||||
#include "shader_vsh_shbin.h"
|
||||
|
||||
|
||||
static int sf2d_initialized = 0;
|
||||
static u32 clear_color = RGBA8(0x00, 0x00, 0x00, 0xFF);
|
||||
static u32 *gpu_cmd = NULL;
|
||||
//GPU init variables
|
||||
static int gpu_cmd_size = 0;
|
||||
// Temporary memory pool
|
||||
static void *pool_addr = NULL;
|
||||
static u32 pool_index = 0;
|
||||
static u32 pool_size = 0;
|
||||
//GPU framebuffer address
|
||||
static u32 *gpu_fb_addr = NULL;
|
||||
//GPU depth buffer address
|
||||
static u32 *gpu_depth_fb_addr = NULL;
|
||||
//VBlank wait
|
||||
static int vblank_wait = 1;
|
||||
//FPS calculation
|
||||
static float current_fps = 0.0f;
|
||||
static unsigned int frames = 0;
|
||||
static u64 last_time = 0;
|
||||
//Current screen/side
|
||||
static gfxScreen_t cur_screen = GFX_TOP;
|
||||
static gfx3dSide_t cur_side = GFX_LEFT;
|
||||
//Shader stuff
|
||||
static DVLB_s *dvlb = NULL;
|
||||
static shaderProgram_s shader;
|
||||
static u32 projection_desc = -1;
|
||||
//Matrix
|
||||
static float ortho_matrix_top[4*4];
|
||||
static float ortho_matrix_bot[4*4];
|
||||
//Apt hook cookie
|
||||
static aptHookCookie apt_hook_cookie;
|
||||
//Functions
|
||||
static void apt_hook_func(int hook, void* param);
|
||||
static void reset_gpu_apt_resume();
|
||||
|
||||
int sf2d_init()
|
||||
{
|
||||
return sf2d_init_advanced(
|
||||
SF2D_GPUCMD_DEFAULT_SIZE,
|
||||
SF2D_TEMPPOOL_DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
int sf2d_init_advanced(int gpucmd_size, int temppool_size)
|
||||
{
|
||||
if (sf2d_initialized) return 0;
|
||||
|
||||
gpu_fb_addr = vramMemAlign(400*240*8, 0x100);
|
||||
gpu_depth_fb_addr = vramMemAlign(400*240*8, 0x100);
|
||||
gpu_cmd = linearAlloc(gpucmd_size * 4);
|
||||
pool_addr = linearAlloc(temppool_size);
|
||||
pool_size = temppool_size;
|
||||
gpu_cmd_size = gpucmd_size;
|
||||
|
||||
gfxInitDefault();
|
||||
GPU_Init(NULL);
|
||||
gfxSet3D(false);
|
||||
GPU_Reset(NULL, gpu_cmd, gpucmd_size);
|
||||
|
||||
//Setup the shader
|
||||
dvlb = DVLB_ParseFile((u32 *)shader_vsh_shbin, shader_vsh_shbin_size);
|
||||
shaderProgramInit(&shader);
|
||||
shaderProgramSetVsh(&shader, &dvlb->DVLE[0]);
|
||||
|
||||
//Get shader uniform descriptors
|
||||
projection_desc = shaderInstanceGetUniformLocation(shader.vertexShader, "projection");
|
||||
|
||||
shaderProgramUse(&shader);
|
||||
|
||||
matrix_init_orthographic(ortho_matrix_top, 0.0f, 400.0f, 0.0f, 240.0f, 0.0f, 1.0f);
|
||||
matrix_init_orthographic(ortho_matrix_bot, 0.0f, 320.0f, 0.0f, 240.0f, 0.0f, 1.0f);
|
||||
matrix_gpu_set_uniform(ortho_matrix_top, projection_desc);
|
||||
|
||||
//Register the apt callback hook
|
||||
aptHook(&apt_hook_cookie, apt_hook_func, NULL);
|
||||
|
||||
vblank_wait = 1;
|
||||
current_fps = 0.0f;
|
||||
frames = 0;
|
||||
last_time = osGetTime();
|
||||
|
||||
cur_screen = GFX_TOP;
|
||||
cur_side = GFX_LEFT;
|
||||
|
||||
GPUCMD_Finalize();
|
||||
GPUCMD_FlushAndRun(NULL);
|
||||
gspWaitForP3D();
|
||||
|
||||
sf2d_pool_reset();
|
||||
|
||||
sf2d_initialized = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sf2d_fini()
|
||||
{
|
||||
if (!sf2d_initialized) return 0;
|
||||
|
||||
aptUnhook(&apt_hook_cookie);
|
||||
|
||||
gfxExit();
|
||||
shaderProgramFree(&shader);
|
||||
DVLB_Free(dvlb);
|
||||
|
||||
linearFree(pool_addr);
|
||||
linearFree(gpu_cmd);
|
||||
vramFree(gpu_fb_addr);
|
||||
vramFree(gpu_depth_fb_addr);
|
||||
|
||||
sf2d_initialized = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sf2d_set_3D(int enable)
|
||||
{
|
||||
gfxSet3D(enable);
|
||||
}
|
||||
|
||||
void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side)
|
||||
{
|
||||
sf2d_pool_reset();
|
||||
GPUCMD_SetBufferOffset(0);
|
||||
|
||||
// Only upload the uniform if the screen changes
|
||||
if (screen != cur_screen) {
|
||||
if (screen == GFX_TOP) {
|
||||
matrix_gpu_set_uniform(ortho_matrix_top, projection_desc);
|
||||
} else {
|
||||
matrix_gpu_set_uniform(ortho_matrix_bot, projection_desc);
|
||||
}
|
||||
cur_screen = screen;
|
||||
}
|
||||
|
||||
int screen_w;
|
||||
if (screen == GFX_TOP) {
|
||||
screen_w = 400;
|
||||
cur_side = side;
|
||||
} else {
|
||||
screen_w = 320;
|
||||
}
|
||||
GPU_SetViewport((u32 *)osConvertVirtToPhys((u32)gpu_depth_fb_addr),
|
||||
(u32 *)osConvertVirtToPhys((u32)gpu_fb_addr),
|
||||
0, 0, 240, screen_w);
|
||||
|
||||
GPU_DepthMap(-1.0f, 0.0f);
|
||||
GPU_SetFaceCulling(GPU_CULL_NONE);
|
||||
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
|
||||
GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP);
|
||||
GPU_SetBlendingColor(0,0,0,0);
|
||||
GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
|
||||
GPUCMD_AddWrite(GPUREG_0118, 0);
|
||||
|
||||
GPU_SetAlphaBlending(
|
||||
GPU_BLEND_ADD,
|
||||
GPU_BLEND_ADD,
|
||||
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA,
|
||||
GPU_ONE, GPU_ZERO
|
||||
);
|
||||
|
||||
GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
|
||||
|
||||
GPU_SetDummyTexEnv(1);
|
||||
GPU_SetDummyTexEnv(2);
|
||||
GPU_SetDummyTexEnv(3);
|
||||
GPU_SetDummyTexEnv(4);
|
||||
GPU_SetDummyTexEnv(5);
|
||||
}
|
||||
|
||||
void sf2d_end_frame()
|
||||
{
|
||||
GPU_FinishDrawing();
|
||||
GPUCMD_Finalize();
|
||||
GPUCMD_FlushAndRun(NULL);
|
||||
gspWaitForP3D();
|
||||
|
||||
//Copy the GPU rendered FB to the screen FB
|
||||
if (cur_screen == GFX_TOP) {
|
||||
GX_SetDisplayTransfer(NULL, gpu_fb_addr, GX_BUFFER_DIM(240, 400),
|
||||
(u32 *)gfxGetFramebuffer(GFX_TOP, cur_side, NULL, NULL),
|
||||
GX_BUFFER_DIM(240, 400), 0x1000);
|
||||
} else {
|
||||
GX_SetDisplayTransfer(NULL, gpu_fb_addr, GX_BUFFER_DIM(240, 320),
|
||||
(u32 *)gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL),
|
||||
GX_BUFFER_DIM(240, 320), 0x1000);
|
||||
}
|
||||
gspWaitForPPF();
|
||||
|
||||
//Clear the screen
|
||||
GX_SetMemoryFill(NULL, gpu_fb_addr, clear_color, &gpu_fb_addr[0x2EE00],
|
||||
0x201, gpu_depth_fb_addr, 0x00000000, &gpu_depth_fb_addr[0x2EE00], 0x201);
|
||||
gspWaitForPSC0();
|
||||
}
|
||||
|
||||
void sf2d_swapbuffers()
|
||||
{
|
||||
gfxSwapBuffersGpu();
|
||||
if (vblank_wait) {
|
||||
gspWaitForEvent(GSPEVENT_VBlank0, false);
|
||||
}
|
||||
//Calculate FPS
|
||||
frames++;
|
||||
u64 delta_time = osGetTime() - last_time;
|
||||
if (delta_time >= 1000) {
|
||||
current_fps = frames/(delta_time/1000.0f);
|
||||
frames = 0;
|
||||
last_time = osGetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void sf2d_set_vblank_wait(int enable)
|
||||
{
|
||||
vblank_wait = enable;
|
||||
}
|
||||
|
||||
float sf2d_get_fps()
|
||||
{
|
||||
return current_fps;
|
||||
}
|
||||
|
||||
void *sf2d_pool_malloc(u32 size)
|
||||
{
|
||||
if ((pool_index + size) < pool_size) {
|
||||
void *addr = (void *)((u32)pool_addr + pool_index);
|
||||
pool_index += size;
|
||||
return addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *sf2d_pool_memalign(u32 size, u32 alignment)
|
||||
{
|
||||
u32 new_index = (pool_index + alignment - 1) & ~(alignment - 1);
|
||||
if ((new_index + size) < pool_size) {
|
||||
void *addr = (void *)((u32)pool_addr + new_index);
|
||||
pool_index = new_index + size;
|
||||
return addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int sf2d_pool_space_free()
|
||||
{
|
||||
return pool_size - pool_index;
|
||||
}
|
||||
|
||||
void sf2d_pool_reset()
|
||||
{
|
||||
pool_index = 0;
|
||||
}
|
||||
|
||||
void sf2d_set_clear_color(u32 color)
|
||||
{
|
||||
clear_color = color;
|
||||
}
|
||||
|
||||
void sf2d_set_scissor_test(GPU_SCISSORMODE mode, u32 x, u32 y, u32 w, u32 h)
|
||||
{
|
||||
if (cur_screen == GFX_TOP) {
|
||||
GPU_SetScissorTest(mode, 240 - (y + h), 400 - (x + w), 240 - y, 400 - x);
|
||||
} else {
|
||||
GPU_SetScissorTest(mode, 240 - (y + h), 320 - (x + w), 240 - y, 320 - x);
|
||||
}
|
||||
}
|
||||
|
||||
gfxScreen_t sf2d_get_current_screen()
|
||||
{
|
||||
return cur_screen;
|
||||
}
|
||||
|
||||
gfx3dSide_t sf2d_get_current_side()
|
||||
{
|
||||
return cur_side;
|
||||
}
|
||||
|
||||
static void apt_hook_func(int hook, void* param)
|
||||
{
|
||||
if (hook == APTHOOK_ONRESTORE) {
|
||||
reset_gpu_apt_resume();
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_gpu_apt_resume()
|
||||
{
|
||||
GPU_Reset(NULL, gpu_cmd, gpu_cmd_size); // Only required for custom GPU cmd sizes
|
||||
shaderProgramUse(&shader);
|
||||
|
||||
if (cur_screen == GFX_TOP) {
|
||||
matrix_gpu_set_uniform(ortho_matrix_top, projection_desc);
|
||||
} else {
|
||||
matrix_gpu_set_uniform(ortho_matrix_bot, projection_desc);
|
||||
}
|
||||
|
||||
GPUCMD_Finalize();
|
||||
GPUCMD_FlushAndRun(NULL);
|
||||
gspWaitForP3D();
|
||||
}
|
||||
212
libs/sf2dlib/libsf2d/source/sf2d_draw.c
Normal file
212
libs/sf2dlib/libsf2d/source/sf2d_draw.c
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#include "sf2d.h"
|
||||
#include "sf2d_private.h"
|
||||
#include <math.h>
|
||||
|
||||
void sf2d_draw_line(int x0, int y0, int x1, int y1, u32 color)
|
||||
{
|
||||
sf2d_vertex_pos_col *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_col));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x0+1.0f, (float)y0+1.0f, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x0-1.0f, (float)y0-1.0f, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x1+1.0f, (float)y1+1.0f, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x1-1.0f, (float)y1-1.0f, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
u8 r = (color>>24) & 0xFF;
|
||||
u8 g = (color>>16) & 0xFF;
|
||||
u8 b = (color>>8) & 0xFF;
|
||||
u8 a = color & 0xFF;
|
||||
|
||||
vertices[0].color = (sf2d_vector_4f){r/255.0f, g/255.0f, b/255.0f, a/255.0f};
|
||||
vertices[1].color = vertices[0].color;
|
||||
vertices[2].color = vertices[0].color;
|
||||
vertices[3].color = vertices[0].color;
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 4, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_rectangle(int x, int y, int w, int h, u32 color)
|
||||
{
|
||||
sf2d_vertex_pos_col *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_col));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+w, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+w, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
u8 r = (color>>24) & 0xFF;
|
||||
u8 g = (color>>16) & 0xFF;
|
||||
u8 b = (color>>8) & 0xFF;
|
||||
u8 a = color & 0xFF;
|
||||
|
||||
vertices[0].color = (sf2d_vector_4f){r/255.0f, g/255.0f, b/255.0f, a/255.0f};
|
||||
vertices[1].color = vertices[0].color;
|
||||
vertices[2].color = vertices[0].color;
|
||||
vertices[3].color = vertices[0].color;
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 4, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_rectangle_rotate(int x, int y, int w, int h, u32 color, float rad)
|
||||
{
|
||||
sf2d_vertex_pos_col *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_col));
|
||||
if (!vertices) return;
|
||||
|
||||
int w2 = w/2.0f;
|
||||
int h2 = h/2.0f;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
u8 r = (color>>24) & 0xFF;
|
||||
u8 g = (color>>16) & 0xFF;
|
||||
u8 b = (color>>8) & 0xFF;
|
||||
u8 a = color & 0xFF;
|
||||
|
||||
vertices[0].color = (sf2d_vector_4f){r/255.0f, g/255.0f, b/255.0f, a/255.0f};
|
||||
vertices[1].color = vertices[0].color;
|
||||
vertices[2].color = vertices[0].color;
|
||||
vertices[3].color = vertices[0].color;
|
||||
|
||||
float m[4*4];
|
||||
matrix_set_z_rotation(m, rad);
|
||||
sf2d_vector_3f rot[4];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]);
|
||||
vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z};
|
||||
}
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 4, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_fill_circle(int x, int y, int radius, u32 color)
|
||||
{
|
||||
static const int num_segments = 100;
|
||||
sf2d_vertex_pos_col *vertices = sf2d_pool_malloc((num_segments + 2) * sizeof(sf2d_vertex_pos_col));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
u8 r = (color>>24) & 0xFF;
|
||||
u8 g = (color>>16) & 0xFF;
|
||||
u8 b = (color>>8) & 0xFF;
|
||||
u8 a = color & 0xFF;
|
||||
|
||||
vertices[0].color = (sf2d_vector_4f){r/255.0f, g/255.0f, b/255.0f, a/255.0f};
|
||||
|
||||
float theta = 2 * M_PI / (float)num_segments;
|
||||
float c = cosf(theta);
|
||||
float s = sinf(theta);
|
||||
float t;
|
||||
|
||||
float xx = radius;
|
||||
float yy = 0;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= num_segments; i++) {
|
||||
vertices[i].position = (sf2d_vector_3f){(float)(x + xx), (float)(y + yy), SF2D_DEFAULT_DEPTH};
|
||||
vertices[i].color = vertices[0].color;
|
||||
|
||||
t = xx;
|
||||
xx = c * xx - s * yy;
|
||||
yy = s * t + c * yy;
|
||||
}
|
||||
|
||||
vertices[num_segments + 1].position = vertices[1].position;
|
||||
vertices[num_segments + 1].color = vertices[1].color;
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 4, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_FAN, num_segments + 2);
|
||||
}
|
||||
155
libs/sf2dlib/libsf2d/source/sf2d_private.c
Normal file
155
libs/sf2dlib/libsf2d/source/sf2d_private.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sf2d_private.h"
|
||||
|
||||
//stolen from staplebutt
|
||||
void GPU_SetDummyTexEnv(u8 num)
|
||||
{
|
||||
GPU_SetTexEnv(num,
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_REPLACE,
|
||||
GPU_REPLACE,
|
||||
0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void vector_mult_matrix4x4(const float *msrc, const sf2d_vector_3f *vsrc, sf2d_vector_3f *vdst)
|
||||
{
|
||||
vdst->x = msrc[0*4 + 0]*vsrc->x + msrc[0*4 + 1]*vsrc->y + msrc[0*4 + 2]*vsrc->z + msrc[0*4 + 3];
|
||||
vdst->y = msrc[1*4 + 0]*vsrc->x + msrc[1*4 + 1]*vsrc->y + msrc[1*4 + 2]*vsrc->z + msrc[1*4 + 3];
|
||||
vdst->z = msrc[2*4 + 0]*vsrc->x + msrc[2*4 + 1]*vsrc->y + msrc[2*4 + 2]*vsrc->z + msrc[2*4 + 3];
|
||||
}
|
||||
|
||||
void matrix_gpu_set_uniform(const float *m, u32 startreg)
|
||||
{
|
||||
float mu[4*4];
|
||||
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mu[i*4 + j] = m[i*4 + (3-j)];
|
||||
}
|
||||
}
|
||||
|
||||
GPU_SetFloatUniform(GPU_VERTEX_SHADER, startreg, (u32 *)mu, 4);
|
||||
}
|
||||
|
||||
void matrix_copy(float *dst, const float *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(float)*4*4);
|
||||
}
|
||||
|
||||
void matrix_identity4x4(float *m)
|
||||
{
|
||||
m[0] = m[5] = m[10] = m[15] = 1.0f;
|
||||
m[1] = m[2] = m[3] = 0.0f;
|
||||
m[4] = m[6] = m[7] = 0.0f;
|
||||
m[8] = m[9] = m[11] = 0.0f;
|
||||
m[12] = m[13] = m[14] = 0.0f;
|
||||
}
|
||||
|
||||
void matrix_mult4x4(const float *src1, const float *src2, float *dst)
|
||||
{
|
||||
int i, j, k;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
dst[i*4 + j] = 0.0f;
|
||||
for (k = 0; k < 4; k++) {
|
||||
dst[i*4 + j] += src1[i*4 + k]*src2[k*4 + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void matrix_set_z_rotation(float *m, float rad)
|
||||
{
|
||||
float c = cosf(rad);
|
||||
float s = sinf(rad);
|
||||
|
||||
matrix_identity4x4(m);
|
||||
|
||||
m[0] = c;
|
||||
m[1] = -s;
|
||||
m[4] = s;
|
||||
m[5] = c;
|
||||
}
|
||||
|
||||
void matrix_rotate_z(float *m, float rad)
|
||||
{
|
||||
float mr[4*4], mt[4*4];
|
||||
matrix_set_z_rotation(mr, rad);
|
||||
matrix_mult4x4(mr, m, mt);
|
||||
matrix_copy(m, mt);
|
||||
}
|
||||
|
||||
void matrix_set_scaling(float *m, float x_scale, float y_scale, float z_scale)
|
||||
{
|
||||
matrix_identity4x4(m);
|
||||
m[0] = x_scale;
|
||||
m[5] = y_scale;
|
||||
m[10] = z_scale;
|
||||
}
|
||||
|
||||
void matrix_swap_xy(float *m)
|
||||
{
|
||||
float ms[4*4], mt[4*4];
|
||||
matrix_identity4x4(ms);
|
||||
|
||||
ms[0] = 0.0f;
|
||||
ms[1] = 1.0f;
|
||||
ms[4] = 1.0f;
|
||||
ms[5] = 0.0f;
|
||||
|
||||
matrix_mult4x4(ms, m, mt);
|
||||
matrix_copy(m, mt);
|
||||
}
|
||||
|
||||
void matrix_init_orthographic(float *m, float left, float right, float bottom, float top, float near, float far)
|
||||
{
|
||||
float mo[4*4], mp[4*4];
|
||||
|
||||
mo[0x0] = 2.0f/(right-left);
|
||||
mo[0x1] = 0.0f;
|
||||
mo[0x2] = 0.0f;
|
||||
mo[0x3] = -(right+left)/(right-left);
|
||||
|
||||
mo[0x4] = 0.0f;
|
||||
mo[0x5] = 2.0f/(top-bottom);
|
||||
mo[0x6] = 0.0f;
|
||||
mo[0x7] = -(top+bottom)/(top-bottom);
|
||||
|
||||
mo[0x8] = 0.0f;
|
||||
mo[0x9] = 0.0f;
|
||||
mo[0xA] = -2.0f/(far-near);
|
||||
mo[0xB] = (far+near)/(far-near);
|
||||
|
||||
mo[0xC] = 0.0f;
|
||||
mo[0xD] = 0.0f;
|
||||
mo[0xE] = 0.0f;
|
||||
mo[0xF] = 1.0f;
|
||||
|
||||
matrix_identity4x4(mp);
|
||||
mp[0xA] = 0.5;
|
||||
mp[0xB] = -0.5;
|
||||
|
||||
//Convert Z [-1, 1] to [-1, 0] (PICA shiz)
|
||||
matrix_mult4x4(mp, mo, m);
|
||||
// Rotate 180 degrees
|
||||
matrix_rotate_z(m, M_PI);
|
||||
// Swap X and Y axis
|
||||
matrix_swap_xy(m);
|
||||
}
|
||||
|
||||
//Grabbed from: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
unsigned int next_pow2(unsigned int v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return v+1;
|
||||
}
|
||||
620
libs/sf2dlib/libsf2d/source/sf2d_texture.c
Normal file
620
libs/sf2dlib/libsf2d/source/sf2d_texture.c
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sf2d.h"
|
||||
#include "sf2d_private.h"
|
||||
|
||||
#define TEX_MIN_SIZE 8
|
||||
|
||||
static unsigned int nibbles_per_pixel(sf2d_texfmt format)
|
||||
{
|
||||
switch (format) {
|
||||
case TEXFMT_RGBA8:
|
||||
return 8;
|
||||
case TEXFMT_RGB8:
|
||||
return 6;
|
||||
case TEXFMT_RGB5A1:
|
||||
case TEXFMT_RGB565:
|
||||
case TEXFMT_RGBA4:
|
||||
case TEXFMT_IA8:
|
||||
return 4;
|
||||
case TEXFMT_A4:
|
||||
return 1;
|
||||
case TEXFMT_I8:
|
||||
case TEXFMT_A8:
|
||||
case TEXFMT_IA4:
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int calc_buffer_size(sf2d_texfmt pixel_format, int width, int height)
|
||||
{
|
||||
return width * height * (nibbles_per_pixel(pixel_format)>>1);
|
||||
}
|
||||
|
||||
sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_format, sf2d_place place)
|
||||
{
|
||||
int pow2_w = next_pow2(width);
|
||||
int pow2_h = next_pow2(height);
|
||||
|
||||
if (pow2_w < TEX_MIN_SIZE) pow2_w = TEX_MIN_SIZE;
|
||||
if (pow2_h < TEX_MIN_SIZE) pow2_h = TEX_MIN_SIZE;
|
||||
|
||||
int data_size = calc_buffer_size(pixel_format, pow2_w, pow2_h);
|
||||
void *data;
|
||||
|
||||
if (place == SF2D_PLACE_RAM) {
|
||||
// If there's not enough linear heap space, return
|
||||
if (linearSpaceFree() < data_size) {
|
||||
return NULL;
|
||||
}
|
||||
data = linearMemAlign(data_size, 0x80);
|
||||
} else if (place == SF2D_PLACE_VRAM) {
|
||||
// If there's not enough VRAM heap space, return
|
||||
if (vramSpaceFree() < data_size) {
|
||||
return NULL;
|
||||
}
|
||||
data = vramMemAlign(data_size, 0x80);
|
||||
} else if (place == SF2D_PLACE_TEMP) {
|
||||
if (sf2d_pool_space_free() < data_size) {
|
||||
return NULL;
|
||||
}
|
||||
data = sf2d_pool_memalign(data_size, 0x80);
|
||||
} else {
|
||||
//wot?
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sf2d_texture *texture = malloc(sizeof(*texture));
|
||||
|
||||
texture->tiled = 0;
|
||||
texture->place = place;
|
||||
texture->pixel_format = pixel_format;
|
||||
texture->width = width;
|
||||
texture->height = height;
|
||||
texture->pow2_w = pow2_w;
|
||||
texture->pow2_h = pow2_h;
|
||||
texture->data_size = data_size;
|
||||
texture->data = data;
|
||||
|
||||
memset(texture->data, 0, texture->data_size);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void sf2d_free_texture(sf2d_texture *texture)
|
||||
{
|
||||
if (texture) {
|
||||
if (texture->place == SF2D_PLACE_RAM) {
|
||||
linearFree(texture->data);
|
||||
} else if (texture->place == SF2D_PLACE_VRAM) {
|
||||
vramFree(texture->data);
|
||||
}
|
||||
free(texture);
|
||||
}
|
||||
}
|
||||
|
||||
void sf2d_fill_texture_from_RGBA8(sf2d_texture *dst, const void *rgba8, int source_w, int source_h)
|
||||
{
|
||||
// TODO: add support for non-RGBA8 textures
|
||||
|
||||
u8 *tmp = linearAlloc(dst->pow2_w * dst->pow2_h * 4);
|
||||
int i, j;
|
||||
for (i = 0; i < source_h; i++) {
|
||||
for (j = 0; j < source_w; j++) {
|
||||
((u32 *)tmp)[i*dst->pow2_w + j] = ((u32 *)rgba8)[i*source_w + j];
|
||||
}
|
||||
}
|
||||
memcpy(dst->data, tmp, dst->pow2_w*dst->pow2_h*4);
|
||||
linearFree(tmp);
|
||||
|
||||
sf2d_texture_tile32(dst);
|
||||
}
|
||||
|
||||
sf2d_texture *sf2d_create_texture_mem_RGBA8(const void *src_buffer, int src_w, int src_h, sf2d_texfmt pixel_format, sf2d_place place)
|
||||
{
|
||||
sf2d_texture *tex = sf2d_create_texture(src_w, src_h, pixel_format, place);
|
||||
if (tex == NULL) return NULL;
|
||||
sf2d_fill_texture_from_RGBA8(tex, src_buffer, src_w, src_h);
|
||||
return tex;
|
||||
}
|
||||
|
||||
void sf2d_bind_texture(const sf2d_texture *texture, GPU_TEXUNIT unit)
|
||||
{
|
||||
GPU_SetTextureEnable(unit);
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0),
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetTexture(
|
||||
unit,
|
||||
(u32 *)osConvertVirtToPhys((u32)texture->data),
|
||||
texture->pow2_w,
|
||||
texture->pow2_h,
|
||||
GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST),
|
||||
texture->pixel_format
|
||||
);
|
||||
}
|
||||
|
||||
void sf2d_bind_texture_color(const sf2d_texture *texture, GPU_TEXUNIT unit, u32 color)
|
||||
{
|
||||
GPU_SetTextureEnable(unit);
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_CONSTANT),
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_CONSTANT),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_MODULATE, GPU_MODULATE,
|
||||
__builtin_bswap32(color) //RGBA8 -> ABGR8
|
||||
);
|
||||
|
||||
GPU_SetTexture(
|
||||
unit,
|
||||
(u32 *)osConvertVirtToPhys((u32)texture->data),
|
||||
texture->pow2_w,
|
||||
texture->pow2_h,
|
||||
GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST),
|
||||
texture->pixel_format
|
||||
);
|
||||
}
|
||||
|
||||
void sf2d_bind_texture_parameters(const sf2d_texture *texture, GPU_TEXUNIT unit, unsigned int params)
|
||||
{
|
||||
GPU_SetTextureEnable(unit);
|
||||
|
||||
GPU_SetTexEnv(
|
||||
0,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0),
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_TEXTURE0, GPU_TEXTURE0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_TEVOPERANDS(0, 0, 0),
|
||||
GPU_REPLACE, GPU_REPLACE,
|
||||
0xFFFFFFFF
|
||||
);
|
||||
|
||||
GPU_SetTexture(
|
||||
unit,
|
||||
(u32 *)osConvertVirtToPhys((u32)texture->data),
|
||||
texture->pow2_w,
|
||||
texture->pow2_h,
|
||||
params,
|
||||
texture->pixel_format
|
||||
);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture(const sf2d_texture *texture, int x, int y)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
int w = texture->width;
|
||||
int h = texture->height;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+w, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+w, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u = texture->width/(float)texture->pow2_w;
|
||||
float v = texture->height/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){0.0f, v};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u, v};
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
int w2 = texture->width/2.0f;
|
||||
int h2 = texture->height/2.0f;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u = texture->width/(float)texture->pow2_w;
|
||||
float v = texture->height/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){0.0f, v};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u, v};
|
||||
|
||||
float m[4*4];
|
||||
matrix_set_z_rotation(m, rad);
|
||||
sf2d_vector_3f rot[4];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]);
|
||||
vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z};
|
||||
}
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u0 = tex_x/(float)texture->pow2_w;
|
||||
float v0 = tex_y/(float)texture->pow2_h;
|
||||
float u1 = (tex_x+tex_w)/(float)texture->pow2_w;
|
||||
float v1 = (tex_y+tex_h)/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){u0, v0};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u1, v0};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){u0, v1};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u1, v1};
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
int ws = texture->width * x_scale;
|
||||
int hs = texture->height * y_scale;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+ws, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+hs, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+ws, (float)y+hs, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u = texture->width/(float)texture->pow2_w;
|
||||
float v = texture->height/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){0.0f, v};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u, v};
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
//Don't even try to understand what I'm doing here (because I don't even understand it).
|
||||
//Matrices are boring.
|
||||
|
||||
int w2 = (tex_w * x_scale)/2.0f;
|
||||
int h2 = (tex_h * y_scale)/2.0f;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u0 = tex_x/(float)texture->pow2_w;
|
||||
float v0 = tex_y/(float)texture->pow2_h;
|
||||
float u1 = (tex_x+tex_w)/(float)texture->pow2_w;
|
||||
float v1 = (tex_y+tex_h)/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){u0, v0};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u1, v0};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){u0, v1};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u1, v1};
|
||||
|
||||
float m[4*4];
|
||||
matrix_set_z_rotation(m, rad);
|
||||
sf2d_vector_3f rot[4];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]);
|
||||
vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z};
|
||||
}
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
int w = texture->width;
|
||||
int h = texture->height;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+w, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+w, (float)y+h, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u = texture->width/(float)texture->pow2_w;
|
||||
float v = texture->height/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){0.0f, v};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u, v};
|
||||
|
||||
sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
float u0 = tex_x/(float)texture->pow2_w;
|
||||
float v0 = tex_y/(float)texture->pow2_h;
|
||||
float u1 = (tex_x+tex_w)/(float)texture->pow2_w;
|
||||
float v1 = (tex_y+tex_h)/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){u0, v0};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u1, v0};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){u0, v1};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u1, v1};
|
||||
|
||||
sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
int w = texture->width;
|
||||
int h = texture->height;
|
||||
float depth = z/32768.0f + 0.5f;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, depth};
|
||||
vertices[1].position = (sf2d_vector_3f){(float)x+w, (float)y, depth};
|
||||
vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+h, depth};
|
||||
vertices[3].position = (sf2d_vector_3f){(float)x+w, (float)y+h, depth};
|
||||
|
||||
float u = texture->width/(float)texture->pow2_w;
|
||||
float v = texture->height/(float)texture->pow2_h;
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){0.0f, v};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u, v};
|
||||
|
||||
sf2d_bind_texture(texture, GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
void sf2d_draw_quad_uv(const sf2d_texture *texture, float left, float top, float right, float bottom, float u0, float v0, float u1, float v1, unsigned int params)
|
||||
{
|
||||
sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex));
|
||||
if (!vertices) return;
|
||||
|
||||
vertices[0].position = (sf2d_vector_3f){left, top, SF2D_DEFAULT_DEPTH};
|
||||
vertices[1].position = (sf2d_vector_3f){right, top, SF2D_DEFAULT_DEPTH};
|
||||
vertices[2].position = (sf2d_vector_3f){left, bottom, SF2D_DEFAULT_DEPTH};
|
||||
vertices[3].position = (sf2d_vector_3f){right, bottom, SF2D_DEFAULT_DEPTH};
|
||||
|
||||
vertices[0].texcoord = (sf2d_vector_2f){u0, v0};
|
||||
vertices[1].texcoord = (sf2d_vector_2f){u1, v0};
|
||||
vertices[2].texcoord = (sf2d_vector_2f){u0, v1};
|
||||
vertices[3].texcoord = (sf2d_vector_2f){u1, v1};
|
||||
|
||||
sf2d_bind_texture_parameters(texture, GPU_TEXUNIT0, params);
|
||||
|
||||
GPU_SetAttributeBuffers(
|
||||
2, // number of attributes
|
||||
(u32*)osConvertVirtToPhys((u32)vertices),
|
||||
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
|
||||
0xFFFC, //0b1100
|
||||
0x10,
|
||||
1, //number of buffers
|
||||
(u32[]){0x0}, // buffer offsets (placeholders)
|
||||
(u64[]){0x10}, // attribute permutations for each buffer
|
||||
(u8[]){2} // number of attributes for each buffer
|
||||
);
|
||||
|
||||
GPU_DrawArray(GPU_TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
// Grabbed from Citra Emulator (citra/src/video_core/utils.h)
|
||||
static inline u32 morton_interleave(u32 x, u32 y)
|
||||
{
|
||||
u32 i = (x & 7) | ((y & 7) << 8); // ---- -210
|
||||
i = (i ^ (i << 2)) & 0x1313; // ---2 --10
|
||||
i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0
|
||||
i = (i | (i >> 7)) & 0x3F;
|
||||
return i;
|
||||
}
|
||||
|
||||
//Grabbed from Citra Emulator (citra/src/video_core/utils.h)
|
||||
static inline u32 get_morton_offset(u32 x, u32 y, u32 bytes_per_pixel)
|
||||
{
|
||||
u32 i = morton_interleave(x, y);
|
||||
unsigned int offset = (x & ~7) * 8;
|
||||
return (i + offset) * bytes_per_pixel;
|
||||
}
|
||||
|
||||
void sf2d_set_pixel(sf2d_texture *texture, int x, int y, u32 new_color)
|
||||
{
|
||||
y = (texture->pow2_h - 1 - y);
|
||||
if (texture->tiled) {
|
||||
u32 coarse_y = y & ~7;
|
||||
u32 offset = get_morton_offset(x, y, 4) + coarse_y * texture->pow2_w * 4;
|
||||
*(u32 *)(texture->data + offset) = __builtin_bswap32(new_color);
|
||||
} else {
|
||||
((u32 *)texture->data)[x + y * texture->pow2_w] = __builtin_bswap32(new_color);
|
||||
}
|
||||
}
|
||||
|
||||
u32 sf2d_get_pixel(sf2d_texture *texture, int x, int y)
|
||||
{
|
||||
y = (texture->pow2_h - 1 - y);
|
||||
if (texture->tiled) {
|
||||
u32 coarse_y = y & ~7;
|
||||
u32 offset = get_morton_offset(x, y, 4) + coarse_y * texture->pow2_w * 4;
|
||||
return __builtin_bswap32(*(u32 *)(texture->data + offset));
|
||||
} else {
|
||||
return __builtin_bswap32(((u32 *)texture->data)[x + y * texture->pow2_w]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sf2d_texture_tile32(sf2d_texture *texture)
|
||||
{
|
||||
if (texture->tiled) return;
|
||||
|
||||
// TODO: add support for non-RGBA8 textures
|
||||
u8 *tmp = linearAlloc(texture->pow2_w * texture->pow2_h * 4);
|
||||
|
||||
int i, j;
|
||||
for (j = 0; j < texture->pow2_h; j++) {
|
||||
for (i = 0; i < texture->pow2_w; i++) {
|
||||
|
||||
u32 coarse_y = j & ~7;
|
||||
u32 dst_offset = get_morton_offset(i, j, 4) + coarse_y * texture->pow2_w * 4;
|
||||
|
||||
u32 v = ((u32 *)texture->data)[i + (texture->pow2_h - 1 - j)*texture->pow2_w];
|
||||
*(u32 *)(tmp + dst_offset) = __builtin_bswap32(v);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(texture->data, tmp, texture->pow2_w*texture->pow2_h*4);
|
||||
linearFree(tmp);
|
||||
|
||||
texture->tiled = 1;
|
||||
}
|
||||
199
libs/sf2dlib/sample/Makefile
Normal file
199
libs/sf2dlib/sample/Makefile
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sf2d_sample
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
APP_TITLE := SF2DLIB sample
|
||||
APP_DESCRIPTION := SF2DLIB sample
|
||||
APP_AUTHOR := xerpi
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lsf2d -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(CURDIR)/../libsf2d
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(TARGET)-strip.elf $(TARGET).cia $(TARGET).3ds
|
||||
#---------------------------------------------------------------------------------
|
||||
$(TARGET)-strip.elf: $(BUILD)
|
||||
@$(STRIP) --strip-all $(TARGET).elf -o $(TARGET)-strip.elf
|
||||
#---------------------------------------------------------------------------------
|
||||
cci: $(TARGET)-strip.elf
|
||||
@makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds
|
||||
@echo "built ... sf2d_sample.3ds"
|
||||
#---------------------------------------------------------------------------------
|
||||
cia: $(TARGET)-strip.elf
|
||||
@makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf resources/$(TARGET).rsf -icon resources/icon.icn -banner resources/banner.bnr -exefslogo -target t
|
||||
@echo "built ... sf2d_sample.cia"
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@3dslink $(TARGET).3dsx
|
||||
#---------------------------------------------------------------------------------
|
||||
run: $(BUILD)
|
||||
@citra $(TARGET).3dsx
|
||||
#---------------------------------------------------------------------------------
|
||||
copy_cia: $(TARGET).cia
|
||||
@cp $(TARGET).cia /mnt/GATEWAYNAND
|
||||
sync
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
|
||||
else
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
236
libs/sf2dlib/sample/resources/sf2d_sample.rsf
Normal file
236
libs/sf2dlib/sample/resources/sf2d_sample.rsf
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
BasicInfo:
|
||||
Title : "sf2dlibS"
|
||||
CompanyCode : "00"
|
||||
ProductCode : "CTR-N-S3DS"
|
||||
ContentType : Application # Application / SystemUpdate / Manual / Child / Trial
|
||||
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
|
||||
|
||||
RomFs:
|
||||
# Specifies the root path of the file system to include in the ROM.
|
||||
# HostRoot : "$(ROMFS_ROOT)"
|
||||
|
||||
|
||||
TitleInfo:
|
||||
UniqueId : 0xf1001 # This was/is the first real homebrew app. I hope this TID range is not used by any retail game/app.
|
||||
Category : Application # Application / SystemApplication / Applet / Firmware / Base / DlpChild / Demo / Contents / SystemContents / SharedContents / AddOnContents / Patch / AutoUpdateContents
|
||||
|
||||
CardInfo:
|
||||
MediaSize : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB / 8GB / 16GB / 32GB
|
||||
MediaType : Card1 # Card1 / Card2
|
||||
CardDevice : None # NorFlash / None
|
||||
|
||||
|
||||
Option:
|
||||
UseOnSD : true # true if App is to be installed to SD
|
||||
EnableCompress : true # Compresses exefs code
|
||||
FreeProductCode : true # Removes limitations on ProductCode
|
||||
EnableCrypt : false # Enables encryption for NCCH and CIA
|
||||
MediaFootPadding : false # If true CCI files are created with padding
|
||||
|
||||
ExeFs: # these are the program segments from the ELF, check your elf for the appropriate segment names
|
||||
ReadOnly:
|
||||
- .rodata
|
||||
- RO
|
||||
ReadWrite:
|
||||
- .data
|
||||
- RO
|
||||
Text:
|
||||
- .init
|
||||
- .text
|
||||
- STUP_ENTRY
|
||||
|
||||
PlainRegion: # only used with SDK ELFs
|
||||
# - .module_id
|
||||
|
||||
AccessControlInfo:
|
||||
# UseOtherVariationSaveData : true
|
||||
# UseExtSaveData : true
|
||||
# ExtSaveDataId: 0xffffffff
|
||||
# SystemSaveDataId1: 0x220
|
||||
# SystemSaveDataId2: 0x00040010
|
||||
# OtherUserSaveDataId1: 0x220
|
||||
# OtherUserSaveDataId2: 0x330
|
||||
# OtherUserSaveDataId3: 0x440
|
||||
# UseExtendedSaveDataAccessControl: true
|
||||
# AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]
|
||||
FileSystemAccess:
|
||||
# - CategorySystemApplication
|
||||
# - CategoryHardwareCheck
|
||||
# - CategoryFileSystemTool
|
||||
- Debug
|
||||
# - TwlCardBackup
|
||||
# - TwlNandData
|
||||
# - Boss
|
||||
- DirectSdmc
|
||||
# - Core
|
||||
# - CtrNandRo
|
||||
# - CtrNandRw
|
||||
# - CtrNandRoWrite
|
||||
# - CategorySystemSettings
|
||||
# - CardBoard
|
||||
# - ExportImportIvs
|
||||
# - DirectSdmcWrite
|
||||
# - SwitchCleanup
|
||||
# - SaveDataMove
|
||||
# - Shop
|
||||
# - Shell
|
||||
# - CategoryHomeMenu
|
||||
IoAccessControl:
|
||||
# - FsMountNand
|
||||
# - FsMountNandRoWrite
|
||||
# - FsMountTwln
|
||||
# - FsMountWnand
|
||||
# - FsMountCardSpi
|
||||
# - UseSdif3
|
||||
# - CreateSeed
|
||||
# - UseCardSpi
|
||||
|
||||
IdealProcessor : 0
|
||||
AffinityMask : 1
|
||||
|
||||
Priority : 16
|
||||
|
||||
MaxCpu : 0x9E # Default
|
||||
|
||||
DisableDebug : true
|
||||
EnableForceDebug : false
|
||||
CanWriteSharedPage : true
|
||||
CanUsePrivilegedPriority : false
|
||||
CanUseNonAlphabetAndNumber : true
|
||||
PermitMainFunctionArgument : true
|
||||
CanShareDeviceMemory : true
|
||||
RunnableOnSleep : false
|
||||
SpecialMemoryArrange : true
|
||||
|
||||
CoreVersion : 2
|
||||
DescVersion : 2
|
||||
|
||||
ReleaseKernelMajor : "02"
|
||||
ReleaseKernelMinor : "33"
|
||||
MemoryType : Application # Application / System / Base
|
||||
HandleTableSize: 512
|
||||
IORegisterMapping:
|
||||
- 1ff50000-1ff57fff
|
||||
- 1ff70000-1ff77fff
|
||||
MemoryMapping:
|
||||
- 1f000000-1f5fffff:r
|
||||
SystemCallAccess:
|
||||
ArbitrateAddress: 34
|
||||
Break: 60
|
||||
CancelTimer: 28
|
||||
ClearEvent: 25
|
||||
ClearTimer: 29
|
||||
CloseHandle: 35
|
||||
ConnectToPort: 45
|
||||
ControlMemory: 1
|
||||
CreateAddressArbiter: 33
|
||||
CreateEvent: 23
|
||||
CreateMemoryBlock: 30
|
||||
CreateMutex: 19
|
||||
CreateSemaphore: 21
|
||||
CreateThread: 8
|
||||
CreateTimer: 26
|
||||
DuplicateHandle: 39
|
||||
ExitProcess: 3
|
||||
ExitThread: 9
|
||||
GetCurrentProcessorNumber: 17
|
||||
GetHandleInfo: 41
|
||||
GetProcessId: 53
|
||||
GetProcessIdOfThread: 54
|
||||
GetProcessIdealProcessor: 6
|
||||
GetProcessInfo: 43
|
||||
GetResourceLimit: 56
|
||||
GetResourceLimitCurrentValues: 58
|
||||
GetResourceLimitLimitValues: 57
|
||||
GetSystemInfo: 42
|
||||
GetSystemTick: 40
|
||||
GetThreadContext: 59
|
||||
GetThreadId: 55
|
||||
GetThreadIdealProcessor: 15
|
||||
GetThreadInfo: 44
|
||||
GetThreadPriority: 11
|
||||
MapMemoryBlock: 31
|
||||
OutputDebugString: 61
|
||||
QueryMemory: 2
|
||||
ReleaseMutex: 20
|
||||
ReleaseSemaphore: 22
|
||||
SendSyncRequest1: 46
|
||||
SendSyncRequest2: 47
|
||||
SendSyncRequest3: 48
|
||||
SendSyncRequest4: 49
|
||||
SendSyncRequest: 50
|
||||
SetThreadPriority: 12
|
||||
SetTimer: 27
|
||||
SignalEvent: 24
|
||||
SleepThread: 10
|
||||
UnmapMemoryBlock: 32
|
||||
WaitSynchronization1: 36
|
||||
WaitSynchronizationN: 37
|
||||
InterruptNumbers:
|
||||
ServiceAccessControl:
|
||||
- APT:U
|
||||
- $hioFIO
|
||||
- $hostio0
|
||||
- $hostio1
|
||||
- ac:u
|
||||
- boss:U
|
||||
- cam:u
|
||||
- cecd:u
|
||||
- cfg:u
|
||||
- dlp:FKCL
|
||||
- dlp:SRVR
|
||||
- dsp::DSP
|
||||
- frd:u
|
||||
- fs:USER
|
||||
- gsp::Gpu
|
||||
- hid:USER
|
||||
- http:C
|
||||
- mic:u
|
||||
- ndm:u
|
||||
- news:u
|
||||
- nwm::UDS
|
||||
- ptm:u
|
||||
- pxi:dev
|
||||
- soc:U
|
||||
- ssl:C
|
||||
- y2r:u
|
||||
- ldr:ro
|
||||
- ir:USER
|
||||
|
||||
|
||||
SystemControlInfo:
|
||||
SaveDataSize: 0KB # It doesn't use any save data.
|
||||
RemasterVersion: 2
|
||||
StackSize: 0x40000
|
||||
# JumpId: 0
|
||||
Dependency:
|
||||
ac: 0x0004013000002402L
|
||||
am: 0x0004013000001502L
|
||||
boss: 0x0004013000003402L
|
||||
camera: 0x0004013000001602L
|
||||
cecd: 0x0004013000002602L
|
||||
cfg: 0x0004013000001702L
|
||||
codec: 0x0004013000001802L
|
||||
csnd: 0x0004013000002702L
|
||||
dlp: 0x0004013000002802L
|
||||
dsp: 0x0004013000001a02L
|
||||
friends: 0x0004013000003202L
|
||||
gpio: 0x0004013000001b02L
|
||||
gsp: 0x0004013000001c02L
|
||||
hid: 0x0004013000001d02L
|
||||
http: 0x0004013000002902L
|
||||
i2c: 0x0004013000001e02L
|
||||
ir: 0x0004013000003302L
|
||||
mcu: 0x0004013000001f02L
|
||||
mic: 0x0004013000002002L
|
||||
ndm: 0x0004013000002b02L
|
||||
news: 0x0004013000003502L
|
||||
nim: 0x0004013000002c02L
|
||||
nwm: 0x0004013000002d02L
|
||||
pdn: 0x0004013000002102L
|
||||
ps: 0x0004013000003102L
|
||||
ptm: 0x0004013000002202L
|
||||
ro: 0x0004013000003702L
|
||||
socket: 0x0004013000002e02L
|
||||
spi: 0x0004013000002302L
|
||||
ssl: 0x0004013000002f02L
|
||||
2585
libs/sf2dlib/sample/source/citra_img.c
Normal file
2585
libs/sf2dlib/sample/source/citra_img.c
Normal file
File diff suppressed because it is too large
Load diff
2363
libs/sf2dlib/sample/source/dice_img.c
Normal file
2363
libs/sf2dlib/sample/source/dice_img.c
Normal file
File diff suppressed because it is too large
Load diff
83
libs/sf2dlib/sample/source/main.c
Normal file
83
libs/sf2dlib/sample/source/main.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
|
||||
extern const struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bytes_per_pixel;
|
||||
unsigned char pixel_data[];
|
||||
} citra_img;
|
||||
|
||||
extern const struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bytes_per_pixel;
|
||||
unsigned char pixel_data[];
|
||||
} dice_img;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Set the random seed based on the time
|
||||
srand(time(NULL));
|
||||
|
||||
sf2d_init();
|
||||
sf2d_set_clear_color(RGBA8(0x40, 0x40, 0x40, 0xFF));
|
||||
|
||||
|
||||
sf2d_texture *tex1 = sf2d_create_texture_mem_RGBA8(dice_img.pixel_data, dice_img.width, dice_img.height, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
sf2d_texture *tex2 = sf2d_create_texture_mem_RGBA8(citra_img.pixel_data, citra_img.width, citra_img.height, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
|
||||
float rad = 0.0f;
|
||||
u16 touch_x = 320/2;
|
||||
u16 touch_y = 240/2;
|
||||
touchPosition touch;
|
||||
circlePosition circle;
|
||||
u32 held;
|
||||
|
||||
while (aptMainLoop()) {
|
||||
|
||||
hidScanInput();
|
||||
hidCircleRead(&circle);
|
||||
held = hidKeysHeld();
|
||||
|
||||
if (held & KEY_START) {
|
||||
break;
|
||||
} else if (held & KEY_TOUCH) {
|
||||
hidTouchRead(&touch);
|
||||
touch_x = touch.px;
|
||||
touch_y = touch.py;
|
||||
} else if (held & (KEY_L | KEY_R)) {
|
||||
sf2d_set_clear_color(RGBA8(rand()%255, rand()%255, rand()%255, 255));
|
||||
}
|
||||
|
||||
sf2d_start_frame(GFX_TOP, GFX_LEFT);
|
||||
sf2d_draw_rectangle_rotate(260, 20, 40, 40, RGBA8(0xFF, 0xFF, 0x00, 0xFF), -2.0f*rad);
|
||||
sf2d_draw_rectangle(20, 60, 40, 40, RGBA8(0xFF, 0x00, 0x00, 0xFF));
|
||||
sf2d_draw_rectangle(5, 5, 30, 30, RGBA8(0x00, 0xFF, 0xFF, 0xFF));
|
||||
sf2d_draw_texture_rotate(tex1, 320/2-tex1->width/2 + circle.dx, 240/2-tex1->height/2 - circle.dy, rad);
|
||||
sf2d_end_frame();
|
||||
|
||||
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||
sf2d_draw_rectangle_rotate(190, 160, 70, 60, RGBA8(0xFF, 0xFF, 0xFF, 0xFF), 3.0f*rad);
|
||||
sf2d_draw_rectangle(30, 100, 40, 60, RGBA8(0xFF, 0x00, 0xFF, 0xFF));
|
||||
sf2d_draw_texture_rotate(tex2, touch_x-tex1->width/2, touch_y-tex1->height/2, -rad);
|
||||
sf2d_draw_rectangle(160-15 + cosf(rad)*50.0f, 120-15 + sinf(rad)*50.0f, 30, 30, RGBA8(0x00, 0xFF, 0xFF, 0xFF));
|
||||
sf2d_draw_fill_circle(40, 40, 35, RGBA8(0x00, 0xFF, 0x00, 0xFF));
|
||||
sf2d_end_frame();
|
||||
|
||||
rad += 0.2f;
|
||||
|
||||
sf2d_swapbuffers();
|
||||
}
|
||||
|
||||
sf2d_free_texture(tex1);
|
||||
sf2d_free_texture(tex2);
|
||||
|
||||
sf2d_fini();
|
||||
return 0;
|
||||
}
|
||||
21
libs/sfillib/LICENSE
Normal file
21
libs/sfillib/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Sergi Granell (xerpi), xerpi.g.12@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
7
libs/sfillib/README.md
Normal file
7
libs/sfillib/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
## SFILLIB
|
||||
|
||||
|
||||
Simple and Fast Image Loading library for the Nintendo 3DS (using sf2dlib and ctrulib)
|
||||
|
||||
### Documentation
|
||||
http://xerpi.github.io/sfillib/html/sfil_8h.html
|
||||
2362
libs/sfillib/libsfil/Doxyfile
Normal file
2362
libs/sfillib/libsfil/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
145
libs/sfillib/libsfil/Makefile
Normal file
145
libs/sfillib/libsfil/Makefile
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sfil
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(PORTLIBS) \
|
||||
$(CURDIR)/../../3ds_portlibs/build \
|
||||
$(CURDIR)/../../sf2dlib/libsf2d
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(foreach dir,$(PORTLIBS),-I$(dir)/include/freetype2) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
$(BUILD): lib
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) lib latex html
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
install: $(BUILD)
|
||||
@cp $(OUTPUT) $(CTRULIB)/lib
|
||||
@cp include/sfil.h $(CTRULIB)/include
|
||||
@echo "Installed!"
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
docs:
|
||||
@doxygen Doxyfile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%_vsh.h %.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
71
libs/sfillib/libsfil/include/sfil.h
Normal file
71
libs/sfillib/libsfil/include/sfil.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* @file sfil.h
|
||||
* @author Sergi Granell (xerpi)
|
||||
* @date 2 April 2015
|
||||
* @brief sfillib header
|
||||
*/
|
||||
|
||||
#ifndef SFIL_H
|
||||
#define SFIL_H
|
||||
|
||||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Loads a PNG image from the SD card
|
||||
* @param filename the path of the image to load
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_PNG_file(const char *filename, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Loads a PNG image from a memory buffer
|
||||
* @param buffer the pointer of the memory buffer to load the image from
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_PNG_buffer(const void *buffer, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Loads a JPG/JPEG image from the SD card
|
||||
* @param filename the path of the image to load
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_JPEG_file(const char *filename, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Loads a JPG/JPEG image from a memory buffer
|
||||
* @param buffer the pointer of the memory buffer to load the image from
|
||||
* @param buffer_size the size of the memory buffer
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_JPEG_buffer(const void *buffer, unsigned long buffer_size, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Loads a BMP image from the SD card
|
||||
* @param filename the path of the image to load
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_BMP_file(const char *filename, sf2d_place place);
|
||||
|
||||
/**
|
||||
* @brief Loads a BMP image from a memory buffer
|
||||
* @param buffer the pointer of the memory buffer to load the image from
|
||||
* @param place where to allocate the texture
|
||||
* @return a pointer to the newly created texture/image
|
||||
*/
|
||||
sf2d_texture *sfil_load_BMP_buffer(const void *buffer, sf2d_place place);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
171
libs/sfillib/libsfil/source/sfil_bmp.c
Normal file
171
libs/sfillib/libsfil/source/sfil_bmp.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#include "sfil.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BMP_SIGNATURE (0x4D42)
|
||||
|
||||
typedef struct {
|
||||
unsigned short bfType;
|
||||
unsigned int bfSize;
|
||||
unsigned short bfReserved1;
|
||||
unsigned short bfReserved2;
|
||||
unsigned int bfOffBits;
|
||||
}__attribute__((packed)) BITMAPFILEHEADER;
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int biSize;
|
||||
unsigned int biWidth;
|
||||
unsigned int biHeight;
|
||||
unsigned short biPlanes;
|
||||
unsigned short biBitCount;
|
||||
unsigned int biCompression;
|
||||
unsigned int biSizeImage;
|
||||
unsigned int biXPelsPerMeter;
|
||||
unsigned int biYPelsPerMeter;
|
||||
unsigned int biClrUsed;
|
||||
unsigned int biClrImportant;
|
||||
}__attribute__((packed)) BITMAPINFOHEADER;
|
||||
|
||||
|
||||
static sf2d_texture *_sfil_load_BMP_generic(
|
||||
BITMAPFILEHEADER *bmp_fh,
|
||||
BITMAPINFOHEADER *bmp_ih,
|
||||
void *user_data,
|
||||
void (*seek_fn)(void *user_data, unsigned int offset),
|
||||
void (*read_fn)(void *user_data, void *buffer, unsigned int length),
|
||||
sf2d_place place)
|
||||
{
|
||||
unsigned int row_size = bmp_ih->biWidth * (bmp_ih->biBitCount/8);
|
||||
if (row_size%4 != 0) {
|
||||
row_size += 4-(row_size%4);
|
||||
}
|
||||
|
||||
sf2d_texture *texture = sf2d_create_texture(bmp_ih->biWidth, bmp_ih->biHeight,
|
||||
GPU_RGBA8, place);
|
||||
|
||||
seek_fn(user_data, bmp_fh->bfOffBits);
|
||||
|
||||
int stride = texture->pow2_w * 4;
|
||||
|
||||
void *buffer = malloc(row_size);
|
||||
unsigned int *tex_ptr;
|
||||
unsigned int color;
|
||||
int i, x, y;
|
||||
|
||||
for (i = 0; i < bmp_ih->biHeight; i++) {
|
||||
|
||||
read_fn(user_data, buffer, row_size);
|
||||
|
||||
y = bmp_ih->biHeight - 1 - i;
|
||||
tex_ptr = (unsigned int *)(texture->data + y*stride);
|
||||
|
||||
for (x = 0; x < bmp_ih->biWidth; x++) {
|
||||
|
||||
if (bmp_ih->biBitCount == 32) { //ABGR8888
|
||||
color = *(unsigned int *)(buffer + x*4);
|
||||
*tex_ptr = (color&0xFF)<<24 | ((color>>8)&0xFF)<<16 |
|
||||
((color>>16)&0xFF)<<8 | (color>>24);
|
||||
|
||||
} else if (bmp_ih->biBitCount == 24) { //BGR888
|
||||
unsigned char *address = buffer + x*3;
|
||||
*tex_ptr = (*address)<<16 | (*(address+1))<<8 |
|
||||
(*(address+2)) | (0xFF<<24);
|
||||
|
||||
} else if (bmp_ih->biBitCount == 16) { //BGR565
|
||||
color = *(unsigned short *)(buffer + x*2);
|
||||
unsigned char r = (color & 0x1F) *((float)255/31);
|
||||
unsigned char g = ((color>>5) & 0x3F) *((float)255/63);
|
||||
unsigned char b = ((color>>11) & 0x1F) *((float)255/31);
|
||||
*tex_ptr = ((r<<16) | (g<<8) | b | (0xFF<<24));
|
||||
}
|
||||
|
||||
tex_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
sf2d_texture_tile32(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void _sfil_read_bmp_file_seek_fn(void *user_data, unsigned int offset)
|
||||
{
|
||||
fseek((FILE *)user_data, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
static void _sfil_read_bmp_file_read_fn(void *user_data, void *buffer, unsigned int length)
|
||||
{
|
||||
fread(buffer, 1, length, (FILE *)user_data);
|
||||
}
|
||||
|
||||
static void _sfil_read_bmp_buffer_seek_fn(void *user_data, unsigned int offset)
|
||||
{
|
||||
*(unsigned int *)user_data += offset;
|
||||
}
|
||||
|
||||
static void _sfil_read_bmp_buffer_read_fn(void *user_data, void *buffer, unsigned int length)
|
||||
{
|
||||
memcpy(buffer, (void *)*(unsigned int *)user_data, length);
|
||||
*(unsigned int *)user_data += length;
|
||||
}
|
||||
|
||||
sf2d_texture *sfil_load_BMP_file(const char *filename, sf2d_place place)
|
||||
{
|
||||
FILE *fp;
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
BITMAPFILEHEADER bmp_fh;
|
||||
fread((void *)&bmp_fh, 1, sizeof(BITMAPFILEHEADER), fp);
|
||||
if (bmp_fh.bfType != BMP_SIGNATURE) {
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER bmp_ih;
|
||||
fread((void *)&bmp_ih, 1, sizeof(BITMAPINFOHEADER), fp);
|
||||
|
||||
sf2d_texture *texture = _sfil_load_BMP_generic(&bmp_fh,
|
||||
&bmp_ih,
|
||||
(void *)&fp,
|
||||
_sfil_read_bmp_file_seek_fn,
|
||||
_sfil_read_bmp_file_read_fn,
|
||||
place);
|
||||
|
||||
fclose(fp);
|
||||
return texture;
|
||||
|
||||
exit_close:
|
||||
fclose(fp);
|
||||
exit_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
sf2d_texture *sfil_load_BMP_buffer(const void *buffer, sf2d_place place)
|
||||
{
|
||||
BITMAPFILEHEADER bmp_fh;
|
||||
memcpy(&bmp_fh, buffer, sizeof(BITMAPFILEHEADER));
|
||||
if (bmp_fh.bfType != BMP_SIGNATURE) {
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER bmp_ih;
|
||||
memcpy(&bmp_ih, buffer + sizeof(BITMAPFILEHEADER), sizeof(BITMAPINFOHEADER));
|
||||
|
||||
unsigned int buffer_address = (unsigned int)buffer;
|
||||
|
||||
sf2d_texture *texture = _sfil_load_BMP_generic(&bmp_fh,
|
||||
&bmp_ih,
|
||||
(void *)&buffer_address,
|
||||
_sfil_read_bmp_buffer_seek_fn,
|
||||
_sfil_read_bmp_buffer_read_fn,
|
||||
place);
|
||||
|
||||
return texture;
|
||||
exit_error:
|
||||
return NULL;
|
||||
}
|
||||
97
libs/sfillib/libsfil/source/sfil_jpeg.c
Normal file
97
libs/sfillib/libsfil/source/sfil_jpeg.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include "sfil.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <jpeglib.h>
|
||||
|
||||
|
||||
static sf2d_texture *_sfil_load_JPEG_generic(struct jpeg_decompress_struct *jinfo, struct jpeg_error_mgr *jerr, sf2d_place place)
|
||||
{
|
||||
int row_bytes;
|
||||
switch (jinfo->out_color_space) {
|
||||
case JCS_RGB:
|
||||
row_bytes = jinfo->image_width * 3;
|
||||
break;
|
||||
default:
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
sf2d_texture *texture = sf2d_create_texture(jinfo->image_width,
|
||||
jinfo->image_height,
|
||||
GPU_RGBA8, place);
|
||||
|
||||
JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW));
|
||||
buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_bytes);
|
||||
|
||||
unsigned int i, color, *tex_ptr;
|
||||
unsigned char *jpeg_ptr;
|
||||
void *row_ptr = texture->data;
|
||||
jpeg_start_decompress(jinfo);
|
||||
|
||||
int stride = texture->pow2_w * 4;
|
||||
|
||||
while (jinfo->output_scanline < jinfo->output_height) {
|
||||
jpeg_read_scanlines(jinfo, buffer, 1);
|
||||
tex_ptr = (row_ptr += stride);
|
||||
for (i = 0, jpeg_ptr = buffer[0]; i < jinfo->output_width; i++) {
|
||||
color = *(jpeg_ptr++);
|
||||
color |= *(jpeg_ptr++)<<8;
|
||||
color |= *(jpeg_ptr++)<<16;
|
||||
*(tex_ptr++) = color | 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer[0]);
|
||||
free(buffer);
|
||||
|
||||
sf2d_texture_tile32(texture);
|
||||
return texture;
|
||||
|
||||
exit_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
sf2d_texture *sfil_load_JPEG_file(const char *filename, sf2d_place place)
|
||||
{
|
||||
FILE *fp;
|
||||
if ((fp = fopen(filename, "rb")) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct jpeg_decompress_struct jinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
jinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_decompress(&jinfo);
|
||||
jpeg_stdio_src(&jinfo, fp);
|
||||
jpeg_read_header(&jinfo, 1);
|
||||
|
||||
sf2d_texture *texture = _sfil_load_JPEG_generic(&jinfo, &jerr, place);
|
||||
|
||||
jpeg_finish_decompress(&jinfo);
|
||||
jpeg_destroy_decompress(&jinfo);
|
||||
|
||||
fclose(fp);
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
sf2d_texture *sfil_load_JPEG_buffer(const void *buffer, unsigned long buffer_size, sf2d_place place)
|
||||
{
|
||||
struct jpeg_decompress_struct jinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
jinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
jpeg_create_decompress(&jinfo);
|
||||
jpeg_mem_src(&jinfo, (void *)buffer, buffer_size);
|
||||
jpeg_read_header(&jinfo, 1);
|
||||
|
||||
sf2d_texture *texture = _sfil_load_JPEG_generic(&jinfo, &jerr, place);
|
||||
|
||||
jpeg_finish_decompress(&jinfo);
|
||||
jpeg_destroy_decompress(&jinfo);
|
||||
|
||||
return texture;
|
||||
}
|
||||
139
libs/sfillib/libsfil/source/sfil_png.c
Normal file
139
libs/sfillib/libsfil/source/sfil_png.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include "sfil.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <png.h>
|
||||
|
||||
#define PNG_SIGSIZE (8)
|
||||
|
||||
static void _sfil_read_png_file_fn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
FILE *fp = (FILE *)png_get_io_ptr(png_ptr);
|
||||
fread(data, 1, length, fp);
|
||||
}
|
||||
|
||||
static void _sfil_read_png_buffer_fn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
unsigned int *address = png_get_io_ptr(png_ptr);
|
||||
memcpy(data, (void *)*address, length);
|
||||
*address += length;
|
||||
}
|
||||
|
||||
static sf2d_texture *_sfil_load_PNG_generic(const void *io_ptr, png_rw_ptr read_data_fn, sf2d_place place)
|
||||
{
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) {
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
goto exit_destroy_read;
|
||||
}
|
||||
|
||||
png_bytep *row_ptrs = NULL;
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
|
||||
if (row_ptrs != NULL)
|
||||
free(row_ptrs);
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
png_set_read_fn(png_ptr, (png_voidp)io_ptr, read_data_fn);
|
||||
png_set_sig_bytes(png_ptr, PNG_SIGSIZE);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
unsigned int width, height;
|
||||
int bit_depth, color_type;
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
||||
&color_type, NULL, NULL, NULL);
|
||||
|
||||
if ((color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
|
||||
|| (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
|| png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)
|
||||
|| (bit_depth == 16)) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
||||
if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB)
|
||||
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
row_ptrs = (png_bytep *)malloc(sizeof(png_bytep) * height);
|
||||
sf2d_texture *texture = sf2d_create_texture(width, height, GPU_RGBA8, place);
|
||||
|
||||
int stride = texture->pow2_w * 4;
|
||||
int i;
|
||||
for (i = 0; i < height; i++) {
|
||||
row_ptrs[i] = (png_bytep)(texture->data + i*stride);
|
||||
}
|
||||
|
||||
png_read_image(png_ptr, row_ptrs);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
|
||||
free(row_ptrs);
|
||||
|
||||
sf2d_texture_tile32(texture);
|
||||
return texture;
|
||||
|
||||
exit_destroy_read:
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
|
||||
exit_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
sf2d_texture *sfil_load_PNG_file(const char *filename, sf2d_place place)
|
||||
{
|
||||
png_byte pngsig[PNG_SIGSIZE];
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
if (fread(pngsig, 1, PNG_SIGSIZE, fp) != PNG_SIGSIZE) {
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
if (png_sig_cmp(pngsig, 0, PNG_SIGSIZE) != 0) {
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
sf2d_texture *texture = _sfil_load_PNG_generic((void *)fp, _sfil_read_png_file_fn, place);
|
||||
fclose(fp);
|
||||
return texture;
|
||||
|
||||
exit_close:
|
||||
fclose(fp);
|
||||
exit_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sf2d_texture *sfil_load_PNG_buffer(const void *buffer, sf2d_place place)
|
||||
{
|
||||
if (png_sig_cmp((png_byte *) buffer, 0, PNG_SIGSIZE) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int buffer_address = (unsigned int)buffer + PNG_SIGSIZE;
|
||||
|
||||
return _sfil_load_PNG_generic((void *)&buffer_address, _sfil_read_png_buffer_fn, place);
|
||||
}
|
||||
207
libs/sfillib/sample/Makefile
Normal file
207
libs/sfillib/sample/Makefile
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sfil_sample
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
APP_TITLE := SFILLIB sample
|
||||
APP_DESCRIPTION := SFILLIB sample
|
||||
APP_AUTHOR := xerpi
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lsfil -lpng -ljpeg -lz -lsf2d -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(PORTLIBS)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(TARGET)-strip.elf $(TARGET).cia $(TARGET).3ds
|
||||
#---------------------------------------------------------------------------------
|
||||
$(TARGET)-strip.elf: $(BUILD)
|
||||
@$(STRIP) $(TARGET).elf -o $(TARGET)-strip.elf
|
||||
#---------------------------------------------------------------------------------
|
||||
cci: $(TARGET)-strip.elf
|
||||
@makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds
|
||||
@echo "built ... sfil_sample.3ds"
|
||||
#---------------------------------------------------------------------------------
|
||||
cia: $(TARGET)-strip.elf
|
||||
@makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf resources/$(TARGET).rsf -exefslogo -target t
|
||||
@echo "built ... sfil_sample.cia"
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@3dslink $(TARGET).3dsx
|
||||
#---------------------------------------------------------------------------------
|
||||
run: $(BUILD)
|
||||
@citra $(TARGET).3dsx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
|
||||
else
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.jpeg.o: %.jpeg
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.png.o : %.png
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
BIN
libs/sfillib/sample/data/3dbrew.png
Normal file
BIN
libs/sfillib/sample/data/3dbrew.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
BIN
libs/sfillib/sample/data/citra.jpeg
Normal file
BIN
libs/sfillib/sample/data/citra.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
236
libs/sfillib/sample/resources/sfil_sample.rsf
Normal file
236
libs/sfillib/sample/resources/sfil_sample.rsf
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
BasicInfo:
|
||||
Title : "SFILLIB sample"
|
||||
CompanyCode : "00"
|
||||
ProductCode : "sfil-sample"
|
||||
ContentType : Application # Application / SystemUpdate / Manual / Child / Trial
|
||||
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
|
||||
|
||||
#Rom:
|
||||
# Specifies the root path of the file system to include in the ROM.
|
||||
# HostRoot : "$(ROMFS_ROOT)"
|
||||
|
||||
|
||||
TitleInfo:
|
||||
UniqueId : 0xf0030 # This was/is the first real homebrew app. I hope this TID range is not used by any retail game/app.
|
||||
Category : Application # Application / SystemApplication / Applet / Firmware / Base / DlpChild / Demo / Contents / SystemContents / SharedContents / AddOnContents / Patch / AutoUpdateContents
|
||||
|
||||
CardInfo:
|
||||
MediaSize : 512MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB / 8GB / 16GB / 32GB
|
||||
MediaType : Card1 # Card1 / Card2
|
||||
CardDevice : NorFlash # NorFlash(Pick this if you use savedata) / None
|
||||
|
||||
|
||||
Option:
|
||||
UseOnSD : true # true if App is to be installed to SD
|
||||
EnableCompress : true # Compresses exefs code
|
||||
FreeProductCode : true # Removes limitations on ProductCode
|
||||
EnableCrypt : false # Enables encryption for NCCH and CIA
|
||||
MediaFootPadding : false # If true CCI files are created with padding
|
||||
|
||||
ExeFs: # these are the program segments from the ELF, check your elf for the appropriate segment names
|
||||
ReadOnly:
|
||||
- .rodata
|
||||
- RO
|
||||
ReadWrite:
|
||||
- .data
|
||||
- RO
|
||||
Text:
|
||||
- .init
|
||||
- .text
|
||||
- STUP_ENTRY
|
||||
|
||||
PlainRegion: # only used with SDK ELFs
|
||||
# - .module_id
|
||||
|
||||
AccessControlInfo:
|
||||
# UseOtherVariationSaveData : true
|
||||
# UseExtSaveData : true
|
||||
# ExtSaveDataId: 0xffffffff
|
||||
# SystemSaveDataId1: 0x220
|
||||
# SystemSaveDataId2: 0x00040010
|
||||
# OtherUserSaveDataId1: 0x220
|
||||
# OtherUserSaveDataId2: 0x330
|
||||
# OtherUserSaveDataId3: 0x440
|
||||
# UseExtendedSaveDataAccessControl: true
|
||||
# AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]
|
||||
FileSystemAccess:
|
||||
# - CategorySystemApplication
|
||||
# - CategoryHardwareCheck
|
||||
# - CategoryFileSystemTool
|
||||
- Debug
|
||||
# - TwlCardBackup
|
||||
# - TwlNandData
|
||||
# - Boss
|
||||
- DirectSdmc
|
||||
# - Core
|
||||
# - CtrNandRo
|
||||
# - CtrNandRw
|
||||
# - CtrNandRoWrite
|
||||
# - CategorySystemSettings
|
||||
# - CardBoard
|
||||
# - ExportImportIvs
|
||||
# - DirectSdmcWrite
|
||||
# - SwitchCleanup
|
||||
# - SaveDataMove
|
||||
# - Shop
|
||||
# - Shell
|
||||
# - CategoryHomeMenu
|
||||
IoAccessControl:
|
||||
# - FsMountNand
|
||||
# - FsMountNandRoWrite
|
||||
# - FsMountTwln
|
||||
# - FsMountWnand
|
||||
# - FsMountCardSpi
|
||||
# - UseSdif3
|
||||
# - CreateSeed
|
||||
# - UseCardSpi
|
||||
|
||||
IdealProcessor : 0
|
||||
AffinityMask : 1
|
||||
|
||||
Priority : 16
|
||||
|
||||
MaxCpu : 0x9E # Default
|
||||
|
||||
DisableDebug : true
|
||||
EnableForceDebug : false
|
||||
CanWriteSharedPage : true
|
||||
CanUsePrivilegedPriority : false
|
||||
CanUseNonAlphabetAndNumber : true
|
||||
PermitMainFunctionArgument : true
|
||||
CanShareDeviceMemory : true
|
||||
RunnableOnSleep : false
|
||||
SpecialMemoryArrange : true
|
||||
|
||||
CoreVersion : 2
|
||||
DescVersion : 2
|
||||
|
||||
ReleaseKernelMajor : "02"
|
||||
ReleaseKernelMinor : "33"
|
||||
MemoryType : Application # Application / System / Base
|
||||
HandleTableSize: 512
|
||||
IORegisterMapping:
|
||||
- 1ff50000-1ff57fff
|
||||
- 1ff70000-1ff77fff
|
||||
MemoryMapping:
|
||||
- 1f000000-1f5fffff:r
|
||||
SystemCallAccess:
|
||||
ArbitrateAddress: 34
|
||||
Break: 60
|
||||
CancelTimer: 28
|
||||
ClearEvent: 25
|
||||
ClearTimer: 29
|
||||
CloseHandle: 35
|
||||
ConnectToPort: 45
|
||||
ControlMemory: 1
|
||||
CreateAddressArbiter: 33
|
||||
CreateEvent: 23
|
||||
CreateMemoryBlock: 30
|
||||
CreateMutex: 19
|
||||
CreateSemaphore: 21
|
||||
CreateThread: 8
|
||||
CreateTimer: 26
|
||||
DuplicateHandle: 39
|
||||
ExitProcess: 3
|
||||
ExitThread: 9
|
||||
GetCurrentProcessorNumber: 17
|
||||
GetHandleInfo: 41
|
||||
GetProcessId: 53
|
||||
GetProcessIdOfThread: 54
|
||||
GetProcessIdealProcessor: 6
|
||||
GetProcessInfo: 43
|
||||
GetResourceLimit: 56
|
||||
GetResourceLimitCurrentValues: 58
|
||||
GetResourceLimitLimitValues: 57
|
||||
GetSystemInfo: 42
|
||||
GetSystemTick: 40
|
||||
GetThreadContext: 59
|
||||
GetThreadId: 55
|
||||
GetThreadIdealProcessor: 15
|
||||
GetThreadInfo: 44
|
||||
GetThreadPriority: 11
|
||||
MapMemoryBlock: 31
|
||||
OutputDebugString: 61
|
||||
QueryMemory: 2
|
||||
ReleaseMutex: 20
|
||||
ReleaseSemaphore: 22
|
||||
SendSyncRequest1: 46
|
||||
SendSyncRequest2: 47
|
||||
SendSyncRequest3: 48
|
||||
SendSyncRequest4: 49
|
||||
SendSyncRequest: 50
|
||||
SetThreadPriority: 12
|
||||
SetTimer: 27
|
||||
SignalEvent: 24
|
||||
SleepThread: 10
|
||||
UnmapMemoryBlock: 32
|
||||
WaitSynchronization1: 36
|
||||
WaitSynchronizationN: 37
|
||||
InterruptNumbers:
|
||||
ServiceAccessControl:
|
||||
- APT:U
|
||||
- $hioFIO
|
||||
- $hostio0
|
||||
- $hostio1
|
||||
- ac:u
|
||||
- boss:U
|
||||
- cam:u
|
||||
- cecd:u
|
||||
- cfg:u
|
||||
- dlp:FKCL
|
||||
- dlp:SRVR
|
||||
- dsp::DSP
|
||||
- frd:u
|
||||
- fs:USER
|
||||
- gsp::Gpu
|
||||
- hid:USER
|
||||
- http:C
|
||||
- mic:u
|
||||
- ndm:u
|
||||
- news:u
|
||||
- nwm::UDS
|
||||
- ptm:u
|
||||
- pxi:dev
|
||||
- soc:U
|
||||
- ssl:C
|
||||
- y2r:u
|
||||
- ldr:ro
|
||||
- ir:USER
|
||||
|
||||
|
||||
SystemControlInfo:
|
||||
SaveDataSize: 0KB # It doesn't use any save data.
|
||||
RemasterVersion: 2
|
||||
StackSize: 0x40000
|
||||
# JumpId: 0
|
||||
Dependency:
|
||||
ac: 0x0004013000002402L
|
||||
am: 0x0004013000001502L
|
||||
boss: 0x0004013000003402L
|
||||
camera: 0x0004013000001602L
|
||||
cecd: 0x0004013000002602L
|
||||
cfg: 0x0004013000001702L
|
||||
codec: 0x0004013000001802L
|
||||
csnd: 0x0004013000002702L
|
||||
dlp: 0x0004013000002802L
|
||||
dsp: 0x0004013000001a02L
|
||||
friends: 0x0004013000003202L
|
||||
gpio: 0x0004013000001b02L
|
||||
gsp: 0x0004013000001c02L
|
||||
hid: 0x0004013000001d02L
|
||||
http: 0x0004013000002902L
|
||||
i2c: 0x0004013000001e02L
|
||||
ir: 0x0004013000003302L
|
||||
mcu: 0x0004013000001f02L
|
||||
mic: 0x0004013000002002L
|
||||
ndm: 0x0004013000002b02L
|
||||
news: 0x0004013000003502L
|
||||
nim: 0x0004013000002c02L
|
||||
nwm: 0x0004013000002d02L
|
||||
pdn: 0x0004013000002102L
|
||||
ps: 0x0004013000003102L
|
||||
ptm: 0x0004013000002202L
|
||||
ro: 0x0004013000003702L
|
||||
socket: 0x0004013000002e02L
|
||||
spi: 0x0004013000002302L
|
||||
ssl: 0x0004013000002f02L
|
||||
45
libs/sfillib/sample/source/main.c
Normal file
45
libs/sfillib/sample/source/main.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
#include <sfil.h>
|
||||
|
||||
#include "citra_jpeg.h"
|
||||
#include "3dbrew_png.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
sf2d_init();
|
||||
sf2d_set_clear_color(RGBA8(0x40, 0x40, 0x40, 0xFF));
|
||||
|
||||
sf2d_texture *tex1 = sfil_load_JPEG_buffer(citra_jpeg, citra_jpeg_size, SF2D_PLACE_RAM);
|
||||
sf2d_texture *tex2 = sfil_load_PNG_buffer(_3dbrew_png, SF2D_PLACE_RAM);
|
||||
|
||||
while (aptMainLoop()) {
|
||||
|
||||
hidScanInput();
|
||||
|
||||
if (hidKeysHeld() & KEY_START) {
|
||||
break;
|
||||
}
|
||||
|
||||
sf2d_start_frame(GFX_TOP, GFX_LEFT);
|
||||
|
||||
sf2d_draw_texture(tex1, 400/2 - tex1->width/2, 240/2 - tex1->height/2);
|
||||
|
||||
sf2d_end_frame();
|
||||
|
||||
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||
|
||||
sf2d_draw_texture(tex2, 320/2 - tex2->width/2, 240/2 - tex2->height/2);
|
||||
|
||||
sf2d_end_frame();
|
||||
|
||||
sf2d_swapbuffers();
|
||||
}
|
||||
|
||||
sf2d_free_texture(tex1);
|
||||
sf2d_free_texture(tex2);
|
||||
|
||||
sf2d_fini();
|
||||
return 0;
|
||||
}
|
||||
21
libs/sftdlib/LICENSE
Normal file
21
libs/sftdlib/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Sergi Granell (xerpi), xerpi.g.12@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
11
libs/sftdlib/README.md
Normal file
11
libs/sftdlib/README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## SFTDLIB
|
||||
|
||||
Simple and Fast Text Drawing library for the Nintendo 3DS (using sf2dlib and ctrulib)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
ctrulib: https://github.com/smealum/ctrulib
|
||||
|
||||
SF2D: https://github.com/xerpi/sf2dlib
|
||||
|
||||
FreeType2 (portlib): https://github.com/xerpi/3ds_portlibs
|
||||
2303
libs/sftdlib/libsftd/Doxyfile
Normal file
2303
libs/sftdlib/libsftd/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
141
libs/sftdlib/libsftd/Makefile
Normal file
141
libs/sftdlib/libsftd/Makefile
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sftd
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(PORTLIBS) \
|
||||
$(CURDIR)/../../3ds_portlibs/build \
|
||||
$(CURDIR)/../../sf2dlib/libsf2d
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(foreach dir,$(PORTLIBS),-I$(dir)/include/freetype2) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
$(BUILD): lib
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) lib latex html
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
install: $(BUILD)
|
||||
@cp $(OUTPUT) $(CTRULIB)/lib
|
||||
@cp include/sftd.h $(CTRULIB)/include
|
||||
@echo "Installed!"
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%_vsh.h %.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
113
libs/sftdlib/libsftd/include/sftd.h
Normal file
113
libs/sftdlib/libsftd/include/sftd.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* @file sftd.h
|
||||
* @author Sergi Granell (xerpi)
|
||||
* @date 2 April 2015
|
||||
* @brief sftdlib header
|
||||
*/
|
||||
|
||||
#ifndef SFTD_H
|
||||
#define SFTD_H
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Structs
|
||||
|
||||
/**
|
||||
* @brief Represents a font
|
||||
*/
|
||||
typedef struct sftd_font sftd_font;
|
||||
|
||||
// Basic functions
|
||||
|
||||
/**
|
||||
* @brief Initializates the library
|
||||
* @return Whether the initialization has been successful or not
|
||||
*/
|
||||
int sftd_init();
|
||||
|
||||
/**
|
||||
* @brief Finishes the library
|
||||
* @return Whether the finalization has been successful or not
|
||||
*/
|
||||
int sftd_fini();
|
||||
|
||||
/**
|
||||
* @brief Loads a font from a file
|
||||
* @param filename the path to the font
|
||||
* @return a pointer to the loaded font (NULL on error)
|
||||
*/
|
||||
sftd_font *sftd_load_font_file(const char *filename);
|
||||
|
||||
/**
|
||||
* @brief Loads a font from memory
|
||||
* @param buffer the address of the font
|
||||
* @param size the size of the font buffer
|
||||
* @return a pointer to the loaded font (NULL on error)
|
||||
*/
|
||||
sftd_font *sftd_load_font_mem(const void *buffer, unsigned int size);
|
||||
|
||||
/**
|
||||
* @brief Frees a font
|
||||
* @param font pointer to the font to freeze
|
||||
*/
|
||||
void sftd_free_font(sftd_font *font);
|
||||
|
||||
// Draw functions
|
||||
|
||||
/**
|
||||
* @brief Draws text using a font
|
||||
* @param font the font to use
|
||||
* @param x the x coordinate to draw the text to
|
||||
* @param y the y coordinate to draw the text to
|
||||
* @param color the color to draw the font
|
||||
* @param size the font size
|
||||
* @param text a pointer to the text to draw
|
||||
*/
|
||||
void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text);
|
||||
|
||||
/**
|
||||
* @brief Draws formatted text using a font
|
||||
* @param font the font to use
|
||||
* @param x the x coordinate to draw the text to
|
||||
* @param y the y coordinate to draw the text to
|
||||
* @param color the color to draw the font
|
||||
* @param size the font size
|
||||
* @param text a pointer to the text to draw
|
||||
* @param ... variable arguments
|
||||
*/
|
||||
void sftd_draw_textf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text, ...);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws wide text using a font
|
||||
* @param font the font to use
|
||||
* @param x the x coordinate to draw the text to
|
||||
* @param y the y coordinate to draw the text to
|
||||
* @param color the color to draw the font
|
||||
* @param size the font size
|
||||
* @param text a pointer to the wide text to draw
|
||||
*/
|
||||
void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const wchar_t *text);
|
||||
|
||||
/**
|
||||
* @brief Draws formatted wide text using a font
|
||||
* @param font the font to use
|
||||
* @param x the x coordinate to draw the text to
|
||||
* @param y the y coordinate to draw the text to
|
||||
* @param color the color to draw the font
|
||||
* @param size the font size
|
||||
* @param text a pointer to the wide text to draw
|
||||
* @param ... variable arguments
|
||||
*/
|
||||
void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const wchar_t *text, ...);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
269
libs/sftdlib/libsftd/source/sftd.c
Normal file
269
libs/sftdlib/libsftd/source/sftd.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
#include "sftd.h"
|
||||
#include <wchar.h>
|
||||
#include <sf2d.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
static int sftd_initialized = 0;
|
||||
static FT_Library ftlibrary;
|
||||
static FTC_Manager ftcmanager;
|
||||
|
||||
typedef enum {
|
||||
SFTD_LOAD_FROM_FILE,
|
||||
SFTD_LOAD_FROM_MEM
|
||||
} sftd_font_load_from;
|
||||
|
||||
struct sftd_font {
|
||||
sftd_font_load_from from;
|
||||
union {
|
||||
char *filename;
|
||||
struct {
|
||||
const void *font_buffer;
|
||||
unsigned int buffer_size;
|
||||
};
|
||||
};
|
||||
FTC_CMapCache cmapcache;
|
||||
FTC_ImageCache imagecache;
|
||||
};
|
||||
|
||||
static FT_Error ftc_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face)
|
||||
{
|
||||
sftd_font *font = (sftd_font *)face_id;
|
||||
|
||||
FT_Error error = FT_Err_Cannot_Open_Resource;
|
||||
|
||||
if (font->from == SFTD_LOAD_FROM_FILE) {
|
||||
error = FT_New_Face(
|
||||
library,
|
||||
font->filename,
|
||||
0,
|
||||
face);
|
||||
} else if (font->from == SFTD_LOAD_FROM_MEM) {
|
||||
error = FT_New_Memory_Face(
|
||||
library,
|
||||
font->font_buffer,
|
||||
font->buffer_size,
|
||||
0,
|
||||
face);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int sftd_init()
|
||||
{
|
||||
if (sftd_initialized) return 2;
|
||||
|
||||
FT_Error error = FT_Init_FreeType(&ftlibrary);
|
||||
if (error != FT_Err_Ok) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = FTC_Manager_New(
|
||||
ftlibrary,
|
||||
0, /* use default */
|
||||
0, /* use default */
|
||||
0, /* use default */
|
||||
&ftc_face_requester, /* use our requester */
|
||||
NULL, /* user data */
|
||||
&ftcmanager);
|
||||
|
||||
if (error != FT_Err_Ok) {
|
||||
FT_Done_FreeType(ftlibrary);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sftd_initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sftd_fini()
|
||||
{
|
||||
if (!sftd_initialized) return 2;
|
||||
|
||||
FT_Error error = FT_Done_FreeType(ftlibrary);
|
||||
if (error != FT_Err_Ok) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FTC_Manager_Done(ftcmanager);
|
||||
|
||||
sftd_initialized = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sftd_font *sftd_load_font_file(const char *filename)
|
||||
{
|
||||
sftd_font *font = malloc(sizeof(*font));
|
||||
|
||||
size_t len = strlen(filename);
|
||||
|
||||
font->filename = malloc(len + 1);
|
||||
strcpy(font->filename, filename);
|
||||
font->filename[len] = '\0';
|
||||
|
||||
FTC_CMapCache_New(ftcmanager, &font->cmapcache);
|
||||
FTC_ImageCache_New(ftcmanager, &font->imagecache);
|
||||
|
||||
font->from = SFTD_LOAD_FROM_FILE;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
sftd_font *sftd_load_font_mem(const void *buffer, unsigned int size)
|
||||
{
|
||||
sftd_font *font = malloc(sizeof(*font));
|
||||
font->font_buffer = buffer;
|
||||
font->buffer_size = size;
|
||||
|
||||
FTC_CMapCache_New(ftcmanager, &font->cmapcache);
|
||||
FTC_ImageCache_New(ftcmanager, &font->imagecache);
|
||||
|
||||
font->from = SFTD_LOAD_FROM_MEM;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void sftd_free_font(sftd_font *font)
|
||||
{
|
||||
if (font) {
|
||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||
FTC_Manager_RemoveFaceID(ftcmanager, face_id);
|
||||
if (font->from == SFTD_LOAD_FROM_FILE) {
|
||||
free(font->filename);
|
||||
}
|
||||
free(font);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_bitmap(FT_Bitmap *bitmap, int x, int y, unsigned int color)
|
||||
{
|
||||
//This is too ugly
|
||||
sf2d_texture *tex = sf2d_create_texture(bitmap->width, bitmap->rows, GPU_RGBA8, SF2D_PLACE_TEMP);
|
||||
|
||||
int j, k;
|
||||
for (j = 0; j < bitmap->rows; j++) {
|
||||
for (k = 0; k < bitmap->width; k++) {
|
||||
((u32 *)tex->data)[j*tex->pow2_w + k] = __builtin_bswap32((color & ~0xFF) | bitmap->buffer[j*bitmap->width + k]);
|
||||
}
|
||||
}
|
||||
|
||||
sf2d_texture_tile32(tex);
|
||||
sf2d_draw_texture(tex, x, y);
|
||||
sf2d_free_texture(tex);
|
||||
}
|
||||
|
||||
void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text)
|
||||
{
|
||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||
FT_Face face;
|
||||
FTC_Manager_LookupFace(ftcmanager, face_id, &face);
|
||||
|
||||
FT_Int charmap_index;
|
||||
charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
|
||||
FT_Glyph glyph;
|
||||
FT_Bool use_kerning = FT_HAS_KERNING(face);
|
||||
FT_UInt glyph_index, previous = 0;
|
||||
int pen_x = x;
|
||||
int pen_y = y;
|
||||
|
||||
FTC_ScalerRec scaler;
|
||||
scaler.face_id = face_id;
|
||||
scaler.width = size;
|
||||
scaler.height = size;
|
||||
scaler.pixel = 1;
|
||||
|
||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||
|
||||
while (*text) {
|
||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||
|
||||
if (use_kerning && previous && glyph_index) {
|
||||
FT_Vector delta;
|
||||
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
||||
pen_x += delta.x >> 6;
|
||||
}
|
||||
|
||||
FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL);
|
||||
if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
|
||||
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
|
||||
|
||||
draw_bitmap(&bitmap_glyph->bitmap, pen_x + bitmap_glyph->left + x, pen_y - bitmap_glyph->top + y, color);
|
||||
|
||||
pen_x += bitmap_glyph->root.advance.x >> 16;
|
||||
pen_y += bitmap_glyph->root.advance.y >> 16;
|
||||
}
|
||||
|
||||
previous = glyph_index;
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
void sftd_draw_textf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text, ...)
|
||||
{
|
||||
char buffer[256];
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vsnprintf(buffer, 256, text, args);
|
||||
sftd_draw_text(font, x, y, color, size, buffer);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const wchar_t *text)
|
||||
{
|
||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||
FT_Face face;
|
||||
FTC_Manager_LookupFace(ftcmanager, face_id, &face);
|
||||
|
||||
FT_Int charmap_index;
|
||||
charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
|
||||
FT_Glyph glyph;
|
||||
FT_Bool use_kerning = FT_HAS_KERNING(face);
|
||||
FT_UInt glyph_index, previous = 0;
|
||||
int pen_x = x;
|
||||
int pen_y = y;
|
||||
|
||||
FTC_ScalerRec scaler;
|
||||
scaler.face_id = face_id;
|
||||
scaler.width = size;
|
||||
scaler.height = size;
|
||||
scaler.pixel = 1;
|
||||
|
||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||
|
||||
while (*text) {
|
||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||
|
||||
if (use_kerning && previous && glyph_index) {
|
||||
FT_Vector delta;
|
||||
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
||||
pen_x += delta.x >> 6;
|
||||
}
|
||||
|
||||
FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL);
|
||||
if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
|
||||
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
|
||||
|
||||
draw_bitmap(&bitmap_glyph->bitmap, pen_x + bitmap_glyph->left + x, pen_y - bitmap_glyph->top + y, color);
|
||||
|
||||
pen_x += bitmap_glyph->root.advance.x >> 16;
|
||||
pen_y += bitmap_glyph->root.advance.y >> 16;
|
||||
}
|
||||
|
||||
previous = glyph_index;
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const wchar_t *text, ...)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vswprintf(buffer, 256, text, args);
|
||||
sftd_draw_wtext(font, x, y, color, size, buffer);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
201
libs/sftdlib/sample/Makefile
Normal file
201
libs/sftdlib/sample/Makefile
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := sftd_sample
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
APP_TITLE := SFFTLIB sample
|
||||
APP_DESCRIPTION := SFFTLIB sample
|
||||
APP_AUTHOR := xerpi
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lsftd -lfreetype -lpng -lz -lsf2d -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB) $(PORTLIBS)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(TARGET)-strip.elf $(TARGET).cia $(TARGET).3ds
|
||||
#---------------------------------------------------------------------------------
|
||||
$(TARGET)-strip.elf: $(BUILD)
|
||||
@$(STRIP) $(TARGET).elf -o $(TARGET)-strip.elf
|
||||
#---------------------------------------------------------------------------------
|
||||
cci: $(TARGET)-strip.elf
|
||||
@makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds
|
||||
@echo "built ... sf2d_sample.3ds"
|
||||
#---------------------------------------------------------------------------------
|
||||
cia: $(TARGET)-strip.elf
|
||||
@makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf resources/$(TARGET).rsf -exefslogo -target t
|
||||
@echo "built ... sf2d_sample.cia"
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@3dslink $(TARGET).3dsx
|
||||
#---------------------------------------------------------------------------------
|
||||
run: $(BUILD)
|
||||
@citra $(TARGET).3dsx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
|
||||
else
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.ttf.o : %.ttf
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
BIN
libs/sftdlib/sample/data/airstrike.ttf
Normal file
BIN
libs/sftdlib/sample/data/airstrike.ttf
Normal file
Binary file not shown.
236
libs/sftdlib/sample/resources/sftd_sample.rsf
Normal file
236
libs/sftdlib/sample/resources/sftd_sample.rsf
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
BasicInfo:
|
||||
Title : "SFTDLIB sample"
|
||||
CompanyCode : "00"
|
||||
ProductCode : "sftd-sample"
|
||||
ContentType : Application # Application / SystemUpdate / Manual / Child / Trial
|
||||
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
|
||||
|
||||
#Rom:
|
||||
# Specifies the root path of the file system to include in the ROM.
|
||||
# HostRoot : "$(ROMFS_ROOT)"
|
||||
|
||||
|
||||
TitleInfo:
|
||||
UniqueId : 0xf0024 # This was/is the first real homebrew app. I hope this TID range is not used by any retail game/app.
|
||||
Category : Application # Application / SystemApplication / Applet / Firmware / Base / DlpChild / Demo / Contents / SystemContents / SharedContents / AddOnContents / Patch / AutoUpdateContents
|
||||
|
||||
CardInfo:
|
||||
MediaSize : 512MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB / 8GB / 16GB / 32GB
|
||||
MediaType : Card1 # Card1 / Card2
|
||||
CardDevice : NorFlash # NorFlash(Pick this if you use savedata) / None
|
||||
|
||||
|
||||
Option:
|
||||
UseOnSD : true # true if App is to be installed to SD
|
||||
EnableCompress : true # Compresses exefs code
|
||||
FreeProductCode : true # Removes limitations on ProductCode
|
||||
EnableCrypt : false # Enables encryption for NCCH and CIA
|
||||
MediaFootPadding : false # If true CCI files are created with padding
|
||||
|
||||
ExeFs: # these are the program segments from the ELF, check your elf for the appropriate segment names
|
||||
ReadOnly:
|
||||
- .rodata
|
||||
- RO
|
||||
ReadWrite:
|
||||
- .data
|
||||
- RO
|
||||
Text:
|
||||
- .init
|
||||
- .text
|
||||
- STUP_ENTRY
|
||||
|
||||
PlainRegion: # only used with SDK ELFs
|
||||
# - .module_id
|
||||
|
||||
AccessControlInfo:
|
||||
# UseOtherVariationSaveData : true
|
||||
# UseExtSaveData : true
|
||||
# ExtSaveDataId: 0xffffffff
|
||||
# SystemSaveDataId1: 0x220
|
||||
# SystemSaveDataId2: 0x00040010
|
||||
# OtherUserSaveDataId1: 0x220
|
||||
# OtherUserSaveDataId2: 0x330
|
||||
# OtherUserSaveDataId3: 0x440
|
||||
# UseExtendedSaveDataAccessControl: true
|
||||
# AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]
|
||||
FileSystemAccess:
|
||||
# - CategorySystemApplication
|
||||
# - CategoryHardwareCheck
|
||||
# - CategoryFileSystemTool
|
||||
- Debug
|
||||
# - TwlCardBackup
|
||||
# - TwlNandData
|
||||
# - Boss
|
||||
- DirectSdmc
|
||||
# - Core
|
||||
# - CtrNandRo
|
||||
# - CtrNandRw
|
||||
# - CtrNandRoWrite
|
||||
# - CategorySystemSettings
|
||||
# - CardBoard
|
||||
# - ExportImportIvs
|
||||
# - DirectSdmcWrite
|
||||
# - SwitchCleanup
|
||||
# - SaveDataMove
|
||||
# - Shop
|
||||
# - Shell
|
||||
# - CategoryHomeMenu
|
||||
IoAccessControl:
|
||||
# - FsMountNand
|
||||
# - FsMountNandRoWrite
|
||||
# - FsMountTwln
|
||||
# - FsMountWnand
|
||||
# - FsMountCardSpi
|
||||
# - UseSdif3
|
||||
# - CreateSeed
|
||||
# - UseCardSpi
|
||||
|
||||
IdealProcessor : 0
|
||||
AffinityMask : 1
|
||||
|
||||
Priority : 16
|
||||
|
||||
MaxCpu : 0x9E # Default
|
||||
|
||||
DisableDebug : true
|
||||
EnableForceDebug : false
|
||||
CanWriteSharedPage : true
|
||||
CanUsePrivilegedPriority : false
|
||||
CanUseNonAlphabetAndNumber : true
|
||||
PermitMainFunctionArgument : true
|
||||
CanShareDeviceMemory : true
|
||||
RunnableOnSleep : false
|
||||
SpecialMemoryArrange : true
|
||||
|
||||
CoreVersion : 2
|
||||
DescVersion : 2
|
||||
|
||||
ReleaseKernelMajor : "02"
|
||||
ReleaseKernelMinor : "33"
|
||||
MemoryType : Application # Application / System / Base
|
||||
HandleTableSize: 512
|
||||
IORegisterMapping:
|
||||
- 1ff50000-1ff57fff
|
||||
- 1ff70000-1ff77fff
|
||||
MemoryMapping:
|
||||
- 1f000000-1f5fffff:r
|
||||
SystemCallAccess:
|
||||
ArbitrateAddress: 34
|
||||
Break: 60
|
||||
CancelTimer: 28
|
||||
ClearEvent: 25
|
||||
ClearTimer: 29
|
||||
CloseHandle: 35
|
||||
ConnectToPort: 45
|
||||
ControlMemory: 1
|
||||
CreateAddressArbiter: 33
|
||||
CreateEvent: 23
|
||||
CreateMemoryBlock: 30
|
||||
CreateMutex: 19
|
||||
CreateSemaphore: 21
|
||||
CreateThread: 8
|
||||
CreateTimer: 26
|
||||
DuplicateHandle: 39
|
||||
ExitProcess: 3
|
||||
ExitThread: 9
|
||||
GetCurrentProcessorNumber: 17
|
||||
GetHandleInfo: 41
|
||||
GetProcessId: 53
|
||||
GetProcessIdOfThread: 54
|
||||
GetProcessIdealProcessor: 6
|
||||
GetProcessInfo: 43
|
||||
GetResourceLimit: 56
|
||||
GetResourceLimitCurrentValues: 58
|
||||
GetResourceLimitLimitValues: 57
|
||||
GetSystemInfo: 42
|
||||
GetSystemTick: 40
|
||||
GetThreadContext: 59
|
||||
GetThreadId: 55
|
||||
GetThreadIdealProcessor: 15
|
||||
GetThreadInfo: 44
|
||||
GetThreadPriority: 11
|
||||
MapMemoryBlock: 31
|
||||
OutputDebugString: 61
|
||||
QueryMemory: 2
|
||||
ReleaseMutex: 20
|
||||
ReleaseSemaphore: 22
|
||||
SendSyncRequest1: 46
|
||||
SendSyncRequest2: 47
|
||||
SendSyncRequest3: 48
|
||||
SendSyncRequest4: 49
|
||||
SendSyncRequest: 50
|
||||
SetThreadPriority: 12
|
||||
SetTimer: 27
|
||||
SignalEvent: 24
|
||||
SleepThread: 10
|
||||
UnmapMemoryBlock: 32
|
||||
WaitSynchronization1: 36
|
||||
WaitSynchronizationN: 37
|
||||
InterruptNumbers:
|
||||
ServiceAccessControl:
|
||||
- APT:U
|
||||
- $hioFIO
|
||||
- $hostio0
|
||||
- $hostio1
|
||||
- ac:u
|
||||
- boss:U
|
||||
- cam:u
|
||||
- cecd:u
|
||||
- cfg:u
|
||||
- dlp:FKCL
|
||||
- dlp:SRVR
|
||||
- dsp::DSP
|
||||
- frd:u
|
||||
- fs:USER
|
||||
- gsp::Gpu
|
||||
- hid:USER
|
||||
- http:C
|
||||
- mic:u
|
||||
- ndm:u
|
||||
- news:u
|
||||
- nwm::UDS
|
||||
- ptm:u
|
||||
- pxi:dev
|
||||
- soc:U
|
||||
- ssl:C
|
||||
- y2r:u
|
||||
- ldr:ro
|
||||
- ir:USER
|
||||
|
||||
|
||||
SystemControlInfo:
|
||||
SaveDataSize: 0KB # It doesn't use any save data.
|
||||
RemasterVersion: 2
|
||||
StackSize: 0x40000
|
||||
# JumpId: 0
|
||||
Dependency:
|
||||
ac: 0x0004013000002402L
|
||||
am: 0x0004013000001502L
|
||||
boss: 0x0004013000003402L
|
||||
camera: 0x0004013000001602L
|
||||
cecd: 0x0004013000002602L
|
||||
cfg: 0x0004013000001702L
|
||||
codec: 0x0004013000001802L
|
||||
csnd: 0x0004013000002702L
|
||||
dlp: 0x0004013000002802L
|
||||
dsp: 0x0004013000001a02L
|
||||
friends: 0x0004013000003202L
|
||||
gpio: 0x0004013000001b02L
|
||||
gsp: 0x0004013000001c02L
|
||||
hid: 0x0004013000001d02L
|
||||
http: 0x0004013000002902L
|
||||
i2c: 0x0004013000001e02L
|
||||
ir: 0x0004013000003302L
|
||||
mcu: 0x0004013000001f02L
|
||||
mic: 0x0004013000002002L
|
||||
ndm: 0x0004013000002b02L
|
||||
news: 0x0004013000003502L
|
||||
nim: 0x0004013000002c02L
|
||||
nwm: 0x0004013000002d02L
|
||||
pdn: 0x0004013000002102L
|
||||
ps: 0x0004013000003102L
|
||||
ptm: 0x0004013000002202L
|
||||
ro: 0x0004013000003702L
|
||||
socket: 0x0004013000002e02L
|
||||
spi: 0x0004013000002302L
|
||||
ssl: 0x0004013000002f02L
|
||||
41
libs/sftdlib/sample/source/main.c
Normal file
41
libs/sftdlib/sample/source/main.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
#include <sftd.h>
|
||||
#include "airstrike_ttf.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
sf2d_init();
|
||||
sf2d_set_clear_color(RGBA8(0x40, 0x40, 0x40, 0xFF));
|
||||
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
printf("sftd sample\n");
|
||||
|
||||
// Font loading
|
||||
sftd_init();
|
||||
sftd_font *font = sftd_load_font_mem(airstrike_ttf, airstrike_ttf_size);
|
||||
|
||||
while (aptMainLoop()) {
|
||||
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) break;
|
||||
|
||||
sf2d_start_frame(GFX_TOP, GFX_LEFT);
|
||||
|
||||
sftd_draw_text(font, 10, 10, RGBA8(255, 0, 0, 255), 20, "Font drawing on the top screen!");
|
||||
sftd_draw_textf(font, 10, 40, RGBA8(0, 255, 0, 255), 20, "FPS %f", sf2d_get_fps());
|
||||
|
||||
sf2d_end_frame();
|
||||
|
||||
sf2d_swapbuffers();
|
||||
}
|
||||
|
||||
sftd_free_font(font);
|
||||
sftd_fini();
|
||||
|
||||
sf2d_fini();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue