Merge 86f6d29dcb
into cecae02b1d
This commit is contained in:
commit
7bbc594cf7
@ -24,7 +24,7 @@ bufferMatrix_s bufferMatrixList[BUFFERMATRIXLIST_SIZE];
|
||||
int bufferMatrixListLength;
|
||||
|
||||
//----------------------
|
||||
// GS SYSTEM STUFF
|
||||
// GS SYSTEM STUFF
|
||||
//----------------------
|
||||
|
||||
void initBufferMatrixList()
|
||||
@ -74,7 +74,7 @@ void gsLinearFree(void* mem)
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// MATRIX STACK STUFF
|
||||
// MATRIX STACK STUFF
|
||||
//----------------------
|
||||
|
||||
static mtx44 gsMatrixStacks[GS_MATRIXTYPES][GS_MATRIXSTACK_SIZE];
|
||||
@ -149,7 +149,7 @@ int gsMatrixMode(GS_MATRIX m)
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// MATRIX TRANSFORM STUFF
|
||||
// MATRIX TRANSFORM STUFF
|
||||
//------------------------
|
||||
|
||||
int gsMultMatrix(float* data)
|
||||
@ -208,7 +208,7 @@ void gsTranslate(float x, float y, float z)
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// MATRIX RENDER STUFF
|
||||
// MATRIX RENDER STUFF
|
||||
//----------------------
|
||||
|
||||
static void gsSetUniformMatrix(u32 startreg, float* m)
|
||||
@ -279,7 +279,7 @@ void gsAdjustBufferMatrices(mtx44 transformation)
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// VBO STUFF
|
||||
// VBO STUFF
|
||||
//----------------------
|
||||
|
||||
int gsVboInit(gsVbo_s* vbo)
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////
|
||||
// GPU example //
|
||||
///////////////////////////////////////
|
||||
//////////////////////////////////////
|
||||
// GPU example //
|
||||
//////////////////////////////////////
|
||||
|
||||
//this example is meant to show how to use the GPU to render a 3D object
|
||||
//it also shows how to do stereoscopic 3D
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////
|
||||
// SDMC example //
|
||||
///////////////////////////////////////
|
||||
//////////////////////////////////////
|
||||
// SDMC example //
|
||||
//////////////////////////////////////
|
||||
|
||||
//this example shows you how to load a binary image file from the SD card and display it on the lower screen
|
||||
//for this to work you should copy test.bin to same folder as your .3dsx
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
/*! \file console.h
|
||||
\brief 3ds stdio support.
|
||||
\brief 3ds stdio support.
|
||||
|
||||
<div class="fileHeader">
|
||||
Provides stdio integration for printing to the 3DS screen as well as debug print
|
||||
@ -29,7 +29,7 @@ typedef bool(* ConsolePrint)(void* con, int c);
|
||||
typedef struct ConsoleFont
|
||||
{
|
||||
u8* gfx; //!< A pointer to the font graphics
|
||||
u16 asciiOffset; //!< Offset to the first valid character in the font table
|
||||
u16 asciiOffset; //!< Offset to the first valid character in the font table
|
||||
u16 numChars; //!< Number of characters in the font graphics
|
||||
|
||||
}ConsoleFont;
|
||||
@ -50,13 +50,13 @@ PrintConsole defaultConsole =
|
||||
0,0, //prevcursorX prevcursorY
|
||||
40, //console width
|
||||
30, //console height
|
||||
0, //window x
|
||||
0, //window y
|
||||
0, //window x
|
||||
0, //window y
|
||||
32, //window width
|
||||
24, //window height
|
||||
3, //tab size
|
||||
0, //font character offset
|
||||
0, //print callback
|
||||
0, //print callback
|
||||
false //console initialized
|
||||
};
|
||||
</pre></div>
|
||||
@ -74,7 +74,7 @@ typedef struct PrintConsole
|
||||
int prevCursorY; /*!< Internal state */
|
||||
|
||||
int consoleWidth; /*!< Width of the console hardware layer in characters */
|
||||
int consoleHeight; /*!< Height of the console hardware layer in characters */
|
||||
int consoleHeight; /*!< Height of the console hardware layer in characters */
|
||||
|
||||
int windowX; /*!< Window X location in characters (not implemented) */
|
||||
int windowY; /*!< Window Y location in characters (not implemented) */
|
||||
|
@ -23,17 +23,17 @@ typedef enum{
|
||||
}APP_STATUS;
|
||||
|
||||
enum {
|
||||
APTSIGNAL_HOMEBUTTON = 1,
|
||||
APTSIGNAL_HOMEBUTTON = 1,
|
||||
// 2: sleep-mode related?
|
||||
APTSIGNAL_PREPARESLEEP = 3,
|
||||
APTSIGNAL_PREPARESLEEP = 3,
|
||||
// 4: triggered when ptm:s GetShellStatus() returns 5.
|
||||
APTSIGNAL_ENTERSLEEP = 5,
|
||||
APTSIGNAL_WAKEUP = 6,
|
||||
APTSIGNAL_ENABLE = 7,
|
||||
APTSIGNAL_POWERBUTTON = 8,
|
||||
APTSIGNAL_UTILITY = 9,
|
||||
APTSIGNAL_SLEEPSYSTEM = 10,
|
||||
APTSIGNAL_ERROR = 11
|
||||
APTSIGNAL_ENTERSLEEP = 5,
|
||||
APTSIGNAL_WAKEUP = 6,
|
||||
APTSIGNAL_ENABLE = 7,
|
||||
APTSIGNAL_POWERBUTTON = 8,
|
||||
APTSIGNAL_UTILITY = 9,
|
||||
APTSIGNAL_SLEEPSYSTEM = 10,
|
||||
APTSIGNAL_ERROR = 11
|
||||
};
|
||||
|
||||
|
||||
@ -82,4 +82,3 @@ Result APT_DoAppJump(Handle* handle, u32 NSbuf0Size, u32 NSbuf1Size, u8 *NSbuf0P
|
||||
Result APT_PrepareToStartLibraryApplet(Handle* handle, NS_APPID appID);
|
||||
Result APT_StartLibraryApplet(Handle* handle, NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize);
|
||||
Result APT_LaunchLibraryApplet(NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize);//This should be used for launching library applets, this uses the above APT_StartLibraryApplet/APT_PrepareToStartLibraryApplet funcs + apt*Session(). parambuf is used for APT params input, when the applet closes the output param block is copied here. This is not usable from the homebrew launcher. This is broken: when the applet does get launched at all, the applet process doesn't actually get terminated when the applet gets closed.
|
||||
|
||||
|
@ -3,67 +3,67 @@
|
||||
|
||||
/*! @file FS.h
|
||||
*
|
||||
* Filesystem Services
|
||||
* Filesystem Services
|
||||
*/
|
||||
|
||||
/*! @defgroup fs_open_flags FS Open Flags
|
||||
*
|
||||
* @sa FSUSER_OpenFile
|
||||
* @sa FSUSER_OpenFileDirectly
|
||||
* @sa FSUSER_OpenFile
|
||||
* @sa FSUSER_OpenFileDirectly
|
||||
*
|
||||
* @{
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! Open file for read. */
|
||||
#define FS_OPEN_READ (1<<0)
|
||||
#define FS_OPEN_READ (1<<0)
|
||||
/*! Open file for write. */
|
||||
#define FS_OPEN_WRITE (1<<1)
|
||||
#define FS_OPEN_WRITE (1<<1)
|
||||
/*! Create file if it doesn't exist. */
|
||||
#define FS_OPEN_CREATE (1<<2)
|
||||
#define FS_OPEN_CREATE (1<<2)
|
||||
/* @} */
|
||||
|
||||
/*! @defgroup fs_create_attributes FS Create Attributes
|
||||
*
|
||||
* @sa FSUSER_OpenFile
|
||||
* @sa FSUSER_OpenFileDirectly
|
||||
* @sa FSUSER_OpenFile
|
||||
* @sa FSUSER_OpenFileDirectly
|
||||
*
|
||||
* @{
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! No attributes. */
|
||||
#define FS_ATTRIBUTE_NONE (0x00000000)
|
||||
#define FS_ATTRIBUTE_NONE (0x00000000)
|
||||
/*! Create with read-only attribute. */
|
||||
#define FS_ATTRIBUTE_READONLY (0x00000001)
|
||||
#define FS_ATTRIBUTE_READONLY (0x00000001)
|
||||
/*! Create with archive attribute. */
|
||||
#define FS_ATTRIBUTE_ARCHIVE (0x00000100)
|
||||
#define FS_ATTRIBUTE_ARCHIVE (0x00000100)
|
||||
/*! Create with hidden attribute. */
|
||||
#define FS_ATTRIBUTE_HIDDEN (0x00010000)
|
||||
#define FS_ATTRIBUTE_HIDDEN (0x00010000)
|
||||
/*! Create with directory attribute. */
|
||||
#define FS_ATTRIBUTE_DIRECTORY (0x01000000)
|
||||
#define FS_ATTRIBUTE_DIRECTORY (0x01000000)
|
||||
/*! @} */
|
||||
|
||||
/*! @defgroup fs_write_flush_flags FS Flush Flags
|
||||
*
|
||||
* @sa FSFILE_Write
|
||||
* @sa FSFILE_Write
|
||||
*
|
||||
* @{
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! Don't flush */
|
||||
#define FS_WRITE_NOFLUSH (0x00000000)
|
||||
#define FS_WRITE_NOFLUSH (0x00000000)
|
||||
/*! Flush */
|
||||
#define FS_WRITE_FLUSH (0x00010001)
|
||||
#define FS_WRITE_FLUSH (0x00010001)
|
||||
|
||||
/* @} */
|
||||
|
||||
/*! FS path type */
|
||||
typedef enum
|
||||
{
|
||||
PATH_INVALID = 0, //!< Specifies an invalid path.
|
||||
PATH_EMPTY = 1, //!< Specifies an empty path.
|
||||
PATH_BINARY = 2, //!< Specifies a binary path, which is non-text based.
|
||||
PATH_CHAR = 3, //!< Specifies a text based path with a 8-bit byte per character.
|
||||
PATH_WCHAR = 4, //!< Specifies a text based path with a 16-bit short per character.
|
||||
PATH_INVALID = 0, //!< Specifies an invalid path.
|
||||
PATH_EMPTY = 1, //!< Specifies an empty path.
|
||||
PATH_BINARY = 2, //!< Specifies a binary path, which is non-text based.
|
||||
PATH_CHAR = 3, //!< Specifies a text based path with a 8-bit byte per character.
|
||||
PATH_WCHAR = 4, //!< Specifies a text based path with a 16-bit short per character.
|
||||
} FS_pathType;
|
||||
|
||||
/*! FS archive ids */
|
||||
@ -86,51 +86,51 @@ typedef enum
|
||||
/*! FS path */
|
||||
typedef struct
|
||||
{
|
||||
FS_pathType type; //!< FS path type.
|
||||
u32 size; //!< FS path size.
|
||||
const u8 *data; //!< Pointer to FS path data.
|
||||
FS_pathType type; //!< FS path type.
|
||||
u32 size; //!< FS path size.
|
||||
const u8 *data; //!< Pointer to FS path data.
|
||||
} FS_path;
|
||||
|
||||
/*! FS archive */
|
||||
typedef struct
|
||||
{
|
||||
u32 id; //!< Archive ID.
|
||||
FS_path lowPath; //!< FS path.
|
||||
Handle handleLow; //!< High word of handle.
|
||||
Handle handleHigh; //!< Low word of handle.
|
||||
u32 id; //!< Archive ID.
|
||||
FS_path lowPath; //!< FS path.
|
||||
Handle handleLow; //!< High word of handle.
|
||||
Handle handleHigh; //!< Low word of handle.
|
||||
} FS_archive;
|
||||
|
||||
/*! Directory entry */
|
||||
typedef struct
|
||||
{
|
||||
// 0x00
|
||||
u16 name[0x106]; //!< UTF-16 encoded name
|
||||
// 0x20C
|
||||
u8 shortName[0x09]; //!< 8.3 file name
|
||||
// 0x215
|
||||
u8 unknown1; //!< ???
|
||||
// 0x216
|
||||
u8 shortExt[0x04]; //!< 8.3 file extension (set to spaces for directories)
|
||||
// 0x21A
|
||||
u8 unknown2; //!< ???
|
||||
// 0x21B
|
||||
u8 unknown3; //!< ???
|
||||
// 0x21C
|
||||
u8 isDirectory; //!< directory bit
|
||||
// 0x21D
|
||||
u8 isHidden; //!< hidden bit
|
||||
// 0x21E
|
||||
u8 isArchive; //!< archive bit
|
||||
// 0x21F
|
||||
u8 isReadOnly; //!< read-only bit
|
||||
// 0x220
|
||||
u64 fileSize; //!< file size
|
||||
// 0x00
|
||||
u16 name[0x106]; //!< UTF-16 encoded name
|
||||
// 0x20C
|
||||
u8 shortName[0x09]; //!< 8.3 file name
|
||||
// 0x215
|
||||
u8 unknown1; //!< ???
|
||||
// 0x216
|
||||
u8 shortExt[0x04]; //!< 8.3 file extension (set to spaces for directories)
|
||||
// 0x21A
|
||||
u8 unknown2; //!< ???
|
||||
// 0x21B
|
||||
u8 unknown3; //!< ???
|
||||
// 0x21C
|
||||
u8 isDirectory; //!< directory bit
|
||||
// 0x21D
|
||||
u8 isHidden; //!< hidden bit
|
||||
// 0x21E
|
||||
u8 isArchive; //!< archive bit
|
||||
// 0x21F
|
||||
u8 isReadOnly; //!< read-only bit
|
||||
// 0x220
|
||||
u64 fileSize; //!< file size
|
||||
} FS_dirent;
|
||||
|
||||
Result fsInit(void);
|
||||
Result fsExit(void);
|
||||
|
||||
FS_path FS_makePath(FS_pathType type, const char *path);
|
||||
FS_path FS_makePath(FS_pathType type, const char *path);
|
||||
|
||||
Result FSUSER_Initialize(Handle* handle);
|
||||
Result FSUSER_OpenArchive(Handle* handle, FS_archive* archive);
|
||||
|
@ -6,35 +6,35 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KEY_A = BIT(0),
|
||||
KEY_B = BIT(1),
|
||||
KEY_SELECT = BIT(2),
|
||||
KEY_START = BIT(3),
|
||||
KEY_DRIGHT = BIT(4),
|
||||
KEY_DLEFT = BIT(5),
|
||||
KEY_DUP = BIT(6),
|
||||
KEY_DDOWN = BIT(7),
|
||||
KEY_R = BIT(8),
|
||||
KEY_L = BIT(9),
|
||||
KEY_X = BIT(10),
|
||||
KEY_Y = BIT(11),
|
||||
KEY_ZL = BIT(14), // (new 3DS only)
|
||||
KEY_ZR = BIT(15), // (new 3DS only)
|
||||
KEY_TOUCH = BIT(20), // Not actually provided by HID
|
||||
KEY_CSTICK_RIGHT = BIT(24), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_LEFT = BIT(25), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_UP = BIT(26), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_DOWN = BIT(27), // c-stick (new 3DS only)
|
||||
KEY_CPAD_RIGHT = BIT(28), // circle pad
|
||||
KEY_CPAD_LEFT = BIT(29), // circle pad
|
||||
KEY_CPAD_UP = BIT(30), // circle pad
|
||||
KEY_CPAD_DOWN = BIT(31), // circle pad
|
||||
KEY_A = BIT(0),
|
||||
KEY_B = BIT(1),
|
||||
KEY_SELECT = BIT(2),
|
||||
KEY_START = BIT(3),
|
||||
KEY_DRIGHT = BIT(4),
|
||||
KEY_DLEFT = BIT(5),
|
||||
KEY_DUP = BIT(6),
|
||||
KEY_DDOWN = BIT(7),
|
||||
KEY_R = BIT(8),
|
||||
KEY_L = BIT(9),
|
||||
KEY_X = BIT(10),
|
||||
KEY_Y = BIT(11),
|
||||
KEY_ZL = BIT(14), // (new 3DS only)
|
||||
KEY_ZR = BIT(15), // (new 3DS only)
|
||||
KEY_TOUCH = BIT(20), // Not actually provided by HID
|
||||
KEY_CSTICK_RIGHT = BIT(24), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_LEFT = BIT(25), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_UP = BIT(26), // c-stick (new 3DS only)
|
||||
KEY_CSTICK_DOWN = BIT(27), // c-stick (new 3DS only)
|
||||
KEY_CPAD_RIGHT = BIT(28), // circle pad
|
||||
KEY_CPAD_LEFT = BIT(29), // circle pad
|
||||
KEY_CPAD_UP = BIT(30), // circle pad
|
||||
KEY_CPAD_DOWN = BIT(31), // circle pad
|
||||
|
||||
// Generic catch-all directions
|
||||
KEY_UP = KEY_DUP | KEY_CPAD_UP,
|
||||
KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN,
|
||||
KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT,
|
||||
KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT,
|
||||
KEY_UP = KEY_DUP | KEY_CPAD_UP,
|
||||
KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN,
|
||||
KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT,
|
||||
KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT,
|
||||
} PAD_KEY;
|
||||
|
||||
typedef struct
|
||||
@ -90,12 +90,12 @@ void hidGyroRead(angularRate* rate);
|
||||
void hidWaitForEvent(HID_Event id, bool nextEvent);
|
||||
|
||||
// libnds compatibility defines
|
||||
#define scanKeys hidScanInput
|
||||
#define keysHeld hidKeysHeld
|
||||
#define keysDown hidKeysDown
|
||||
#define keysUp hidKeysUp
|
||||
#define touchRead hidTouchRead
|
||||
#define circleRead hidCircleRead
|
||||
#define scanKeys hidScanInput
|
||||
#define keysHeld hidKeysHeld
|
||||
#define keysDown hidKeysDown
|
||||
#define keysUp hidKeysUp
|
||||
#define touchRead hidTouchRead
|
||||
#define circleRead hidCircleRead
|
||||
|
||||
Result HIDUSER_GetHandles(Handle* outMemHandle, Handle *eventpad0, Handle *eventpad1, Handle *eventaccel, Handle *eventgyro, Handle *eventdebugpad);
|
||||
Result HIDUSER_EnableAccelerometer();
|
||||
|
@ -1,45 +1,45 @@
|
||||
/*
|
||||
svc.h _ Syscall wrappers.
|
||||
svc.h _ Syscall wrappers.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
MEMOP_FREE =1, // Free heap
|
||||
MEMOP_ALLOC=3, // Allocate heap
|
||||
MEMOP_MAP =4, // Mirror mapping
|
||||
MEMOP_UNMAP=5, // Mirror unmapping
|
||||
MEMOP_PROT =6, // Change protection
|
||||
MEMOP_FREE =1, // Free heap
|
||||
MEMOP_ALLOC =3, // Allocate heap
|
||||
MEMOP_MAP =4, // Mirror mapping
|
||||
MEMOP_UNMAP =5, // Mirror unmapping
|
||||
MEMOP_PROT =6, // Change protection
|
||||
|
||||
MEMOP_FREE_LINEAR =0x10001, // Free linear heap
|
||||
MEMOP_ALLOC_LINEAR=0x10003 // Allocate linear heap
|
||||
MEMOP_ALLOC_LINEAR=0x10003 // Allocate linear heap
|
||||
} MemOp;
|
||||
|
||||
typedef enum {
|
||||
MEMPERM_READ = 1,
|
||||
MEMPERM_WRITE = 2,
|
||||
MEMPERM_EXECUTE = 4,
|
||||
MEMPERM_DONTCARE = 0x10000000,
|
||||
MEMPERM_MAX = 0xFFFFFFFF //force 4-byte
|
||||
MEMPERM_READ = 1,
|
||||
MEMPERM_WRITE = 2,
|
||||
MEMPERM_EXECUTE = 4,
|
||||
MEMPERM_DONTCARE = 0x10000000,
|
||||
MEMPERM_MAX = 0xFFFFFFFF //force 4-byte
|
||||
} MemPerm;
|
||||
|
||||
typedef struct {
|
||||
u32 base_addr;
|
||||
u32 size;
|
||||
u32 perm;
|
||||
u32 state;
|
||||
u32 base_addr;
|
||||
u32 size;
|
||||
u32 perm;
|
||||
u32 state;
|
||||
} MemInfo;
|
||||
|
||||
typedef struct {
|
||||
u32 flags;
|
||||
u32 flags;
|
||||
} PageInfo;
|
||||
|
||||
typedef enum {
|
||||
ARBITER_FREE =0,
|
||||
ARBITER_ACQUIRE =1,
|
||||
ARBITER_KERNEL2 =2,
|
||||
ARBITER_ACQUIRE_TIMEOUT=3,
|
||||
ARBITER_KERNEL4 =4,
|
||||
ARBITER_FREE =0,
|
||||
ARBITER_ACQUIRE =1,
|
||||
ARBITER_KERNEL2 =2,
|
||||
ARBITER_ACQUIRE_TIMEOUT =3,
|
||||
ARBITER_KERNEL4 =4,
|
||||
} ArbitrationType;
|
||||
|
||||
static inline void* getThreadLocalStorage(void)
|
||||
@ -54,38 +54,38 @@ static inline u32* getThreadCommandBuffer(void)
|
||||
return (u32*)((u8*)getThreadLocalStorage() + 0x80);
|
||||
}
|
||||
|
||||
s32 svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm);
|
||||
s32 svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr);
|
||||
void __attribute__((noreturn)) svcExitProcess();
|
||||
s32 svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id);
|
||||
void __attribute__((noreturn)) svcExitThread();
|
||||
void svcSleepThread(s64 ns);
|
||||
s32 svcSetThreadPriority(Handle thread, s32 prio);
|
||||
s32 svcCreateMutex(Handle* mutex, bool initially_locked);
|
||||
s32 svcReleaseMutex(Handle handle);
|
||||
s32 svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count);
|
||||
s32 svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count);
|
||||
s32 svcCreateEvent(Handle* event, u8 reset_type);
|
||||
s32 svcSignalEvent(Handle handle);
|
||||
s32 svcClearEvent(Handle handle);
|
||||
s32 svcCreateTimer(Handle* timer, u8 reset_type);
|
||||
s32 svcSetTimer(Handle timer, s64 initial, s64 interval);
|
||||
s32 svcCancelTimer(Handle timer);
|
||||
s32 svcClearTimer(Handle timer);
|
||||
s32 svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm);
|
||||
s32 svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm);
|
||||
s32 svcUnmapMemoryBlock(Handle memblock, u32 addr);
|
||||
s32 svcCreateAddressArbiter(Handle *arbiter);
|
||||
s32 svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds);
|
||||
s32 svcWaitSynchronization(Handle handle, s64 nanoseconds);
|
||||
s32 svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds);
|
||||
s32 svcCloseHandle(Handle handle);
|
||||
s32 svcDuplicateHandle(Handle* out, Handle original);
|
||||
u64 svcGetSystemTick();
|
||||
s32 svcGetSystemInfo(s64* out, u32 type, s32 param);
|
||||
s32 svcGetProcessInfo(s64* out, Handle process, u32 type);
|
||||
s32 svcConnectToPort(volatile Handle* out, const char* portName);
|
||||
s32 svcSendSyncRequest(Handle session);
|
||||
s32 svcGetProcessId(u32 *out, Handle handle);
|
||||
s32 svcGetThreadId(u32 *out, Handle handle);
|
||||
s32 svcOutputDebugString(const char* str, int length);
|
||||
s32 svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm);
|
||||
s32 svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr);
|
||||
void __attribute__((noreturn)) svcExitProcess();
|
||||
s32 svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id);
|
||||
void __attribute__((noreturn)) svcExitThread();
|
||||
void svcSleepThread(s64 ns);
|
||||
s32 svcSetThreadPriority(Handle thread, s32 prio);
|
||||
s32 svcCreateMutex(Handle* mutex, bool initially_locked);
|
||||
s32 svcReleaseMutex(Handle handle);
|
||||
s32 svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count);
|
||||
s32 svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count);
|
||||
s32 svcCreateEvent(Handle* event, u8 reset_type);
|
||||
s32 svcSignalEvent(Handle handle);
|
||||
s32 svcClearEvent(Handle handle);
|
||||
s32 svcCreateTimer(Handle* timer, u8 reset_type);
|
||||
s32 svcSetTimer(Handle timer, s64 initial, s64 interval);
|
||||
s32 svcCancelTimer(Handle timer);
|
||||
s32 svcClearTimer(Handle timer);
|
||||
s32 svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm);
|
||||
s32 svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm);
|
||||
s32 svcUnmapMemoryBlock(Handle memblock, u32 addr);
|
||||
s32 svcCreateAddressArbiter(Handle *arbiter);
|
||||
s32 svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds);
|
||||
s32 svcWaitSynchronization(Handle handle, s64 nanoseconds);
|
||||
s32 svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds);
|
||||
s32 svcCloseHandle(Handle handle);
|
||||
s32 svcDuplicateHandle(Handle* out, Handle original);
|
||||
u64 svcGetSystemTick();
|
||||
s32 svcGetSystemInfo(s64* out, u32 type, s32 param);
|
||||
s32 svcGetProcessInfo(s64* out, Handle process, u32 type);
|
||||
s32 svcConnectToPort(volatile Handle* out, const char* portName);
|
||||
s32 svcSendSyncRequest(Handle session);
|
||||
s32 svcGetProcessId(u32 *out, Handle handle);
|
||||
s32 svcGetThreadId(u32 *out, Handle handle);
|
||||
s32 svcOutputDebugString(const char* str, int length);
|
||||
|
@ -4,25 +4,25 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#define rbtree_item(ptr, type, member) \
|
||||
((type*)(((char*)ptr) - offsetof(type, member)))
|
||||
((type*)(((char*)ptr) - offsetof(type, member)))
|
||||
|
||||
typedef struct rbtree rbtree_t;
|
||||
typedef struct rbtree_node rbtree_node_t;
|
||||
typedef struct rbtree rbtree_t;
|
||||
typedef struct rbtree_node rbtree_node_t;
|
||||
|
||||
typedef void (*rbtree_node_destructor_t)(rbtree_node_t *Node);
|
||||
typedef int (*rbtree_node_comparator_t)(const rbtree_node_t *lhs,
|
||||
const rbtree_node_t *rhs);
|
||||
typedef int (*rbtree_node_comparator_t)(const rbtree_node_t *lhs,
|
||||
const rbtree_node_t *rhs);
|
||||
struct rbtree_node
|
||||
{
|
||||
uintptr_t parent_color;
|
||||
rbtree_node_t *child[2];
|
||||
uintptr_t parent_color;
|
||||
rbtree_node_t *child[2];
|
||||
};
|
||||
|
||||
struct rbtree
|
||||
{
|
||||
rbtree_node_t *root;
|
||||
rbtree_node_comparator_t comparator;
|
||||
size_t size;
|
||||
rbtree_node_t *root;
|
||||
rbtree_node_comparator_t comparator;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -30,8 +30,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
rbtree_init(rbtree_t *tree,
|
||||
rbtree_node_comparator_t comparator);
|
||||
rbtree_init(rbtree_t *tree,
|
||||
rbtree_node_comparator_t comparator);
|
||||
|
||||
int
|
||||
rbtree_empty(const rbtree_t *tree);
|
||||
@ -41,16 +41,16 @@ rbtree_size(const rbtree_t *tree);
|
||||
|
||||
__attribute__((warn_unused_result))
|
||||
rbtree_node_t*
|
||||
rbtree_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
rbtree_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
|
||||
void
|
||||
rbtree_insert_multi(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
rbtree_insert_multi(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_find(const rbtree_t *tree,
|
||||
const rbtree_node_t *node);
|
||||
rbtree_find(const rbtree_t *tree,
|
||||
const rbtree_node_t *node);
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_min(const rbtree_t *tree);
|
||||
@ -65,13 +65,13 @@ rbtree_node_t*
|
||||
rbtree_node_prev(const rbtree_node_t *node);
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_remove(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
rbtree_node_destructor_t destructor);
|
||||
rbtree_remove(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
rbtree_node_destructor_t destructor);
|
||||
|
||||
void
|
||||
rbtree_clear(rbtree_t *tree,
|
||||
rbtree_node_destructor_t destructor);
|
||||
rbtree_clear(rbtree_t *tree,
|
||||
rbtree_node_destructor_t destructor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -63,9 +63,9 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
||||
if (nSize)
|
||||
{
|
||||
// We need to add the tail chunk that wasn't used to the list
|
||||
auto n = MemBlock::Create(nAddr, nSize);
|
||||
if (n) InsertAfter(b, n);
|
||||
else chunk.size += nSize; // we have no choice but to waste the space.
|
||||
auto n = MemBlock::Create(nAddr, nSize);
|
||||
if (n) InsertAfter(b, n);
|
||||
else chunk.size += nSize; // we have no choice but to waste the space.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -76,9 +76,9 @@ bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
||||
|
||||
void MemPool::Deallocate(const MemChunk& chunk)
|
||||
{
|
||||
u8* cAddr = chunk.addr;
|
||||
auto cSize = chunk.size;
|
||||
bool done = false;
|
||||
u8* cAddr = chunk.addr;
|
||||
auto cSize = chunk.size;
|
||||
bool done = false;
|
||||
|
||||
// Try to merge the chunk somewhere into the list
|
||||
for (auto b = first; !done && b; b = b->next)
|
||||
@ -121,7 +121,7 @@ void MemPool::Dump(const char* title)
|
||||
{
|
||||
printf("<%s> VRAM Pool Dump\n", title);
|
||||
for (auto b = first; b; b = b->next)
|
||||
printf(" - %p (%u bytes)\n", b->base, b->size);
|
||||
printf(" - %p (%u bytes)\n", b->base, b->size);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -31,17 +31,17 @@ void gfxSet3D(bool enable)
|
||||
}
|
||||
|
||||
void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format) {
|
||||
if(screen==GFX_TOP)
|
||||
topFormat = format;
|
||||
else
|
||||
botFormat = format;
|
||||
if(screen==GFX_TOP)
|
||||
topFormat = format;
|
||||
else
|
||||
botFormat = format;
|
||||
}
|
||||
|
||||
GSP_FramebufferFormats gfxGetScreenFormat(gfxScreen_t screen) {
|
||||
if(screen==GFX_TOP)
|
||||
return topFormat;
|
||||
else
|
||||
return botFormat;
|
||||
if(screen==GFX_TOP)
|
||||
return topFormat;
|
||||
else
|
||||
return botFormat;
|
||||
}
|
||||
|
||||
void gfxSetDoubleBuffering( gfxScreen_t screen, bool doubleBuffering) {
|
||||
@ -49,18 +49,18 @@ void gfxSetDoubleBuffering( gfxScreen_t screen, bool doubleBuffering) {
|
||||
}
|
||||
|
||||
static u32 __get_bytes_per_pixel(GSP_FramebufferFormats format) {
|
||||
switch(format) {
|
||||
case GSP_RGBA8_OES:
|
||||
return 4;
|
||||
case GSP_BGR8_OES:
|
||||
return 3;
|
||||
case GSP_RGB565_OES:
|
||||
case GSP_RGB5_A1_OES:
|
||||
case GSP_RGBA4_OES:
|
||||
return 2;
|
||||
}
|
||||
switch(format) {
|
||||
case GSP_RGBA8_OES:
|
||||
return 4;
|
||||
case GSP_BGR8_OES:
|
||||
return 3;
|
||||
case GSP_RGB565_OES:
|
||||
case GSP_RGB5_A1_OES:
|
||||
case GSP_RGBA4_OES:
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 3;
|
||||
return 3;
|
||||
}
|
||||
|
||||
void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -39,14 +39,14 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
|
||||
if(ret!=0) {
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle);
|
||||
if(ret!=0) {
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
svcCloseHandle(context->servhandle);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if(use_defaultproxy==0)return 0;
|
||||
|
||||
@ -55,7 +55,7 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
svcCloseHandle(context->servhandle);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#define O_NONBLOCK_3DS 0x4
|
||||
|
||||
#define ALL_3DS (O_NONBLOCK_3DS)
|
||||
#define ALL_FLAGS (O_NONBLOCK)
|
||||
#define ALL_3DS (O_NONBLOCK_3DS)
|
||||
#define ALL_FLAGS (O_NONBLOCK)
|
||||
|
||||
static int from_3ds(int flags)
|
||||
{
|
||||
|
@ -2,9 +2,9 @@
|
||||
#include <netdb.h>
|
||||
|
||||
#define MAX_HOSTENT_RESULTS 16
|
||||
static struct hostent SOC_hostent;
|
||||
static char *SOC_hostent_results[MAX_HOSTENT_RESULTS+1];
|
||||
static char *SOC_hostent_alias = NULL;
|
||||
static struct hostent SOC_hostent;
|
||||
static char *SOC_hostent_results[MAX_HOSTENT_RESULTS+1];
|
||||
static char *SOC_hostent_alias = NULL;
|
||||
|
||||
int h_errno = 0;
|
||||
|
||||
@ -30,11 +30,11 @@ struct hostent* gethostbyname(const char *name)
|
||||
if(( ret = svcSendSyncRequest(SOCU_handle))!=0)return NULL;
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
/* TODO: set h_errno based on SOCU_errno */
|
||||
|
||||
if(ret<0)return NULL;
|
||||
@ -44,11 +44,11 @@ struct hostent* gethostbyname(const char *name)
|
||||
if(num_results > MAX_HOSTENT_RESULTS)
|
||||
num_results = MAX_HOSTENT_RESULTS;
|
||||
|
||||
SOC_hostent.h_name = (char*)outbuf + 8;
|
||||
SOC_hostent.h_aliases = &SOC_hostent_alias;
|
||||
SOC_hostent.h_addrtype = AF_INET;
|
||||
SOC_hostent.h_length = 4;
|
||||
SOC_hostent.h_addr_list = SOC_hostent_results;
|
||||
SOC_hostent.h_name = (char*)outbuf + 8;
|
||||
SOC_hostent.h_aliases = &SOC_hostent_alias;
|
||||
SOC_hostent.h_addrtype = AF_INET;
|
||||
SOC_hostent.h_length = 4;
|
||||
SOC_hostent.h_addr_list = SOC_hostent_results;
|
||||
|
||||
SOC_hostent_alias = NULL;
|
||||
|
||||
|
@ -5,11 +5,11 @@
|
||||
|
||||
int inet_aton(const char *cp, struct in_addr *inp)
|
||||
{
|
||||
int base;
|
||||
uint32_t val;
|
||||
int c;
|
||||
char bytes[4];
|
||||
size_t num_bytes = 0;
|
||||
int base;
|
||||
uint32_t val;
|
||||
int c;
|
||||
char bytes[4];
|
||||
size_t num_bytes = 0;
|
||||
|
||||
c = *cp;
|
||||
for(;;) {
|
||||
@ -31,12 +31,12 @@ int inet_aton(const char *cp, struct in_addr *inp)
|
||||
if(base == 8 && c >= '8') return 0;
|
||||
val *= base;
|
||||
val += c - '0';
|
||||
c = *++cp;
|
||||
c = *++cp;
|
||||
}
|
||||
else if(base == 16 && isxdigit(c)) {
|
||||
val *= base;
|
||||
val += c + 10 - (islower(c) ? 'a' : 'A');
|
||||
c = *++cp;
|
||||
c = *++cp;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ int ioctl(int fd, int request, ...)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(*value) ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
else ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
if(*value) ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
else ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
if(ret != 0)
|
||||
errno = SOC_GetErrno();
|
||||
|
@ -24,7 +24,7 @@ int poll(struct pollfd *fds, nfds_t nfsd, int timeout)
|
||||
if((ret = svcSendSyncRequest(SOCU_handle)) != 0)return ret;
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
|
@ -28,9 +28,9 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
|
||||
if((readfds && FD_ISSET(i, readfds))
|
||||
|| (writefds && FD_ISSET(i, writefds))
|
||||
|| (exceptfds && FD_ISSET(i, exceptfds))) {
|
||||
pollinfo[j].fd = i;
|
||||
pollinfo[j].events = 0;
|
||||
pollinfo[j].revents = 0;
|
||||
pollinfo[j].fd = i;
|
||||
pollinfo[j].events = 0;
|
||||
pollinfo[j].revents = 0;
|
||||
|
||||
if(readfds && FD_ISSET(i, readfds))
|
||||
pollinfo[j].events |= POLLIN;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
srv.c _ Service manager.
|
||||
srv.c _ Service manager.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@ -9,15 +9,15 @@
|
||||
|
||||
|
||||
/*
|
||||
The homebrew loader can choose to supply a list of service handles that have
|
||||
been "stolen" from other processes that have been compromised. This allows us
|
||||
to access services that are normally restricted from the current process.
|
||||
The homebrew loader can choose to supply a list of service handles that have
|
||||
been "stolen" from other processes that have been compromised. This allows us
|
||||
to access services that are normally restricted from the current process.
|
||||
|
||||
For every service requested by the application, we shall first check if the
|
||||
list given to us contains the requested service and if so use it. If we don't
|
||||
find the service in that list, we ask the service manager and hope for the
|
||||
best.
|
||||
*/
|
||||
For every service requested by the application, we shall first check if the
|
||||
list given to us contains the requested service and if so use it. If we don't
|
||||
find the service in that list, we ask the service manager and hope for the
|
||||
best.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
u32 num;
|
||||
@ -100,9 +100,9 @@ Result srvExit()
|
||||
Result srvRegisterClient()
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
|
||||
u32* cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
|
||||
cmdbuf[0] = 0x10002;
|
||||
cmdbuf[1] = 0x20;
|
||||
|
||||
@ -116,7 +116,7 @@ Result srvGetServiceHandle(Handle* out, const char* name)
|
||||
Result rc = 0;
|
||||
|
||||
/* Look in service-list given to us by loader. If we find find a match,
|
||||
we return it. */
|
||||
we return it. */
|
||||
Handle h = __get_handle_from_list(name);
|
||||
|
||||
if(h != 0) {
|
||||
@ -129,7 +129,7 @@ Result srvGetServiceHandle(Handle* out, const char* name)
|
||||
strcpy((char*) &cmdbuf[1], name);
|
||||
cmdbuf[3] = strlen(name);
|
||||
cmdbuf[4] = 0x0;
|
||||
|
||||
|
||||
if((rc = svcSendSyncRequest(g_srv_handle)))return rc;
|
||||
|
||||
*out = cmdbuf[3];
|
||||
@ -138,11 +138,11 @@ Result srvGetServiceHandle(Handle* out, const char* name)
|
||||
|
||||
// Old srv:pm interface, will only work on systems where srv:pm was a port (<7.X)
|
||||
Result srvPmInit()
|
||||
{
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
|
||||
if((rc = svcConnectToPort(&g_srv_handle, "srv:pm")))return rc;
|
||||
|
||||
|
||||
if((rc = srvRegisterClient())) {
|
||||
svcCloseHandle(g_srv_handle);
|
||||
g_srv_handle = 0;
|
||||
@ -154,7 +154,7 @@ Result srvPmInit()
|
||||
Result srvRegisterProcess(u32 procid, u32 count, void *serviceaccesscontrol)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x04030082; // <7.x
|
||||
@ -162,22 +162,22 @@ Result srvRegisterProcess(u32 procid, u32 count, void *serviceaccesscontrol)
|
||||
cmdbuf[2] = count;
|
||||
cmdbuf[3] = (count << 16) | 2;
|
||||
cmdbuf[4] = (u32)serviceaccesscontrol;
|
||||
|
||||
|
||||
if((rc = svcSendSyncRequest(g_srv_handle))) return rc;
|
||||
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result srvUnregisterProcess(u32 procid)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x04040040; // <7.x
|
||||
cmdbuf[1] = procid;
|
||||
|
||||
|
||||
if((rc = svcSendSyncRequest(g_srv_handle))) return rc;
|
||||
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
@ -2,33 +2,33 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
void
|
||||
rbtree_clear(rbtree_t *tree,
|
||||
rbtree_node_destructor_t destructor)
|
||||
rbtree_clear(rbtree_t *tree,
|
||||
rbtree_node_destructor_t destructor)
|
||||
{
|
||||
rbtree_node_t *node = tree->root;
|
||||
rbtree_node_t *node = tree->root;
|
||||
|
||||
while(tree->root != NULL)
|
||||
{
|
||||
while(node->child[LEFT] != NULL)
|
||||
node = node->child[LEFT];
|
||||
while(tree->root != NULL)
|
||||
{
|
||||
while(node->child[LEFT] != NULL)
|
||||
node = node->child[LEFT];
|
||||
|
||||
if(node->child[RIGHT] != NULL)
|
||||
node = node->child[RIGHT];
|
||||
else
|
||||
{
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
if(node->child[RIGHT] != NULL)
|
||||
node = node->child[RIGHT];
|
||||
else
|
||||
{
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
|
||||
if(parent == NULL)
|
||||
tree->root = NULL;
|
||||
else
|
||||
parent->child[node != parent->child[LEFT]] = NULL;
|
||||
if(parent == NULL)
|
||||
tree->root = NULL;
|
||||
else
|
||||
parent->child[node != parent->child[LEFT]] = NULL;
|
||||
|
||||
if(destructor != NULL)
|
||||
(*destructor)(node);
|
||||
if(destructor != NULL)
|
||||
(*destructor)(node);
|
||||
|
||||
node = parent;
|
||||
}
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
}
|
||||
|
||||
tree->size = 0;
|
||||
tree->size = 0;
|
||||
}
|
||||
|
@ -2,29 +2,29 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_find(const rbtree_t *tree,
|
||||
const rbtree_node_t *node)
|
||||
rbtree_find(const rbtree_t *tree,
|
||||
const rbtree_node_t *node)
|
||||
{
|
||||
rbtree_node_t *tmp = tree->root;
|
||||
rbtree_node_t *save = NULL;
|
||||
rbtree_node_t *tmp = tree->root;
|
||||
rbtree_node_t *save = NULL;
|
||||
|
||||
while(tmp != NULL)
|
||||
{
|
||||
int rc = (*tree->comparator)(node, tmp);
|
||||
if(rc < 0)
|
||||
{
|
||||
tmp = tmp->child[LEFT];
|
||||
}
|
||||
else if(rc > 0)
|
||||
{
|
||||
tmp = tmp->child[RIGHT];
|
||||
}
|
||||
else
|
||||
{
|
||||
save = tmp;
|
||||
tmp = tmp->child[LEFT];
|
||||
}
|
||||
}
|
||||
while(tmp != NULL)
|
||||
{
|
||||
int rc = (*tree->comparator)(node, tmp);
|
||||
if(rc < 0)
|
||||
{
|
||||
tmp = tmp->child[LEFT];
|
||||
}
|
||||
else if(rc > 0)
|
||||
{
|
||||
tmp = tmp->child[RIGHT];
|
||||
}
|
||||
else
|
||||
{
|
||||
save = tmp;
|
||||
tmp = tmp->child[LEFT];
|
||||
}
|
||||
}
|
||||
|
||||
return save;
|
||||
return save;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <3ds/util/rbtree.h>
|
||||
|
||||
void
|
||||
rbtree_init(rbtree_t *tree,
|
||||
rbtree_node_comparator_t comparator)
|
||||
rbtree_init(rbtree_t *tree,
|
||||
rbtree_node_comparator_t comparator)
|
||||
{
|
||||
tree->root = NULL;
|
||||
tree->comparator = comparator;
|
||||
tree->size = 0;
|
||||
tree->root = NULL;
|
||||
tree->comparator = comparator;
|
||||
tree->size = 0;
|
||||
}
|
||||
|
@ -2,95 +2,95 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
static rbtree_node_t*
|
||||
do_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int multi)
|
||||
do_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int multi)
|
||||
{
|
||||
rbtree_node_t *original = node;
|
||||
rbtree_node_t **tmp = &tree->root;
|
||||
rbtree_node_t *parent = NULL;
|
||||
rbtree_node_t *save = NULL;
|
||||
rbtree_node_t *original = node;
|
||||
rbtree_node_t **tmp = &tree->root;
|
||||
rbtree_node_t *parent = NULL;
|
||||
rbtree_node_t *save = NULL;
|
||||
|
||||
while(*tmp != NULL)
|
||||
{
|
||||
int cmp = (*(tree->comparator))(node, *tmp);
|
||||
parent = *tmp;
|
||||
while(*tmp != NULL)
|
||||
{
|
||||
int cmp = (*(tree->comparator))(node, *tmp);
|
||||
parent = *tmp;
|
||||
|
||||
if(cmp < 0)
|
||||
tmp = &((*tmp)->child[LEFT]);
|
||||
else if(cmp > 0)
|
||||
tmp = &((*tmp)->child[RIGHT]);
|
||||
else
|
||||
{
|
||||
if(!multi)
|
||||
save = *tmp;
|
||||
if(cmp < 0)
|
||||
tmp = &((*tmp)->child[LEFT]);
|
||||
else if(cmp > 0)
|
||||
tmp = &((*tmp)->child[RIGHT]);
|
||||
else
|
||||
{
|
||||
if(!multi)
|
||||
save = *tmp;
|
||||
|
||||
tmp = &((*tmp)->child[LEFT]);
|
||||
}
|
||||
}
|
||||
tmp = &((*tmp)->child[LEFT]);
|
||||
}
|
||||
}
|
||||
|
||||
if(save != NULL)
|
||||
{
|
||||
return save;
|
||||
}
|
||||
if(save != NULL)
|
||||
{
|
||||
return save;
|
||||
}
|
||||
|
||||
*tmp = node;
|
||||
*tmp = node;
|
||||
|
||||
node->child[LEFT] = node->child[RIGHT] = NULL;
|
||||
set_parent(node, parent);
|
||||
node->child[LEFT] = node->child[RIGHT] = NULL;
|
||||
set_parent(node, parent);
|
||||
|
||||
set_red(node);
|
||||
set_red(node);
|
||||
|
||||
while(is_red((parent = get_parent(node))))
|
||||
{
|
||||
rbtree_node_t *grandparent = get_parent(parent);
|
||||
int left = (parent == grandparent->child[LEFT]);
|
||||
rbtree_node_t *uncle = grandparent->child[left];
|
||||
while(is_red((parent = get_parent(node))))
|
||||
{
|
||||
rbtree_node_t *grandparent = get_parent(parent);
|
||||
int left = (parent == grandparent->child[LEFT]);
|
||||
rbtree_node_t *uncle = grandparent->child[left];
|
||||
|
||||
if(is_red(uncle))
|
||||
{
|
||||
set_black(uncle);
|
||||
set_black(parent);
|
||||
set_red(grandparent);
|
||||
if(is_red(uncle))
|
||||
{
|
||||
set_black(uncle);
|
||||
set_black(parent);
|
||||
set_red(grandparent);
|
||||
|
||||
node = grandparent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(parent->child[left] == node)
|
||||
{
|
||||
rbtree_node_t *tmp;
|
||||
node = grandparent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(parent->child[left] == node)
|
||||
{
|
||||
rbtree_node_t *tmp;
|
||||
|
||||
rbtree_rotate(tree, parent, left);
|
||||
rbtree_rotate(tree, parent, left);
|
||||
|
||||
tmp = parent;
|
||||
parent = node;
|
||||
node = tmp;
|
||||
}
|
||||
tmp = parent;
|
||||
parent = node;
|
||||
node = tmp;
|
||||
}
|
||||
|
||||
set_black(parent);
|
||||
set_red(grandparent);
|
||||
rbtree_rotate(tree, grandparent, !left);
|
||||
}
|
||||
}
|
||||
set_black(parent);
|
||||
set_red(grandparent);
|
||||
rbtree_rotate(tree, grandparent, !left);
|
||||
}
|
||||
}
|
||||
|
||||
set_black(tree->root);
|
||||
set_black(tree->root);
|
||||
|
||||
tree->size += 1;
|
||||
tree->size += 1;
|
||||
|
||||
return original;
|
||||
return original;
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node)
|
||||
rbtree_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node)
|
||||
{
|
||||
return do_insert(tree, node, 0);
|
||||
return do_insert(tree, node, 0);
|
||||
}
|
||||
|
||||
void
|
||||
rbtree_insert_multi(rbtree_t *tree,
|
||||
rbtree_node_t *node)
|
||||
rbtree_insert_multi(rbtree_t *tree,
|
||||
rbtree_node_t *node)
|
||||
{
|
||||
do_insert(tree, node, 1);
|
||||
do_insert(tree, node, 1);
|
||||
}
|
||||
|
@ -1,64 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
|
||||
typedef enum rbtree_color
|
||||
{
|
||||
RED = 0,
|
||||
BLACK = 1,
|
||||
RED = 0,
|
||||
BLACK = 1,
|
||||
} rbtree_color_t;
|
||||
|
||||
#define COLOR_MASK (RED|BLACK)
|
||||
#define COLOR_MASK (RED|BLACK)
|
||||
|
||||
static inline void
|
||||
set_black(rbtree_node_t *node)
|
||||
{
|
||||
node->parent_color &= ~COLOR_MASK;
|
||||
node->parent_color |= BLACK;
|
||||
node->parent_color &= ~COLOR_MASK;
|
||||
node->parent_color |= BLACK;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_red(rbtree_node_t *node)
|
||||
{
|
||||
node->parent_color &= ~COLOR_MASK;
|
||||
node->parent_color |= RED;
|
||||
node->parent_color &= ~COLOR_MASK;
|
||||
node->parent_color |= RED;
|
||||
}
|
||||
|
||||
static inline rbtree_color_t
|
||||
get_color(const rbtree_node_t *node)
|
||||
{
|
||||
if(node == NULL)
|
||||
return BLACK;
|
||||
return (rbtree_color_t)(node->parent_color & COLOR_MASK);
|
||||
if(node == NULL)
|
||||
return BLACK;
|
||||
return (rbtree_color_t)(node->parent_color & COLOR_MASK);
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_black(const rbtree_node_t *node)
|
||||
{
|
||||
return get_color(node) == BLACK;
|
||||
return get_color(node) == BLACK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_red(const rbtree_node_t *node)
|
||||
{
|
||||
return get_color(node) == RED;
|
||||
return get_color(node) == RED;
|
||||
}
|
||||
|
||||
static inline rbtree_node_t*
|
||||
get_parent(const rbtree_node_t *node)
|
||||
{
|
||||
return (rbtree_node_t*)(node->parent_color & ~COLOR_MASK);
|
||||
return (rbtree_node_t*)(node->parent_color & ~COLOR_MASK);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_parent(rbtree_node_t *node,
|
||||
const rbtree_node_t *parent)
|
||||
set_parent(rbtree_node_t *node,
|
||||
const rbtree_node_t *parent)
|
||||
{
|
||||
node->parent_color = (get_color(node)) | ((uintptr_t)parent);
|
||||
node->parent_color = (get_color(node)) | ((uintptr_t)parent);
|
||||
}
|
||||
|
||||
void
|
||||
rbtree_rotate(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int left);
|
||||
rbtree_rotate(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int left);
|
||||
|
@ -2,40 +2,40 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
static inline rbtree_node_t*
|
||||
do_iterate(const rbtree_node_t *node,
|
||||
int next)
|
||||
do_iterate(const rbtree_node_t *node,
|
||||
int next)
|
||||
{
|
||||
rbtree_node_t *it = (rbtree_node_t*)node;
|
||||
rbtree_node_t *it = (rbtree_node_t*)node;
|
||||
|
||||
if(it->child[next] != NULL)
|
||||
{
|
||||
it = it->child[next];
|
||||
while(it->child[!next] != NULL)
|
||||
it = it->child[!next];
|
||||
}
|
||||
else
|
||||
{
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
while(parent != NULL && it == parent->child[next])
|
||||
{
|
||||
it = parent;
|
||||
parent = get_parent(it);
|
||||
}
|
||||
if(it->child[next] != NULL)
|
||||
{
|
||||
it = it->child[next];
|
||||
while(it->child[!next] != NULL)
|
||||
it = it->child[!next];
|
||||
}
|
||||
else
|
||||
{
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
while(parent != NULL && it == parent->child[next])
|
||||
{
|
||||
it = parent;
|
||||
parent = get_parent(it);
|
||||
}
|
||||
|
||||
it = parent;
|
||||
}
|
||||
it = parent;
|
||||
}
|
||||
|
||||
return it;
|
||||
return it;
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_node_next(const rbtree_node_t *node)
|
||||
{
|
||||
return do_iterate(node, RIGHT);
|
||||
return do_iterate(node, RIGHT);
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_node_prev(const rbtree_node_t *node)
|
||||
{
|
||||
return do_iterate(node, LEFT);
|
||||
return do_iterate(node, LEFT);
|
||||
}
|
||||
|
@ -2,36 +2,36 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
static inline rbtree_node_t*
|
||||
do_minmax(const rbtree_t *tree,
|
||||
int max)
|
||||
do_minmax(const rbtree_t *tree,
|
||||
int max)
|
||||
{
|
||||
rbtree_node_t *node = tree->root;
|
||||
rbtree_node_t *node = tree->root;
|
||||
|
||||
if(node == NULL)
|
||||
return NULL;
|
||||
if(node == NULL)
|
||||
return NULL;
|
||||
|
||||
while(node->child[max] != NULL)
|
||||
node = node->child[max];
|
||||
while(node->child[max] != NULL)
|
||||
node = node->child[max];
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_min(const rbtree_t *tree)
|
||||
{
|
||||
rbtree_node_t *node;
|
||||
rbtree_node_t *node;
|
||||
|
||||
node = do_minmax(tree, LEFT);
|
||||
node = do_minmax(tree, LEFT);
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_max(const rbtree_t *tree)
|
||||
{
|
||||
rbtree_node_t *node;
|
||||
rbtree_node_t *node;
|
||||
|
||||
node = do_minmax(tree, RIGHT);
|
||||
node = do_minmax(tree, RIGHT);
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
@ -2,139 +2,139 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
static void
|
||||
recolor(rbtree_t *tree,
|
||||
rbtree_node_t *parent,
|
||||
rbtree_node_t *node)
|
||||
recolor(rbtree_t *tree,
|
||||
rbtree_node_t *parent,
|
||||
rbtree_node_t *node)
|
||||
{
|
||||
rbtree_node_t *sibling;
|
||||
rbtree_node_t *sibling;
|
||||
|
||||
while(is_black(node) && node != tree->root)
|
||||
{
|
||||
int left = (node == parent->child[LEFT]);
|
||||
while(is_black(node) && node != tree->root)
|
||||
{
|
||||
int left = (node == parent->child[LEFT]);
|
||||
|
||||
sibling = parent->child[left];
|
||||
sibling = parent->child[left];
|
||||
|
||||
if(is_red(sibling))
|
||||
{
|
||||
set_black(sibling);
|
||||
set_red(parent);
|
||||
rbtree_rotate(tree, parent, left);
|
||||
sibling = parent->child[left];
|
||||
}
|
||||
if(is_red(sibling))
|
||||
{
|
||||
set_black(sibling);
|
||||
set_red(parent);
|
||||
rbtree_rotate(tree, parent, left);
|
||||
sibling = parent->child[left];
|
||||
}
|
||||
|
||||
if(is_black(sibling->child[LEFT]) && is_black(sibling->child[RIGHT]))
|
||||
{
|
||||
set_red(sibling);
|
||||
node = parent;
|
||||
parent = get_parent(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_black(sibling->child[left]))
|
||||
{
|
||||
set_black(sibling->child[!left]);
|
||||
set_red(sibling);
|
||||
rbtree_rotate(tree, sibling, !left);
|
||||
sibling = parent->child[left];
|
||||
}
|
||||
if(is_black(sibling->child[LEFT]) && is_black(sibling->child[RIGHT]))
|
||||
{
|
||||
set_red(sibling);
|
||||
node = parent;
|
||||
parent = get_parent(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_black(sibling->child[left]))
|
||||
{
|
||||
set_black(sibling->child[!left]);
|
||||
set_red(sibling);
|
||||
rbtree_rotate(tree, sibling, !left);
|
||||
sibling = parent->child[left];
|
||||
}
|
||||
|
||||
if(is_black(parent))
|
||||
set_black(sibling);
|
||||
else
|
||||
set_red(sibling);
|
||||
set_black(parent);
|
||||
set_black(sibling->child[left]);
|
||||
if(is_black(parent))
|
||||
set_black(sibling);
|
||||
else
|
||||
set_red(sibling);
|
||||
set_black(parent);
|
||||
set_black(sibling->child[left]);
|
||||
|
||||
rbtree_rotate(tree, parent, left);
|
||||
rbtree_rotate(tree, parent, left);
|
||||
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
|
||||
if(node != NULL)
|
||||
set_black(node);
|
||||
if(node != NULL)
|
||||
set_black(node);
|
||||
}
|
||||
|
||||
rbtree_node_t*
|
||||
rbtree_remove(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
rbtree_node_destructor_t destructor)
|
||||
rbtree_remove(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
rbtree_node_destructor_t destructor)
|
||||
{
|
||||
rbtree_color_t color;
|
||||
rbtree_node_t *child, *parent, *original = node;
|
||||
rbtree_node_t *next;
|
||||
rbtree_color_t color;
|
||||
rbtree_node_t *child, *parent, *original = node;
|
||||
rbtree_node_t *next;
|
||||
|
||||
next = rbtree_node_next(node);
|
||||
next = rbtree_node_next(node);
|
||||
|
||||
if(node->child[LEFT] != NULL && node->child[RIGHT] != NULL)
|
||||
{
|
||||
rbtree_node_t *old = node;
|
||||
if(node->child[LEFT] != NULL && node->child[RIGHT] != NULL)
|
||||
{
|
||||
rbtree_node_t *old = node;
|
||||
|
||||
node = node->child[RIGHT];
|
||||
while(node->child[LEFT] != NULL)
|
||||
node = node->child[LEFT];
|
||||
node = node->child[RIGHT];
|
||||
while(node->child[LEFT] != NULL)
|
||||
node = node->child[LEFT];
|
||||
|
||||
parent = get_parent(old);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(parent->child[LEFT] == old)
|
||||
parent->child[LEFT] = node;
|
||||
else
|
||||
parent->child[RIGHT] = node;
|
||||
}
|
||||
else
|
||||
tree->root = node;
|
||||
parent = get_parent(old);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(parent->child[LEFT] == old)
|
||||
parent->child[LEFT] = node;
|
||||
else
|
||||
parent->child[RIGHT] = node;
|
||||
}
|
||||
else
|
||||
tree->root = node;
|
||||
|
||||
child = node->child[RIGHT];
|
||||
parent = get_parent(node);
|
||||
color = get_color(node);
|
||||
child = node->child[RIGHT];
|
||||
parent = get_parent(node);
|
||||
color = get_color(node);
|
||||
|
||||
if(parent == old)
|
||||
parent = node;
|
||||
else
|
||||
{
|
||||
if(child != NULL)
|
||||
set_parent(child, parent);
|
||||
parent->child[LEFT] = child;
|
||||
if(parent == old)
|
||||
parent = node;
|
||||
else
|
||||
{
|
||||
if(child != NULL)
|
||||
set_parent(child, parent);
|
||||
parent->child[LEFT] = child;
|
||||
|
||||
node->child[RIGHT] = old->child[RIGHT];
|
||||
set_parent(old->child[RIGHT], node);
|
||||
}
|
||||
node->child[RIGHT] = old->child[RIGHT];
|
||||
set_parent(old->child[RIGHT], node);
|
||||
}
|
||||
|
||||
node->parent_color = old->parent_color;
|
||||
node->child[LEFT] = old->child[LEFT];
|
||||
set_parent(old->child[LEFT], node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node->child[LEFT] == NULL)
|
||||
child = node->child[RIGHT];
|
||||
else
|
||||
child = node->child[LEFT];
|
||||
node->parent_color = old->parent_color;
|
||||
node->child[LEFT] = old->child[LEFT];
|
||||
set_parent(old->child[LEFT], node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node->child[LEFT] == NULL)
|
||||
child = node->child[RIGHT];
|
||||
else
|
||||
child = node->child[LEFT];
|
||||
|
||||
parent = get_parent(node);
|
||||
color = get_color(node);
|
||||
parent = get_parent(node);
|
||||
color = get_color(node);
|
||||
|
||||
if(child != NULL)
|
||||
set_parent(child, parent);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(parent->child[LEFT] == node)
|
||||
parent->child[LEFT] = child;
|
||||
else
|
||||
parent->child[RIGHT] = child;
|
||||
}
|
||||
else
|
||||
tree->root = child;
|
||||
}
|
||||
if(child != NULL)
|
||||
set_parent(child, parent);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(parent->child[LEFT] == node)
|
||||
parent->child[LEFT] = child;
|
||||
else
|
||||
parent->child[RIGHT] = child;
|
||||
}
|
||||
else
|
||||
tree->root = child;
|
||||
}
|
||||
|
||||
if(color == BLACK)
|
||||
recolor(tree, parent, child);
|
||||
if(color == BLACK)
|
||||
recolor(tree, parent, child);
|
||||
|
||||
if(destructor != NULL)
|
||||
(*destructor)(original);
|
||||
if(destructor != NULL)
|
||||
(*destructor)(original);
|
||||
|
||||
tree->size -= 1;
|
||||
tree->size -= 1;
|
||||
|
||||
return next;
|
||||
return next;
|
||||
}
|
||||
|
@ -2,27 +2,27 @@
|
||||
#include "rbtree_internal.h"
|
||||
|
||||
void
|
||||
rbtree_rotate(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int left)
|
||||
rbtree_rotate(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
int left)
|
||||
{
|
||||
rbtree_node_t *tmp = node->child[left];
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
rbtree_node_t *tmp = node->child[left];
|
||||
rbtree_node_t *parent = get_parent(node);
|
||||
|
||||
node->child[left] = tmp->child[!left];
|
||||
if(tmp->child[!left] != NULL)
|
||||
set_parent(tmp->child[!left], node);
|
||||
node->child[left] = tmp->child[!left];
|
||||
if(tmp->child[!left] != NULL)
|
||||
set_parent(tmp->child[!left], node);
|
||||
|
||||
tmp->child[!left] = node;
|
||||
set_parent(tmp, parent);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(node == parent->child[!left])
|
||||
parent->child[!left] = tmp;
|
||||
else
|
||||
parent->child[left] = tmp;
|
||||
}
|
||||
else
|
||||
tree->root = tmp;
|
||||
set_parent(node, tmp);
|
||||
tmp->child[!left] = node;
|
||||
set_parent(tmp, parent);
|
||||
if(parent != NULL)
|
||||
{
|
||||
if(node == parent->child[!left])
|
||||
parent->child[!left] = tmp;
|
||||
else
|
||||
parent->child[left] = tmp;
|
||||
}
|
||||
else
|
||||
tree->root = tmp;
|
||||
set_parent(node, tmp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user