Initial commit

This commit is contained in:
joel16 2022-10-17 21:29:39 -04:00
commit b97b42e153
24 changed files with 10052 additions and 0 deletions

54
.gitignore vendored Normal file
View File

@ -0,0 +1,54 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
*.PBP
*.prx
*.SFO
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

BIN
ICON0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Joel
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.

39
Makefile Normal file
View File

@ -0,0 +1,39 @@
TARGET = PSPickr
SOURCES := data source
CFILES := $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.c))
CPPFILES := $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.cpp))
GFXFILES := $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.png))
WAVFILES := $(foreach dir, $(SOURCES), $(wildcard $(dir)/*.wav))
OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(GFXFILES:.png=.o) $(WAVFILES:.wav=.o)
VERSION_MAJOR := 1
VERSION_MINOR := 0
VERSION_MICRO := 0
INCDIR = libs/ libs/include include
CFLAGS = -Os -Wall -ffast-math -Wno-narrowing -Wno-unused-variable \
-DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO)
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti -std=gnu++17
ASFLAGS := $(CFLAGS)
BUILD_PRX = 1
PSP_LARGE_MEMORY = 1
LIBDIR = libs/lib
LDFLAGS =
LIBS = -lintrafont -lglib2d -ljpeg -lpng16 -lstdc++ -lz -lpspgu -lpspvram -lpspaudiolib -lpspaudio -lpspreg
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = PSPickr v$(VERSION_MAJOR).$(VERSION_MINOR)$(VERSION_MICRO)
# PSP_EBOOT_ICON = ICON0.PNG
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
%.o: %.png
bin2o -i $< $@ $(addsuffix _png, $(basename $(notdir $<) ))
%.o: %.wav
bin2o -i $< $@ $(addsuffix _wav, $(basename $(notdir $<) ))

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# PSPickr
Based on seanmtracey's Pickr

BIN
data/game_over.wav Normal file

Binary file not shown.

BIN
data/lives.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

BIN
data/nope.wav Normal file

Binary file not shown.

12
include/audio.hpp Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <cstddef>
namespace Audio {
void Init(void);
void Exit(void);
int InitGameOverWav(void);
int InitNopeWav(void);
void PlayGameOverWav(void);
void PlayNopeWav(void);
}

8350
include/dr_wav.h Normal file

File diff suppressed because it is too large Load Diff

9
include/fs.hpp Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <string>
namespace FS {
bool FileExists(const std::string &path);
int ReadFile(const std::string &path, void *buf, int size);
int WriteFile(const std::string &path, void *buf, int size);
}

6
include/game.hpp Normal file
View File

@ -0,0 +1,6 @@
#pragma once
namespace Game {
void MainMenu(void);
void Loop(void);
}

18
include/gui.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <glib2d.h>
#include <intraFont.h>
#include <string>
extern intraFont *g_font;
extern bool g_running;
namespace GUI {
void DrawRect(float x, float y, float width, float height, g2dColor colour);
void DrawImage(g2dTexture *tex, float x, float y, float w, float h);
void DrawImageTint(g2dTexture *tex, float x, float y, float w, float h, g2dColor colour);
void FontSetStyle(float size, unsigned int colour, unsigned int options);
float GetTextHeight(void);
float GetTextWidth(const std::string &text);
float DrawText(float x, float y, const std::string &text);
}

9
include/textures.hpp Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <glib2d.h>
namespace Textures {
void Init(void);
void Exit(void);
g2dTexture *GetLives(void);
}

22
include/utils.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <pspctrl.h>
#include <psptypes.h>
/// Checks whether a result code indicates success.
#define R_SUCCEEDED(res) ((res) >= 0)
/// Checks whether a result code indicates failure.
#define R_FAILED(res) ((res) < 0)
extern enum PspCtrlButtons PSP_CTRL_ENTER, PSP_CTRL_CANCEL;
namespace Utils {
void SetBounds(int &set, int min, int max);
int ReadControls(void);
int IsButtonPressed(enum PspCtrlButtons buttons);
int IsButtonHeld(enum PspCtrlButtons buttons);
enum PspCtrlButtons GetEnterButton(void);
enum PspCtrlButtons GetCancelButton(void);
float GetAnalogX(void);
float GetAnalogY(void);
}

778
libs/include/glib2d.h Normal file
View File

@ -0,0 +1,778 @@
/** \mainpage gLib2D Documentation
*
* \section intro Introduction
*
* gLib2D by Geecko - A simple, fast, light-weight 2D graphics library. \n\n
* This library has been designed to replace the old graphics.c library
* and to simplify the use of pspgu.\n
* The goals : keep it simple, keep it small, keep it fast.
*
* \section limits Known limitations
*
* - Draw & display buffers can't actually be used as real textures. Just a way
* to get the vram pointer.
* - No support for multiples contexts (e.g. sharing coordinates beetween
* textures using some gBegin calls at a time).
* - Manipulating textures (clear, get pixel info...) is not possible.
* - When some 512*512 rotated, colorized and scaled textures are rendered
* at a time, the framerate *could* go under 60 fps.
*
* \section install Installation
*
* - Simply put glib2d.c and glib2d.h in your source directory. \n
* - Then add glib2d.o and link "-lpng -ljpeg -lz -lpspgu -lm -lpspvram"
* in your Makefile.
* - You're done !
*
* \section copyright License
*
* This work is licensed under the LGPLv3 License. \n
* See the LICENSE file for more details. \n
* You can support the library by marking your homebrew with
* "Using gLib2D by Geecko".
*
* \section contact Contact
*
* Please report bugs or submit ideas at : \n geecko.dev@free.fr \n\n
* Get the full documentation on : \n http://geecko.dev.free.fr \n\n
* Also stay tuned on... \n
* https://github.com/GeeckoDev (contributors would be a plus!) \n
* http://twitter.com/GeeckoDev
*/
/**
* \file glib2d.h
* \brief gLib2D Header
* \version Beta 5
*/
#ifndef GLIB2D_H
#define GLIB2D_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
/**
* \def G2D_SCR_W
* \brief Screen width constant, in pixels.
*/
/**
* \def G2D_SCR_H
* \brief Screen height constant, in pixels.
*/
#define G2D_SCR_W (480)
#define G2D_SCR_H (272)
/**
* \def G2D_RGBA(r,g,b,a)
* \brief Create a g2dColor.
*
* This macro creates a g2dColor from 4 values, red, green, blue and alpha.
* Input range is from 0 to 255.
*/
#define G2D_RGBA(r, g, b, a) ((r)|((g)<<8)|((b)<<16)|((a)<<24))
/**
* \def G2D_GET_R(color)
* \brief Get red channel value from a g2dColor.
*/
/**
* \def G2D_GET_G(color)
* \brief Get green channel value from a g2dColor.
*/
/**
* \def G2D_GET_B(color)
* \brief Get blue channel value from a g2dColor.
*/
/**
* \def G2D_GET_A(color)
* \brief Get alpha channel value from a g2dColor.
*/
#define G2D_GET_R(color) (((color) ) & 0xFF)
#define G2D_GET_G(color) (((color) >> 8) & 0xFF)
#define G2D_GET_B(color) (((color) >> 16) & 0xFF)
#define G2D_GET_A(color) (((color) >> 24) & 0xFF)
/**
* \def G2D_MODULATE(color,luminance,alpha)
* \brief g2dColor modulation.
*
* This macro modulates the luminance & alpha of a g2dColor.
* Input range is from 0 to 255.
*/
#define G2D_MODULATE(color,luminance,alpha) \
G2D_RGBA((int)(luminance) * G2D_GET_R(color) / 255, \
(int)(luminance) * G2D_GET_G(color) / 255, \
(int)(luminance) * G2D_GET_B(color) / 255, \
(int)(alpha ) * G2D_GET_A(color) / 255)
/**
* \enum g2dColors
* \brief Colors enumeration.
*
* Primary, secondary, tertiary and grayscale colors are defined.
*/
enum g2dColors {
// Primary colors
RED = 0xFF0000FF,
GREEN = 0xFF00FF00,
BLUE = 0xFFFF0000,
// Secondary colors
CYAN = 0xFFFFFF00,
MAGENTA = 0xFFFF00FF,
YELLOW = 0xFF00FFFF,
// Tertiary colors
AZURE = 0xFFFF7F00,
VIOLET = 0xFFFF007F,
ROSE = 0xFF7F00FF,
ORANGE = 0xFF007FFF,
CHARTREUSE = 0xFF00FF7F,
SPRING_GREEN = 0xFF7FFF00,
// Grayscale
WHITE = 0xFFFFFFFF,
LITEGRAY = 0xFFBFBFBF,
GRAY = 0xFF7F7F7F,
DARKGRAY = 0xFF3F3F3F,
BLACK = 0xFF000000
};
/**
* \enum g2dCoord_Mode
* \brief Coordinates modes enumeration.
*
* Choose where the coordinates correspond in the object.
* Can only be used with g2dSetCoordMode.
*/
/**
* \enum g2dLine_Mode
* \brief Line modes enumeration.
*
* Change line draw properties.
* Can only be used with g2dBeginLines.
*/
/**
* \enum g2dFlip_Mode
* \brief Flip modes enumeration.
*
* Change flip properties.
* Can only be used with g2dFlip.
*/
/**
* \enum g2dTex_Mode
* \brief Texture modes enumeration.
*
* Change texture properties.
* Can only be used with g2dTexLoad.
*/
typedef enum {
G2D_UP_LEFT,
G2D_UP_RIGHT,
G2D_DOWN_RIGHT,
G2D_DOWN_LEFT,
G2D_CENTER
} g2dCoord_Mode;
typedef enum {
G2D_STRIP = 1 /**< Make a line strip. */
} g2dLine_Mode;
typedef enum {
G2D_VSYNC = 1 /**< Limit the FPS to 60 (synchronized with the screen).
Better quality and less power consumption. */
} g2dFlip_Mode;
typedef enum {
G2D_SWIZZLE = 1 /**< Recommended. Use it to speedup rendering. */
} g2dTex_Mode;
/**
* \var g2dAlpha
* \brief Alpha type.
*/
/**
* \var g2dColor
* \brief Color type.
*/
typedef int g2dAlpha;
typedef unsigned int g2dColor;
/**
* \struct g2dTexture
* \brief Texture structure.
*/
typedef struct {
int tw; /**< Real texture width. A power of two. */
int th; /**< Real texture height. A power of two. */
int w; /**< Texture width, as seen when drawing. */
int h; /**< Texture height, as seen when drawing. */
float ratio; /**< Width/height ratio. */
bool swizzled; /**< Is the texture swizzled ? */
g2dColor *data; /**< Pointer to raw data. */
} g2dTexture;
/**
* \var g2d_draw_buffer
* \brief The current draw buffer as a texture.
*/
/**
* \var g2d_disp_buffer
* \brief The current display buffer as a texture.
*/
extern g2dTexture g2d_draw_buffer;
extern g2dTexture g2d_disp_buffer;
/**
* \brief Initializes the library.
*
* This function will create a GU context and setup the display buffers.
* Automatically called by the other functions.
*/
void g2dInit(void);
/**
* \brief Shutdowns the library.
*
* This function will destroy the GU context.
*/
void g2dTerm(void);
/**
* \brief Clears screen & depth buffer.
* @param color Screen clear color
*
* This function clears the screen, and clears the zbuffer if depth coordinate
* is used in the loop. Will automatically init the GU if needed.
*/
void g2dClear(g2dColor color);
/**
* \brief Clears depth buffer.
*
* This function clears the zbuffer to zero (z range 0-65535).
* Will automatically init the GU if needed.
*/
void g2dClearZ(void);
/**
* \brief Begins rectangles rendering.
* @param tex Pointer to a texture, pass NULL to get a colored rectangle.
*
* This function begins object rendering. Resets all properties.
* One g2dAdd() call per object.
* Only one texture can be used, but multiple objects can be rendered at a time.
* g2dBegin*() / g2dEnd() couple can be called multiple times in the loop,
* to render multiple textures.
*/
void g2dBeginRects(g2dTexture *tex);
/**
* \brief Begins lines rendering.
* @param line_mode A g2dLine_Mode constant.
*
* This function begins object rendering. Calls g2dReset().
* Two g2dAdd() calls per object.
* Pass G2D_LINE_STRIP to make a line strip (two calls, then one per object).
*/
void g2dBeginLines(g2dLine_Mode mode);
/**
* \brief Begins quads rendering.
* @param tex Pointer to a texture, pass NULL to get a colored quad.
*
* This function begins object rendering. Resets all properties.
* Four g2dAdd() calls per object, first for the up left corner, then clockwise.
* Only one texture can be used, but multiple objects can be rendered at a time.
* g2dBegin*() / g2dEnd() couple can be called multiple times in the loop,
* to render multiple textures.
*/
void g2dBeginQuads(g2dTexture *tex);
/**
* \brief Begins points rendering.
*
* This function begins object rendering. Resets all properties.
* One g2dAdd() call per object.
*/
void g2dBeginPoints(void);
/**
* \brief Ends object rendering.
*
* This function ends object rendering. Must be called after g2dBegin*() to add
* objects to the display list. Automatically adapts pspgu functionnalities
* to get the best performance possible.
*/
void g2dEnd(void);
/**
* \brief Resets current transformation and attribution.
*
* This function must be called during object rendering.
* Calls g2dResetCoord(), g2dResetRotation(), g2dResetScale(),
* g2dResetColor(), g2dResetAlpha(), g2dResetCrop() and g2dResetTex().
*/
void g2dReset(void);
/**
* \brief Flips the screen.
* @param flip_mode A g2dFlip_Mode constant.
*
* This function must be called at the end of the loop.
* Renders the whole display list to the draw buffer.
* Inverts framebuffers to display the whole thing.
*/
void g2dFlip(g2dFlip_Mode mode);
/**
* \brief Pushes the current transformation & attribution to a new object.
*
* This function must be called during object rendering.
*/
void g2dAdd(void);
/**
* \brief Saves the current transformation to stack.
*
* This function must be called during object rendering.
* The stack is 64 saves high.
* Use it like the OpenGL one.
*/
void g2dPush(void);
/**
* \brief Restore the current transformation from stack.
*
* This function must be called during object rendering.
* The stack is 64 saves high.
* Use it like the OpenGL one.
*/
void g2dPop(void);
/**
* \brief Creates a new blank texture.
* @param w Width of the texture.
* @param h Height of the texture.
*
* This function returns NULL on allocation fail.
*/
g2dTexture* g2dTexCreate(int w, int h);
/**
* \brief Frees a texture & set its pointer to NULL.
* @param tex Pointer to the variable which contains the texture pointer.
*
* This function is used to gain memory when a texture is useless.
* Must pass the pointer to the variable which contains the pointer,
* to set it to NULL (passing NULL to a g2dBegin* function is safe).
*/
void g2dTexFree(g2dTexture **tex);
/**
* \brief Loads an image.
* @param data RGBA texture buffer.
* @param width Texture width.
* @param height Texture height.
* @param tex_mode A g2dTex_Mode constant.
* @returns Pointer to the generated texture.
*
* Swizzling is enabled only for 16*16+ textures (useless on small textures), pass G2D_SWIZZLE to enable it.
* Texture supported up to 512*512 in size only (hardware limitation).
*/
g2dTexture *g2dTexLoad(void *data, int width, int height, g2dTex_Mode mode);
/**
* \brief Resets the current coordinates.
*
* This function must be called during object rendering.
* Sets g2dSetCoordMode() to G2D_UP_LEFT and g2dSetCoordXYZ() to (0,0,0).
*/
void g2dResetCoord(void);
/**
* \brief Set coordinate mode.
* @param coord_mode A gCoord_Mode.
*
* This function must be called during object rendering.
* Defines where the coordinates correspond in the object.
*/
void g2dSetCoordMode(g2dCoord_Mode mode);
/**
* \brief Gets the current position.
* @param x Pointer to save the current x (in pixels).
* @param y Pointer to save the current y (in pixels).
* @param z Pointer to save the current z (in pixels).
*
* This function must be called during object rendering.
* Parameters are pointers to float, not int !
* Pass NULL if not needed.
*/
void g2dGetCoordXYZ(float *x, float *y, float *z);
/**
* \brief Sets the new position.
* @param x New x, in pixels.
* @param y New y, in pixels.
*
* This function must be called during object rendering.
*/
void g2dSetCoordXY(float x, float y);
/**
* \brief Sets the new position, with depth support.
* @param x New x, in pixels.
* @param y New y, in pixels.
* @param z New z, in pixels. (front 0-65535 back)
*
* This function must be called during object rendering.
*/
void g2dSetCoordXYZ(float x, float y, float z);
/**
* \brief Sets the new position, relative to the current.
* @param x New x increment, in pixels.
* @param y New y increment, in pixels.
*
* This function must be called during object rendering.
*/
void g2dSetCoordXYRelative(float x, float y);
/**
* \brief Sets the new position, with depth support, relative to the current.
* @param x New x increment, in pixels.
* @param y New y increment, in pixels.
* @param z New z increment, in pixels.
*
* This function must be called during object rendering.
*/
void g2dSetCoordXYZRelative(float x, float y, float z);
/**
* \brief Use integer coordinates.
* @param use false to desactivate (better look, by default),
true to activate (can be useful when you have glitches).
*
* This function must be called during object rendering.
*/
void g2dSetCoordInteger(bool use);
/**
* \brief Resets the global scale.
*
* This function resets the global scale to 1.f.
* Translations and scales are multiplied by this factor.
*/
void g2dResetGlobalScale(void);
/**
* \brief Resets the current scale.
*
* This function must be called during object rendering.
* Sets the scale to the current texture size or (10,10).
*/
void g2dResetScale(void);
/**
* \brief Gets the global scale.
* @param scale Pointer to save the global scale (factor).
*
* Pass NULL if not needed.
*/
void g2dGetGlobalScale(float *scale);
/**
* \brief Gets the current scale.
* @param w Pointer to save the current width (in pixels).
* @param h Pointer to save the current height (in pixels).
*
* This function must be called during object rendering.
* Parameters are pointers to float, not int !
* Pass NULL if not needed.
*/
void g2dGetScaleWH(float *w, float *h);
/**
* \brief Sets the global scale.
*
* Translations and scales are multiplied by this factor.
*/
void g2dSetGlobalScale(float scale);
/**
* \brief Sets the new scale.
* @param w Width scale factor.
* @param h Height scale factor.
*
* This function must be called during object rendering.
* g2dResetScale() is called, then width & height scale are
* multiplied by these values.
* Negative values can be passed to invert the texture.
*/
void g2dSetScale(float w, float h);
/**
* \brief Sets the new scale, in pixels.
* @param w New width, in pixels.
* @param h New height, in pixels.
*
* This function must be called during object rendering.
* Negative values can be passed to invert the texture.
*/
void g2dSetScaleWH(float w, float h);
/**
* \brief Sets the new scale, relative to the current.
* @param w Width scale factor.
* @param h Height scale factor.
*
* This function must be called during object rendering.
* Current width & height scale are multiplied by these values.
* Negative values can be passed to invert the texture.
*/
void g2dSetScaleRelative(float w, float h);
/**
* \brief Sets the new scale, in pixels, relative to the current.
* @param w New width to increment, in pixels.
* @param h New height to increment, in pixels.
*
* This function must be called during object rendering.
* Negative values can be passed to invert the texture.
*/
void g2dSetScaleWHRelative(float w, float h);
/**
* \brief Resets the current color.
*
* This function must be called during object rendering.
* Sets g2dSetColor() to WHITE.
*/
void g2dResetColor(void);
/**
* \brief Resets the current alpha.
*
* This function must be called during object rendering.
* Sets g2dSetAlpha() to 255.
*/
void g2dResetAlpha(void);
/**
* \brief Gets the current alpha.
* @param alpha Pointer to save the current alpha (0-255).
*
* This function must be called during object rendering.
* Pass NULL if not needed.
*/
void g2dGetAlpha(g2dAlpha *alpha);
/**
* \brief Sets the new color.
* @param color The new color.
*
* This function must be called during object rendering.
* Can be used to colorize any object.
*/
void g2dSetColor(g2dColor color);
/**
* \brief Sets the new alpha.
* @param alpha The new alpha (0-255).
*
* This function must be called during object rendering.
* Can be used to make any object transparent.
*/
void g2dSetAlpha(g2dAlpha alpha);
/**
* \brief Sets the new alpha, relative to the current alpha.
* @param alpha The new alpha increment.
*
* This function must be called during object rendering.
* Can be used to make any object transparent.
*/
void g2dSetAlphaRelative(int alpha);
/**
* \brief Resets the current rotation.
*
* This function must be called during object rendering.
* Sets g2dSetRotation() to 0°.
*/
void g2dResetRotation(void);
/**
* \brief Gets the current rotation, in radians.
* @param radians Pointer to save the current rotation.
*
* This function must be called during object rendering.
* Pass NULL if not needed.
*/
void g2dGetRotationRad(float *radians);
/**
* \brief Gets the current rotation, in degrees.
* @param degrees Pointer to save the current rotation.
*
* This function must be called during object rendering.
* Pass NULL if not needed.
*/
void g2dGetRotation(float *degrees);
/**
* \brief Sets the new rotation, in radians.
* @param radians The new angle.
*
* This function must be called during object rendering.
* The rotation center is the actual coordinates.
*/
void g2dSetRotationRad(float radians);
/**
* \brief Sets the new rotation, in degrees.
* @param degrees The new angle.
*
* This function must be called during object rendering.
* The rotation center is the actual coordinates.
*/
void g2dSetRotation(float degrees);
/**
* \brief Sets the new rotation, relative to the current, in radians.
* @param radians The new angle increment.
*
* This function must be called during object rendering.
* The rotation center is the actual coordinates.
*/
void g2dSetRotationRadRelative(float radians);
/**
* \brief Sets the new rotation, relative to the current, in degrees.
* @param degrees The new angle increment.
*
* This function must be called during object rendering.
* The rotation center is the actual coordinates.
*/
void g2dSetRotationRelative(float degrees);
/**
* \brief Resets the current crop.
*
* This function must be called during object rendering.
* Sets g2dSetCropXY() to (0;0) and g2dSetCropWH() to (tex->w,tex->h).
*/
void g2dResetCrop(void);
/**
* \brief Gets the current crop position.
* @param x Pointer to save the current crop x.
* @param y Pointer to save the current crop y.
*
* This function must be called during object rendering.
* Pass NULL if not needed.
*/
void g2dGetCropXY(int *x, int *y);
/**
* \brief Gets the current crop scale.
* @param w Pointer to save the current crop width.
* @param h Pointer to save the current crop height.
*
* This function must be called during object rendering.
* Pass NULL if not needed.
*/
void g2dGetCropWH(int *w, int *h);
/**
* \brief Sets the new crop position.
* @param x New x, in pixels.
* @param y New y, in pixels.
*
* This function must be called during object rendering. Defines crop position.
* If the rectangle is larger or next to the texture, it will be repeated
* when g2dSetTexRepeat is enabled. Useful for a tileset.
*/
void g2dSetCropXY(int x, int y);
/**
* \brief Sets the new crop size.
* @param w New width, in pixels.
* @param h New height, in pixels.
*
* This function must be called during object rendering. Defines crop size.
* If the rectangle is larger or next to the texture, it will be repeated
* when g2dSetTexRepeat is enabled. Useful for a tileset.
*/
void g2dSetCropWH(int w, int h);
/**
* \brief Sets the new crop position, relative to the current.
* @param x New x increment, in pixels.
* @param y New y increment, in pixels.
*
* This function must be called during object rendering. Defines crop position.
* If the rectangle is larger or next to the texture, texture will be repeated
* when g2dSetTexRepeat is enabled. Useful for a tileset.
*/
void g2dSetCropXYRelative(int x, int y);
/**
* \brief Sets the new crop size, relative to the current.
* @param w New width increment, in pixels.
* @param h New height increment, in pixels.
*
* This function must be called during object rendering. Defines crop size.
* If the rectangle is larger or next to the texture, texture will be repeated
* when g2dSetTexRepeat is enabled. Useful for a tileset.
*/
void g2dSetCropWHRelative(int w, int h);
/**
* \brief Resets texture properties.
*
* This function must be called during object rendering.
*/
void g2dResetTex(void);
/**
* \brief Set texture wrap.
* @param use true to repeat, false to clamp (by default).
*
* This function must be called during object rendering.
*/
void g2dSetTexRepeat(bool use);
/**
* \brief Use the bilinear filter with the texture.
* @param use true to activate (better look, by default).
false to desactivate (better performance).
*
* This function must be called during object rendering.
* Only useful when scaling.
*/
void g2dSetTexLinear(bool use);
/**
* \brief Resets the draw zone to the entire screen.
*
* This function can be called everywhere in the loop.
*/
void g2dResetScissor(void);
/**
* \brief Sets the draw zone.
* @param x New x position.
* @param y New y position.
* @param w New width.
* @param h New height.
*
* This function can be called everywhere in the loop.
* Pixel draw will be skipped outside this rectangle.
*/
void g2dSetScissor(int x, int y, int w, int h);
#ifdef __cplusplus
}
#endif
#endif

BIN
libs/lib/libglib2d.a Normal file

Binary file not shown.

70
source/audio.cpp Normal file
View File

@ -0,0 +1,70 @@
#include <pspaudio.h>
#include <pspaudiolib.h>
#include <pspthreadman.h>
#include "audio.hpp"
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
extern unsigned char game_over_wav_start[], nope_wav_start[];
extern unsigned int game_over_wav_size, nope_wav_size;
namespace Audio {
static drwav game_over_wav, nope_wav;
static drwav_uint64 frames_read = 0;
static bool playing = false;
static void Decode(void *buf, unsigned int length, void *userdata) {
drwav *wav = static_cast<drwav *>(userdata);
frames_read += drwav_read_pcm_frames_s16(wav, static_cast<drwav_uint64>(length), static_cast<drwav_int16 *>(buf));
if (frames_read >= wav->totalPCMFrameCount) {
playing = false;
}
}
void Init(void) {
pspAudioInit();
}
void Exit(void) {
playing = false;
frames_read = 0;
pspAudioEndPre();
pspAudioEnd();
drwav_uninit(&game_over_wav);
drwav_uninit(&nope_wav);
}
int InitGameOverWav(void) {
if (!drwav_init_memory(&game_over_wav, game_over_wav_start, game_over_wav_size, nullptr))
return -1;
return 0;
}
int InitNopeWav(void) {
if (!drwav_init_memory(&nope_wav, nope_wav_start, nope_wav_size, nullptr))
return -1;
return 0;
}
static void Clear(void) {
playing = true;
pspAudioSetChannelCallback(0, nullptr, nullptr); // Clear channel callback
frames_read = 0;
}
void PlayGameOverWav(void) {
Audio::Clear();
drwav_seek_to_pcm_frame(&game_over_wav, 0);
pspAudioSetChannelCallback(0, Audio::Decode, &game_over_wav);
}
void PlayNopeWav(void) {
Audio::Clear();
drwav_seek_to_pcm_frame(&nope_wav, 0);
pspAudioSetChannelCallback(0, Audio::Decode, &nope_wav);
}
}

35
source/fs.cpp Normal file
View File

@ -0,0 +1,35 @@
#include <pspiofilemgr.h>
#include "fs.hpp"
#include "utils.hpp"
namespace FS {
bool FileExists(const std::string &path) {
SceIoStat stat = { 0 };
return sceIoGetstat(path.c_str(), &stat) >= 0;
}
int ReadFile(const std::string &path, void *buf, int size) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_RDONLY, 0))) {
int read = sceIoRead(file, buf, size);
sceIoClose(file);
return read;
}
return file;
}
int WriteFile(const std::string &path, void *buf, int size) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777))) {
int written = sceIoWrite(file, buf, size);
sceIoClose(file);
return written;
}
return file;
}
}

278
source/game.cpp Normal file
View File

@ -0,0 +1,278 @@
#include <time.h>
#include "audio.hpp"
#include "fs.hpp"
#include "gui.hpp"
#include "textures.hpp"
#include "utils.hpp"
namespace Game {
static const float tex_size = 12.f;
static int time_left = 0, diff = 0, stages = 0, max_stages = 0, lives = 0, matches = 0, row = 0, selection = 0;
static bool pattern[16];
static unsigned int color[3];
void MainMenu(void) {
const std::string subtitle_0 = "One of these colours is not like the other one!";
const std::string subtitle_1 = "Which one?";
const std::string instruc_0 = "Press X to start new game (with timer)";
const std::string instruc_1 = "Press [ ] to start new game (without timer)";
const std::string instruc_2 = "Press Start to exit";
const std::string text = "Based on Sean M. Tracey's Pickr";
g2dClear(WHITE);
GUI::FontSetStyle(1.2f, G2D_RGBA(0, 0, 0, 0), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((480 - GUI::GetTextWidth("PSPickr")) / 2, 80, "PSPickr");
GUI::FontSetStyle(1.0f, G2D_RGBA(0, 0, 0, 200), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((480 - GUI::GetTextWidth(subtitle_0)) / 2, 95, subtitle_0);
GUI::DrawText((480 - GUI::GetTextWidth(subtitle_1)) / 2, 110, subtitle_1);
GUI::FontSetStyle(0.8f, G2D_RGBA(0, 0, 0, 200), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((480 - GUI::GetTextWidth(instruc_0)) / 2, 140, instruc_0);
GUI::DrawText((480 - GUI::GetTextWidth(instruc_1)) / 2, 160, instruc_1);
GUI::DrawText((480 - GUI::GetTextWidth(instruc_2)) / 2, 180, instruc_2);
GUI::FontSetStyle(0.8f, G2D_RGBA(0, 0, 0, 200), INTRAFONT_ALIGN_LEFT);
intraFontPrintf(g_font, 10, 262, "Version %d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
GUI::DrawText((470 - GUI::GetTextWidth(text)), 262, text);
g2dFlip(G2D_VSYNC);
}
static void Init(void) {
lives = 5;
time_left = 480;
diff = 10;
stages = 0;
row = 0;
}
static void Fill(void) {
for (unsigned int i = 0; i < 16; i++) {
pattern[i] = false;
}
pattern[rand() % 16] = true;
color[0] = rand() % (255 - 2 * diff) + diff;
color[1] = rand() % (255 - 2 * diff) + diff;
color[2] = rand() % (255 - 2 * diff) + diff;
}
static void Update(void) {
diff = 10;
}
static int GetHighscore(void) {
char buf[10] = { 0 };
int score = 0;
if (FS::FileExists("highscore.txt")) {
FS::ReadFile("highscore.txt", buf, 10);
std::sscanf(buf, "%d", &score);
}
return score;
}
static void SaveHighscore(void) {
int score = Game::GetHighscore();
if (max_stages > score) {
char buf[10] = { 0 };
std::snprintf(buf, 10, "%d\n", max_stages);
FS::WriteFile("highscore.txt", buf, 10);
}
}
static void Begin(bool timer) {
int x, y;
bool win = false, paused = false;
char stage_str[10], row_str[13];
std::snprintf(stage_str, 10, "Score %d", stages);
std::snprintf(row_str, 13, "%d in a row", row);
time_left = 480;
Game::Fill();
diff = (rand() % 2) ? diff : -diff;
while (true && time_left > 0 && lives > 0) {
int ctrl = Utils::ReadControls();
Utils::SetBounds(selection, 0, 15);
if (ctrl & PSP_CTRL_LEFT) {
selection--;
}
else if (ctrl & PSP_CTRL_RIGHT) {
selection++;
}
if (ctrl & PSP_CTRL_UP) {
selection -= 4;
}
else if (ctrl & PSP_CTRL_DOWN) {
selection += 4;
}
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
if (!paused) {
if (pattern[selection]) {
win = true;
}
else {
Audio::PlayNopeWav();
lives--;
row = 0;
}
}
}
if (Utils::IsButtonPressed(PSP_CTRL_START)) {
paused = !paused;
}
y = 34;
g2dClear(GRAY);
for (int i = 0, max = (lives < 5) ? 5 : lives; i < max; i++) {
if (i < lives) {
GUI::DrawImage(Textures::GetLives(), 5 + i * 13, 5, tex_size, tex_size);
}
else {
GUI::DrawImageTint(Textures::GetLives(), 5 + i * 13, 5, tex_size, tex_size, G2D_RGBA(50, 50, 50, 200));
}
}
GUI::FontSetStyle(1.0f, G2D_RGBA(255, 255, 255, 255), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((472 - GUI::GetTextWidth(stage_str)), 17, stage_str);
GUI::DrawText((472 - GUI::GetTextWidth(row_str)), 35, row_str);
for (int i = 0; i < 4; i++) {
x = 138;
for (int j = 0; j < 4; j++) {
if (selection == (i * 4 + j)) {
GUI::DrawRect(x - 1, y - 1, 52, 52, G2D_RGBA(255, 255, 255, 255));
}
GUI::DrawRect(x, y, 50, 50, (pattern[i * 4 + j]) ? G2D_RGBA(color[0] - diff, color[1] - diff, color[2] - diff, 255) : G2D_RGBA(color[0], color[1], color[2], 255));
x += 52;
}
y += 52;
}
if (timer) {
GUI::DrawRect(0, 257, time_left, 15, (time_left > 100) ? G2D_RGBA(0, 255, 0, 255) : G2D_RGBA(255, 0, 0, 255));
}
if (paused) {
GUI::DrawRect(0, 0, 480, 282, G2D_RGBA(128, 128, 128, 130));
GUI::FontSetStyle(1.0f, G2D_RGBA(200, 0, 0, 255), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((472 - GUI::GetTextWidth("Paused")) / 2, 100, "Paused");
GUI::FontSetStyle(1.0f, G2D_RGBA(0, 0, 0, 255), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((472 - GUI::GetTextWidth("Press start to continue")) / 2, 130, "Press start to continue");
GUI::DrawText((472 - GUI::GetTextWidth(PSP_CTRL_CANCEL == PSP_CTRL_CIRCLE? "Press O button to exit" : "Press X button to exit")) / 2,
150, PSP_CTRL_CANCEL == PSP_CTRL_CIRCLE? "Press O button to exit" : "Press X button to exit");
if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
lives = 0;
}
}
g2dFlip(G2D_VSYNC);
if (timer) {
if (!paused) {
if (--time_left == 0 && lives > 0) {
Audio::PlayNopeWav();
time_left = 480;
lives--;
row = 0;
}
}
}
if (win) {
if (++stages % 10 == 0 && lives < 10) {
lives++;
}
Game::Update();
max_stages = (stages >= max_stages) ? stages : max_stages;
row++;
if (timer == true) {
Game::Begin(true);
}
else {
Game::Begin(false);
}
}
}
}
static void End(void) {
char stages_str[26], score_str[20], matches_str[20];
Game::SaveHighscore();
std::snprintf(stages_str, 24, "You scored %d!", stages);
std::snprintf(score_str, 20, "Best score: %d", Game::GetHighscore());
std::snprintf(matches_str, 20, "Games played: %d", matches);
Audio::PlayGameOverWav();
while(true) {
Utils::ReadControls();
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
break;
}
g2dClear(WHITE);
GUI::FontSetStyle(1.5f, G2D_RGBA(200, 0, 0, 255), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((480 - GUI::GetTextWidth("GAME OVER")) / 2, 40, "GAME OVER");
GUI::FontSetStyle(1.0f, G2D_RGBA(128, 128, 128, 255), INTRAFONT_ALIGN_LEFT);
GUI::DrawText((480 - GUI::GetTextWidth(stages_str)) / 2, 80, stages_str);
GUI::DrawText((480 - GUI::GetTextWidth(score_str)) / 2, 100, score_str);
GUI::DrawText((480 - GUI::GetTextWidth(matches_str)) / 2, 120, matches_str);
GUI::DrawText((480 - GUI::GetTextWidth("Press X to try again")) / 2, 140, "Press X to try again");
g2dFlip(G2D_VSYNC);
}
}
void Loop(void) {
srand(time(nullptr));
Game::Init();
matches = 0;
max_stages = 0;
while(g_running) {
int ctrl = Utils::ReadControls();
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
Game::Begin(true);
matches++;
Game::End();
Game::Init();
}
if (Utils::IsButtonPressed(PSP_CTRL_SQUARE)) {
Game::Begin(false);
matches++;
Game::End();
Game::Init();
}
Game::MainMenu();
if (Utils::IsButtonPressed(PSP_CTRL_START)) {
g_running = false;
}
}
}
}

50
source/gui.cpp Normal file
View File

@ -0,0 +1,50 @@
#include "gui.hpp"
intraFont *g_font;
namespace GUI {
void DrawRect(float x, float y, float width, float height, g2dColor colour) {
g2dBeginRects(nullptr); {
g2dSetColor(colour);
g2dSetScaleWH(width, height);
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
void DrawImage(g2dTexture *tex, float x, float y, float w, float h) {
g2dBeginRects(tex); {
g2dSetScaleWH(w, h);
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
void DrawImageTint(g2dTexture *tex, float x, float y, float w, float h, g2dColor colour) {
g2dBeginRects(tex); {
g2dSetColor(colour);
g2dSetScaleWH(w, h);
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
void FontSetStyle(float size, unsigned int colour, unsigned int options) {
intraFontSetStyle(g_font, size, colour, G2D_RGBA(0, 0, 0, 0), 0.f, options);
}
float GetTextHeight(void) {
return g_font->advancey * g_font->size / 4.f + 2.f;
}
float GetTextWidth(const std::string &text) {
return intraFontMeasureText(g_font, text.c_str());
}
float DrawText(float x, float y, const std::string &text) {
return intraFontPrintf(g_font, x, y, text.c_str());
}
}

74
source/main.cpp Normal file
View File

@ -0,0 +1,74 @@
#include <pspkernel.h>
#include "audio.hpp"
#include "game.hpp"
#include "gui.hpp"
#include "textures.hpp"
#include "utils.hpp"
PSP_MODULE_INFO("PSPickr", 0, VERSION_MAJOR, VERSION_MINOR);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
bool g_running = true;
namespace Services {
int Init(void) {
int ret = 0;
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
if (R_FAILED(ret = intraFontInit())) {
pspDebugScreenPrintf("intraFontInit failed: 0x%08x\n", ret);
return ret;
}
// Load audio, font and textures.
Audio::Init();
Audio::InitGameOverWav();
Audio::InitNopeWav();
g_font = intraFontLoad("flash0:/font/ltn8.pgf", INTRAFONT_CACHE_ALL);
Textures::Init();
PSP_CTRL_ENTER = Utils::GetEnterButton();
PSP_CTRL_CANCEL = Utils::GetCancelButton();
return 0;
}
void Exit(void) {
Textures::Exit();
intraFontUnload(g_font);
Audio::Exit();
sceKernelExitGame();
}
static int ExitCallback(int arg1, int arg2, void *common) {
g_running = false;
Services::Exit();
return 0;
}
static int CallbackThread(SceSize args, void *argp) {
int callback = 0;
callback = sceKernelCreateCallback("ExitCallback", Services::ExitCallback, nullptr);
sceKernelRegisterExitCallback(callback);
sceKernelSleepThreadCB();
return 0;
}
int SetupCallbacks(void) {
int thread = 0;
if (R_SUCCEEDED(thread = sceKernelCreateThread("CallbackThread", Services::CallbackThread, 0x11, 0xFA0, 0, nullptr)))
sceKernelStartThread(thread, 0, 0);
return thread;
}
}
int main(int argc, char *argv[]) {
Services::SetupCallbacks();
Services::Init();
Game::Loop();
Services::Exit();
}

57
source/textures.cpp Normal file
View File

@ -0,0 +1,57 @@
#include <cstring>
#include <png.h>
#include <pspdebug.h>
#include "textures.hpp"
extern unsigned char lives_png_start[];
extern unsigned int lives_png_size;
namespace Textures {
static g2dTexture *lives_tex;
g2dTexture *LoadImageBufferPNG(unsigned char *data, int size) {
g2dTexture *tex = nullptr;
png_image image;
std::memset(&image, 0, (sizeof image));
image.version = PNG_IMAGE_VERSION;
if (png_image_begin_read_from_memory(&image, data, size) != 0) {
png_bytep buffer;
image.format = PNG_FORMAT_RGBA;
buffer = new png_byte[PNG_IMAGE_SIZE(image)];
if (buffer != nullptr && png_image_finish_read(&image, nullptr, buffer, 0, nullptr) != 0) {
tex = g2dTexLoad(buffer, image.width, image.height, G2D_SWIZZLE);
delete[] buffer;
png_image_free(&image);
}
else {
if (buffer == nullptr) {
pspDebugScreenPrintf("png_byte buffer: returned nullptr\n");
png_image_free(&image);
}
else {
pspDebugScreenPrintf("png_image_finish_read failed: %s\n", image.message);
delete[] buffer;
}
}
}
else
pspDebugScreenPrintf("png_image_begin_read_from_memory failed: %s\n", image.message);
return tex;
}
void Init(void) {
lives_tex = Textures::LoadImageBufferPNG(lives_png_start, lives_png_size);
}
void Exit(void) {
g2dTexFree(&lives_tex);
}
g2dTexture *GetLives(void) {
return lives_tex;
}
}

168
source/utils.cpp Normal file
View File

@ -0,0 +1,168 @@
#include <cstring>
#include <pspkernel.h>
#include <pspreg.h>
#include <psputility_sysparam.h>
#include "utils.hpp"
enum PspCtrlButtons PSP_CTRL_ENTER, PSP_CTRL_CANCEL;
namespace Utils {
constexpr unsigned int CTRL_DEADZONE_DELAY = 500000;
constexpr unsigned int CTRL_DELAY = 100000;
static SceCtrlData pad, prev_pad;
static unsigned int last_button = 0;
static int last_button_tick = 0, deadzone_tick = 0;
void SetBounds(int &set, int min, int max) {
if (set > max)
set = min;
else if (set < min)
set = max;
}
static int GetRegistryValue(const char *dir, const char *name, unsigned int *value) {
int ret = 0;
struct RegParam reg_param;
REGHANDLE reg_handle = 0, reg_handle_cat = 0, reg_handle_key = 0;
unsigned int type = 0, size = 0;
std::memset(&reg_param, 0, sizeof(RegParam));
reg_param.regtype = 1;
reg_param.namelen = std::strlen("/system");
reg_param.unk2 = 1;
reg_param.unk3 = 1;
std::strcpy(reg_param.name, "/system");
if (R_FAILED(ret = sceRegOpenRegistry(&reg_param, 2, &reg_handle))) {
pspDebugScreenPrintf("sceRegOpenRegistry() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegOpenCategory(reg_handle, dir, 2, &reg_handle_cat))) {
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegOpenCategory() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegGetKeyInfo(reg_handle_cat, name, &reg_handle_key, &type, &size))) {
sceRegCloseCategory(reg_handle_cat);
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegGetKeyInfo() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegGetKeyValue(reg_handle_cat, reg_handle_key, value, 4))) {
sceRegCloseCategory(reg_handle_cat);
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegGetKeyValue() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegFlushCategory(reg_handle_cat))) {
sceRegCloseCategory(reg_handle_cat);
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegFlushCategory() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegCloseCategory(reg_handle_cat))) {
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegCloseCategory() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegFlushRegistry(reg_handle))) {
sceRegCloseRegistry(reg_handle);
pspDebugScreenPrintf("sceRegFlushRegistry() failed: 0x%08x\n", ret);
return ret;
}
if (R_FAILED(ret = sceRegCloseRegistry(reg_handle))) {
pspDebugScreenPrintf("sceRegFlushRegistry() failed: 0x%08x\n", ret);
return ret;
}
return 0;
}
int ReadControls(void) {
prev_pad = pad;
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons == last_button) {
if (pad.TimeStamp - deadzone_tick < CTRL_DEADZONE_DELAY)
return 0;
if (pad.TimeStamp - last_button_tick < CTRL_DELAY)
return 0;
last_button_tick = pad.TimeStamp;
return last_button;
}
last_button = pad.Buttons;
deadzone_tick = last_button_tick = pad.TimeStamp;
return last_button;
}
int IsButtonPressed(enum PspCtrlButtons buttons) {
return ((pad.Buttons & buttons) == buttons) && ((prev_pad.Buttons & buttons) != buttons);
}
int IsButtonHeld(enum PspCtrlButtons buttons) {
return pad.Buttons & buttons;
}
enum PspCtrlButtons GetEnterButton(void) {
int ret = 0, button = -1;
if (R_FAILED(ret = sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &button))) {
pspDebugScreenPrintf("sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN) failed: 0x%08x\n", ret);
unsigned int reg_button = -1;
if (R_SUCCEEDED(Utils::GetRegistryValue("/CONFIG/SYSTEM/XMB", "button_assign", &reg_button))) {
if (reg_button == 0)
return PSP_CTRL_CIRCLE;
return PSP_CTRL_CROSS;
}
}
if (button == 0)
return PSP_CTRL_CIRCLE;
return PSP_CTRL_CROSS; // By default return PSP_CTRL_CROSS
}
// Basically the opposite of GetEnterButton()
enum PspCtrlButtons GetCancelButton(void) {
int ret = 0, button = -1;
if (R_FAILED(ret = sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &button))) {
pspDebugScreenPrintf("sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN) failed: 0x%08x\n", ret);
unsigned int reg_button = -1;
if (R_SUCCEEDED(Utils::GetRegistryValue("/CONFIG/SYSTEM/XMB", "button_assign", &reg_button))) {
if (reg_button == 0)
return PSP_CTRL_CROSS;
return PSP_CTRL_CIRCLE;
}
}
if (button == 0)
return PSP_CTRL_CROSS;
return PSP_CTRL_CIRCLE; // By default return PSP_CTRL_CIRCLE
}
float GetAnalogX(void) {
return ((static_cast<float>(pad.Lx - 122.5f)) / 122.5f);
}
float GetAnalogY(void) {
return ((static_cast<float>(pad.Ly - 122.5f)) / 122.5f);
}
}