1
0
Fork 0
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:
Reuh 2015-08-17 21:10:54 +02:00
parent 03baa21c10
commit ebcd9f00ed
47 changed files with 18405 additions and 0 deletions

21
libs/sf2dlib/LICENSE Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

View 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
#---------------------------------------------------------------------------------------

View 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

View 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

View 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

View 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();
}

View 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);
}

View 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;
}

View 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;
}

View 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
#---------------------------------------------------------------------------------------

View 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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;
}