mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-04-24 15:37:59 -05:00
Adding libugba interrupt handler
This commit is contained in:
parent
e219892664
commit
e18f3232ab
|
|
@ -38,8 +38,6 @@ Name | Type | Default | Description
|
|||
|
||||
## Documentation
|
||||
|
||||

|
||||
|
||||
```
|
||||
Multi-Player mode can be used to communicate between up to 4 units.
|
||||
|
||||
|
|
|
|||
1
examples/_lib/LinkConnection.h
Symbolic link
1
examples/_lib/LinkConnection.h
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../lib/LinkConnection.h
|
||||
90
examples/_lib/libugba/include/background.h
Normal file
90
examples/_lib/libugba/include/background.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef BACKGROUND_H__
|
||||
#define BACKGROUND_H__
|
||||
|
||||
#include "bios.h"
|
||||
#include "hardware.h"
|
||||
|
||||
// List of all possible sizes of regular backgrounds
|
||||
typedef enum {
|
||||
BG_REGULAR_256x256,
|
||||
BG_REGULAR_512x256,
|
||||
BG_REGULAR_256x512,
|
||||
BG_REGULAR_512x512,
|
||||
|
||||
BG_REGULAR_NUMBER,
|
||||
|
||||
BG_REGULAR_INVALID
|
||||
} bg_regular_size;
|
||||
|
||||
// List of all possible sizes of affine backgrounds
|
||||
typedef enum {
|
||||
BG_AFFINE_128x128,
|
||||
BG_AFFINE_256x256,
|
||||
BG_AFFINE_512x512,
|
||||
BG_AFFINE_1024x1024,
|
||||
|
||||
BG_AFFINE_NUMBER,
|
||||
|
||||
BG_AFFINE_INVALID
|
||||
} bg_affine_size;
|
||||
|
||||
// Types of background based on their bit depth
|
||||
typedef enum {
|
||||
BG_16_COLORS,
|
||||
BG_256_COLORS
|
||||
} bg_color_mode;
|
||||
|
||||
// Initialize a regular background.
|
||||
EXPORT_API
|
||||
void BG_RegularInit(int index, bg_regular_size size, bg_color_mode colors,
|
||||
uintptr_t tile_base_addr, uintptr_t map_base_addr);
|
||||
|
||||
// Functions to set and get the scroll of a regular background. It doesn't work
|
||||
// for affine backgrounds. Note that the scroll hardware registers are
|
||||
// read-only. The functions below keep a copy of the scroll value so that it can
|
||||
// be recovered later.
|
||||
EXPORT_API void BG_RegularScrollSet(int index, int x, int y);
|
||||
EXPORT_API void BG_RegularScrollGet(int index, int *x, int *y);
|
||||
|
||||
// Initialize an affine background.
|
||||
EXPORT_API
|
||||
void BG_AffineInit(int index, bg_affine_size size, uintptr_t tile_base_addr,
|
||||
uintptr_t map_base_addr, int wrap);
|
||||
|
||||
// Set affine transformation values for the specified affine background.
|
||||
EXPORT_API void BG_AffineTransformSet(int index, bg_affine_dst *tr);
|
||||
|
||||
// Enable wrap mode of an affine background.
|
||||
EXPORT_API void BG_AffineWrapEnable(int index, int wrap);
|
||||
|
||||
// Set priority of a background.
|
||||
EXPORT_API void BG_PrioritySet(int index, int priority);
|
||||
|
||||
// Enable mosaic effect in the specified background.
|
||||
EXPORT_API void BG_MosaicEnable(int index, int enabled);
|
||||
|
||||
// Get a pointer to the framebuffer (in mode 3).
|
||||
EXPORT_API uint16_t *BG_Mode3FramebufferGet(void);
|
||||
|
||||
// Get a pointer to the active or non-active framebuffer (in mode 4).
|
||||
EXPORT_API uint16_t *BG_Mode4FramebufferActiveGet(void);
|
||||
EXPORT_API uint16_t *BG_Mode4FramebufferBackGet(void);
|
||||
|
||||
// Get a pointer to the active or non-active framebuffer (in mode 5).
|
||||
EXPORT_API uint16_t *BG_Mode5FramebufferActiveGet(void);
|
||||
EXPORT_API uint16_t *BG_Mode5FramebufferBackGet(void);
|
||||
|
||||
// Set active buffer (0 or 1).
|
||||
EXPORT_API void BG_FramebufferSet(int backbuffer);
|
||||
|
||||
// Swap active framebuffer (used for modes 4 and 5).
|
||||
EXPORT_API void BG_FramebufferSwap(void);
|
||||
|
||||
// Set backdrop color (background palette 0 color).
|
||||
EXPORT_API void BG_BackdropColorSet(uint16_t color);
|
||||
|
||||
#endif // BACKGROUND_H__
|
||||
207
examples/_lib/libugba/include/bios.h
Normal file
207
examples/_lib/libugba/include/bios.h
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020, 2022 Antonio Niño Díaz
|
||||
|
||||
#ifndef BIOS_H__
|
||||
#define BIOS_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "hardware.h"
|
||||
|
||||
// Note: Names taken from GBATEK
|
||||
|
||||
// Perform a soft reset. Not supported on the SDL2 port.
|
||||
EXPORT_API NORETURN void SWI_SoftReset(void);
|
||||
|
||||
// Flags to use with SWI_RegisterRamReset()
|
||||
#define SWI_RAM_RESET_EWRAM (1 << 0)
|
||||
#define SWI_RAM_RESET_IWRAM (1 << 1) // Except for the last 0x200 bytes
|
||||
#define SWI_RAM_RESET_PALETTE (1 << 2)
|
||||
#define SWI_RAM_RESET_VRAM (1 << 3)
|
||||
#define SWI_RAM_RESET_OAM (1 << 4)
|
||||
#define SWI_RAM_RESET_IO_SERIAL (1 << 5)
|
||||
#define SWI_RAM_RESET_IO_SOUND (1 << 6)
|
||||
#define SWI_RAM_RESET_IO_OTHER (1 << 7)
|
||||
|
||||
// Clear different areas of memory and I/O registers
|
||||
EXPORT_API void SWI_RegisterRamReset(uint32_t flags);
|
||||
|
||||
// Wait until an interrupt happens.
|
||||
EXPORT_API void SWI_Halt(void);
|
||||
|
||||
// Wait until the VBlank interrupt happens.
|
||||
EXPORT_API void SWI_VBlankIntrWait(void);
|
||||
|
||||
// Wait for any of the interrupts in the flags specified. If an interrupt has
|
||||
// already happened, it is possible to discard it by setting the argument to 1.
|
||||
// If it is set to 0, and the interrupt has happened already, this function will
|
||||
// return right away.
|
||||
//
|
||||
// Note that if no flags are passed the CPU will stay in an infinite loop inside
|
||||
// this function.
|
||||
EXPORT_API void SWI_IntrWait(uint32_t discard_old_flags, uint16_t wait_flags);
|
||||
|
||||
// For SWI_CpuSet() and SWI_CpuFastSet()
|
||||
#define SWI_MODE_COPY (0 << 24)
|
||||
#define SWI_MODE_FILL (1 << 24)
|
||||
// For SWI_CpuSet() only
|
||||
#define SWI_MODE_16BIT (0 << 26)
|
||||
#define SWI_MODE_32BIT (1 << 26)
|
||||
|
||||
// Source and destination must be aligned to 4 bytes for 32-bit copies, or 2
|
||||
// bytes for 16-bit copies. The length is expressed either in 32-bit or 16-bit
|
||||
// chunks (words or halfwords).
|
||||
EXPORT_API void SWI_CpuSet(const void *src, void *dst, uint32_t len_mode);
|
||||
|
||||
// Source and destination must be aligned to 4 bytes. The length must be a
|
||||
// multiple of 8 bytes.
|
||||
EXPORT_API void SWI_CpuFastSet(const void *src, void *dst, uint32_t len_mode);
|
||||
|
||||
// Calculate result or modulus of dividing num by div.
|
||||
EXPORT_API int32_t SWI_Div(int32_t num, int32_t div);
|
||||
EXPORT_API int32_t SWI_DivMod(int32_t num, int32_t div);
|
||||
|
||||
// Calculate square root.
|
||||
EXPORT_API uint16_t SWI_Sqrt(uint32_t value);
|
||||
|
||||
// Calculate arc tangent
|
||||
EXPORT_API int16_t SWI_ArcTan(int16_t tan);
|
||||
|
||||
// Calculate arc tangent 2
|
||||
EXPORT_API int16_t SWI_ArcTan2(int16_t x, int16_t y);
|
||||
|
||||
// Known values that SWI_GetBiosChecksum() can return
|
||||
#define SWI_CHECKSUM_GBA (0xBAAE187F) // GBA, GBA SP, GB Micro
|
||||
#define SWI_CHECKSUM_NDS (0xBAAE1880) // NDS, 3DS in NDS mode
|
||||
|
||||
// Returns checksum of the BIOS
|
||||
EXPORT_API uint32_t SWI_GetBiosChecksum(void);
|
||||
|
||||
// Struct that holds the input to SWI_BgAffineSet()
|
||||
typedef struct ALIGNED(4) {
|
||||
int32_t bgx; // 24.8 fixed point
|
||||
int32_t bgy; // 24.8 fixed point
|
||||
int16_t scrx;
|
||||
int16_t scry;
|
||||
int16_t scalex; // 8.8 fixed point
|
||||
int16_t scaley; // 8.8 fixed point
|
||||
uint32_t angle; // 8.8 fixed point. Low 8 bits ignored.
|
||||
// The angle is a 32 bit integer (instead of adding a padding field) for
|
||||
// conveniency. Only bits 8-15 are actually used.
|
||||
} bg_affine_src;
|
||||
|
||||
static_assert(sizeof(bg_affine_src) == 20, "Wrong bg_affine_src size");
|
||||
|
||||
// Struct that holds the state of a background affine transformation. It is used
|
||||
// as container of the output of SWI_BgAffineSet()
|
||||
typedef struct ALIGNED(4) {
|
||||
int16_t pa;
|
||||
int16_t pb;
|
||||
int16_t pc;
|
||||
int16_t pd;
|
||||
int32_t xoff;
|
||||
int32_t yoff;
|
||||
} bg_affine_dst;
|
||||
|
||||
static_assert(sizeof(bg_affine_dst) == 16, "Wrong bg_affine_dst size");
|
||||
|
||||
// This function gets a list of background transformations and outputs the
|
||||
// correct affine matrices for the GBA hardware.
|
||||
EXPORT_API
|
||||
void SWI_BgAffineSet(const bg_affine_src *src, bg_affine_dst *dst,
|
||||
uint32_t count);
|
||||
|
||||
// Struct that holds the input to SWI_ObjAffineSet()
|
||||
typedef struct ALIGNED(2) {
|
||||
int16_t sx; // 8.8 fixed point
|
||||
int16_t sy; // 8.8 fixed point
|
||||
uint16_t angle; // 8.8 fixed point. Range: 0 - 0xFFFF
|
||||
uint16_t padding;
|
||||
} obj_affine_src;
|
||||
|
||||
static_assert(sizeof(obj_affine_src) == 8, "Wrong obj_affine_src size");
|
||||
|
||||
// This function gets a list of objects transformations and outputs the correct
|
||||
// affine matrices for the GBA hardware.
|
||||
EXPORT_API
|
||||
void SWI_ObjAffineSet(const obj_affine_src *src, void *dst,
|
||||
uint32_t count, uint32_t increment);
|
||||
|
||||
// Struct that holds information used by SWI_BitUnPack()
|
||||
typedef struct ALIGNED(4) {
|
||||
int16_t source_length;
|
||||
uint8_t source_width;
|
||||
uint8_t dest_width;
|
||||
uint32_t data_offset;
|
||||
} bit_unpack_info;
|
||||
|
||||
static_assert(sizeof(bit_unpack_info) == 8, "Wrong bit_unpack_info size");
|
||||
|
||||
// Used in data_offset in bit_unpack_info.
|
||||
#define SWI_BITUNPACK_OFFSET_ZERO (1 << 31)
|
||||
|
||||
// Unpack data of the specified width in source into the specified width in the
|
||||
// destination. Used to increase the color depth of images, for example. It
|
||||
// writes the result to the destination using 32-bit writes. VRAM can be used as
|
||||
// destination.
|
||||
EXPORT_API
|
||||
void SWI_BitUnPack(const void *source, void *dest, const bit_unpack_info *info);
|
||||
|
||||
// Values that specify the type of the compression in the 32-bit header of a
|
||||
// compressed blob. It can be found in bits 4-7 of the header.
|
||||
#define SWI_UNCOMP_TYPE_LZ77 (1)
|
||||
#define SWI_UNCOMP_TYPE_HUFFMAN (2)
|
||||
#define SWI_UNCOMP_TYPE_RL (3)
|
||||
#define SWI_UNCOMP_TYPE_DIFF (8)
|
||||
|
||||
// Value specified in bits 0-3 of the header
|
||||
#define SWI_DIFF_SIZE_8BIT (1)
|
||||
#define SWI_DIFF_SIZE_16BIT (2)
|
||||
|
||||
// Decompresses LZ77 data from the source and writes the result to the
|
||||
// destination using 8-bit writes. It can't be used to decompress directly to
|
||||
// VRAM, as it only accepts 16 and 32-bit accesses.
|
||||
EXPORT_API
|
||||
void SWI_LZ77UnCompReadNormalWrite8bit(const void *source, void *dest);
|
||||
|
||||
// Decompresses LZ77 data from the source and writes the result to the
|
||||
// destination using 16-bit writes. VRAM can be used as destination.
|
||||
EXPORT_API
|
||||
void SWI_LZ77UnCompReadNormalWrite16bit(const void *source, void *dest);
|
||||
|
||||
// Decompresses Huffman-encoded data from the source and writes the result to
|
||||
// the destination using 32-bit writes. VRAM can be used as destination.
|
||||
EXPORT_API void SWI_HuffUnComp(const void *source, void *dest);
|
||||
|
||||
// Decompresses Run-Length data from the source and writes the result to the
|
||||
// destination using 8-bit writes. It can't be used to decompress directly to
|
||||
// VRAM, as it only accepts 16 and 32-bit accesses.
|
||||
EXPORT_API void SWI_RLUnCompWram(const void *source, void *dest);
|
||||
|
||||
// Decompresses Run-Length data from the source and writes the result to the
|
||||
// destination using 16-bit writes. VRAM can be used as destination.
|
||||
EXPORT_API void SWI_RLUnCompVram(const void *source, void *dest);
|
||||
|
||||
// Convert data in diff format to original data. In this version, data elements
|
||||
// are 8 bits wide and the result is writen in 8-bit accesses.
|
||||
EXPORT_API void SWI_Diff8bitUnFilterWram(const void *source, void *dest);
|
||||
|
||||
// Convert data in diff format to original data. In this version, data elements
|
||||
// are 8 bits wide and the result is writen in 16-bit accesses. This means that
|
||||
// VRAM can be used as destination, as it doesn't accept 8-bit writes.
|
||||
EXPORT_API void SWI_Diff8bitUnFilterVram(const void *source, void *dest);
|
||||
|
||||
// Convert data in diff format to original data. In this version, data elements
|
||||
// are 16 bits wide and the result is writen in 16-bit accesses.
|
||||
EXPORT_API void SWI_Diff16bitUnFilter(const void *source, void *dest);
|
||||
|
||||
// Set the level of the SOUNDBIAS register by doing small changes. A level of 0
|
||||
// sets the BIAS level to 0, any other value sets it to 0x200.
|
||||
EXPORT_API void SWI_SoundBias(uint32_t level);
|
||||
|
||||
// Perform a hard reset. Not supported on the SDL2 port.
|
||||
EXPORT_API NORETURN void SWI_HardReset(void);
|
||||
|
||||
#endif // BIOS_H__
|
||||
39
examples/_lib/libugba/include/bios_wrappers.h
Normal file
39
examples/_lib/libugba/include/bios_wrappers.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef BIOS_WRAPPERS_H__
|
||||
#define BIOS_WRAPPERS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "bios.h"
|
||||
|
||||
// Note: This file contains wrappers to use some BIOS services easier than with
|
||||
// the actual interface.
|
||||
|
||||
// Copy from source to destination in 16-bit chunks.
|
||||
EXPORT_API void SWI_CpuSet_Copy16(const void *src, void *dst, size_t len);
|
||||
|
||||
// Fill destination with the 16-bit value from source.
|
||||
EXPORT_API void SWI_CpuSet_Fill16(const void *src, void *dst, size_t len);
|
||||
|
||||
// Copy from source to destination in 32-bit chunks.
|
||||
EXPORT_API void SWI_CpuSet_Copy32(const void *src, void *dst, size_t len);
|
||||
|
||||
// Fill destination with the 32-bit value from source.
|
||||
EXPORT_API void SWI_CpuSet_Fill32(const void *src, void *dst, size_t len);
|
||||
|
||||
|
||||
// Copy from source to destination in 32-bit chunks.
|
||||
EXPORT_API void SWI_CpuFastSet_Copy32(const void *src, void *dst, size_t len);
|
||||
|
||||
// Fill destination with the 32-bit value from source.
|
||||
EXPORT_API void SWI_CpuFastSet_Fill32(const void *src, void *dst, size_t len);
|
||||
|
||||
|
||||
// Fills an array of object affine matrices from an array of transformations.
|
||||
EXPORT_API void SWI_ObjAffineSet_OAM(const obj_affine_src *src,
|
||||
oam_matrix_entry *dst, uint32_t count);
|
||||
|
||||
#endif // BIOS_WRAPPERS_H__
|
||||
26
examples/_lib/libugba/include/console.h
Normal file
26
examples/_lib/libugba/include/console.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef CONSOLE_H__
|
||||
#define CONSOLE_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Initialize the console by loading the needed tileset and map to the last tile
|
||||
// block in VRAM.
|
||||
EXPORT_API void CON_InitDefault(void);
|
||||
|
||||
// Print a character.
|
||||
EXPORT_API void CON_PutChar(char c);
|
||||
|
||||
// Print an unformatted string.
|
||||
EXPORT_API void CON_Print(const char *string);
|
||||
|
||||
// Set cursor at the specified coordinates.
|
||||
EXPORT_API void CON_CursorSet(int x, int y);
|
||||
|
||||
// Clear the console.
|
||||
EXPORT_API void CON_Clear(void);
|
||||
|
||||
#endif // CONSOLE_H__
|
||||
35
examples/_lib/libugba/include/debug.h
Normal file
35
examples/_lib/libugba/include/debug.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020-2021 Antonio Niño Díaz
|
||||
|
||||
#ifndef DEBUG_H__
|
||||
#define DEBUG_H__
|
||||
|
||||
// This file has debug utilities that don't work on GBA binaries. However, there
|
||||
// are defines here that remove them automatically so that code that uses them
|
||||
// can still build without errors.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Take a screenshot. If the specified name is NULL, it defaults to
|
||||
// "screenshot.png".
|
||||
#ifdef __GBA__
|
||||
#define Debug_Screenshot(n) do { (void)(n); } while (0)
|
||||
#else
|
||||
EXPORT_API void Debug_Screenshot(const char *name);
|
||||
#endif
|
||||
|
||||
// Custom assert() that works on GBA and PC.
|
||||
#ifndef UGBA_DEBUG
|
||||
# define UGBA_Assert(expr) ((void)0)
|
||||
#else
|
||||
# define UGBA_Assert(expr) \
|
||||
((expr) ? (void)0 : \
|
||||
UGBA_AssertFunction(__FILE__, __LINE__, __func__, #expr))
|
||||
#endif // UGBA_DEBUG
|
||||
|
||||
EXPORT_API void UGBA_AssertFunction(const char *file, int line,
|
||||
const char *func, const char *expr);
|
||||
#endif // DEBUG_H__
|
||||
72
examples/_lib/libugba/include/definitions.h
Normal file
72
examples/_lib/libugba/include/definitions.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef DEFINITIONS_H__
|
||||
#define DEFINITIONS_H__
|
||||
|
||||
#define BIT(n) (1 << (n))
|
||||
|
||||
// For functions with unused arguments, for example
|
||||
#if defined(_MSC_VER)
|
||||
# define UNUSED
|
||||
#else
|
||||
# define UNUSED __attribute__((unused))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define ALIGNED(x) __declspec(align(x))
|
||||
#else
|
||||
# define ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define NORETURN __declspec(noreturn)
|
||||
#else
|
||||
# define NORETURN __attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
// The library is built static for GBA and shared for PC
|
||||
#if defined(__GBA__)
|
||||
# define EXPORT_API
|
||||
#else
|
||||
# if defined(_MSC_VER)
|
||||
# define EXPORT_API __declspec(dllexport)
|
||||
# else
|
||||
# define EXPORT_API __attribute__((visibility("default")))
|
||||
// TODO: Is this one below needed in MinGW?
|
||||
//# define EXPORT_API __attribute__((dllexport))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// NOTE: To use the following defines:
|
||||
//
|
||||
// ARM_CODE IWRAM_CODE int add(int a, int b)
|
||||
// {
|
||||
// return a + b;
|
||||
// }
|
||||
//
|
||||
// IWRAM_BSS int empty_array[100];
|
||||
//
|
||||
// IWRAM_DATA int non_empty_array[3] = { 1, 2, 3 };
|
||||
#ifdef __GBA__
|
||||
# define ARM_CODE __attribute__((target("arm")))
|
||||
# define THUMB_CODE __attribute__((target("thumb")))
|
||||
# define IWRAM_BSS // IWRAM is the default location for .bss symbols
|
||||
# define IWRAM_DATA // IWRAM is the default location for .data symbols
|
||||
# define IWRAM_CODE __attribute__((section(".iwram_code"), long_call))
|
||||
# define EWRAM_BSS __attribute__((section(".sbss")))
|
||||
# define EWRAM_DATA __attribute__((section(".ewram_data")))
|
||||
# define EWRAM_CODE __attribute__((section(".ewram_code"), long_call))
|
||||
#else
|
||||
# define ARM_CODE
|
||||
# define THUMB_CODE
|
||||
# define IWRAM_BSS
|
||||
# define IWRAM_DATA
|
||||
# define IWRAM_CODE
|
||||
# define EWRAM_BSS
|
||||
# define EWRAM_DATA
|
||||
# define EWRAM_CODE
|
||||
#endif
|
||||
|
||||
#endif // DEFINITIONS_H__
|
||||
62
examples/_lib/libugba/include/display.h
Normal file
62
examples/_lib/libugba/include/display.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020-2021 Antonio Niño Díaz
|
||||
|
||||
#ifndef DISPLAY_H__
|
||||
#define DISPLAY_H__
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
// Set background display mode and set the other fields of the register to 0.
|
||||
EXPORT_API void DISP_ModeSet(int mode);
|
||||
|
||||
// Enable or disable screen layers.
|
||||
EXPORT_API void DISP_LayersEnable(int bg0, int bg1, int bg2, int bg3, int obj);
|
||||
|
||||
// Enable or disable windows.
|
||||
EXPORT_API void DISP_WindowsEnable(int win0, int win1, int obj);
|
||||
|
||||
// Enable or disable the HBL Interval Free mode.
|
||||
EXPORT_API void DISP_HBLIntervalFreeEnable(int enable);
|
||||
|
||||
// Enable or disable forced blank.
|
||||
EXPORT_API void DISP_ForcedBlankEnable(int enable);
|
||||
|
||||
// Enable 1D mapping or disable it (and use 2D mapping).
|
||||
EXPORT_API void DISP_Object1DMappingEnable(int enable);
|
||||
|
||||
// Setup window 0 dimensions.
|
||||
EXPORT_API void WIN_Win0SizeSet(uint32_t left, uint32_t right,
|
||||
uint32_t top, uint32_t bottom);
|
||||
|
||||
// Setup window 1 dimensions.
|
||||
EXPORT_API void WIN_Win1SizeSet(uint32_t left, uint32_t right,
|
||||
uint32_t top, uint32_t bottom);
|
||||
|
||||
// Set the layers enabled for window 0.
|
||||
EXPORT_API void WIN_Win0LayersSet(uint16_t flags);
|
||||
|
||||
// Set the layers enabled for window 1 and outside of window 0.
|
||||
EXPORT_API void WIN_Win1LayersSet(uint16_t flags);
|
||||
|
||||
// Set the layers enabled outside of windows 0 and 1.
|
||||
EXPORT_API void WIN_WinOutLayersSet(uint16_t flags);
|
||||
|
||||
// Set the layers enabled inside object windows.
|
||||
EXPORT_API void WIN_WinObjLayersSet(uint16_t flags);
|
||||
|
||||
// Setup blending/brightness effect and layers affected.
|
||||
EXPORT_API void DISP_BlendSetup(uint16_t layers_1, uint16_t layers_2,
|
||||
uint16_t effect);
|
||||
|
||||
// Set blending factors for BLDCNT_ALPHA_BLENDING.
|
||||
EXPORT_API void DISP_BlendAlphaSet(int eva, int evb);
|
||||
|
||||
// Set blending factor for BLDCNT_BRIGTHNESS_INCRESE/DECREASE.
|
||||
EXPORT_API void DISP_BlendYSet(int evy);
|
||||
|
||||
// Setup mosaic for background and objects.
|
||||
EXPORT_API void DISP_MosaicSet(uint32_t bgh, uint32_t bgw,
|
||||
uint32_t objh, uint32_t objw);
|
||||
|
||||
#endif // DISPLAY_H__
|
||||
52
examples/_lib/libugba/include/dma.h
Normal file
52
examples/_lib/libugba/include/dma.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020-2021 Antonio Niño Díaz
|
||||
|
||||
#ifndef DMA_H__
|
||||
#define DMA_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Important note: The only DMA channel that can read from ROM is 3.
|
||||
|
||||
// Generic DMA transfer function. It is needed to start repeating transfers or
|
||||
// anything other than a simple copy, as there are only helpers for simple
|
||||
// copy scenarios.
|
||||
//
|
||||
// Returns 0 on success. A transfer can fail if:
|
||||
// - The channel number isn't valid
|
||||
// - the source address is set in ROM/SRAM and the specified channel isn't 3.
|
||||
// This check only works on GBA binaries.
|
||||
EXPORT_API
|
||||
int DMA_Transfer(int channel, const void *src, void *dst, size_t size,
|
||||
uint16_t flags);
|
||||
|
||||
// Stop DMA transfers that repeat. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_Stop(int channel);
|
||||
|
||||
// Copy from source to destination in 16-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_Copy16(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
// Copy from source to destination in 32-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_Copy32(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
// During the next HBL do a copy, in 16-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_HBLCopy16(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
// During the next HBL do a copy, in 32-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_HBLCopy32(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
// During the next VBL do a copy, in 16-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_VBLCopy16(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
// During the next VBL do a copy, in 32-bit chunks. Returns 0 on success.
|
||||
EXPORT_API
|
||||
int DMA_VBLCopy32(int channel, const void *src, void *dst, size_t size);
|
||||
|
||||
#endif // DMA_H__
|
||||
19
examples/_lib/libugba/include/fp_math.h
Normal file
19
examples/_lib/libugba/include/fp_math.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef FP_MATH_H__
|
||||
#define FP_MATH_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
#define FP_PI (0x8000)
|
||||
#define FP_PI_2 (FP_PI / 2)
|
||||
#define FP_2_PI (2 * FP_PI)
|
||||
|
||||
// Input: A full cirle is 0x10000 (PI = 0x8000)
|
||||
// Output: Between 1 << 16 and -1 << 16 (1.0 to -1.0)
|
||||
EXPORT_API IWRAM_CODE int32_t FP_Sin(int32_t x);
|
||||
EXPORT_API IWRAM_CODE int32_t FP_Cos(int32_t x);
|
||||
|
||||
#endif // FP_MATH_H__
|
||||
1080
examples/_lib/libugba/include/hardware.h
Normal file
1080
examples/_lib/libugba/include/hardware.h
Normal file
File diff suppressed because it is too large
Load Diff
35
examples/_lib/libugba/include/input.h
Normal file
35
examples/_lib/libugba/include/input.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef INPUT_H__
|
||||
#define INPUT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Update keypad state.
|
||||
EXPORT_API void KEYS_Update(void);
|
||||
|
||||
// Returns keys that have just been pressed.
|
||||
EXPORT_API uint16_t KEYS_Pressed(void);
|
||||
|
||||
// Returns keys that are pressed.
|
||||
EXPORT_API uint16_t KEYS_Held(void);
|
||||
|
||||
// Returns keys that have just been released.
|
||||
EXPORT_API uint16_t KEYS_Released(void);
|
||||
|
||||
// Enable keypad interrupt that is triggered when all specified keys are pressed
|
||||
// at the same time.
|
||||
EXPORT_API void KEYS_IRQEnablePressedAll(uint16_t keys);
|
||||
|
||||
// Enable keypad interrupt that is triggered when any of the specified keys is
|
||||
// pressed at any time.
|
||||
EXPORT_API void KEYS_IRQEnablePressedAny(uint16_t keys);
|
||||
|
||||
// Disable keypad interrupt.
|
||||
EXPORT_API void KEYS_IRQDisable(void);
|
||||
|
||||
#endif // INPUT_H__
|
||||
50
examples/_lib/libugba/include/interrupts.h
Normal file
50
examples/_lib/libugba/include/interrupts.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef INTERRUPTS_H__
|
||||
#define INTERRUPTS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
typedef enum {
|
||||
IRQ_VBLANK = 0,
|
||||
IRQ_HBLANK = 1,
|
||||
IRQ_VCOUNT = 2,
|
||||
IRQ_TIMER0 = 3,
|
||||
IRQ_TIMER1 = 4,
|
||||
IRQ_TIMER2 = 5,
|
||||
IRQ_TIMER3 = 6,
|
||||
IRQ_SERIAL = 7,
|
||||
IRQ_DMA0 = 8,
|
||||
IRQ_DMA1 = 9,
|
||||
IRQ_DMA2 = 10,
|
||||
IRQ_DMA3 = 11,
|
||||
IRQ_KEYPAD = 12,
|
||||
IRQ_GAMEPAK = 13,
|
||||
IRQ_NUMBER
|
||||
} irq_index;
|
||||
|
||||
typedef void (*irq_vector)(void);
|
||||
|
||||
// Initialize global interrupt handling. This is called before reaching
|
||||
// GBA_main(), so it isn't normally needed to call it.
|
||||
EXPORT_API void IRQ_Init(void);
|
||||
|
||||
// Set interrupt handler for the specified interrupt.
|
||||
EXPORT_API void IRQ_SetHandler(irq_index index, irq_vector function);
|
||||
|
||||
// Enable the specified interrupt. For VBLANK, HBLANK and VCOUNT, this function
|
||||
// also sets the corresponding flags in DISPSTAT automatically.
|
||||
EXPORT_API void IRQ_Enable(irq_index index);
|
||||
|
||||
// Disable the specified interrupt.
|
||||
EXPORT_API void IRQ_Disable(irq_index index);
|
||||
|
||||
// Set the reference VCOUNT that triggers the VCOUNT interrupt.
|
||||
EXPORT_API void IRQ_SetReferenceVCOUNT(uint32_t y);
|
||||
|
||||
#endif // INTERRUPTS_H__
|
||||
90
examples/_lib/libugba/include/obj.h
Normal file
90
examples/_lib/libugba/include/obj.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef OBJ_H__
|
||||
#define OBJ_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
typedef enum {
|
||||
OBJ_16_COLORS,
|
||||
OBJ_256_COLORS
|
||||
} oam_color_mode;
|
||||
|
||||
typedef enum {
|
||||
OBJ_MODE_NORMAL,
|
||||
OBJ_MODE_TRANSPARENT,
|
||||
OBJ_MODE_WINDOW
|
||||
} oam_entry_mode;
|
||||
|
||||
typedef enum {
|
||||
// Square
|
||||
OBJ_SIZE_8x8,
|
||||
OBJ_SIZE_16x16,
|
||||
OBJ_SIZE_32x32,
|
||||
OBJ_SIZE_64x64,
|
||||
|
||||
// Horizontal
|
||||
OBJ_SIZE_16x8,
|
||||
OBJ_SIZE_32x8,
|
||||
OBJ_SIZE_32x16,
|
||||
OBJ_SIZE_64x32,
|
||||
|
||||
// Vertical
|
||||
OBJ_SIZE_8x16,
|
||||
OBJ_SIZE_8x32,
|
||||
OBJ_SIZE_16x32,
|
||||
OBJ_SIZE_32x64,
|
||||
|
||||
OBJ_SIZE_NUMBER,
|
||||
|
||||
OBJ_SIZE_INVALID
|
||||
|
||||
} oam_entry_size;
|
||||
|
||||
// Regular objects functions
|
||||
// -------------------------
|
||||
|
||||
EXPORT_API void OBJ_RegularInit(int index, int x, int y, oam_entry_size size,
|
||||
oam_color_mode colors, int pal, int tile);
|
||||
EXPORT_API void OBJ_RegularEnableSet(int index, int enable);
|
||||
EXPORT_API void OBJ_RegularHFlipSet(int index, int enable);
|
||||
EXPORT_API void OBJ_RegularVFlipSet(int index, int enable);
|
||||
|
||||
// Affine objects functions
|
||||
// ------------------------
|
||||
|
||||
EXPORT_API void OBJ_AffineInit(int index, int x, int y, oam_entry_size size,
|
||||
int matrix, oam_color_mode colors, int pal,
|
||||
int tile, int doublesize);
|
||||
EXPORT_API void OBJ_AffineMatrixSet(int index, int matrix_index);
|
||||
EXPORT_API void OBJ_AffineDoubleSizeSet(int index, int enable);
|
||||
|
||||
// Common objects functions
|
||||
// ------------------------
|
||||
|
||||
EXPORT_API void OBJ_PositionSet(int index, int x, int y);
|
||||
EXPORT_API void OBJ_PositionGet(int index, int *x, int *y);
|
||||
|
||||
EXPORT_API void OBJ_ModeSet(int index, oam_entry_mode mode);
|
||||
|
||||
EXPORT_API void OBJ_GetShapeSize(oam_entry_size size,
|
||||
uint16_t *attr0_shape, uint16_t *attr1_size);
|
||||
EXPORT_API oam_entry_size OBJ_GetSizeFromDimensions(int width, int height);
|
||||
EXPORT_API void OBJ_GetDimensionsFromSize(oam_entry_size size,
|
||||
int *width, int *height);
|
||||
EXPORT_API void OBJ_SizeSet(int index, oam_entry_size size);
|
||||
|
||||
// Enable or disable mosaic effect.
|
||||
EXPORT_API void OBJ_MosaicSet(int index, int enable);
|
||||
|
||||
// Set palette of the object. Only for 16 color objects.
|
||||
EXPORT_API void OBJ_Palette16Set(int index, int palette);
|
||||
|
||||
EXPORT_API void OBJ_PrioritySet(int index, int priority);
|
||||
|
||||
// This function automatically detects if the object is in 16 or 256 color mode
|
||||
EXPORT_API void OBJ_TileSet(int index, int tile);
|
||||
|
||||
#endif // OBJ_H__
|
||||
54
examples/_lib/libugba/include/sound.h
Normal file
54
examples/_lib/libugba/include/sound.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020-2021 Antonio Niño Díaz
|
||||
|
||||
#ifndef SOUND_H__
|
||||
#define SOUND_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Enable or disable sound hardware. It must be enabled before doing anything
|
||||
// else with sound hardware.
|
||||
EXPORT_API void SOUND_MasterEnable(int enable);
|
||||
|
||||
// Set volume of DMA channels. Valid values are 100 and 50. Any other value will
|
||||
// be treated as 50%.
|
||||
EXPORT_API void SOUND_DMA_Volume(int dma_a_max, int dma_b_max);
|
||||
|
||||
// Set master volume of all PSG channels. Valid values are 100, 50 and 25.. Any
|
||||
// other value will be treated as 25%.
|
||||
EXPORT_API void SOUND_PSG_MasterVolume(int volume);
|
||||
|
||||
// Set left and right volume of all PSG channels. Valid values are 0 to 7.
|
||||
EXPORT_API void SOUND_PSG_Volume(int volume_left, int volume_right);
|
||||
|
||||
// Specify which DMA channels are heard from which speakers.
|
||||
EXPORT_API
|
||||
void SOUND_DMA_Pan(int dma_a_left, int dma_a_right,
|
||||
int dma_b_left, int dma_b_right);
|
||||
|
||||
// Specify which PSG channels are heard from which speakers.
|
||||
EXPORT_API
|
||||
void SOUND_PSG_Pan(int left_1, int right_1, int left_2, int right_2,
|
||||
int left_3, int right_3, int left_4, int right_4);
|
||||
|
||||
// Set buffer that will be streamed to DMA channel A. The buffer needs to be
|
||||
// aligned to 32 bits.
|
||||
EXPORT_API void SOUND_DMA_Stream_A(const void *source);
|
||||
|
||||
// Set buffer that will be streamed to DMA channel B. The buffer needs to be
|
||||
// aligned to 32 bits.
|
||||
EXPORT_API void SOUND_DMA_Stream_B(const void *source);
|
||||
|
||||
// Set buffers that will be streamed to DMA channels A and B. The buffers need
|
||||
// to be aligned to 32 bits.
|
||||
EXPORT_API void SOUND_DMA_Setup_AB(const void *source_a, const void *source_b);
|
||||
|
||||
// Restart DMA transfer used for audio.
|
||||
EXPORT_API void SOUND_DMA_Retrigger_AB(void);
|
||||
|
||||
// Specify which timer is assigned to each one of the DMA channels. Only timers
|
||||
// 0 and 1 are valid.
|
||||
EXPORT_API void SOUND_DMA_TimerSetup(int dma_a_timer, int dma_b_timer);
|
||||
|
||||
#endif // SOUND_H__
|
||||
40
examples/_lib/libugba/include/sram.h
Normal file
40
examples/_lib/libugba/include/sram.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2022 Antonio Niño Díaz
|
||||
|
||||
#ifndef SRAM_H__
|
||||
#define SRAM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// SRAM can only be accessed in 8-bits reads and writes.
|
||||
//
|
||||
// The functions in this file are placed in EWRAM. According to some sources,
|
||||
// reading SRAM from code in ROM doesn't work (even though it hasn't been
|
||||
// verified).
|
||||
//
|
||||
// If you are going to use SRAM, you should try to make it easier for emulators
|
||||
// and flashcarts to detect your save type:
|
||||
//
|
||||
// - Add a string like "SRAM_V111" to your ROM, preferably close to the start.
|
||||
// Magic strings like that are found in commercial games developed with the
|
||||
// SDK of Nintendo. Emulators look for them when loading ROMs.
|
||||
//
|
||||
// - The game code of your ROM should start with "2" for the EverDrive GBA to
|
||||
// detect it as SRAM:
|
||||
//
|
||||
// 1 - EEPROM || 2 - SRAM || 3 - FLASH-64 || 4 - FLASH-128
|
||||
//
|
||||
// https://krikzz.com/pub/support/everdrive-gba/OS/changelist.txt
|
||||
|
||||
// Writes a buffer into SRAM. The destination must be inside SRAM, and the size
|
||||
// of the buffer must be at most MEM_SRAM_SIZE bytes long. Returns 0 on success.
|
||||
EXPORT_API EWRAM_CODE int SRAM_Write(void *dst, const void *src, size_t size);
|
||||
|
||||
// Reads a buffer from SRAM. The source must be inside SRAM, and the size of the
|
||||
// buffer must be at most MEM_SRAM_SIZE bytes long. Returns 0 on success.
|
||||
EXPORT_API EWRAM_CODE int SRAM_Read(void *dst, const void *src, size_t size);
|
||||
|
||||
#endif // SRAM_H__
|
||||
31
examples/_lib/libugba/include/timer.h
Normal file
31
examples/_lib/libugba/include/timer.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef TIMER_H__
|
||||
#define TIMER_H__
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Start timer. The value passed to prescaler can be 1, 64, 256 or 1024.
|
||||
EXPORT_API
|
||||
void TM_TimerStart(int index, uint16_t reload_value, int prescaler,
|
||||
int enable_irq);
|
||||
|
||||
// Start timer in cascade mode. Note that the prescaler value is ignored in this
|
||||
// mode, so it isn't needed.
|
||||
EXPORT_API
|
||||
void TM_TimerStartCascade(int index, uint16_t period_ticks, int enable_irq);
|
||||
|
||||
// Start timer that is triggered every `period_ms` milliseconds. Internally it
|
||||
// looks for the lowest prescaler that allows this period (to have the best
|
||||
// accuracy). It returns 0 on success.
|
||||
EXPORT_API
|
||||
int TM_TimerStartMs(int index, uint32_t period_ms, int enable_irq);
|
||||
|
||||
// Stop the specified timer.
|
||||
EXPORT_API
|
||||
void TM_TimerStop(int index);
|
||||
|
||||
#endif // TIMER_H__
|
||||
|
||||
49
examples/_lib/libugba/include/ugba.h
Normal file
49
examples/_lib/libugba/include/ugba.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef UGBA_H__
|
||||
#define UGBA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "background.h"
|
||||
#include "bios.h"
|
||||
#include "bios_wrappers.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "definitions.h"
|
||||
#include "display.h"
|
||||
#include "dma.h"
|
||||
#include "fp_math.h"
|
||||
#include "hardware.h"
|
||||
#include "input.h"
|
||||
#include "interrupts.h"
|
||||
#include "obj.h"
|
||||
#include "sound.h"
|
||||
#include "sram.h"
|
||||
#include "timer.h"
|
||||
#include "vram.h"
|
||||
|
||||
// Initialize library. This function needs to be called at the start of main().
|
||||
EXPORT_API void UGBA_Init(int* argc, char** argv[]);
|
||||
|
||||
#ifndef __GBA__
|
||||
// Initialize library with no video output (for testing). This function needs to
|
||||
// be called at the start of main(). Not implemented in GBA as it isn't usedul
|
||||
// there.
|
||||
EXPORT_API void UGBA_InitHeadless(int* argc, char** argv[]);
|
||||
#endif
|
||||
|
||||
// This function tries to detect specific flashcarts with special needs and
|
||||
// returns a value to be written to REG_WAITCNT based on the flashcart. The best
|
||||
// possible returned value is WAITCNT_OPTIMIZED.
|
||||
EXPORT_API uint16_t UGBA_FlashcartOptimizedWaitstates(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // UGBA_H__
|
||||
35
examples/_lib/libugba/include/version.h
Normal file
35
examples/_lib/libugba/include/version.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef VERSION_H__
|
||||
#define VERSION_H__
|
||||
|
||||
#include <ugba/ugba.h>
|
||||
|
||||
// This library follows the Semantic Versioning rules: https://semver.org/
|
||||
|
||||
#define LIBUGBA_VERSION_MAJOR (0U)
|
||||
#define LIBUGBA_VERSION_MINOR (2U)
|
||||
#define LIBUGBA_VERSION_PATCH (0U)
|
||||
|
||||
#define LIBUGBA_VERSION ((LIBUGBA_VERSION_MAJOR << 16) | \
|
||||
(LIBUGBA_VERSION_MINOR << 8) | \
|
||||
(LIBUGBA_VERSION_PATCH << 0))
|
||||
|
||||
// Returns the version of the shared library when it was compiled.
|
||||
EXPORT_API uint32_t UGBA_VersionCompiledGet(void);
|
||||
|
||||
// This function can ve used to see if the version of the shared library is the
|
||||
// same as the one that the program was compiled with. It isn't needed for the
|
||||
// GBA version because it is linked statically.
|
||||
//
|
||||
// You should use the following right at the start of main() before UGBA_Init():
|
||||
//
|
||||
// if (!UGBA_VersionIsCompatible(LIBUGBA_VERSION))
|
||||
// VersionCheckFailed();
|
||||
//
|
||||
// It follows the rules of Semantic Versioning.
|
||||
EXPORT_API int UGBA_VersionIsCompatible(uint32_t version);
|
||||
|
||||
#endif // VERSION_H__
|
||||
49
examples/_lib/libugba/include/vram.h
Normal file
49
examples/_lib/libugba/include/vram.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright (c) 2020 Antonio Niño Díaz
|
||||
|
||||
#ifndef VRAM_H__
|
||||
#define VRAM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
// Copy 16-color object tiles to VRAM (0x06010000) starting at the given
|
||||
// index (0 - 1023).
|
||||
EXPORT_API
|
||||
void VRAM_OBJTiles16Copy(const void *src, size_t size, uint32_t tile_index);
|
||||
|
||||
// Copy 256-color object tiles to VRAM (0x06010000) starting at the given
|
||||
// index (0 - 511).
|
||||
EXPORT_API
|
||||
void VRAM_OBJTiles256Copy(const void *src, size_t size, uint32_t tile_index);
|
||||
|
||||
// Copy a 16-bit palette to object palette memory.
|
||||
EXPORT_API
|
||||
void VRAM_OBJPalette16Copy(const void *src, size_t size, uint32_t pal_index);
|
||||
|
||||
// Copy a 256-bit palette to object palette memory.
|
||||
EXPORT_API
|
||||
void VRAM_OBJPalette256Copy(const void *src, size_t size);
|
||||
|
||||
// Copy 16-color background tiles to VRAM (0x06000000) starting at the given
|
||||
// index (0 - 2047).
|
||||
EXPORT_API
|
||||
void VRAM_BGTiles16Copy(const void *src, size_t size, uint32_t tile_index);
|
||||
|
||||
// Copy 256-color background tiles to VRAM (0x06000000) starting at the given
|
||||
// index (0 - 1023).
|
||||
EXPORT_API
|
||||
void VRAM_BGTiles256Copy(const void *src, size_t size, uint32_t tile_index);
|
||||
|
||||
// Copy a 16-bit palette to background palette memory.
|
||||
EXPORT_API
|
||||
void VRAM_BGPalette16Copy(const void *src, size_t size, uint32_t pal_index);
|
||||
|
||||
// Copy a 256-bit palette to background palette memory.
|
||||
EXPORT_API
|
||||
void VRAM_BGPalette256Copy(const void *src, size_t size);
|
||||
|
||||
#endif // VRAM_H__
|
||||
BIN
examples/_lib/libugba/lib/libugba.a
Normal file
BIN
examples/_lib/libugba/lib/libugba.a
Normal file
Binary file not shown.
|
|
@ -131,13 +131,13 @@ export PATH := $(DEVKITARM)/bin:$(PATH)
|
|||
export PROJ ?= $(notdir $(CURDIR))
|
||||
TITLE := $(PROJ)
|
||||
|
||||
LIBS := -ltonc
|
||||
LIBS := -ltonc -lugba
|
||||
|
||||
BUILD := build
|
||||
SRCDIRS := src
|
||||
DATADIRS := data
|
||||
INCDIRS := src lib
|
||||
LIBDIRS := $(TONCLIB)
|
||||
INCDIRS := src
|
||||
LIBDIRS := $(TONCLIB) $(PWD)/../_lib/libugba
|
||||
|
||||
# --- switches ---
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../../lib/LinkConnection.h
|
||||
22
examples/basic/src/interrupt.cpp
Normal file
22
examples/basic/src/interrupt.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "interrupt.h"
|
||||
#include <ugba.h>
|
||||
|
||||
void interrupt_init(void) {
|
||||
IRQ_Init();
|
||||
}
|
||||
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function) {
|
||||
IRQ_SetHandler((irq_index)index, function);
|
||||
}
|
||||
|
||||
void interrupt_enable(interrupt_index index) {
|
||||
IRQ_Enable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_disable(interrupt_index index) {
|
||||
IRQ_Disable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_set_reference_vcount(unsigned long y) {
|
||||
IRQ_SetReferenceVCOUNT(y);
|
||||
}
|
||||
30
examples/basic/src/interrupt.h
Normal file
30
examples/basic/src/interrupt.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef INTERRUPT_H
|
||||
#define INTERRUPT_H
|
||||
|
||||
typedef enum {
|
||||
INTR_VBLANK = 0,
|
||||
INTR_HBLANK = 1,
|
||||
INTR_VCOUNT = 2,
|
||||
INTR_TIMER0 = 3,
|
||||
INTR_TIMER1 = 4,
|
||||
INTR_TIMER2 = 5,
|
||||
INTR_TIMER3 = 6,
|
||||
INTR_SERIAL = 7,
|
||||
INTR_DMA0 = 8,
|
||||
INTR_DMA1 = 9,
|
||||
INTR_DMA2 = 10,
|
||||
INTR_DMA3 = 11,
|
||||
INTR_KEYPAD = 12,
|
||||
INTR_GAMEPAK = 13,
|
||||
INTR_NUMBER
|
||||
} interrupt_index;
|
||||
|
||||
typedef void (*interrupt_vector)(void);
|
||||
|
||||
void interrupt_init(void);
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function);
|
||||
void interrupt_enable(interrupt_index index);
|
||||
void interrupt_disable(interrupt_index index);
|
||||
void interrupt_set_reference_vcount(unsigned long y);
|
||||
|
||||
#endif // INTERRUPT_H
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#include <tonc.h>
|
||||
|
||||
#include <string>
|
||||
#include "interrupt.h"
|
||||
|
||||
// (0) Include the header
|
||||
#include "../lib/LinkConnection.h"
|
||||
#include "../../_lib/LinkConnection.h"
|
||||
|
||||
void log(std::string text);
|
||||
|
||||
|
|
@ -14,12 +14,14 @@ void init() {
|
|||
REG_DISPCNT = DCNT_MODE0 | DCNT_BG0;
|
||||
tte_init_se_default(0, BG_CBB(0) | BG_SBB(31));
|
||||
|
||||
irq_init(NULL);
|
||||
|
||||
// (2) Add the interrupt service routines
|
||||
irq_add(II_VBLANK, LINK_ISR_VBLANK);
|
||||
irq_add(II_SERIAL, LINK_ISR_SERIAL);
|
||||
irq_add(II_TIMER3, LINK_ISR_TIMER);
|
||||
interrupt_init();
|
||||
interrupt_set_handler(INTR_VBLANK, LINK_ISR_VBLANK);
|
||||
interrupt_enable(INTR_VBLANK);
|
||||
interrupt_set_handler(INTR_SERIAL, LINK_ISR_SERIAL);
|
||||
interrupt_enable(INTR_SERIAL);
|
||||
interrupt_set_handler(INTR_TIMER3, LINK_ISR_TIMER);
|
||||
interrupt_enable(INTR_TIMER3);
|
||||
|
||||
// (3) Initialize the library
|
||||
linkConnection->activate();
|
||||
|
|
@ -32,7 +34,7 @@ int main() {
|
|||
for (u32 i = 0; i < LINK_MAX_PLAYERS; i++)
|
||||
data[i] = 0;
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
// (4) Send/read messages messages
|
||||
u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
u16 message = keys + 1;
|
||||
|
|
@ -44,8 +46,9 @@ int main() {
|
|||
output += "Players: " + std::to_string(linkState->playerCount) + "\n";
|
||||
|
||||
for (u32 i = 0; i < linkState->playerCount; i++) {
|
||||
while (linkState->hasMessage(i))
|
||||
while (linkState->hasMessage(i)) {
|
||||
data[i] = linkState->readMessage(i) - 1;
|
||||
}
|
||||
|
||||
output += "Player " + std::to_string(i) + ": " +
|
||||
std::to_string(data[i]) + "\n";
|
||||
|
|
@ -53,8 +56,9 @@ int main() {
|
|||
|
||||
output += "_sent: " + std::to_string(message) + "\n";
|
||||
output += "_self pID: " + std::to_string(linkState->currentPlayerId);
|
||||
} else
|
||||
} else {
|
||||
output += std::string("Waiting...");
|
||||
}
|
||||
log(output);
|
||||
|
||||
VBlankIntrWait();
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ endef
|
|||
export PROJ ?= $(notdir $(CURDIR))
|
||||
TITLE := $(PROJ)
|
||||
|
||||
LIBS := -ltonc -lgba-sprite-engine
|
||||
LIBS := -ltonc -lugba -lgba-sprite-engine
|
||||
|
||||
BUILD := build
|
||||
SRCDIRS := src \
|
||||
|
|
@ -129,7 +129,7 @@ SRCDIRS := src \
|
|||
|
||||
DATADIRS :=
|
||||
INCDIRS := src
|
||||
LIBDIRS := $(TONCLIB) $(BASE_DIR)/lib/libgba-sprite-engine
|
||||
LIBDIRS := $(TONCLIB) $(PWD)/../_lib/libugba $(PWD)/../_lib/libgba-sprite-engine
|
||||
|
||||
# --- switches ---
|
||||
|
||||
|
|
@ -277,21 +277,13 @@ endif # End BUILD switch
|
|||
|
||||
# --- More targets ----------------------------------------------------
|
||||
|
||||
.PHONY: clean rebuild start check-env
|
||||
.PHONY: clean rebuild start
|
||||
|
||||
check-env:
|
||||
ifndef BASE_DIR
|
||||
$(warning Please export a BASE_DIR environment variable pointing to this directory.)
|
||||
$(warning Example:)
|
||||
$(warning export BASE_DIR="D:\work\gba\projects\gba-link-connection\examples\full")
|
||||
$(error "Aborting")
|
||||
endif
|
||||
rebuild: clean $(BUILD)
|
||||
|
||||
rebuild: check-env clean $(BUILD)
|
||||
|
||||
start: check-env
|
||||
start:
|
||||
start "$(TARGET).gba"
|
||||
|
||||
restart: check-env rebuild start
|
||||
restart: rebuild start
|
||||
|
||||
# EOF
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../../lib/LinkConnection.h
|
||||
22
examples/full/src/interrupt.cpp
Normal file
22
examples/full/src/interrupt.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "interrupt.h"
|
||||
#include <ugba.h>
|
||||
|
||||
void interrupt_init(void) {
|
||||
IRQ_Init();
|
||||
}
|
||||
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function) {
|
||||
IRQ_SetHandler((irq_index)index, function);
|
||||
}
|
||||
|
||||
void interrupt_enable(interrupt_index index) {
|
||||
IRQ_Enable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_disable(interrupt_index index) {
|
||||
IRQ_Disable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_set_reference_vcount(unsigned long y) {
|
||||
IRQ_SetReferenceVCOUNT(y);
|
||||
}
|
||||
30
examples/full/src/interrupt.h
Normal file
30
examples/full/src/interrupt.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef INTERRUPT_H
|
||||
#define INTERRUPT_H
|
||||
|
||||
typedef enum {
|
||||
INTR_VBLANK = 0,
|
||||
INTR_HBLANK = 1,
|
||||
INTR_VCOUNT = 2,
|
||||
INTR_TIMER0 = 3,
|
||||
INTR_TIMER1 = 4,
|
||||
INTR_TIMER2 = 5,
|
||||
INTR_TIMER3 = 6,
|
||||
INTR_SERIAL = 7,
|
||||
INTR_DMA0 = 8,
|
||||
INTR_DMA1 = 9,
|
||||
INTR_DMA2 = 10,
|
||||
INTR_DMA3 = 11,
|
||||
INTR_KEYPAD = 12,
|
||||
INTR_GAMEPAK = 13,
|
||||
INTR_NUMBER
|
||||
} interrupt_index;
|
||||
|
||||
typedef void (*interrupt_vector)(void);
|
||||
|
||||
void interrupt_init(void);
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function);
|
||||
void interrupt_enable(interrupt_index index);
|
||||
void interrupt_disable(interrupt_index index);
|
||||
void interrupt_set_reference_vcount(unsigned long y);
|
||||
|
||||
#endif // INTERRUPT_H
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <tonc.h>
|
||||
|
||||
#include "../lib/LinkConnection.h"
|
||||
#include "../../_lib/LinkConnection.h"
|
||||
#include "interrupt.h"
|
||||
#include "scenes/TestScene.h"
|
||||
#include "utils/SceneUtils.h"
|
||||
|
||||
// FULL:
|
||||
// This test has a menu and lets the user send data in different ways.
|
||||
|
||||
void setUpInterrupts();
|
||||
void printTutorial();
|
||||
static std::shared_ptr<GBAEngine> engine{new GBAEngine()};
|
||||
|
|
@ -55,17 +58,19 @@ inline void ISR_reset() {
|
|||
}
|
||||
|
||||
inline void setUpInterrupts() {
|
||||
irq_init(NULL);
|
||||
interrupt_init();
|
||||
|
||||
// LinkConnection
|
||||
irq_add(II_VBLANK, LINK_ISR_VBLANK);
|
||||
irq_add(II_SERIAL, LINK_ISR_SERIAL);
|
||||
irq_add(II_TIMER3, LINK_ISR_TIMER);
|
||||
irq_add(II_TIMER2, NULL);
|
||||
interrupt_set_handler(INTR_VBLANK, LINK_ISR_VBLANK);
|
||||
interrupt_enable(INTR_VBLANK);
|
||||
interrupt_set_handler(INTR_SERIAL, LINK_ISR_SERIAL);
|
||||
interrupt_enable(INTR_SERIAL);
|
||||
interrupt_set_handler(INTR_TIMER3, LINK_ISR_TIMER);
|
||||
interrupt_enable(INTR_TIMER3);
|
||||
|
||||
// A+B+START+SELECT
|
||||
REG_KEYCNT = 0b1100000000001111;
|
||||
irq_add(II_KEYPAD, ISR_reset);
|
||||
interrupt_set_handler(INTR_KEYPAD, ISR_reset);
|
||||
}
|
||||
|
||||
void printTutorial() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <libgba-sprite-engine/background/text_stream.h>
|
||||
|
||||
#include "../lib/LinkConnection.h"
|
||||
#include "../../_lib/LinkConnection.h"
|
||||
#include "utils/InputHandler.h"
|
||||
#include "utils/SceneUtils.h"
|
||||
|
||||
|
|
|
|||
284
examples/stress/Makefile
Normal file
284
examples/stress/Makefile
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
#
|
||||
# Template tonc makefile
|
||||
#
|
||||
# Yoinked mostly from DKP's template
|
||||
#
|
||||
|
||||
# === SETUP ===========================================================
|
||||
|
||||
# --- No implicit rules ---
|
||||
.SUFFIXES:
|
||||
|
||||
# --- Paths ---
|
||||
export TONCLIB := ${DEVKITPRO}/libtonc
|
||||
|
||||
# === TONC RULES ======================================================
|
||||
#
|
||||
# Yes, this is almost, but not quite, completely like to
|
||||
# DKP's base_rules and gba_rules
|
||||
#
|
||||
|
||||
export PATH := $(DEVKITARM)/bin:$(PATH)
|
||||
|
||||
|
||||
# --- Executable names ---
|
||||
|
||||
PREFIX ?= arm-none-eabi-
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AS := $(PREFIX)as
|
||||
export AR := $(PREFIX)ar
|
||||
export NM := $(PREFIX)nm
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
|
||||
# LD defined in Makefile
|
||||
|
||||
|
||||
# === LINK / TRANSLATE ================================================
|
||||
|
||||
%.gba : %.elf
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
@gbafix $@ -t$(TITLE)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.mb.elf :
|
||||
@echo Linking multiboot
|
||||
$(LD) -specs=gba_mb.specs $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
$(NM) -Sn $@ > $(basename $(notdir $@)).map
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.elf :
|
||||
@echo Linking cartridge
|
||||
$(LD) -specs=gba.specs $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
$(NM) -Sn $@ > $(basename $(notdir $@)).map
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.a :
|
||||
@echo $(notdir $@)
|
||||
@rm -f $@
|
||||
$(AR) -crs $@ $^
|
||||
|
||||
|
||||
# === OBJECTIFY =======================================================
|
||||
|
||||
%.iwram.o : %.iwram.cpp
|
||||
@echo $(notdir $<)
|
||||
$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(IARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
%.iwram.o : %.iwram.c
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(IARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.cpp
|
||||
@echo $(notdir $<)
|
||||
$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(RARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.c
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(RARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.s
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.S
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# canned command sequence for binary data
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
define bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(<F) | tr . _)`.h
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(<F) | tr . _)`.h
|
||||
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(<F) | tr . _)`.h
|
||||
endef
|
||||
# =====================================================================
|
||||
|
||||
# --- Main path ---
|
||||
|
||||
export PATH := $(DEVKITARM)/bin:$(PATH)
|
||||
|
||||
|
||||
# === PROJECT DETAILS =================================================
|
||||
# PROJ : Base project name
|
||||
# TITLE : Title for ROM header (12 characters)
|
||||
# LIBS : Libraries to use, formatted as list for linker flags
|
||||
# BUILD : Directory for build process temporaries. Should NOT be empty!
|
||||
# SRCDIRS : List of source file directories
|
||||
# DATADIRS : List of data file directories
|
||||
# INCDIRS : List of header file directories
|
||||
# LIBDIRS : List of library directories
|
||||
# General note: use `.' for the current dir, don't leave the lists empty.
|
||||
|
||||
export PROJ ?= $(notdir $(CURDIR))
|
||||
TITLE := $(PROJ)
|
||||
|
||||
LIBS := -ltonc -lugba
|
||||
|
||||
BUILD := build
|
||||
SRCDIRS := src
|
||||
DATADIRS := data
|
||||
INCDIRS := src lib
|
||||
LIBDIRS := $(TONCLIB) $(PWD)/../_lib/libugba
|
||||
|
||||
# --- switches ---
|
||||
|
||||
bMB := 0 # Multiboot build
|
||||
bTEMPS := 0 # Save gcc temporaries (.i and .s files)
|
||||
bDEBUG2 := 0 # Generate debug info (bDEBUG2? Not a full DEBUG flag. Yet)
|
||||
|
||||
|
||||
# === BUILD FLAGS =====================================================
|
||||
# This is probably where you can stop editing
|
||||
# NOTE: I've noticed that -fgcse and -ftree-loop-optimize sometimes muck
|
||||
# up things (gcse seems fond of building masks inside a loop instead of
|
||||
# outside them for example). Removing them sometimes helps
|
||||
|
||||
# --- Architecture ---
|
||||
|
||||
ARCH := -mthumb-interwork -mthumb
|
||||
RARCH := -mthumb-interwork -mthumb
|
||||
IARCH := -mthumb-interwork -marm -mlong-calls
|
||||
|
||||
# --- Main flags ---
|
||||
|
||||
CFLAGS := -mcpu=arm7tdmi -mtune=arm7tdmi -O2
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += $(INCLUDE)
|
||||
CFLAGS += -ffast-math -fno-strict-aliasing
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := $(ARCH) $(INCLUDE)
|
||||
LDFLAGS := $(ARCH) -Wl,-Map,$(PROJ).map
|
||||
|
||||
# --- switched additions ----------------------------------------------
|
||||
|
||||
# --- Multiboot ? ---
|
||||
ifeq ($(strip $(bMB)), 1)
|
||||
TARGET := $(PROJ).mb
|
||||
else
|
||||
TARGET := $(PROJ)
|
||||
endif
|
||||
|
||||
# --- Save temporary files ? ---
|
||||
ifeq ($(strip $(bTEMPS)), 1)
|
||||
CFLAGS += -save-temps
|
||||
CXXFLAGS += -save-temps
|
||||
endif
|
||||
|
||||
# --- Debug info ? ---
|
||||
|
||||
ifeq ($(strip $(bDEBUG)), 1)
|
||||
CFLAGS += -DDEBUG -g
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
ASFLAGS += -DDEBUG -g
|
||||
LDFLAGS += -g
|
||||
else
|
||||
CFLAGS += -DNDEBUG
|
||||
CXXFLAGS += -DNDEBUG
|
||||
ASFLAGS += -DNDEBUG
|
||||
endif
|
||||
|
||||
|
||||
# === BUILD PROC ======================================================
|
||||
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
|
||||
# Still in main dir:
|
||||
# * Define/export some extra variables
|
||||
# * Invoke this file again from the build dir
|
||||
# PONDER: what happens if BUILD == "" ?
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export VPATH := \
|
||||
$(foreach dir, $(SRCDIRS) , $(CURDIR)/$(dir)) \
|
||||
$(foreach dir, $(DATADIRS), $(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
# --- List source and data files ---
|
||||
|
||||
CFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir, $(DATADIRS), $(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
# --- Set linker depending on C++ file existence ---
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
# --- Define object file list ---
|
||||
export OFILES := $(addsuffix .o, $(BINFILES)) \
|
||||
$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) \
|
||||
$(SFILES:.s=.o)
|
||||
|
||||
# --- Create include and library search paths ---
|
||||
export INCLUDE := $(foreach dir,$(INCDIRS),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := -L$(CURDIR) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
# --- Create BUILD if necessary, and run this makefile from there ---
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
arm-none-eabi-nm -Sn $(OUTPUT).elf > $(BUILD)/$(TARGET).map
|
||||
|
||||
all : $(BUILD)
|
||||
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -rf $(BUILD) $(TARGET).elf $(TARGET).gba $(TARGET).sav
|
||||
|
||||
|
||||
else # If we're here, we should be in the BUILD dir
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
# --- Main targets ----
|
||||
|
||||
$(OUTPUT).gba : $(OUTPUT).elf
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
|
||||
endif # End BUILD switch
|
||||
|
||||
# --- More targets ----------------------------------------------------
|
||||
|
||||
.PHONY: clean rebuild start
|
||||
|
||||
rebuild: clean $(BUILD)
|
||||
|
||||
start:
|
||||
start "$(TARGET).gba"
|
||||
|
||||
restart: rebuild start
|
||||
|
||||
# EOF
|
||||
22
examples/stress/src/interrupt.cpp
Normal file
22
examples/stress/src/interrupt.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "interrupt.h"
|
||||
#include <ugba.h>
|
||||
|
||||
void interrupt_init(void) {
|
||||
IRQ_Init();
|
||||
}
|
||||
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function) {
|
||||
IRQ_SetHandler((irq_index)index, function);
|
||||
}
|
||||
|
||||
void interrupt_enable(interrupt_index index) {
|
||||
IRQ_Enable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_disable(interrupt_index index) {
|
||||
IRQ_Disable((irq_index)index);
|
||||
}
|
||||
|
||||
void interrupt_set_reference_vcount(unsigned long y) {
|
||||
IRQ_SetReferenceVCOUNT(y);
|
||||
}
|
||||
30
examples/stress/src/interrupt.h
Normal file
30
examples/stress/src/interrupt.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef INTERRUPT_H
|
||||
#define INTERRUPT_H
|
||||
|
||||
typedef enum {
|
||||
INTR_VBLANK = 0,
|
||||
INTR_HBLANK = 1,
|
||||
INTR_VCOUNT = 2,
|
||||
INTR_TIMER0 = 3,
|
||||
INTR_TIMER1 = 4,
|
||||
INTR_TIMER2 = 5,
|
||||
INTR_TIMER3 = 6,
|
||||
INTR_SERIAL = 7,
|
||||
INTR_DMA0 = 8,
|
||||
INTR_DMA1 = 9,
|
||||
INTR_DMA2 = 10,
|
||||
INTR_DMA3 = 11,
|
||||
INTR_KEYPAD = 12,
|
||||
INTR_GAMEPAK = 13,
|
||||
INTR_NUMBER
|
||||
} interrupt_index;
|
||||
|
||||
typedef void (*interrupt_vector)(void);
|
||||
|
||||
void interrupt_init(void);
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function);
|
||||
void interrupt_enable(interrupt_index index);
|
||||
void interrupt_disable(interrupt_index index);
|
||||
void interrupt_set_reference_vcount(unsigned long y);
|
||||
|
||||
#endif // INTERRUPT_H
|
||||
84
examples/stress/src/main.cpp
Normal file
84
examples/stress/src/main.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#include <tonc.h>
|
||||
#include <string>
|
||||
#include "interrupt.h"
|
||||
|
||||
#include "../../_lib/LinkConnection.h"
|
||||
|
||||
// STRESS:
|
||||
// This test sends consecutive values in a two-player setup.
|
||||
// When a GBA receives something not equal to previousValue + 1, it hangs.
|
||||
// It should work indefinitely (with no packet loss).
|
||||
|
||||
void log(std::string text);
|
||||
|
||||
LinkConnection* linkConnection = new LinkConnection();
|
||||
|
||||
void init() {
|
||||
REG_DISPCNT = DCNT_MODE0 | DCNT_BG0;
|
||||
tte_init_se_default(0, BG_CBB(0) | BG_SBB(31));
|
||||
|
||||
interrupt_init();
|
||||
interrupt_set_handler(INTR_VBLANK, LINK_ISR_VBLANK);
|
||||
interrupt_enable(INTR_VBLANK);
|
||||
interrupt_set_handler(INTR_SERIAL, LINK_ISR_SERIAL);
|
||||
interrupt_enable(INTR_SERIAL);
|
||||
interrupt_set_handler(INTR_TIMER3, LINK_ISR_TIMER);
|
||||
interrupt_enable(INTR_TIMER3);
|
||||
|
||||
linkConnection->activate();
|
||||
}
|
||||
|
||||
int main() {
|
||||
init();
|
||||
|
||||
u16 counter = 0;
|
||||
u16 remoteCounter = 0;
|
||||
bool error = false;
|
||||
|
||||
while (true) {
|
||||
auto linkState = linkConnection->linkState.get();
|
||||
|
||||
std::string output = "";
|
||||
if (linkState->isConnected()) {
|
||||
output += "Players: " + std::to_string(linkState->playerCount) + "\n";
|
||||
|
||||
if (linkState->playerCount == 2) {
|
||||
linkConnection->send(counter + 1);
|
||||
counter++;
|
||||
}
|
||||
|
||||
while (linkState->hasMessage(!linkState->currentPlayerId)) {
|
||||
u16 msg = linkState->readMessage(!linkState->currentPlayerId) - 1;
|
||||
if (msg == remoteCounter) {
|
||||
remoteCounter++;
|
||||
} else {
|
||||
error = true;
|
||||
output += "ERROR!\nExpected " + std::to_string(remoteCounter) +
|
||||
" but got " + std::to_string(msg) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
output += "(" + std::to_string(counter) + ", " +
|
||||
std::to_string(remoteCounter) + ")\n";
|
||||
} else {
|
||||
output += std::string("Waiting...");
|
||||
}
|
||||
|
||||
log(output);
|
||||
|
||||
if (error) {
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
|
||||
VBlankIntrWait();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log(std::string text) {
|
||||
tte_erase_screen();
|
||||
tte_write("#{P:0,0}");
|
||||
tte_write(text.c_str());
|
||||
}
|
||||
|
|
@ -30,12 +30,13 @@
|
|||
#define LINK_SET_HIGH(REG, BIT) REG |= 1 << BIT
|
||||
#define LINK_SET_LOW(REG, BIT) REG &= ~(1 << BIT)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// A Link Cable connection for Multi-player mode.
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Usage:
|
||||
// - 1) Include this header in your main.cpp file and add:
|
||||
// LinkConnection* linkConnection = new LinkConnection();
|
||||
// - 2) Add the required interrupt service routines:
|
||||
// - 2) Add the required interrupt service routines: (*)
|
||||
// irq_init(NULL);
|
||||
// irq_add(II_VBLANK, LINK_ISR_VBLANK);
|
||||
// irq_add(II_SERIAL, LINK_ISR_SERIAL);
|
||||
|
|
@ -45,10 +46,15 @@
|
|||
// - 4) Send/read messages by using:
|
||||
// linkConnection->send(...);
|
||||
// linkConnection->linkState
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// (*) libtonc's interrupt handler sometimes ignores interrupts due to a bug.
|
||||
// That can cause packet loss. You might want to use libugba's instead.
|
||||
// (see examples)
|
||||
// --------------------------------------------------------------------------
|
||||
// `data` restrictions:
|
||||
// 0xFFFF and 0x0 are reserved values, so don't use them
|
||||
// (they mean 'disconnected' and 'no data' respectively)
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void LINK_ISR_VBLANK();
|
||||
void LINK_ISR_TIMER();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user