-all:
- @$(MAKE) -C acesskernel_src
- @$(MAKE) -C ld-acess_src
+.PHONY: all clean
+
+all clean:
+ @$(MAKE) -C acesskernel_src $@
+ @$(MAKE) -C ld-acess_src $@
endif\r
ifeq ($(PLATFORM),lin)\r
BIN := ../AcessKernel\r
- CFLAGS +=\r
+ CFLAGS += \r
+ LDFLAGS += -lpthread\r
endif\r
\r
.PHONY: all clean\r
--- /dev/null
+
+#ifndef _ACESSNATIVE__MOUSE_INT_H_
+#define _ACESSNATIVE__MOUSE_INT_H_
+
+#include <api_drv_joystick.h>
+
+typedef struct sPointer tPointer;
+
+#define MAX_BUTTONS 5
+#define MAX_AXIES 2
+#define MAX_FILESIZE (sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS)
+
+/**
+ */
+struct sPointer
+{
+ tPointer *Next;
+
+ // Node
+ tVFS_Node Node;
+
+ // Data
+ Uint8 FileData[MAX_FILESIZE];
+ tJoystick_FileHeader *FileHeader;
+ tJoystick_Axis *Axies;
+ Uint8 *Buttons;
+
+ // Limits for axis positions
+ Uint16 AxisLimits[MAX_AXIES];
+};
+
+extern void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
+
+#endif
+
extern int NativeFS_Install(char **Arguments);
extern void Debug_SetKTerminal(char *Path);
extern int VT_Install(char **Arguments);
+extern int Mouse_Install(char **Arguments);
extern int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options);
extern int VFS_MkDir(const char *Path);
extern int SyscallServer(void);
const char *gsAcessDir = "../Usermode/Output/x86_64";
// === CODE ===
+#ifndef __WIN32__
+#define P_NOWAIT 0
+int spawnv(int flags, const char *execuable, char * const argv[])
+{
+ int pid = fork();
+ if( pid != 0 ) return pid;
+
+ execv(execuable, argv);
+ perror("spawnv - execve");
+ for(;;);
+}
+#endif
+
int main(int argc, char *argv[])
{
char **rootapp = NULL;
Log_Error("Init", "Unable to load NativeKeyboard");
}
NativeFS_Install(NULL);
+ Mouse_Install(NULL);
// - Start VTerm
{
char *args[] = {
+/*
+ * Acess2 Kernel - Mouse Mulitplexing Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Mouse mulitplexing
+ */
+#define DEBUG 0
+#define VERSION VER2(0,1)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include "include/mouse_int.h"
+
+// === PROTOTYPES ===
+ int Mouse_Install(char **Arguments);
+ int Mouse_Cleanup(void);
+// - "User" side
+ int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
+ int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data);
+// - Device Side
+void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
+
+// === GLOBALS ===
+tVFS_NodeType gMouse_RootNodeType = {
+ .ReadDir = Mouse_Root_ReadDir,
+ .FindDir = Mouse_Root_FindDir
+};
+tVFS_NodeType gMouse_DevNodeType = {
+ .IOCtl = Mouse_Dev_IOCtl,
+ .Read = Mouse_Dev_Read
+};
+tDevFS_Driver gMouse_DevInfo = {
+ NULL, "Mouse",
+ { .Flags = VFS_FFLAG_DIRECTORY, .Type = &gMouse_RootNodeType, .Size = 1 }
+};
+tPointer gMouse_Pointer;
+
+// === CODE ===
+/**
+ * \brief Initialise the keyboard driver
+ */
+int Mouse_Install(char **Arguments)
+{
+ /// - Register with DevFS
+ DevFS_AddDevice( &gMouse_DevInfo );
+
+ gMouse_Pointer.Node.Type = &gMouse_DevNodeType;
+ gMouse_Pointer.Node.ImplPtr = &gMouse_Pointer;
+ gMouse_Pointer.FileHeader = (void*)gMouse_Pointer.FileData;
+ gMouse_Pointer.Axies = (void*)( gMouse_Pointer.FileHeader + 1 );
+ gMouse_Pointer.Buttons = (void*)( gMouse_Pointer.Axies + MAX_AXIES );
+ gMouse_Pointer.FileHeader->NAxies = MAX_AXIES;
+ gMouse_Pointer.FileHeader->NButtons = MAX_BUTTONS;
+
+ return 0;
+}
+
+/**
+ * \brief Pre-unload cleanup function
+ */
+int Mouse_Cleanup(void)
+{
+ return 0;
+}
+
+// --- VFS Interface ---
+int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
+{
+ if( Pos != 0 )
+ return -EINVAL;
+ strcpy(Dest, "system");
+ return 0;
+}
+
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
+{
+ if( strcmp(Name, "system") != 0 ) return NULL;
+ return &gMouse_Pointer.Node;
+}
+
+static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
+/**
+ * \brief IOCtl handler for the mouse
+ */
+int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ tJoystick_NumValue *numval = Data;
+ tPointer *ptr = Node->ImplPtr;
+ switch(ID)
+ {
+ BASE_IOCTLS(DRV_TYPE_MOUSE, "Mouse", VERSION, csaIOCTL_NAMES);
+
+ case JOY_IOCTL_GETSETAXISLIMIT:
+ if( !numval || !CheckMem(numval, sizeof(*numval)) )
+ return -1;
+ LOG("GetSetAxisLimit %i = %i", numval->Num, numval->Value);
+ if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
+ return 0;
+ if(numval->Value != -1)
+ ptr->AxisLimits[numval->Num] = numval->Value;
+ return ptr->AxisLimits[numval->Num];
+
+ case JOY_IOCTL_GETSETAXISPOSITION:
+ if( !numval || !CheckMem(numval, sizeof(*numval)) )
+ return -1;
+ if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
+ return 0;
+ if(numval->Value != -1)
+ ptr->Axies[numval->Num].CursorPos = numval->Value;
+ return ptr->Axies[numval->Num].CursorPos;
+ }
+ return -1;
+}
+
+/**
+ * \brief Read from a device
+ */
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data)
+{
+ tPointer *ptr = Node->ImplPtr;
+ int n_buttons = ptr->FileHeader->NButtons;
+ int n_axies = ptr->FileHeader->NAxies;
+
+ ENTER("pNode iLength pData", Node, Length, Data);
+
+ // TODO: Locking (Acquire)
+
+ Length = MIN(
+ Length,
+ sizeof(tJoystick_FileHeader) + n_axies*sizeof(tJoystick_Axis) + n_buttons
+ );
+
+ // Mark as checked
+ VFS_MarkAvaliable( Node, 0 );
+
+ memcpy( Data, ptr->FileData, Length );
+
+ // TODO: Locking (Release)
+
+ LEAVE('i', Length);
+ return Length;
+}
+
+// --- Device Interface ---
+/*
+ * Handle a mouse event (movement or button press/release)
+ * - See Input/Mouse/include/mouse.h
+ */
+void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues)
+{
+ tPointer *ptr = &gMouse_Pointer;
+
+ ENTER("pHandle xButtonState pAxisDeltas", Handle, ButtonState, AxisDeltas);
+
+ // Update cursor position
+ for( int i = 0; i < 2; i ++ )
+ {
+ ptr->Axies[i].CursorPos = AxisValues[i];
+ ptr->Axies[i].CurValue = AxisDeltas ? AxisDeltas[i] : 0;
+ }
+ for( int i = 0; i < 5; i ++ )
+ ptr->Buttons[i] = ButtonState & (1 << i) ? 255 : 0;
+
+ VFS_MarkAvaliable( &ptr->Node, 1 );
+ LEAVE('-');
+}
+
# include <unistd.h>
# include <sys/socket.h>
# include <netinet/in.h>
-# include <arpa/inet.h> // inet_ntop
+# include <netdb.h> // getaddrinfo
#endif
#define DONT_INCLUDE_SYSCALL_NAMES
#include "../syscalls.h"
Log_Debug("Server", "Worker %p", ClientPtr);
#if USE_TCP
-
while( *((volatile typeof(Client->Socket)*)&Client->Socket) == 0 )
;
Threads_SetThread( Client->ClientID );
perror("select");
continue ;
}
- Log_Debug("Server", "%p: rv=%i", Client, rv);
+// Log_Debug("Server", "%p: rv=%i", Client, rv);
if( FD_ISSET(Client->Socket, &fds) )
{
char lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
tRequestHeader *hdr = (void*)lbuf;
size_t len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
- Log_Debug("Server", "%i bytes of header", len);
- if( len == 0 ) break;
+// Log_Debug("Server", "%i bytes of header", len);
+ if( len == 0 ) {
+ Log_Notice("Server", "Zero RX on %i (worker %p)", Client->Socket, Client);
+ break;
+ }
if( len == -1 ) {
perror("recv header");
// Log_Warning("Server", "recv() error - %s", strerror(errno));
if( hdr->NParams > 0 )
{
len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
- Log_Debug("Server", "%i bytes of params", len);
+// Log_Debug("Server", "%i bytes of params", len);
if( len != hdr->NParams*sizeof(tRequestValue) ) {
// Oops.
perror("recv params");
}
else
{
- Log_Debug("Server", "No params?");
+// Log_Debug("Server", "No params?");
}
// Get buffer size
while( rem )
{
len = recv(Client->Socket, ptr, rem, 0);
- Log_Debug("Server", "%i bytes of data", len);
+// Log_Debug("Server", "%i bytes of data", len);
if( len == -1 ) {
// Oops?
perror("recv data");
break;
}
}
- else
- Log_Debug("Server", "no data");
+// else
+// Log_Debug("Server", "no data");
int retlen;
tRequestHeader *retHeader;
*
* Syscall Distribution
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <threads.h>
#include <events.h>
+#if DEBUG == 0
+# define DONT_INCLUDE_SYSCALL_NAMES
+#endif
#include "../syscalls.h"
// === IMPORTS ===
extern int Threads_Fork(void); // AcessNative only function
+extern int Threads_Spawn(int nFD, int FDs[], const void *info);
// === TYPES ===
typedef int (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int *Sizes);
return *a0;
);
+SYSCALL3(Syscall_AN_Spawn, "ddd", int *, int *, void *,
+ if(Sizes[0] < sizeof(int))
+ return -1;
+ *a0 = Threads_Spawn(Sizes[1] / sizeof(int), a1, a2);
+ return *a0;
+);
+
SYSCALL2(Syscall_SendMessage, "id", int, void *,
return Proc_SendMessage(a0, Sizes[1], a1);
);
Syscall_Sleep,
Syscall_AN_Fork,
+ Syscall_AN_Spawn,
Syscall_SendMessage,
Syscall_GetMessage,
}
// Allocate the return
- ret = malloc(sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue)
- + retDataLen);
+ size_t msglen = sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue) + retDataLen;
+ ret = malloc(msglen);
ret->ClientID = Request->ClientID;
ret->CallID = Request->CallID;
ret->NParams = retValueCount;
+ ret->MessageLength = msglen;
inData = (char*)&ret->Params[ ret->NParams ];
// Static Uint64 return value
*(Uint64*)inData = retVal;
inData += sizeof(Uint64);
- Log_Debug("Syscalls", "Return 0x%llx", retVal);
+ //Log_Debug("Syscalls", "Return 0x%llx", retVal);
retValueCount = 1;
for( i = 0; i < Request->NParams; i ++ )
#include <acess.h>
#include <mutex.h>
#include "../../KernelLand/Kernel/include/semaphore.h"
+typedef signed long long int time_t;
+#include "../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/syscall_types.h"
#include <rwlock.h>
#include <events.h>
#include <threads_int.h>
#define THREAD_EVENT_WAKEUP 0x80000000
// === IMPORTS ===
-void VFS_CloneHandleList(int PID);
+extern void VFS_CloneHandleList(int PID);
+extern void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
// === STRUCTURES ===
// === PROTOTYPES ===
{
tThread *thread = Threads_CloneTCB(gpCurrentThread);
thread->PID = thread->TID;
+
// Duplicate the VFS handles (and nodes) from vfs_handle.c
-
VFS_CloneHandleList(thread->PID);
return thread->PID;
}
+int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
+{
+ tThread *thread = Threads_CloneTCB(gpCurrentThread);
+ thread->PID = thread->TID;
+ if( info )
+ {
+ // TODO: PGID?
+ //if( info->flags & SPAWNFLAG_NEWPGID )
+ // thread->PGID = thread->PID;
+ if( info->gid && thread->UID == 0 )
+ thread->GID = info->gid;
+ if( info->uid && thread->UID == 0 ) // last because ->UID is used above
+ thread->UID = info->uid;
+ }
+
+ VFS_CloneHandlesFromList(thread->PID, nFD, FDs);
+
+ Log_Debug("Threads", "_spawn: %i", thread->PID);
+ return thread->PID;
+}
+
// --------------------------------------------------------------------
// Mutexes
// --------------------------------------------------------------------
{
Uint32 rv;
- Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
+ //Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
gpCurrentThread->WaitMask = Mask;
if( !(gpCurrentThread->Events & Mask) )
Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
gpCurrentThread, gpCurrentThread->EventSem);
}
- Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
+ //Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
}
rv = gpCurrentThread->Events & Mask;
gpCurrentThread->Events &= ~Mask;
gpCurrentThread->WaitMask = -1;
- Log_Debug("Threads", "- rv = %x", rv);
+ //Log_Debug("Threads", "- rv = %x", rv);
return rv;
}
void Threads_PostEvent(tThread *Thread, Uint32 Events)
{
Thread->Events |= Events;
- Log_Debug("Threads", "Trigger event %x (->Events = %p)", Events, Thread->Events);
-
+// Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
+
if( Events == 0 || Thread->WaitMask & Events ) {
Threads_Glue_SemSignal( Thread->EventSem, 1 );
// Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
typedef void (*tUI_KeybardCallback)(Uint32 Key);
extern tUI_KeybardCallback gUI_KeyboardCallback;
+extern void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
#endif
return 0;
}
-Uint32 UI_GetAcessKeyFromSDL(SDLKey Sym, Uint16 Unicode)
+Uint32 UI_GetAcessKeyFromSDL(SDLKey Sym)
{
Uint8 *keystate = SDL_GetKeyState(NULL);
int shiftState = 0;
if( gUI_Keymap[shiftState][Sym] )
return gUI_Keymap[shiftState][Sym];
- // Enter key on acess returns \n, but SDL returns \r
- if( Sym == SDLK_RETURN )
- Unicode = '\n';
-
- // How nice of you, a unicode value
- if( Unicode )
- {
- ret = Unicode;
- }
- // Ok, we need to do work :(
- else
+ switch(Sym)
{
- switch(Sym)
- {
- case SDLK_UP: ret = KEY_UP; break;
- case SDLK_DOWN: ret = KEY_DOWN; break;
- case SDLK_LEFT: ret = KEY_LEFT; break;
- case SDLK_RIGHT:ret = KEY_RIGHT;break;
- case SDLK_CAPSLOCK: ret = KEY_CAPSLOCK; break;
- case SDLK_F1: ret = KEY_F1; break;
- case SDLK_F2: ret = KEY_F2; break;
- case SDLK_F3: ret = KEY_F3; break;
- case SDLK_F4: ret = KEY_F4; break;
- case SDLK_F5: ret = KEY_F5; break;
- case SDLK_F6: ret = KEY_F6; break;
- case SDLK_F7: ret = KEY_F7; break;
- case SDLK_F8: ret = KEY_F8; break;
- case SDLK_F9: ret = KEY_F9; break;
- case SDLK_F10: ret = KEY_F10; break;
- case SDLK_F11: ret = KEY_F11; break;
- case SDLK_F12: ret = KEY_F12; break;
- case SDLK_RETURN: ret = '\n'; break;
- case SDLK_LALT: ret = KEY_LALT; break;
- case SDLK_RALT: ret = KEY_RALT; break;
- default:
- printf("Unhandled key code %i\n", Sym);
- break;
- }
+ case SDLK_a ... SDLK_z:
+ ret = Sym - SDLK_a + KEYSYM_a;
+ break;
+ case SDLK_0 ... SDLK_9:
+ ret = Sym - SDLK_0 + KEYSYM_0;
+ break;
+ case SDLK_CAPSLOCK: ret = KEYSYM_CAPS; break;
+ case SDLK_TAB: ret = KEYSYM_TAB; break;
+ case SDLK_UP: ret = KEYSYM_UPARROW; break;
+ case SDLK_DOWN: ret = KEYSYM_DOWNARROW; break;
+ case SDLK_LEFT: ret = KEYSYM_LEFTARROW; break;
+ case SDLK_RIGHT:ret = KEYSYM_RIGHTARROW;break;
+ case SDLK_F1: ret = KEYSYM_F1; break;
+ case SDLK_F2: ret = KEYSYM_F2; break;
+ case SDLK_F3: ret = KEYSYM_F3; break;
+ case SDLK_F4: ret = KEYSYM_F4; break;
+ case SDLK_F5: ret = KEYSYM_F5; break;
+ case SDLK_F6: ret = KEYSYM_F6; break;
+ case SDLK_F7: ret = KEYSYM_F7; break;
+ case SDLK_F8: ret = KEYSYM_F8; break;
+ case SDLK_F9: ret = KEYSYM_F9; break;
+ case SDLK_F10: ret = KEYSYM_F10; break;
+ case SDLK_F11: ret = KEYSYM_F11; break;
+ case SDLK_F12: ret = KEYSYM_F12; break;
+ case SDLK_RETURN: ret = KEYSYM_RETURN; break;
+ case SDLK_LALT: ret = KEYSYM_LEFTALT; break;
+ case SDLK_LCTRL: ret = KEYSYM_LEFTCTRL; break;
+ case SDLK_LSHIFT: ret = KEYSYM_LEFTSHIFT; break;
+ case SDLK_LSUPER: ret = KEYSYM_LEFTGUI; break;
+ case SDLK_RALT: ret = KEYSYM_RIGHTALT; break;
+ case SDLK_RCTRL: ret = KEYSYM_RIGHTCTRL; break;
+ case SDLK_RSHIFT: ret = KEYSYM_RIGHTSHIFT; break;
+ case SDLK_RSUPER: ret = KEYSYM_RIGHTGUI; break;
+ default:
+ printf("Unhandled key code %i\n", Sym);
+ break;
}
gUI_Keymap[shiftState][Sym] = ret;
return ret;
}
+Uint32 UI_GetButtonBits(Uint8 sdlstate)
+{
+ Uint32 rv = 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_LEFT) ? (1 << 0) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_RIGHT) ? (1 << 1) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_MIDDLE) ? (1 << 2) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_X1) ? (1 << 3) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_X2) ? (1 << 4) : 0;
+ return rv;
+}
+
void UI_MainLoop(void)
{
SDL_Event event;
return ;
case SDL_KEYDOWN:
- acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym,
- event.key.keysym.unicode);
-
+ acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym);
+ // Enter key on acess returns \n, but SDL returns \r
+ if(event.key.keysym.sym == SDLK_RETURN)
+ event.key.keysym.unicode = '\n';
+
if( gUI_KeyboardCallback ) {
- gUI_KeyboardCallback(KEY_ACTION_RAWSYM|event.key.keysym.sym);
- gUI_KeyboardCallback(KEY_ACTION_PRESS|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RAWSYM|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_PRESS|event.key.keysym.unicode);
}
break;
case SDL_KEYUP:
- acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym,
- event.key.keysym.unicode);
+ acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym);
if( gUI_KeyboardCallback ) {
- gUI_KeyboardCallback(KEY_ACTION_RAWSYM|event.key.keysym.sym);
- gUI_KeyboardCallback(KEY_ACTION_RELEASE|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RAWSYM|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RELEASE|0);
}
break;
case SDL_USEREVENT:
SDL_UpdateRect(gScreen, 0, 0, giUI_Width, giUI_Height);
SDL_Flip(gScreen);
- break;
+ break;
+
+ case SDL_MOUSEMOTION: {
+ int abs[] = {event.motion.x, event.motion.y};
+ int delta[] = {event.motion.xrel, event.motion.yrel};
+ Mouse_HandleEvent(UI_GetButtonBits(SDL_GetMouseState(NULL, NULL)), delta, abs);
+ break; }
+ case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEBUTTONDOWN: {
+ int abs[] = {event.button.x, event.button.y};
+ Mouse_HandleEvent(UI_GetButtonBits(SDL_GetMouseState(NULL, NULL)), NULL, abs);
+ break; }
default:
break;
tUserHandles *ent, *prev = NULL;
for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
if( ent->PID == PID ) {
- if( bCreate )
- Log_Warning("VFS", "Process %i already has a handle list", PID);
+ //if( bCreate )
+ // Log_Warning("VFS", "Process %i already has a handle list", PID);
return ent;
}
if( ent->PID > PID ) break;
}
}
+void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[])
+{
+ tUserHandles *ent;
+ tUserHandles *cur;
+ int i, maxhandles;
+
+ cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
+ if(!cur) return ; // Don't need to do anything if the current list is empty
+
+ ent = VFS_int_GetUserHandles(PID, 1);
+
+ maxhandles = *Threads_GetMaxFD();
+ if( nFD > maxhandles )
+ nFD = maxhandles;
+ for( i = 0; i < nFD; i ++ )
+ {
+ if( FDs[i] >= maxhandles ) {
+ ent->Handles[i].Node = NULL;
+ continue ;
+ }
+ memcpy(&ent->Handles[i], &cur->Handles[ FDs[i] ], sizeof(tVFS_Handle));
+ }
+ for( ; i < maxhandles; i ++ )
+ cur->Handles[i].Node = NULL;
+
+ for( i = 0; i < maxhandles; i ++ )
+ {
+ if(!cur->Handles[i].Node) continue;
+
+ if(ent->Handles[i].Node->Type->Reference)
+ ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
+ }
+}
+
/**
* \fn tVFS_Handle *VFS_GetHandle(int FD)
* \brief Gets a pointer to the handle information structure
LOG("buffer = %p", Buffer);
+ Offset /= 4;
startX = Offset % giUI_Width;
startY = Offset / giUI_Width;
-
- if( Length + startX < giUI_Width )
+ Length /= 4;
+
+ if( startX + Length < giUI_Width )
{
// Single line
UI_BlitBitmap(
Length, 1,
Buffer);
}
+ else if( startX == 0 )
+ {
+ int lines = Length / giUI_Width;
+ int rem = Length % giUI_Width;
+ UI_BlitBitmap(0, startY, giUI_Width, lines, Buffer);
+ if( rem ) {
+ UI_BlitBitmap(0, startY + lines, rem, 1, (Uint32*)Buffer + lines*giUI_Width);
+ }
+ }
else
{
// First scanline (partial or full)
extern void Binary_SetReadyToUse(void *Base);
// HACKS - So this can share the usermode elf.c
-static inline void *GetSymbol(const char*sym, size_t*sz)
+static inline int GetSymbol(const char *sym, void **val, size_t *sz)
{
uintptr_t rv;
if( !Binary_GetSymbol(sym, &rv, sz) )
- return NULL;
- return (void*)rv;
+ return 0;
+ *val = (void*)rv;
+ return 1;
}
static inline void *LoadLibrary(const char *Name, const char *SearchPath, char **envp)
{
Binary_SetReadyToUse(Base);
}
+static inline int SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
+{
+ return 0;
+}
+
extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits);
+++ /dev/null
-#include "common.h"
-#define _COMMON_H // stops real ld-acess.so common.h being included
-#include "../../Usermode/Libraries/ld-acess.so_src/elf.c"
--- /dev/null
+#include "common.h"
+#define _COMMON_H
+// stops real ld-acess.so common.h being included
+#include "../../Usermode/Libraries/ld-acess.so_src/elf.c"
+++ /dev/null
-#include "../../Usermode/Libraries/ld-acess.so_src/elf32.h"
--- /dev/null
+#include "../../Usermode/Libraries/ld-acess.so_src/elf32.h"
+++ /dev/null
-#include "../../Usermode/Libraries/ld-acess.so_src/elf64.h"
--- /dev/null
+#include "../../Usermode/Libraries/ld-acess.so_src/elf64.h"
#include <stdarg.h>
#include <stddef.h>
-#define DEBUG(v...) Debug(v)
+#define DEBUG(v...) do{}while(0)//Debug(v)
#define PAGE_SIZE 4096
typedef struct sFILE FILE;
// === GLOBALS ===
int acess__errno;
+char *gsExecutablePath = "./ld-acess";
// === CODE ===
// --- VFS Calls
return native_execve("./ld-acess", new_argv, envp);
}
+int acess__SysSpawn(const char *binary, const char **argv, const char **envp, int nfd, int fds[], struct s_sys_spawninfo *info)
+{
+ int argc = 0;
+ while( argv[argc++] );
+
+ Debug("_SysSpawn('%s', %p (%i), %p, %i, %p, %p)",
+ binary, argv, argc, envp, nfd, fds, info);
+
+ int kernel_tid;
+ int newID;
+ newID = _Syscall(SYS_AN_SPAWN, "<d >d >d", sizeof(int), &kernel_tid,
+ nfd*sizeof(int), fds,
+ info ? sizeof(*info) : 0, info);
+
+ const char *new_argv[5+argc+1];
+ int new_argc = 0, i;
+ char client_id_str[11];
+ sprintf(client_id_str, "%i", newID);
+ new_argv[new_argc++] = gsExecutablePath; // TODO: Get path to ld-acess executable
+ new_argv[new_argc++] = "--key";
+ new_argv[new_argc++] = client_id_str;
+ new_argv[new_argc++] = "--binary";
+ new_argv[new_argc++] = binary;
+ for( i = 0; argv[i]; i ++)
+ new_argv[new_argc++] = argv[i];
+ new_argv[new_argc++] = NULL;
+
+ // TODO: Debug output?
+
+ native_spawn(gsExecutablePath, new_argv, envp);
+
+ return kernel_tid;
+}
+
void acess_sleep(void)
{
DEBUG("%s()", __func__);
DEFSYM(clone),
DEFSYM(execve),
+ DEFSYM(_SysSpawn),
DEFSYM(sleep),
DEFSYM(waittid),
+ DEFSYM(gettid),
DEFSYM(setuid),
DEFSYM(setgid),
- DEFSYM(gettid),
+ DEFSYM(getuid),
+ DEFSYM(getgid),
DEFSYM(SysSendMessage),
DEFSYM(SysGetMessage),
extern uint64_t native_tell(int FD);
extern int native_execve(const char *filename, const char *const argv[], const char *const envp[]);
+extern int native_spawn(const char *filename, const char *const argv[], const char *const envp[]);
// Syscalls used by the linker
extern int acess_open(const char *Path, int Flags);
printf("\n");
}
#endif
+ #if DEBUG
{
int i;
char *data = (char*)&Request->Params[Request->NParams];
}
DEBUG_S("\n");
}
+ #endif
// Send it off
SendData(Request, RequestSize);
if( Request->CallID == SYS_EXIT ) return 0;
// Wait for a response (no timeout)
- return ReadData(Request, ResponseSize, 0);
+ ReadData(Request, sizeof(*Request), 0);
+ // TODO: Sanity
+ size_t recvbytes = sizeof(*Request), expbytes = Request->MessageLength;
+ char *ptr = (void*)Request->Params;
+ while( recvbytes < expbytes )
+ {
+ size_t len = ReadData(ptr, expbytes - recvbytes, 1000);
+ if( len == -1 ) {
+ return -1;
+ }
+ recvbytes += len;
+ ptr += len;
+ }
+ if( recvbytes > expbytes ) {
+ // TODO: Warning
+ }
+ return recvbytes;
}
void SendData(void *Data, int Length)
if( !ret ) {
printf("[ERROR %i] Timeout reading from socket\n", giSyscall_ClientID);
- return 0; // Timeout
+ return -2; // Timeout
}
#if USE_TCP
perror("ReadData");
exit(-1);
}
+ if( ret == 0 ) {
+ fprintf(stderr, "[ERROR %i] Connection closed.\n", giSyscall_ClientID);
+ close(gSocket);
+ exit(0);
+ }
DEBUG_S("%i bytes read from socket\n", ret);
#include <string.h>
#include <stddef.h>
#include <unistd.h>
+#include <spawn.h> // posix_spawn
#include "request.h"
+#if SYSCALL_TRACE
#define DEBUG(str, x...) Debug(str, x)
+#else
+#define DEBUG(...) do{}while(0)
+#endif
#define MAX_FPS 16
req->ClientID = 0; //< Filled later
req->CallID = SyscallID;
req->NParams = paramCount;
+ req->MessageLength = dataLength;
dataPtr = &req->Params[paramCount];
// Fill `output` and `input`
}
// Write changes to buffers
+ if( req->NParams - 1 != retCount ) {
+ fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
+ req->NParams, retCount, SyscallID);
+ exit(127);
+ }
retCount = 0;
for( i = 1; i < req->NParams; i ++ )
{
int native_execve(const char *filename, const char *const argv[], const char *const envp[])
{
int ret;
- ret = execve(filename, argv, envp);
+ ret = execve(filename, (void*)argv, (void*)envp);
perror("native_execve");
return ret;
}
+
+int native_spawn(const char *filename, const char *const argv[], const char *const envp[])
+{
+ int rv;
+
+ rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);
+
+ return rv;
+}
typedef struct sRequestHeader {
uint16_t ClientID;
uint16_t CallID; //!< \see eSyscalls
+ uint32_t MessageLength;
uint16_t NParams;
tRequestValue Params[];
// IPC
SYS_SLEEP,
SYS_AN_FORK,
+ SYS_AN_SPAWN,
SYS_SENDMSG,
SYS_GETMSG,
SYS_SELECT,
SAVED_CC_ := $(CC)
SAVED_LD_ := $(LD)
+ifeq ($(HOST_ARCH),)
+$(error Please set HOST_ARCH to the architecture to compile, e.g. x86)
+endif
+
include $(ACESSDIR)/BuildConf/$(HOST_ARCH)/Makefile.cfg
OBJDUMP := objdump -S
# Acess2 Build Configuration
#
-#CC = i586-elf-gcc
-#LD = i586-elf-ld
-CC = gcc
-LD = ld
+CC = i586-elf-gcc
+#CC = clang -m32
+LD = i586-elf-ld
+#CC = gcc
+#LD = ld
AS = nasm
#OBJDUMP = i586-elf-objdump
OBJDUMP = objdump
-PREFIX := x86_64-pc-elf
-#PREFIX := x86_64-none-elf
+#PREFIX := x86_64-pc-elf
+PREFIX := x86_64-none-elf
CC := $(PREFIX)-gcc
LD := $(PREFIX)-ld
DISASM = $(PREFIX)-objdump -d -M x86-64 -S
-KERNEL_CFLAGS := -mcmodel=kernel -nostdlib -mno-red-zone -Wall
-DYNMOD_CFLAGS := -mcmodel=small -fPIC -mno-red-zone
+KERNEL_CFLAGS := -mcmodel=kernel -nostdlib -mno-red-zone -Wall -mno-sse
+DYNMOD_CFLAGS := -mcmodel=small -fPIC -mno-red-zone -mno-sse
ARCHDIR = x86_64
val32 |= val32 << 16;
// Force alignment
- while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value;
+ while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value, _length --;
dst = (void *)dst8;
// DWORD copies
#include <hal_proc.h>
#define TRACE_MAPS 0
+#define TRACE_COW 1
#define AP_KRW_ONLY 1 // Kernel page
#define AP_KRO_ONLY 5 // Kernel RO page
#define AP_RO_USER 2 // User RO Page
#define PADDR_MASK_LVL1 0xFFFFFC00
+const char * const caAPValueNames[] = {
+ "AP_NOACCESS", "AP_KRW_ONLY",
+ "AP_RO_USER", "AP_RW_BOTH",
+ "AP_???_4", "AP_KRO_ONLY",
+ "AP_???_6", "AP_RO_BOTH"
+};
+
// === IMPORTS ===
extern Uint32 kernel_table0[];
tVAddr MM_NewKStack(int bGlobal);
void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info);
//void MM_DumpTables(tVAddr Start, tVAddr End);
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch);
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR);
// === GLOBALS ===
tPAddr giMM_ZeroPage;
tVAddr addr, ofs;
addr = USER_STACK_TOP - USER_STACK_SIZE;
- if( MM_GetPhysAddr(addr + PAGE_SIZE) ) {
+ if( MM_GetPhysAddr( (void*)(addr + PAGE_SIZE) ) ) {
Log_Error("MMVirt", "Unable to create initial user stack, addr %p taken",
addr + PAGE_SIZE
);
{
if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage )
{
- Debug("%p => %8s - 0x%7x %i %x %s",
+ Debug("%p => %8s - 0x%7x D%i %x %s %s",
Start, "ZERO", Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
else
{
- Debug("%p => %8x - 0x%7x %i %x %s",
+ Debug("%p => %8x - 0x%7x D%i %x %s %s",
Start, Info->PhysAddr-Len, Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
}
}
// NOTE: Runs in abort context, not much difference, just a smaller stack
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch)
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR)
{
int rv;
tMM_PageInfo pi;
Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR,
(bPrefetch ? " - Prefetch" : "")
);
+ Log_Error("MMVirt", "- User LR = 0x%x", UserLR);
+ const char * const dfsr_errors[] = {
+ /* 00000 */ "-", "Alignment Fault",
+ /* 00010 */ "Debug event", "Access Flag (Section)",
+ /* 00100 */ "Instr Cache Maint", "Translation (Section)",
+ /* 00110 */ "Access Flag (Page)", "Translation (Page)",
+ /* 01000 */ "Sync. External abort", "Domain (Section)",
+ /* 01010 */ "-", "Domain (Page)",
+ /* 01100 */ "Table Walk sync ext (lvl 1)", "Permission (Section)",
+ /* 01110 */ "Table Walk sync ext (lvl 2)", "Permission (Page)",
+ // 0b10000
+ /* 10000 */ "-", "-",
+ /* 10010 */ "-", "-",
+ /* 10100 */ "IMPL (Lockdown)", "-",
+ /* 10110 */ "Async. Extern. Abort", "-",
+ /* 11000 */ "Mem. access async pairity error", "Mem. access async pairity error",
+ /* 11010 */ "IMPL (Coprocessor abort)", "-",
+ /* 11100 */ "Table Walk Sync parity (lvl 1)", "-",
+ /* 11110 */ "Table Walk Sync parity (lvl 2)", "-"
+ };
+ int errcode = (DFSR & 0xF) | (((DFSR >> 10) & 1) << 4);
+ Log_Error("MMVirt", "- Errcode 0b%05b", errcode);
+ Log_Error("MMVirt", "- Dom %i %s %s",
+ (DFSR >> 4) & 0xF, (DFSR & 0x800 ? "Write": "Read"),
+ dfsr_errors[errcode]
+ );
+ Log_Error("MMVirt", "- AP=%i(%s) %s", pi.AP, caAPValueNames[pi.AP], pi.bExecutable ? " Executable":"");
if( Addr < 0x80000000 )
MM_DumpTables(0, 0x80000000);
else
Uint32 sp;
new = Threads_CloneThreadZero();
- if(!new) return -1;
+ if(!new) return NULL;
if(new->ThreadName) free(new->ThreadName);
new->ThreadName = NULL;
@ cpsid ifa, #19
PUSH_GPRS
+ @ Get the user's LR value (and push to stack)
+ cps #31 @ Go to system mode
+ mov r1, lr
+ cps #19 @ Go to supervisor
+ mov r0, lr
+ cps #23 @ back to exception
+ push {r0,r1}
+
mov r3, #0 @ not a prefetch abort
mrc p15, 0, r2, c5, c0, 0 @ Read DFSR (Data Fault Status Register) to R2
mrc p15, 0, r1, c6, c0, 0 @ Read DFAR (Data Fault Address Register) into R1
mov r0, lr @ PC
ldr r4, =MM_PageFault
blx r4
+ add sp, #8 @ Undo push of the user/system LR
POP_GPRS
rfeia sp! @ Pop state (actually RFEFD)
@ cpsid ifa, #19
PUSH_GPRS
- ldr r0, =csAbort_Tag
- ldr r1, =csPrefetchAbort_Fmt
-# mov r2, lr
- mrc p15, 0, r2, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3
- mrc p15, 0, r3, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3
- ldr r5, =Log_Error
- blx r5
-.loop:
- wfi
- b .loop
+ @ Get the user's LR value (and push to stack)
+ cps #31 @ Go to system mode
+ mov r0, lr
+ cps #23 @ back to supervisor
+ push {r0}
+
+ mrc p15, 0, r2, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3
+ mrc p15, 0, r1, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3
+ mov r0, r1
+ mov r3, #1 @ IS a prefetch abort
+ ldr r4, =MM_PageFault
+ blx r4
+ add sp, #4 @ Undo push of the user LR
+
+ POP_GPRS
+ rfeia sp! @ Pop state (actually RFEFD)
+
.globl Undef_Handler
Undef_Handler:
wfi
csDataAbort_Fmt:
.asciz "Data Abort - %p accessed %p, DFSR=%x Unk:%x Unk:%x"
csPrefetchAbort_Fmt:
- .asciz "Prefetch Abort at %p, IFSR=%x"
+ .asciz "Prefetch Abort at %p, IFSR=%x, UserLR:0x%x"
csSyscallPrintRetAddr:
.asciz "Syscall ret to %p"
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * vpci_realview_pb.c
+ * - Realview PB VPCI Definitions
+ */
+#include <virtual_pci.h>
+
+// === PROTOTYPES ===
+
+// === GLOBALS ===
+tVPCI_Device gaVPCI_Devices[] = {
+};
+int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]);
+
* Linker Script
*/
-lowStart = start - 0xC0000000;
-ENTRY(lowStart)
+ENTRY(start)
OUTPUT_FORMAT(elf32-i386)
SECTIONS {
__load_addr = .;
.multiboot : AT(ADDR(.multiboot)) {
*(.multiboot)
+ *(.inittext)
}
. += 0xC0000000;
if( !MM_GetPhysAddr(ent) )
Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)",
nPMemMapEnts, ent);
+ LOG("%llx+%llx", ent->Base, ent->Length);
nent->Start = ent->Base;
nent->Length = ent->Length;
}
// Ensure it's valid
+ LOG("Validating");
nPMemMapEnts = PMemMap_ValidateMap(Map, nPMemMapEnts, MapSize);
// TODO: Error handling
// Replace kernel with PMEMTYPE_USED
+ LOG("Marking kernel");
nPMemMapEnts = PMemMap_MarkRangeUsed(
Map, nPMemMapEnts, MapSize,
KStart, KEnd - KStart
);
+ LOG("Dumping");
PMemMap_DumpBlocks(Map, nPMemMapEnts);
// Check if boot modules were passed
; dd 8
;mboot2_end:
-[section .text]
+[section .inittext]
[extern kmain]
[extern Desctab_Install]
[global start]
or al, 1
mov cr0, eax
; Jump into PMode
- jmp 08h:DWORD .ProtectedMode-KERNEL_BASE
+ jmp 08h:DWORD .ProtectedMode
[bits 32]
.ProtectedMode:
; Load segment registers
jmp .hlt
%endif
+;
+;
+;
+[section .text]
[global GetEIP]
GetEIP:
mov eax, [esp]
%assign i i+1
%endrep
+[extern Proc_int_SetIRQIP]
+
[global IrqCommon]
IrqCommon:
PUSH_GPR
push gs
push fs
-
+
+ mov rdi, [rsp+(16+2+2)*8] ; 2SReg + GPRs + Int/Errcode = RIP
+ call Proc_int_SetIRQIP
+ push rax
+
; mov rdi, csIRQ_Fired
; mov rsi, [rsp+(16+2)*8]
; call Log
- mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
+ mov ebx, [rsp+(1+2+16)*8] ; Get interrupt number (16 GPRS + 2 SRs)
shl ebx, 2 ; *4
mov rax, gaIRQ_Handlers
lea rbx, [rax+rbx*8]
test rax, rax ; Check if it exists
jz .skip.%[i]
; Set RDI to IRQ number
- mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1+1)*8] ; Get IRQ number
mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
call rax ; Call
.skip.%[i]:
; ACK
mov al, 0x20
- mov rdi, [rsp+(16+2)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
cmp rdi, 8
jb .skipAckSecondary
out 0xA0, al
.skipAckSecondary:
out 0x20, al
+
+ pop rdi
+ call Proc_int_SetIRQIP
pop fs
pop gs
mov [rsp+0x28], r10 ; Arg4
mov [rsp+0x30], r8 ; Arg5
mov [rsp+0x38], r9 ; Arg6
-
+
+ mov rdi, rcx
+ call Proc_int_SetIRQIP
+
mov rdi, rsp
sub rsp, 8
call SyscallHandler
extern int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
extern void Error_Backtrace(Uint IP, Uint BP);
extern void Proc_EnableSSE(void);
+extern void Threads_Dump(void);
extern void Proc_RestoreSSE(Uint32 Data);
// === PROTOTYPES ===
*(Uint8*)(Regs->RIP+2), *(Uint8*)(Regs->RIP+3)
);
break;
+ case 2: // NMI
+ Threads_Dump();
+ break;
}
__asm__ __volatile__ ("cli");
// === FUNCTIONS ===
void MM_FinishVirtualInit(void);
tVAddr MM_NewKStack(void);
-tVAddr MM_Clone(void);
+tVAddr MM_Clone(int bCopyUser);
tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize);
#endif
Size += Addr & (PAGE_SIZE-1);
Addr &= ~(PAGE_SIZE-1);
- Addr &= ((1UL << 48)-1); // Clap to address space
+ // NC addr
+ if( ((Addr >> 47) & 1) != ((Addr>>48) == 0xFFFF))
+ return 0;
+ Addr &= ((1UL << 48)-1); // Clamp to address space
pml4 = Addr >> 39;
pdp = Addr >> 30;
dir = Addr >> 21;
tab = Addr >> 12;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
- if( !(PAGEDIR(dir) & 1) ) return 0;
- if( !(PAGETABLE(tab) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "PML4E %i NP", pml4);
+ return 0;
+ }
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "PDPE %i NP", pdp);
+ return 0;
+ }
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "PDE %i NP", dir);
+ return 0;
+ }
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "PTE %i NP", tab);
+ return 0;
+ }
bIsUser = !!(PAGETABLE(tab) & PF_USER);
while( Size >= PAGE_SIZE )
{
+ tab ++;
+ Size -= PAGE_SIZE;
+
if( (tab & 511) == 0 )
{
dir ++;
- if( ((dir >> 9) & 511) == 0 )
+ if( (dir & 511) == 0 )
{
pdp ++;
- if( ((pdp >> 18) & 511) == 0 )
+ if( (pdp & 511) == 0 )
{
pml4 ++;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PML4E %x NP, Size=%x", pml4, Size);
+ return 0;
+ }
}
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDPE %x NP", pdp);
+ return 0;
+ }
+ }
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDE %x NP", dir);
+ return 0;
}
- if( !(PAGEDIR(dir) & 1) ) return 0;
}
- if( !(PAGETABLE(tab) & 1) ) return 0;
- if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0;
-
- tab ++;
- Size -= PAGE_SIZE;
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x NP", tab);
+ return 0;
+ }
+ if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x Not user", tab);
+ return 0;
+ }
}
return 1;
}
// Allocated successfully, now map
ret = MM_MapHWPages(phys, Pages);
+ *PhysAddr = phys;
// MapHWPages references the pages, so deref them back down to 1
for(;Pages--;phys+=0x1000)
MM_DerefPhys(phys);
return 0;
}
- *PhysAddr = phys;
return ret;
}
// --- Address Space Clone --
-tPAddr MM_Clone(void)
+tPAddr MM_Clone(int bNoUserCopy)
{
tPAddr ret;
int i;
INVLPG_ALL();
// #3 Set Copy-On-Write to all user pages
- if( Threads_GetPID() != 0 )
+ if( Threads_GetPID() != 0 && !bNoUserCopy )
{
for( i = 0; i < 256; i ++)
{
mov rdi, [rsp+0x10]
mov rax, [rsp+0x8]
add rsp, 0x10 ; Reclaim stack space (thread/fcn)
- xchg bx, bx
+ ;xchg bx, bx
call rax
; Quit thread with RAX as the return code
PUSH_GPR
; Save RSP
mov [rdi], rsp
+ ; Call MM_Clone (with bNoUserCopy flag)
+ mov rdi, rdx
call MM_Clone
; Save CR3
mov rsi, [rsp+0x30] ; Saved version of RSI
extern Uint GetRIP(void); // start.asm
extern Uint SaveState(Uint *RSP, Uint *Regs);
-extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3);
+extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM);
extern void NewTaskHeader(void); // Actually takes cdecl args
extern void Proc_InitialiseSSE(void);
extern void Proc_SaveSSE(Uint DestPtr);
//void Proc_DumpThreadCPUState(tThread *Thread);
//void Proc_Reschedule(void);
void Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
+Uint Proc_int_SetIRQIP(Uint RIP);
// === GLOBALS ===
//!\brief Used by desctab.asm in SyscallStub
if(!newThread) return -1;
// Save core machine state
- rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
+ rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
if(rip == 0) return 0; // Child
newThread->KernelStack = cur->KernelStack;
newThread->SavedState.RIP = rip;
void Proc_DumpThreadCPUState(tThread *Thread)
{
- Log(" At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ if( Thread->CurCPU == GetCPUNum() ) {
+ // TODO: Backtrace to IRQ
+ Log(" IRQ %016llx", Thread->SavedState.UserRIP);
+ }
+ else {
+ Log(" At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP);
+ Log(" User %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ }
}
void Proc_Reschedule(void)
// Update CPU state
gaCPUs[cpu].Current = nextthread;
- gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
+ gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
__asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
if( curthread )
#endif
}
+Uint Proc_int_SetIRQIP(Uint RIP)
+{
+ int cpu = GetCPUNum();
+ tThread *thread = gaCPUs[cpu].Current;
+ Uint rv = thread->SavedState.UserRIP;
+ thread->SavedState.UserRIP = RIP;
+ return rv;
+}
+
// === EXPORTS ===
EXPORT(Proc_SpawnWorker);
/*\r
- * Acess v0.1\r
- * ELF Executable Loader Code\r
+ * Acess2 Kernel\r
+ * - By John Hodge (thePowersGang)\r
+ *\r
+ * elf.c\r
+ * - ELF Executable Loader Code\r
*/\r
#define DEBUG 0\r
#include <acess.h>\r
#include <binary.h>\r
\r
+// ---- Import linking code from userland\r
#define _COMMON_H\r
#define SysDebug(v...) LOG(v)\r
#if BITS <= 32\r
# define DISABLE_ELF64\r
#endif\r
-void *GetSymbol(const char *Name, size_t *Size);\r
-void *GetSymbol(const char *Name, size_t *Size) { Uint val; Binary_GetSymbol(Name, &val); if(Size)*Size=0; return (void*)val; };\r
+static int GetSymbol(const char *Name, void **Value, size_t *Size);\r
+static int GetSymbol(const char *Name, void **Value, size_t *Size) {\r
+ Uint val;\r
+ if(!Binary_GetSymbol(Name, &val)) {\r
+ Log_Notice("ELF", "Lookup of '%s' failed", Name);\r
+ return 0;\r
+ }\r
+ if(Size)\r
+ *Size=0;\r
+ *Value = (void*)val;\r
+ return 1;\r
+}\r
#define AddLoaded(a,b) do{}while(0)\r
#define LoadLibrary(a,b,c) (Log_Debug("ELF", "Module requested lib '%s'",a),0)\r
+#define SysSetMemFlags(ad,f,m) do{}while(0)\r
#include "../../../Usermode/Libraries/ld-acess.so_src/elf.c"\r
+// ---- / ----\r
\r
#define DEBUG_WARN 1\r
\r
Proc_Execve(Binary, ArgV, EnvP, size);
for(;;);
}
- if( ret < 0 )
+ if( ret == -1 )
{
VFS_FreeSavedHandles(nFD, handles);
+ free(cachebuf);
}
return ret;
Codepoint &= KEY_CODEPOINT_MASK;
- // Ignore Modifer Keys
- if(Codepoint > KEY_MODIFIERS) return;
-
// Get UTF-8/ANSI Encoding
if( Codepoint == 0 )
{
* \}\r
*/\r
\r
-/**\r
- * \brief Symbolic key codes\r
- * \r
- * These key codes represent non-pritable characters and are placed above\r
- * the Unicode character space.\r
- * If the using driver recieves a key code with the 31st bit set, it means\r
- * that that key has been released.\r
- */\r
-enum eTplKeyboard_KeyCodes {\r
- KEY_ESC = 0x1B, //!< Escape Character\r
- \r
- KEY_NP_MASK = 0x20000000, //! Mask for non-printable characters\r
- \r
- /**\r
- * \name Special Keys\r
- * \brief These keys are usually used on their own\r
- * \{\r
- */\r
- KEY_CAPSLOCK,\r
- KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,\r
- KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, \r
- KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,\r
- KEY_NUMLOCK, KEY_SCROLLLOCK,\r
- KEY_HOME, KEY_END, KEY_INS, KEY_DEL,\r
- KEY_PAUSE, KEY_BREAK,\r
- KEY_PGUP, KEY_PGDOWN,\r
- KEY_KPENTER, KEY_KPSLASH, KEY_KPMINUS, KEY_KPPLUS, KEY_KPSTAR,\r
- KEY_KPHOME, KEY_KPUP, KEY_KPPGUP, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT,\r
- KEY_KPEND, KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL,\r
- KEY_LWIN, KEY_RWIN,\r
- KEY_MENU,\r
- /**\r
- * \}\r
- */\r
- \r
- // Modifiers\r
- /**\r
- * \name Modifiers\r
- * \brief These keye usually alter the character stream sent to the user\r
- * \{\r
- */\r
- KEY_MODIFIERS = 0x30000000,\r
- KEY_LCTRL, KEY_RCTRL,\r
- KEY_LALT, KEY_RALT,\r
- KEY_LSHIFT, KEY_RSHIFT,\r
- /**\r
- * \}\r
- */\r
-};\r
-\r
#include "keysyms.h"\r
\r
#endif\r
# define LEAVE_RET(_t,_v...) return (_v)
# define LEAVE_RET0() return
#endif
-#if SANITY
+#if !DISABLE_ASSERTS
# define ASSERT(expr) do{if(!(expr))Panic("%s:%i - %s: Assertion '"#expr"' failed",__FILE__,__LINE__,(char*)__func__);}while(0)
#else
# define ASSERT(expr)
return stamp * 1000;
}
+static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R);
+
+static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R)
+{
+ int sign = (N < 0) != (D < 0);
+ if(N < 0) N = -N;
+ if(D < 0) D = -D;
+ if(sign)
+ return -DivMod64U(N, D, (Uint64*)R);
+ else
+ return DivMod64U(N, D, (Uint64*)R);
+}
+
void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms)
{
int is_leap = 0, i;
- auto Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R);
-
- Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R)
- {
- int sign = (N < 0) != (D < 0);
- if(N < 0) N = -N;
- if(D < 0) D = -D;
- if(sign)
- return -DivMod64U(N, D, (Uint64*)R);
- else
- return DivMod64U(N, D, (Uint64*)R);
- }
-
// Get time
// TODO: Leap-seconds?
{
/**
* \brief Append a character the the vsnprintf output
*/
-#define PUTCH(c) _putch(c)
+#define PUTCH(ch) do { \
+ if(pos < __maxlen) { \
+ if(__s) __s[pos] = ch; \
+ } else { \
+ (void)ch;\
+ } \
+ pos ++; \
+ } while(0)
#define GETVAL() do {\
if(isLongLong) val = va_arg(args, Uint64);\
else val = va_arg(args, unsigned int);\
size_t pos = 0;
// Flags
int bPadLeft = 0;
-
- auto void _putch(char ch);
-
- void _putch(char ch)
- {
- if(pos < __maxlen)
- {
- if(__s) __s[pos] = ch;
- }
- pos ++;
- }
while((c = *__format++) != 0)
{
if(c == 'p') {
Uint ptr = va_arg(args, Uint);
PUTCH('*'); PUTCH('0'); PUTCH('x');
- for( len = BITS/4; len --; )
- PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
+ for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; )
+ ;
+ len ++;
+ if( len == 0 )
+ PUTCH( '0' );
+ else
+ while( len -- )
+ PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
continue ;
}
}
-// NOTE: Strictly not libc, but lib.c is used by userland code too
+// NOTE: Strictly not libc, but lib.c is used by userland code too and hence these two
+// can't be in it.
/**
* \name Memory Validation
* \{
va_list args_tmp;
if( Level >= NUM_LOG_LEVELS ) return;
-
+
va_copy(args_tmp, Args);
len = vsnprintf(NULL, 256, Format, args_tmp);
- //Log("len = %i", len);
-
#if USE_RING_BUFFER || !CACHE_MESSAGES
{
char buf[sizeof(tLogEntry)+len+1];
if( CPU_HAS_LOCK(&glLogOutput) )
return ; // TODO: Error?
SHORTLOCK( &glLogOutput );
- LogF("%s%014lli%s [%-8s] %i - %s",
+ LogF("%s%014lli",
csaLevelColours[Entry->Level],
- Entry->Time,
+ Entry->Time
+ );
+ LogF("%s [%-8s] %i - %s",
csaLevelCodes[Entry->Level],
Entry->Ident,
Threads_GetTID(),
// Remove from list
tmp = cur->Messages;
cur->Messages = cur->Messages->Next;
+ // - Removed last message? Clear the end-of-list pointer
if(cur->Messages == NULL) cur->LastMessage = NULL;
+ // > Otherwise, re-mark the IPCMSG event flag
+ else cur->EventState |= THREAD_EVENT_IPCMSG;
SHORTREL( &cur->IsLocked );
-
+
free(tmp); // Free outside of lock
LEAVE('i', ret);
#include <events.h>
#define CHECK_NUM_NULLOK(v,size) \
- if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NULLOK(v) \
- if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_ValidString((v))){LOG("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_NUM_NONULL(v,size) \
- if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NONULL(v) \
- if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_ValidString((v))){LOG("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
void SyscallHandler(tSyscallRegs *Regs);
int Syscall_ValidString(const char *Addr);
int Syscall_Valid(int Size, const void *Addr);
+ int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask);
// === CODE ===
// TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel
// -- Unmap an address
case SYS_UNMAP: MM_Deallocate(Regs->Arg1); break;
+ // -- Change the protection on an address
+ case SYS_SETFLAGS:
+ ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ break;
+
// -- Get Thread/Process IDs
case SYS_GETTID: ret = Threads_GetTID(); break;
case SYS_GETPID: ret = Threads_GetPID(); break;
CHECK_STR_NONULL((const char*)Regs->Arg1);
CHECK_STR_ARRAY((const char**)Regs->Arg2);
CHECK_STR_ARRAY((const char**)Regs->Arg3);
- CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+ CHECK_NUM_NULLOK((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
ret = Proc_SysSpawn(
(const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
Regs->Arg4, (int*)Regs->Arg5
*/
int Syscall_Valid(int Size, const void *Addr)
{
- if(!MM_IsUser( (tVAddr)Addr )) return 0;
+ if(!MM_IsUser( (tVAddr)Addr )) {
+ Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr);
+ return 0;
+ }
return CheckMem( Addr, Size );
}
+
+int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask)
+{
+ tPAddr paddr = MM_GetPhysAddr(Addr);
+ Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+ Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+
+ //Log_Debug("Syscalls", "SYS_SETFLAGS: %p %x %x", Addr, Flags, Mask);
+
+ // Enable write?
+ if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) {
+ void *node;
+ // HACK - Assume that RO mmap'd files are immutable
+ if( MM_GetPageNode(paddr, &node) == 0 && node ) {
+ Flags |= MM_PFLAG_COW;
+ Mask |= MM_PFLAG_COW;
+ }
+ }
+ MM_SetFlags((tVAddr)Addr, Flags, Mask);
+ return 0;
+}
default: break;
}
Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
- Log(" KStack 0x%x", thread->KernelStack);
+ Log(" KStack %p", thread->KernelStack);
if( thread->bInstrTrace )
Log(" Tracing Enabled");
Proc_DumpThreadCPUState(thread);
PAGE_SIZE - (mapping_base & (PAGE_SIZE-1))
);
memset( (void*)(mapping_base + ofs), 0, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1)));
+ LOG("dune");
}
else {
LOG("New empty page");
tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
{
tInodeCache *cache;
- tCachedInode *newEnt, *ent, *prev;
+ tCachedInode *newEnt, *ent, *prev = NULL;
cache = Inode_int_GetFSCache(Handle);
if(!cache) return NULL;
// Search Cache
ent = cache->FirstNode;
- prev = (tCachedInode*) &cache->FirstNode;
for( ; ent; prev = ent, ent = ent->Next )
{
if(ent->Node.Inode < Node->Inode) continue;
newEnt = malloc(sizeof(tCachedInode));
newEnt->Next = ent;
memcpy(&newEnt->Node, Node, sizeof(tVFS_Node));
- prev->Next = newEnt;
+ if( prev )
+ prev->Next = newEnt;
+ else
+ cache->FirstNode = newEnt;
newEnt->Node.ReferenceCount = 1;
LOG("Cached %llx as %p", Node->Inode, &newEnt->Node);
VBE_DISPI_INDEX_Y_OFFSET\r
};\r
\r
-extern void MM_DumpTables(tVAddr Start, tVAddr End);\r
-\r
// === PROTOTYPES ===\r
// Driver\r
int BGA_Install(char **Arguments);\r
\r
if(bs.bps == 0 || bs.spc == 0)\r
return 0;\r
- \r
+\r
+ Log_Debug("FAT", "_Detect: Media type = %02x", bs.mediaDesc);\r
+ if( bs.mediaDesc < 0xF0 )\r
+ return 0;\r
+\r
return 1;\r
}\r
/**\r
<?php
+date_default_timezone_set("UTC");
+
$lGenDate = date("Y-m-d H:i");
$gOutput = <<<EOF
/*
File "ld-acess.so" "__BIN__/Libs/ld-acess.so"
File "libld-acess.so" "__BIN__/Libs/libld-acess.so"
File "libc.so" "__BIN__/Libs/libc.so"
- File "libgcc.so" "__BIN__/Libs/libgcc.so"
File "libreadline.so" "__BIN__/Libs/libreadline.so"
File "libnet.so" "__BIN__/Libs/libnet.so"
File "liburi.so" "__BIN__/Libs/liburi.so"
{
tUSBHost *host;
- host = malloc(sizeof(tUSBHost) + nPorts*sizeof(tUSBHubPort));
+ host = malloc(sizeof(tUSBHost) + nPorts*sizeof(tUSBHubPort) + sizeof(tUSBDevice) + sizeof(tUSBInterface));
if(!host) {
// Oh, bugger.
return NULL;
host->Ptr = ControllerPtr;
memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
- host->RootHubDev.ParentHub = NULL;
- host->RootHubDev.Host = host;
- host->RootHubDev.Address = 0;
+ host->RootHubDev = (void*)(host->RootHub.Ports + nPorts);
+ host->RootHubDev->ParentHub = NULL;
+ host->RootHubDev->Host = host;
+ host->RootHubDev->Address = 0;
ASSERT(HostDef->InitControl);
- host->RootHubDev.EndpointHandles[0] = HostDef->InitControl(ControllerPtr, 0, 64);
+ host->RootHubDev->EndpointHandles[0] = HostDef->InitControl(ControllerPtr, 0, 64);
+ host->RootHubDev->nInterfaces = 0;
-// host->RootHubIf.Next = NULL;
- host->RootHubIf.Dev = &host->RootHubDev;
- host->RootHubIf.Driver = NULL;
- host->RootHubIf.Data = NULL;
- host->RootHubIf.nEndpoints = 0;
+ host->RootHubIf = (void*)(host->RootHubDev + 1);
+ host->RootHubIf->Dev = host->RootHubDev;
+ host->RootHubIf->Driver = NULL;
+ host->RootHubIf->Data = NULL;
+ host->RootHubIf->nEndpoints = 0;
- host->RootHub.Interface = &host->RootHubIf;
+ host->RootHub.Interface = host->RootHubIf;
host->RootHub.nPorts = nPorts;
memset(host->RootHub.Ports, 0, sizeof(tUSBHubPort)*nPorts);
Uint8 AddressBitmap[128/8];
- tUSBDevice RootHubDev;
- tUSBInterface RootHubIf;
+ tUSBDevice *RootHubDev;
+ tUSBInterface *RootHubIf;
tUSBHub RootHub;
};
int USB_int_AllocateAddress(tUSBHost *Host)
{
int i;
+ ASSERT(Host);
for( i = 1; i < 128; i ++ )
{
if(Host->AddressBitmap[i/8] & (1 << (i%8)))
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
{
- USB_int_Request(&Host->RootHubDev, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
+ USB_int_Request(Host->RootHubDev, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
return 0;
}
int ret;
ENTER("");
-
+
+ if( Arguments && *Arguments && strcmp(*Arguments, "0") == 0 )
+ {
+ LOG("Disabled by argument");
+ LEAVE('i', MODULE_ERR_NOTNEEDED);
+ return MODULE_ERR_NOTNEEDED;
+ }
+
// Initialise with no maximum value
Semaphore_Init( &gUHCI_InterruptSempahore, 0, 0, "UHCI", "Interrupt Queue");
tPAddr tmp;
gaUHCI_TDPool = (void *) MM_AllocDMA(1, 32, &tmp);
memset(gaUHCI_TDPool, 0, PAGE_SIZE);
+ LOG("gaUHCI_TDPool = %p (%P)", gaUHCI_TDPool, tmp);
}
// Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
+ // Class:SubClass:Protocol = 0xC (Serial) : 0x3 (USB) : 0x00 (UHCI)
while( (id = PCI_GetDeviceByClass(0x0C0300, 0xFFFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
{
tUHCI_Controller *cinfo = &gUHCI_Controllers[i];
Uint32 base_addr;
- // NOTE: Check "protocol" from PCI?
cinfo->PciId = id;
base_addr = PCI_GetBAR(id, 4);
LEAVE('i', -1);
return -1;
}
+ LOG("->FrameList = %p (%P)", Host->FrameList, Host->PhysFrameList);
Host->TDQHPage = (void *) MM_AllocDMA(1, 32, &Host->PhysTDQHPage);
if( !Host->TDQHPage ) {
LEAVE('i', -1);
return -1;
}
+ LOG("->TDQHPage = %p (%P)", Host->TDQHPage, Host->PhysTDQHPage);
// Fill frame list
// - The numbers 0...31, but bit reversed (16 (0b1000) = 1 (0b00001)
0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30,
1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31
};
+ // Fill all slots (but every 4th will be changed below
for( int i = 0; i < 1024; i ++ ) {
Uint32 addr = MM_GetPhysAddr( &Host->TDQHPage->ControlQH );
Host->FrameList[i] = addr | 2;
Host->FrameList[768 + i*4] = addr | 2;
}
- // Build up interrupt binary tree
+ // Build up interrupt binary tree
{
tUHCI_QH *dest = Host->TDQHPage->InterruptQHs;
Uint32 destphys = Host->PhysTDQHPage;
// Set up next pointer to index to i/2 in the next step
for( int _count = 64; _count > 1; _count /= 2 )
{
+ LOG("count=%i, dest=%p, destphys=%P", _count, dest, destphys);
for( int i = 0; i < _count; i ++ ) {
+ LOG(" %i-%i: %P==%P", _count, i, MM_GetPhysAddr(dest+i), destphys+i*sizeof(tUHCI_QH));
dest[i].Next = destphys + (_count + i/2) * sizeof(tUHCI_QH) + 2;
dest[i].Child = 1;
}
PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 );
// Enable processing
+ LOG("Processing enabling");
_OutWord( Host, USBCMD, 0x0001 );
LEAVE('i', 0);
TD->Control |= (TD->Token >> 21) & 0x7FF;
// Stop controller
+ tPAddr tdaddr = MM_GetPhysAddr( TD );
+ ASSERT(tdaddr);
_OutWord( Cont, USBCMD, 0x0000 );
// Add
TD->Link = 1;
if( QH->Child & 1 ) {
- QH->Child = MM_GetPhysAddr( TD );
+ QH->Child = tdaddr;
}
else {
// Depth first
- QH->_LastItem->Link = MM_GetPhysAddr( TD ) | 4;
+ QH->_LastItem->Link = tdaddr | 4;
}
QH->_LastItem = TD;
void *InData, size_t InLength
)
{
- ENTER("pPtr pEndpt ibOutbound", Ptr, Endpt, bOutbound);
+ ENTER("pPtr pEndpt bOutbound", Ptr, Endpt, bOutbound);
tUHCI_Controller *Cont = Ptr;
tUHCI_QH *qh = &Cont->TDQHPage->ControlQH;
// Update toggle value
epi->Tgl = tgl;
-
+
+ // --- HACK!!!
+// for( int i = 0; i < 1024; i ++ )
+// {
+// LOG("- FrameList[%i] = %x", i, Cont->FrameList[i]);
+// }
+ // --- /HACK
+
LEAVE('p', td);
return td;
}
int dest, tgl;
size_t mps;
- ENTER("pPtr pEndpt pCb pCbData bOutbound pData iLength", Ptr, Dest, Cb, CbData, bOutbound, Data, Length);
+ ENTER("pPtr pEndpt pCb pCbData bOutbound pData iLength", Ptr, Endpt, Cb, CbData, bOutbound, Data, Length);
if( Endpt == NULL ) {
Log_Error("UHCI", "_SendBulk passed a NULL endpoint handle");
continue ;
}
- LOG("Removed %p from QH %p", td, QH);
+ LOG("Removed %p from QH %p", td, QH);
+ ASSERT(td->Link);
if( !prev )
QH->Child = td->Link;
// USB Error Interrupt
if( status & 2 )
{
-
+ Log_Notice("UHCI", "USB Error");
}
// Resume Detect
// - Fired if in suspend state and a USB device sends the RESUME signal
if( status & 4 )
{
-
+ Log_Notice("UHCI", "Resume Detect");
}
// Host System Error
if( status & 8 )
{
-
+ Log_Notice("UHCI", "Host System Error");
}
// Host Controller Process Error
if( status & 0x10 )
{
Log_Error("UHCI", "Host controller process error on controller %p", Ptr);
+ // Spam Tree
+ //for( int i = 0; i < 1024; i += 4 ) {
+ // LOG("%4i: %x", i, Host->FrameList[i]);
+ //}
+
+ tPAddr phys = Host->TDQHPage->ControlQH.Child;
+ while( !(phys & 1) && MM_GetRefCount(phys & ~15))
+ {
+ tUHCI_TD *td = UHCI_int_GetTDFromPhys(Host, phys);
+ LOG("%08P: %08x %08x %08x", phys, td->Control, td->Token, td->BufferPointer);
+ phys = td->Link;
+ }
}
_OutWord(Host, USBSTS, status);
SUBMAKE = $(MAKE) --no-print-directory
-USRLIBS := crt0.o acess.ld ld-acess.so libgcc.so libc.so
+USRLIBS := crt0.o acess.ld ld-acess.so libc.so
USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
USRLIBS += libimage_sif.so
USRAPPS := init login CLIShell cat ls mount
USRAPPS += bomb lspci
USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3
+USRAPPS += axwin3 gui_ate
ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
ALL_MODULES := $(addprefix all-,$(MODULES))
AI_USRAPPS := $(addprefix allinstall-,$(USRAPPS))
.PHONY: all clean install \
+ kmode all-kmode clean-kmode \
+ all-user clean-user \
$(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \
$(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) \
$(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \
kmode: $(AI_MODULES) $(AI_DYNMODS) allinstall-Kernel
all-kmode: $(ALL_MODULES) $(ALL_DYNMODS) all-Kernel
+clean-kmode: $(CLEAN_MODULES) $(CLEAN_DYNMODS) clean-Kernel
all-user: $(ALL_USRLIBS) $(ALL_USRAPPS)
clean-user: $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
_kfile="KernelLand/Acess2.$1-$2.bin"
fi
BOOTOPT="-kernel $_kfile"
- BOOTOPT=$BOOTOPT" -initrd KernelLand/Modules/Filesystems/FS_InitRD.kmd.$1 -append $3"
+ BOOTOPT=$BOOTOPT" -initrd KernelLand/Modules/Filesystems/FS_InitRD.kmd.$1 -append \"$3\""
shift
shift
;;
if [ "x$_NOUSB" != "xyes" ] ; then
QEMU_PARAMS=$QEMU_PARAMS" -usb"
- QEMU_PARAMS=$QEMU_PARAMS" -device usb-ehci"
+# QEMU_PARAMS=$QEMU_PARAMS" -device usb-ehci"
QEMU_PARAMS=$QEMU_PARAMS" -drive id=test_usb_image,file=USB_Test_Image.img,if=none"
QEMU_PARAMS=$QEMU_PARAMS" -device usb-storage,drive=test_usb_image"
QEMU_PARAMS=$QEMU_PARAMS" -usbdevice mouse"
exit
fi
-$QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
+eval $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
void create_mainmenu(void);
void create_run_dialog(void);
void mainmenu_run_dialog(void *unused);
+void mainmenu_app_terminal(void *unused);
+void mainmenu_app_textedit(void *unused);
// === GLOBALS ===
tHWND gSidebar;
tAxWin3_Widget *gRunInput;
int giScreenWidth;
int giScreenHeight;
+char **gEnvion;
// === CODE ===
int systembutton_fire(tAxWin3_Widget *Widget)
return 0;
}
-int main(int argc, char *argv[])
+int main(int argc, char *argv[], char **envp)
{
+ gEnvion = envp;
// Connect to AxWin3 Server
AxWin3_Connect(NULL);
create_run_dialog();
AxWin3_RegisterAction(gSidebar, "Interface>Run", (tAxWin3_HotkeyCallback)mainmenu_run_dialog);
-// AxWin3_RegisterAction(gSidebar, "Interface>Terminal", mainmenu_app_terminal);
-// AxWin3_RegisterAction(gSidebar, "Interface>TextEdit", mainmenu_app_textedit);
+ AxWin3_RegisterAction(gSidebar, "Interface>Terminal", (tAxWin3_HotkeyCallback)mainmenu_app_terminal);
+ AxWin3_RegisterAction(gSidebar, "Interface>TextEdit", (tAxWin3_HotkeyCallback)mainmenu_app_textedit);
// Idle loop
AxWin3_MainLoop();
void mainmenu_app_textedit(void *unused)
{
- _SysDebug("TODO: Launch text editor");
+ const char *args[] = {"ate",NULL};
+// _SysDebug("TODO: Launch text editor");
+ _SysSpawn("/Acess/Apps/AxWin/3.0/ate", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_app_terminal(void *unused)
OBJ := main.o input.o video.o ipc.o image.o utf-8.o
OBJ += wm.o wm_input.o wm_render.o wm_render_text.o wm_hotkeys.o
OBJ += decorator.o
-OBJ += renderers/passthru.o
+OBJ += renderers/framebuffer.o
OBJ += renderers/background.o
OBJ += renderers/menu.o
+OBJ += renderers/richtext.o
# TODO: Move to a lower makefile
OBJ += renderers/widget.o
OBJ += renderers/widget/button.o
OBJ += renderers/widget/disptext.o
OBJ += renderers/widget/textinput.o
OBJ += renderers/widget/spacer.o
+OBJ += renderers/widget/subwin.o
LDFLAGS += -limage_sif -luri -lnet
#define WINFLAG_NODECORATE 0x00000002
//! Window takes up all of screen
#define WINFLAG_MAXIMIZED 0x00000004
+//! Window is contained within the parent
+#define WINFLAG_RELATIVE 0x00000008
//! Window contents are valid
#define WINFLAG_CLEAN 0x00000040
//! All child windows are un-changed
// === FUNCTIONS ===
// --- Management
extern tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int Flags, const char *Renderer);
+extern tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID);
extern void WM_Invalidate(tWindow *Window);
extern void WM_SetWindowTitle(tWindow *Window, const char *Title);
extern void WM_FocusWindow(tWindow *Destination);
extern void WM_RaiseWindow(tWindow *Window);
extern void WM_ShowWindow(tWindow *Window, int bShow);
extern void WM_DecorateWindow(tWindow *Window, int bDecorate);
+extern void WM_SetRelative(tWindow *Window, int bRelativeToParent);
extern int WM_ResizeWindow(tWindow *Window, int W, int H);
extern int WM_MoveWindow(tWindow *Window, int X, int Y);
extern int WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Length, const void *Data);
// Position and dimensions
int X, Y;
- int RealW, RealH;
int W, H;
+ int RealX, RealY;
+ int RealW, RealH;
void *RenderBuffer; //!< Cached copy of the rendered window
};
* \return Boolean failure (0: Handled, 1: Unhandled)
*/
int (*HandleMessage)(tWindow *Window, int MessageID, int Length, const void *Data);
+
+ int nIPCHandlers;
+
+ /**
+ * \brief IPC Message handler
+ */
+ int (*IPCHandlers[])(tWindow *Window, size_t Length, const void *Data);
};
extern void WM_RegisterRenderer(tWMRenderer *Renderer);
extern tWindow *WM_CreateWindowStruct(size_t ExtraBytes);
+extern int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Data);
#endif
#include <stdio.h>
#include <wm.h>
#include <wm_internals.h>
-#include <wm_hotkeys.h>
+#include <wm_hotkeys.h> // Hotkey registration
+#include <wm_renderer.h> // Renderer IPC messages
#define AXWIN_PORT 4101
return NULL;
if( WindowID >= Client->nWindows ) {
-// _SysDebug("Window %i out of range for %p (%i)", WindowID, Client, Client->nWindows);
return NULL;
}
tIPC_Client *client;
int rv = 0;
- _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
- IPCType, Ident, MsgLen, Msg);
+// _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
+// IPCType, Ident, MsgLen, Msg);
if( MsgLen < sizeof(tAxWin_IPCMessage) )
return ;
return ;
client = IPC_int_GetClient(IPCType, Ident);
-
- if( Msg->ID >= giIPC_NumMessageHandlers ) {
- fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
- _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
- return ;
+ if( !client ) {
+ // Oops?
}
- if( !gIPC_MessageHandlers[ Msg->ID ] ) {
- fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
- _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
- return ;
+ if( Msg->Flags & IPCMSG_FLAG_RENDERER )
+ {
+ tWindow *win = IPC_int_GetWindow(client, Msg->Window);
+ if( !win ) {
+ _SysDebug("WARNING: NULL window in message %i", Msg->ID);
+ return ;
+ }
+ tWMRenderer *renderer = win->Renderer;
+ if( Msg->ID >= renderer->nIPCHandlers ) {
+ _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name);
+ return ;
+ }
+ if( !renderer->IPCHandlers[Msg->ID] ) {
+ _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name);
+ return ;
+ }
+ _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID);
+ rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data);
+ if( rv )
+ _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
+ }
+ else
+ {
+ if( Msg->ID >= giIPC_NumMessageHandlers ) {
+ fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
+ _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
+ return ;
+ }
+
+ if( !gIPC_MessageHandlers[ Msg->ID ] ) {
+ fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
+ _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
+ return ;
+ }
+
+ _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
+ rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
+ if( rv )
+ _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
}
-
- _SysDebug("IPC_Handle: Msg->ID = %i", Msg->ID);
- rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
- _SysDebug("IPC_Handle: rv = %i", rv);
}
-// --- Server->Client replies
+// Dispatch a message to the client
void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int MsgID, int Len, void *Data)
{
tAxWin_IPCMessage *hdr;
Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
}
+// --- Server->Client replies
+void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data)
+{
+ tAxWin_IPCMessage *hdr;
+ char buf[sizeof(*hdr)+Len];
+
+ hdr = (void*)buf;
+
+ hdr->ID = MsgID;
+ hdr->Flags = IPCMSG_FLAG_RENDERER;
+ hdr->Size = Len;
+ hdr->Window = WinID;
+
+ memcpy(hdr->Data, Data, Len);
+ Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
+}
+
extern int Renderer_Widget_Init(void);
extern int Renderer_Background_Init(void);
extern int Renderer_Framebuffer_Init(void);
+extern int Renderer_RichText_Init(void);
extern void WM_Update(void);
extern void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName);
*/
int main(int argc, char *argv[])
{
- int server_tid = gettid();
-
ParseCommandline(argc, argv);
if( gsTerminalDevice == NULL ) {
Renderer_Widget_Init();
Renderer_Background_Init();
Renderer_Framebuffer_Init();
+ Renderer_RichText_Init();
WM_Initialise();
// TODO: Config
WM_Hotkey_Register(2, keys, "Interface>Run");
// Spawn interface root
- if( clone(CLONE_VM, 0) == 0 )
{
+ int server_tid = gettid();
+ _SysDebug("server_tid = %i", server_tid);
static char csInterfaceApp[] = __INSTALL_ROOT"/AxWinUI";
char server_info[] = "AXWIN3_SERVER=00000";
- char *envp[] = {server_info, NULL};
- char *argv[] = {csInterfaceApp, NULL};
+ const char *envp[] = {server_info, NULL};
+ const char *argv[] = {csInterfaceApp, NULL};
_SysDebug("server_tid = %i, &server_tid = %p", server_tid, &server_tid);
sprintf(server_info, "AXWIN3_SERVER=%i", server_tid);
- execve(csInterfaceApp, argv, envp);
- exit(1);
+ // TODO: Does the client need FDs?
+ int rv = _SysSpawn(csInterfaceApp, argv, envp, 0, NULL, NULL);
+ if( rv ) {
+ _SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
+ }
}
// Main Loop
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer_passthru.c
+ * - Passthrough window render (framebuffer essentially)
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <string.h>
+#include <framebuffer_messages.h>
+#include <wm_messages.h>
+
+// === TYPES ===
+typedef struct
+{
+ short W, H;
+ void *Data;
+ char _data[];
+} tFBBuffer;
+typedef struct
+{
+ tFBBuffer BackBuffer;
+ int MaxBufferCount;
+ tFBBuffer *Buffers[];
+} tFBWin;
+
+// === PROTOTYPES ===
+tWindow *Renderer_Framebuffer_Create(int Flags);
+void Renderer_Framebuffer_Redraw(tWindow *Window);
+ int _Handle_Commit(tWindow *Target, size_t Len, const void *Data);
+ int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data);
+ int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer gRenderer_Framebuffer = {
+ .Name = "FrameBuffer",
+ .CreateWindow = Renderer_Framebuffer_Create,
+ .Redraw = Renderer_Framebuffer_Redraw,
+ .HandleMessage = Renderer_Framebuffer_HandleMessage,
+ .nIPCHandlers = N_IPC_FB,
+ .IPCHandlers = {
+ [IPC_FB_COMMIT] = _Handle_Commit,
+ [IPC_FB_NEWBUF] = _Handle_CreateBuf,
+ }
+};
+
+// === CODE ===
+int Renderer_Framebuffer_Init(void)
+{
+ WM_RegisterRenderer(&gRenderer_Framebuffer);
+ return 0;
+}
+
+tWindow *Renderer_Framebuffer_Create(int Flags)
+{
+ tWindow *ret;
+ tFBWin *info;
+ const int max_buffers = 10; // TODO: Have this be configurable
+
+ ret = WM_CreateWindowStruct( sizeof(*info) + max_buffers*sizeof(tFBBuffer*) );
+ info = ret->RendererInfo;
+
+ info->BackBuffer.W = 0;
+ info->BackBuffer.H = 0;
+ info->BackBuffer.Data = NULL;
+ info->MaxBufferCount = max_buffers;
+ memset( info->Buffers, 0, sizeof(tFBBuffer*) * max_buffers );
+
+ return ret;
+}
+
+void Renderer_Framebuffer_Redraw(tWindow *Window)
+{
+
+}
+
+// --- ---
+tFBBuffer *_GetBuffer(tWindow *Win, uint16_t ID)
+{
+ tFBWin *info = Win->RendererInfo;
+ if( ID == 0xFFFF )
+ return &info->BackBuffer;
+ else if( ID >= info->MaxBufferCount )
+ return NULL;
+ else
+ return info->Buffers[ ID ];
+}
+
+void _Blit(
+ tFBBuffer *Dest, uint16_t DX, uint16_t DY,
+ const tFBBuffer *Src, uint16_t SX, uint16_t SY,
+ uint16_t W, uint16_t H
+ )
+{
+ uint32_t *dest_data = Dest->Data;
+ const uint32_t *src_data = Src->Data;
+ // First, some sanity
+ if( DX > Dest->W ) return ;
+ if( DY > Dest->H ) return ;
+ if( SX > Src->W ) return ;
+ if( SY > Src->H ) return ;
+
+ if( DX + W > Dest->W ) W = Dest->W - DX;
+ if( SX + W > Src->W ) W = Src->W - SX;
+ if( DY + H > Dest->H ) H = Dest->H - DY;
+ if( SY + H > Src->H ) H = Src->H - SY;
+
+ dest_data += (DY * Dest->W) + DX;
+ src_data += (SY * Src->W ) + SX;
+ for( int i = 0; i < H; i ++ )
+ {
+ memcpy( dest_data, src_data, W * 4 );
+ dest_data += Dest->W;
+ src_data += Src->W;
+ }
+}
+
+void _Fill(tFBBuffer *Buf, uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint32_t Colour)
+{
+ uint32_t *data = Buf->Data;
+
+ if( X > Buf->W ) return ;
+ if( Y > Buf->H ) return ;
+ if( X + W > Buf->W ) W = Buf->W - X;
+ if( Y + H > Buf->H ) H = Buf->H - Y;
+
+ data += (Y * Buf->W) + X;
+ for( int i = 0; i < H; i ++ )
+ {
+ for( int j = 0; j < W; j ++ )
+ *data++ = Colour;
+ data += Buf->W - W;
+ }
+}
+
+// --- ---
+int _Handle_Commit(tWindow *Target, size_t Len, const void *Data)
+{
+ // Do a window invalidate
+ return 0;
+}
+
+int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_NewBuf *msg = Data;
+ tFBBuffer *buf;
+ tFBWin *info = Target->RendererInfo;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ if( msg->Buffer == -1 || msg->Buffer >= info->MaxBufferCount ) {
+ // Can't reallocate -1
+ return 1;
+ }
+
+ if( info->Buffers[msg->Buffer] ) {
+ free(info->Buffers[msg->Buffer]);
+ info->Buffers[msg->Buffer] = NULL;
+ }
+
+ buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
+ buf->W = msg->W;
+ buf->H = msg->H;
+ buf->Data = buf->_data;
+
+ info->Buffers[msg->Buffer] = buf;
+
+ return 0;
+}
+
+int _Handle_Upload(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Transfer *msg = Data;
+ tFBBuffer *dest, src;
+
+ if( Len < sizeof(*msg) ) return -1;
+ if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return -1;
+
+ dest = _GetBuffer(Target, msg->Buffer);
+
+ src.W = msg->W;
+ src.H = msg->H;
+ src.Data = (void*)msg->ImageData;
+
+ _Blit( dest, msg->X, msg->Y, &src, 0, 0, msg->W, msg->H );
+ return 0;
+}
+
+int _Handle_Download(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Transfer *msg = Data;
+ tFBBuffer dest, *src;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ src = _GetBuffer(Target, msg->Buffer);
+
+ tFBIPC_Transfer *ret;
+ int retlen = sizeof(*ret) + msg->W*msg->H*4;
+ ret = malloc( retlen );
+
+ dest.W = ret->W = msg->W;
+ dest.H = ret->H = msg->H;
+ dest.Data = ret->ImageData;
+
+ _Blit( &dest, 0, 0, src, msg->X, msg->Y, msg->W, msg->H );
+
+ WM_SendIPCReply(Target, IPC_FB_DOWNLOAD, retlen, ret);
+
+ free(ret);
+
+ return 0;
+}
+
+int _Handle_LocalBlit(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Blit *msg = Data;
+ tFBBuffer *dest, *src;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ src = _GetBuffer(Target, msg->Source);
+ dest = _GetBuffer(Target, msg->Dest);
+
+ _Blit( dest, msg->DstX, msg->DstY, src, msg->SrcX, msg->SrcY, msg->W, msg->H );
+ return 0;
+}
+
+int _Handle_FillRect(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Fill *msg = Data;
+ tFBBuffer *dest;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ dest = _GetBuffer(Target, msg->Buffer);
+
+ _Fill( dest, msg->X, msg->Y, msg->W, msg->H, msg->Colour );
+ return 0;
+}
+
+int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+ switch(Msg)
+ {
+ case WNDMSG_RESIZE:
+ // Resize the framebuffer
+ return 1; // Pass on
+
+ // Messages that get passed on
+ case WNDMSG_MOUSEBTN:
+ return 1;
+ }
+ return 1;
+}
+
+
void Renderer_Menu_Init(void);
tWindow *Renderer_Menu_Create(int Argument);
void Renderer_Menu_Redraw(tWindow *Window);
+ int Renderer_Menu_HandleIPC_AddItem(tWindow *Window, size_t Length, const void *Data);
+ int Renderer_Menu_HandleIPC_SetFlags(tWindow *Window, size_t Length, const void *Data);
int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, const void *Data);
// === CONSTANTS ===
.Name = "Menu",
.CreateWindow = Renderer_Menu_Create,
.Redraw = Renderer_Menu_Redraw,
- .HandleMessage = Renderer_Menu_HandleMessage
+ .HandleMessage = Renderer_Menu_HandleMessage,
+ .nIPCHandlers = 2,
+ .IPCHandlers = {
+ Renderer_Menu_HandleIPC_AddItem,
+// Renderer_Menu_HandleIPC_SetFlags
+ }
};
tFont *gMenu_Font = NULL; // System monospace
}
}
-int Renderer_Menu_int_AddItem(tWindow *Window, int Length, const tMenuMsg_AddItem *Msg)
+int Renderer_Menu_HandleIPC_AddItem(tWindow *Window, size_t Length, const void *Data)
{
+ const tMenuIPC_AddItem *Msg = Data;
tMenuWindowInfo *info = Window->RendererInfo;
tMenuItem *item;
return 0; }
- // Manipulation messages
- case MSG_MENU_ADDITEM:
-// _SysDebug("MSG_MENU_ADDITEM");
- return Renderer_Menu_int_AddItem(Window, Length, Data);
-
// Only message to pass to client
case MSG_MENU_SELECT:
return 1;
+++ /dev/null
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * renderer_passthru.c
- * - Passthrough window render (framebuffer essentially)
- */
-#include <common.h>
-#include <wm_renderer.h>
-#include <string.h>
-#include <framebuffer_messages.h>
-#include <wm_messages.h>
-
-// === TYPES ===
-typedef struct
-{
- short W, H;
- void *Data;
- char _data[];
-} tFBBuffer;
-typedef struct
-{
- tFBBuffer BackBuffer;
- int MaxBufferCount;
- tFBBuffer *Buffers[];
-} tFBWin;
-
-// === PROTOTYPES ===
-tWindow *Renderer_Framebuffer_Create(int Flags);
-void Renderer_Framebuffer_Redraw(tWindow *Window);
- int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
-
-// === GLOBALS ===
-tWMRenderer gRenderer_Framebuffer = {
- .Name = "FrameBuffer",
- .CreateWindow = Renderer_Framebuffer_Create,
- .Redraw = Renderer_Framebuffer_Redraw,
- .HandleMessage = Renderer_Framebuffer_HandleMessage
-};
-
-// === CODE ===
-int Renderer_Framebuffer_Init(void)
-{
- WM_RegisterRenderer(&gRenderer_Framebuffer);
- return 0;
-}
-
-tWindow *Renderer_Framebuffer_Create(int Flags)
-{
- tWindow *ret;
- tFBWin *info;
- const int max_buffers = 10; // TODO: Have this be configurable
-
- ret = WM_CreateWindowStruct( sizeof(*info) + max_buffers*sizeof(tFBBuffer*) );
- info = ret->RendererInfo;
-
- info->BackBuffer.W = 0;
- info->BackBuffer.H = 0;
- info->BackBuffer.Data = NULL;
- info->MaxBufferCount = max_buffers;
- memset( info->Buffers, 0, sizeof(tFBBuffer*) * max_buffers );
-
- return ret;
-}
-
-void Renderer_Framebuffer_Redraw(tWindow *Window)
-{
-
-}
-
-// --- ---
-tFBBuffer *_GetBuffer(tWindow *Win, uint16_t ID)
-{
- tFBWin *info = Win->RendererInfo;
- if( ID == 0xFFFF )
- return &info->BackBuffer;
- else if( ID >= info->MaxBufferCount )
- return NULL;
- else
- return info->Buffers[ ID ];
-}
-
-void _Blit(
- tFBBuffer *Dest, uint16_t DX, uint16_t DY,
- const tFBBuffer *Src, uint16_t SX, uint16_t SY,
- uint16_t W, uint16_t H
- )
-{
- uint32_t *dest_data = Dest->Data;
- const uint32_t *src_data = Src->Data;
- // First, some sanity
- if( DX > Dest->W ) return ;
- if( DY > Dest->H ) return ;
- if( SX > Src->W ) return ;
- if( SY > Src->H ) return ;
-
- if( DX + W > Dest->W ) W = Dest->W - DX;
- if( SX + W > Src->W ) W = Src->W - SX;
- if( DY + H > Dest->H ) H = Dest->H - DY;
- if( SY + H > Src->H ) H = Src->H - SY;
-
- dest_data += (DY * Dest->W) + DX;
- src_data += (SY * Src->W ) + SX;
- for( int i = 0; i < H; i ++ )
- {
- memcpy( dest_data, src_data, W * 4 );
- dest_data += Dest->W;
- src_data += Src->W;
- }
-}
-
-void _Fill(tFBBuffer *Buf, uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint32_t Colour)
-{
- uint32_t *data = Buf->Data;
-
- if( X > Buf->W ) return ;
- if( Y > Buf->H ) return ;
- if( X + W > Buf->W ) W = Buf->W - X;
- if( Y + H > Buf->H ) H = Buf->H - Y;
-
- data += (Y * Buf->W) + X;
- for( int i = 0; i < H; i ++ )
- {
- for( int j = 0; j < W; j ++ )
- *data++ = Colour;
- data += Buf->W - W;
- }
-}
-
-// --- ---
-void _Handle_Commit(tWindow *Target, size_t Len, const void *Data)
-{
- // Do a window invalidate
-}
-
-void _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_NewBuf *msg = Data;
- tFBBuffer *buf;
- tFBWin *info = Target->RendererInfo;
-
- if( Len < sizeof(*msg) ) return ;
-
- if( msg->Buffer == -1 || msg->Buffer >= info->MaxBufferCount ) {
- // Can't reallocate -1
- return ;
- }
-
- if( info->Buffers[msg->Buffer] ) {
- free(info->Buffers[msg->Buffer]);
- info->Buffers[msg->Buffer] = NULL;
- }
-
- buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
- buf->W = msg->W;
- buf->H = msg->H;
- buf->Data = buf->_data;
-
- info->Buffers[msg->Buffer] = buf;
-}
-
-void _Handle_Upload(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Transfer *msg = Data;
- tFBBuffer *dest, src;
-
- if( Len < sizeof(*msg) ) return ;
- if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return ;
-
- dest = _GetBuffer(Target, msg->Buffer);
-
- src.W = msg->W;
- src.H = msg->H;
- src.Data = (void*)msg->ImageData;
-
- _Blit( dest, msg->X, msg->Y, &src, 0, 0, msg->W, msg->H );
-}
-
-void _Handle_Download(tWindow *Target, size_t Len, const void *Data)
-{
- #if 0
- const tFBMsg_Transfer *msg = Data;
- tFBBuffer dest, *src;
-
- if( Len < sizeof(*msg) ) return ;
- if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return ;
-
- src = _GetBuffer(Target, msg->Buffer);
-
- dest.W = msg->W;
- dest.H = msg->H;
- dest.Data = msg->ImageData;
-
- _Blit( &dest, 0, 0, src, msg->X, msg->Y, msg->W, msg->H );
- #endif
-}
-
-void _Handle_LocalBlit(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Blit *msg = Data;
- tFBBuffer *dest, *src;
-
- if( Len < sizeof(*msg) ) return ;
-
- src = _GetBuffer(Target, msg->Source);
- dest = _GetBuffer(Target, msg->Dest);
-
- _Blit( dest, msg->DstX, msg->DstY, src, msg->SrcX, msg->SrcY, msg->W, msg->H );
-}
-
-void _Handle_FillRect(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Fill *msg = Data;
- tFBBuffer *dest;
-
- if( Len < sizeof(*msg) ) return ;
-
- dest = _GetBuffer(Target, msg->Buffer);
-
- _Fill( dest, msg->X, msg->Y, msg->W, msg->H, msg->Colour );
-}
-
-int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
-{
- switch(Msg)
- {
- case WNDMSG_RESIZE:
- // Resize the framebuffer
- return 1; // Pass on
-
- // Messages that get passed on
- case WNDMSG_MOUSEBTN:
- return 1;
-
- // --- Local messages ---
- // - Drawing completed, do an update
- case MSG_FB_COMMIT:
- _Handle_Commit(Target, Len, Data);
- return 0;
- // - New Buffer (create a new server-side buffer)
- case MSG_FB_NEWBUF:
- _Handle_CreateBuf(Target, Len, Data);
- return 0;
- // - Upload (Transfer data from client to server)
- case MSG_FB_UPLOAD:
- _Handle_Upload(Target, Len, Data);
- return 0;
- // - Download (Transfer image data from server to client)
- case MSG_FB_DOWNLOAD:
- _Handle_Download(Target, Len, Data);
- return 0;
- // - Local Blit (Transfer from server to server)
- case MSG_FB_BLIT:
- _Handle_LocalBlit(Target, Len, Data);
- return 0;
- // - Fill a rectangle
- case MSG_FB_FILL:
- _Handle_FillRect(Target, Len, Data);
- return 0;
- }
- return 1;
-}
-
-
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render/richtext.c
+ * - Formatted Line Editor
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <wm_messages.h>
+#include <richtext_messages.h>
+#include <stdio.h> // sscanf
+#include <string.h> // memcpy
+
+#define LINES_PER_BLOCK 30
+
+// === TYPES ===
+typedef struct sRichText_Line
+{
+ struct sRichText_Line *Next;
+ struct sRichText_Line *Prev;
+ int Num;
+ // TODO: Pre-rendered cache?
+ short ByteLength;
+ short Space;
+ char Data[];
+} tRichText_Line;
+typedef struct sRichText_Window
+{
+ int DispLines, DispCols;
+ int FirstVisRow, FirstVisCol;
+ int nLines, nCols;
+ int CursorRow, CursorCol;
+ tRichText_Line *FirstLine;
+ tRichText_Line *FirstVisLine;
+ tColour DefaultFG;
+ tColour DefaultBG;
+ tFont *Font;
+
+ short LineHeight;
+} tRichText_Window;
+
+// === PROTOTYPES ===
+ int Renderer_RichText_Init(void);
+tWindow *Renderer_RichText_Create(int Flags);
+void Renderer_RichText_Redraw(tWindow *Window);
+ int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data);
+ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data);
+ int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer gRenderer_RichText = {
+ .Name = "RichText",
+ .CreateWindow = Renderer_RichText_Create,
+ .Redraw = Renderer_RichText_Redraw,
+ .HandleMessage = Renderer_RichText_HandleMessage,
+ .nIPCHandlers = N_IPC_RICHTEXT,
+ .IPCHandlers = {
+ [IPC_RICHTEXT_SETATTR] = Renderer_RichText_HandleIPC_SetAttr,
+ [IPC_RICHTEXT_WRITELINE] = Renderer_RichText_HandleIPC_WriteLine
+ }
+};
+
+// === CODE ===
+int Renderer_RichText_Init(void)
+{
+ WM_RegisterRenderer(&gRenderer_RichText);
+ return 0;
+}
+
+tWindow *Renderer_RichText_Create(int Flags)
+{
+ tRichText_Window *info;
+ tWindow *ret = WM_CreateWindowStruct( sizeof(*info) );
+ if(!ret) return NULL;
+ info = ret->RendererInfo;
+
+ // Initialise font (get an idea of dimensions)
+ int h;
+ WM_Render_GetTextDims(NULL, "yY!", 3, NULL, &h);
+ info->LineHeight = h;
+
+ return ret;
+}
+
+static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Window *info, int X, int Row, const char *Text, int Bytes, tColour FG, tColour BG, int Flags)
+{
+ int rwidth;
+ // TODO: Fill only what is needed? What about the rest of the line?
+ WM_Render_DrawRect(Window, X, Row*info->LineHeight,
+ Window->W - X, info->LineHeight,
+ BG
+ );
+ // TODO: Bold, Italic, Underline
+ rwidth = WM_Render_DrawText(Window,
+ X, Row*info->LineHeight,
+ Window->W - X, info->LineHeight,
+ info->Font, FG,
+ Text, Bytes
+ );
+ return rwidth;
+}
+
+void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ tColour fg = info->DefaultFG;
+ tColour bg = info->DefaultBG;
+ int flagset = 0;
+ int bRender = 0;
+ int curx = 0;
+ const char *oldtext = Text;
+
+ for( int i = 0; curx < Window->W; i ++ )
+ {
+ char ch, flags;
+ int len;
+
+ if( i == info->FirstVisCol )
+ bRender = 1;
+
+ ch = *Text++;
+ if( ch == 0 ) break;
+
+ // Not an escape - move along
+ if( ch > 4 )
+ continue ;
+
+ if( bRender ) {
+ // Render previous characters
+ curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line,
+ oldtext, Text - oldtext - 1, fg, bg, flagset);
+ if( curx >= Window->W )
+ break;
+ }
+ oldtext = Text;
+ switch(ch)
+ {
+ case 1: // FG Select (\1 RRGGBB)
+ if( sscanf(Text, "%6x%n", &fg, &len) != 1 || len != 6 ) {
+ // Bad client
+ _SysDebug("foreground scanf failed - len=%i", len);
+ len = 0;
+ }
+ Text += len;
+ oldtext = Text;
+ _SysDebug("FG update to %x", fg);
+ break ;
+ case 2: // BG Select (\2 RRGGBB)
+ if( sscanf(Text, "%6x%n", &bg, &len) != 1 || len != 6 ) {
+ // Bad client
+ _SysDebug("background scanf failed - len=%i", len);
+ len = 0;
+ }
+ Text += len;
+ oldtext = Text;
+ _SysDebug("BG update to %x", bg);
+ break ;
+ case 3: // Flagset (0,it,uline,bold)
+ if( sscanf(Text, "%1hhx%n", &flags, &len) != 1 || len != 1 ) {
+ // Bad client
+ _SysDebug("Flagset scanf failed - len=%i", len);
+ }
+ flagset = flags & 7;
+ Text += len;
+ oldtext = Text;
+ break ;
+ case 4: // Escape (do nothing)
+ Text ++;
+ // NOTE: No update to oldtext
+ break;
+ default: // Error.
+ break;
+ }
+ }
+ curx += Renderer_RichText_RenderText_Act(Window, info, curx,
+ Line, oldtext, Text - oldtext + 1, fg, bg, flagset);
+ WM_Render_DrawRect(Window, curx, Line * info->LineHeight,
+ Window->W - curx, info->LineHeight, info->DefaultBG);
+}
+
+void Renderer_RichText_Redraw(tWindow *Window)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ int i;
+ tRichText_Line *line = info->FirstVisLine;
+
+ if( !line ) {
+ line = info->FirstLine;
+ while(line && line->Num < info->FirstVisRow )
+ line = line->Next;
+ info->FirstVisLine = line;
+ }
+ while( line && line->Prev && line->Prev->Num > info->FirstVisRow )
+ line = line->Prev;
+
+ for( i = 0; i < info->DispLines && line; i ++ )
+ {
+ if( i >= info->nLines - info->FirstVisRow )
+ break;
+ // TODO: Dirty rectangles?
+ WM_Render_FillRect(Window,
+ 0, i*info->LineHeight,
+ Window->W, info->LineHeight,
+ info->DefaultBG
+ );
+ if( line->Num > info->FirstVisRow + i )
+ continue ;
+ // TODO: Horizontal scrolling?
+ // TODO: Formatting
+
+ // Formatted text out
+ Renderer_RichText_RenderText(Window, i, line->Data);
+ _SysDebug("RichText: %p - Render %i '%.*s'", Window,
+ line->Num, line->ByteLength, line->Data);
+
+ line = line->Next;
+ }
+ // Clear out i -- info->DispLines
+ _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i",
+ Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight);
+ WM_Render_FillRect(Window,
+ 0, i*info->LineHeight,
+ Window->W, (info->DispLines-i)*info->LineHeight,
+ info->DefaultBG
+ );
+}
+
+int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ const struct sRichTextIPC_SetAttr *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ _SysDebug("RichText Attr %i set to %x", msg->Attr, msg->Value);
+ switch(msg->Attr)
+ {
+ case _ATTR_DEFBG:
+ info->DefaultBG = msg->Value;
+ break;
+ case _ATTR_DEFFG:
+ info->DefaultFG = msg->Value;
+ break;
+ case _ATTR_SCROLL:
+ // TODO: Set scroll flag
+ break;
+ case _ATTR_LINECOUNT:
+ info->nLines = msg->Value;
+ break;
+ }
+
+ return 0;
+}
+
+int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ const struct sRichTextIPC_WriteLine *msg = Data;
+ if( Len < sizeof(*msg) ) return -1;
+ if( msg->Line >= info->nLines ) return 1; // Bad count
+
+ tRichText_Line *line = info->FirstLine;
+ tRichText_Line *prev = NULL;
+ while(line && line->Num < msg->Line)
+ prev = line, line = line->Next;
+ if( !line || line->Num > msg->Line )
+ {
+ // New line!
+ // Round up to 32
+ int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
+ tRichText_Line *new = malloc(sizeof(*line) + space);
+ // TODO: Bookkeeping on how much memory each window uses
+ new->Next = line;
+ new->Prev = prev;
+ new->Num = msg->Line;
+ new->Space = space;
+ if(new->Prev) new->Prev->Next = new;
+ else info->FirstLine = new;
+ if(new->Next) new->Next->Prev = new;
+ line = new;
+ }
+ else if( line->Space < Len - sizeof(*msg) )
+ {
+ // Need to allocate more space
+ int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
+ tRichText_Line *new = realloc(line, space);
+ // TODO: Bookkeeping on how much memory each window uses
+ new->Space = space;
+
+ if(new->Prev) new->Prev->Next = new;
+ else info->FirstLine = new;
+ if(new->Next) new->Next->Prev = new;
+ line = new;
+ }
+ else
+ {
+ // It fits :)
+ }
+ line->ByteLength = Len - sizeof(*msg);
+ memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
+
+ return 0;
+}
+
+int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+ tRichText_Window *info = Target->RendererInfo;
+ switch(Msg)
+ {
+ case WNDMSG_RESIZE: {
+ const struct sWndMsg_Resize *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+ info->DispLines = msg->H / info->LineHeight;
+ return 1; }
+ }
+ return 0;
+}
void Widget_UpdatePosition(tElement *Element);
// --- Messages
tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg);
-void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg);
-void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg);
-void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg);
+ int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_Delete(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_SetColour(tWindow *Win, size_t Len, const void *Data);
int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
// === GLOBALS ===
.Name = "Widget",
.CreateWindow = Renderer_Widget_Create,
.Redraw = Renderer_Widget_Redraw,
- .HandleMessage = Renderer_Widget_HandleMessage
+ .HandleMessage = Renderer_Widget_HandleMessage,
+ .nIPCHandlers = N_IPC_WIDGET,
+ .IPCHandlers = {
+ [IPC_WIDGET_CREATE] = Widget_IPC_Create,
+ [IPC_WIDGET_CREATESUBWIN] = Widget_IPC_NewWidgetSubwin,
+ [IPC_WIDGET_SETFOCUS] = Widget_IPC_SetFocus,
+ [IPC_WIDGET_SETFLAGS] = Widget_IPC_SetFlags,
+ [IPC_WIDGET_SETSIZE] = Widget_IPC_SetSize,
+ [IPC_WIDGET_SETTEXT] = Widget_IPC_SetText,
+ [IPC_WIDGET_GETTEXT] = Widget_IPC_GetText,
+ }
};
// --- Element callbacks
tWidgetWin *info;
int eletable_size = DEFAULT_ELETABLE_SIZE;
- _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+ //_SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
// TODO: Use `Flags` as default element count?
// - Actaully, it's taken by the root ele flags
else
fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
- _SysDebug("%i (p=%i) - WxH=%ix%i",
- Element->ID, (Element->Parent ? Element->Parent->ID : -1),
- Element->CachedW, Element->CachedH
- );
- _SysDebug(" %s dynWith = %i, fullCross = %i",
- (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
- dynWith, fullCross
- );
+ //_SysDebug("%i (p=%i) - WxH=%ix%i",
+ // Element->ID, (Element->Parent ? Element->Parent->ID : -1),
+ // Element->CachedW, Element->CachedH
+ // );
+ //_SysDebug(" %s dynWith = %i, fullCross = %i",
+ // (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
+ // dynWith, fullCross
+ // );
// Pass 2 - Set sizes and recurse
for( child = Element->FirstChild; child; child = child->NextSibling )
return ele;
}
-// --- Message Handlers ---
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
+tElement *Widget_int_Create(tWidgetWin *Info, tElement *Parent, int ID, int Type, int Flags)
{
- const int max_debugname_len = Len - sizeof(tWidgetMsg_Create);
- tElement *parent, *new;
-
- // Sanity check
- if( Len < sizeof(*Msg) )
- return ;
- if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
- return ;
-
- _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
- Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
-
- if(Msg->Type >= ciWM_NumWidgetTypes)
- {
- _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
- return ;
- }
-
- // Create
- parent = Widget_GetElementById(Info, Msg->Parent);
- if(!parent)
- {
- _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
- return ;
- }
-
- // Check if the ID is already in use
- if( Widget_GetElementById(Info, Msg->NewID) )
- return ;
+ if( Widget_GetElementById(Info, ID) )
+ return NULL;
// Create new element
- new = calloc(sizeof(tElement), 1);
- new->Window = parent->Window;
- new->ID = Msg->NewID;
- new->Type = Msg->Type;
- new->Parent = parent;
- new->Flags = Msg->Flags;
+ tElement *new = calloc(sizeof(tElement), 1);
+ new->Window = Parent->Window;
+ new->ID = ID;
+ new->Type = Type;
+ new->Parent = Parent;
+ new->Flags = Flags;
new->PaddingT = 2;
new->PaddingB = 2;
new->PaddingL = 2;
new->PaddingR = 2;
new->CachedX = -1;
- if( gaWM_WidgetTypes[new->Type]->Init )
- gaWM_WidgetTypes[new->Type]->Init(new);
+ if( gaWM_WidgetTypes[Type]->Init )
+ gaWM_WidgetTypes[Type]->Init(new);
// Add to parent's list
- if(parent->LastChild)
- parent->LastChild->NextSibling = new;
+ if(Parent->LastChild)
+ Parent->LastChild->NextSibling = new;
else
- parent->FirstChild = new;
- parent->LastChild = new;
+ Parent->FirstChild = new;
+ Parent->LastChild = new;
// Add to info
{
else
Info->ElementTable[new->ID % Info->TableSize] = new;
}
-
- Widget_UpdateMinDims(parent);
+
+ return new;
}
void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
Info->FocusedElement = Ele;
}
-void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
+
+// --- Message Handlers ---
+int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_Create *Msg = Data;
+ const int max_debugname_len = Len - sizeof(*Msg);
+ tElement *parent;
+
+ // Sanity check
+ if( Len < sizeof(*Msg) )
+ return -1;
+ if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+ return -1;
+
+ _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
+ Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
+
+ if(Msg->Type >= ciWM_NumWidgetTypes)
+ {
+ _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
+ return 1;
+ }
+
+ // Create
+ parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent)
+ {
+ _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
+ return 1;
+ }
+
+ Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+
+ Widget_UpdateMinDims(parent);
+ return 0;
+}
+
+int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_CreateSubWin *Msg = Data;
+ const int max_debugname_len = Len - sizeof(*Msg);
+ tElement *parent, *new;
+
+ // Sanity check
+ if( Len < sizeof(*Msg) )
+ return -1;
+ if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+ return -1;
+
+ parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent) return 1;
+ if( Widget_GetElementById(Info, Msg->NewID) ) return 1;
+
+ new = Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+ new->Data = WM_GetWindowByID(parent->Window, Msg->WindowHandle);
+ Widget_UpdateMinDims(parent);
+ return 0;
+}
+
+// TODO: Widget_IPC_Delete
+
+int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *info = Win->RendererInfo;
+ tElement *ele;
+ const tWidgetIPC_SetFocus *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ ele = Widget_GetElementById(info, msg->WidgetID);
+ Widget_SetFocus(info, ele);
+ return 0;
+}
+
+int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetFlags *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) )
- return ;
+ return -1;
_SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return;
+ if(!ele) return 1;
ele->Flags &= ~Msg->Mask;
ele->Flags |= Msg->Value & Msg->Mask;
+
+ return 0;
}
-void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg)
+int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetSize *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) )
- return ;
+ return -1;
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return ;
+ if(!ele) return 1;
ele->FixedWith = Msg->Value;
+ return 0;
}
-void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetText *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) + 1 )
- return ;
+ return -1;
if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' )
- return ;
+ return -1;
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return ;
-
+ if(!ele) return 1;
if( gaWM_WidgetTypes[ele->Type]->UpdateText )
{
// if(ele->Text) free(ele->Text);
// ele->Text = strdup(Msg->Text);
// }
+ return 0;
}
-int Widget_GetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetText *Msg = Data;
if( Len < sizeof(*Msg) )
- return 0;
- if( Len > sizeof(*Msg) )
- return 1; // Pass to user
+ return -1;
const char *text = NULL;
tElement *ele = Widget_GetElementById(Info, Msg->WidgetID);
if(ele)
text = ele->Text;
- char buf[sizeof(tWidgetMsg_SetText) + strlen(text?text:"") + 1];
- tWidgetMsg_SetText *omsg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText) + strlen(text?text:"") + 1];
+ tWidgetIPC_SetText *omsg = (void*)buf;
if( text ) {
omsg->WidgetID = Msg->WidgetID;
omsg->Text[0] = 0;
}
- WM_SendMessage(Info->RootElement.Window, Info->RootElement.Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+ WM_SendIPCReply(Win, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
return 0;
}
}
return 0; }
- // New Widget
- case MSG_WIDGET_CREATE:
- Widget_NewWidget(info, Len, Data);
- return 0;
-
- // Delete a widget
- case MSG_WIDGET_DELETE:
- _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
- return 0;
-
- // Set focused widget
- case MSG_WIDGET_SETFOCUS: {
- tElement *ele;
- const tWidgetMsg_SetFocus *msg = Data;
- if(Len < sizeof(*msg)) return -1;
-
- ele = Widget_GetElementById(info, msg->WidgetID);
- Widget_SetFocus(info, ele);
- return 0; }
-
- // Set Flags
- case MSG_WIDGET_SETFLAGS:
- Widget_SetFlags(info, Len, Data);
- return 0;
-
- // Set length
- case MSG_WIDGET_SETSIZE:
- Widget_SetSize(info, Len, Data);
- return 0;
-
- // Set text
- case MSG_WIDGET_SETTEXT:
- Widget_SetText(info, Len, Data);
- return 0;
- case MSG_WIDGET_GETTEXT:
- return Widget_GetText(info, Len, Data);
-
//
default:
return 1; // Unhandled, pass to user
{
tWidgetMsg_Fire msg;
msg.WidgetID = Element->ID;
+ _SysDebug("Widget_Fire: Fire on %p %i", Element->Window, Element->ID);
WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
}
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer/widget/subwin.c
+ * - Embedded Window Widget Type
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+
+void Widget_SubWin_Render(tWindow *Window, tElement *Element)
+{
+ // Ensure that child window is positioned relative to this window
+ WM_SetRelative(Element->Data, 1);
+ // Note: Doesn't actually render, but does poke the child window
+ WM_MoveWindow(Element->Data, Element->CachedX, Element->CachedY);
+ WM_ResizeWindow(Element->Data, Element->CachedW, Element->CachedH);
+}
+
+DEFWIDGETTYPE(ELETYPE_SUBWIN,
+ WIDGETTYPE_FLAG_NOCHILDREN,
+ .Render = Widget_SubWin_Render
+ )
_SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
seek(giTerminalFD, ofs*4, 1);
- _SysDebug("Video_Update - Sending");
+ _SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4);
write(giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysDebug("Video_Update - Done");
giVideo_FirstDirtyLine = 0;
// TODO: Handle out of bounds by clipping too
if( DstX + W > giScreenWidth ) return;
if( DstY + H > giScreenHeight )
- H = giScreenWidth - DstY;
+ H = giScreenHeight - DstY;
if( W <= 0 || H <= 0 ) return;
// === IMPORTS ===
extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data);
+extern void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data);
+extern tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t ID);
// === GLOBALS ===
tWMRenderer *gpWM_Renderers;
return ret;
}
+tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID)
+{
+ return IPC_int_GetWindow(Requester->Client, ID);
+}
+
tWindow *WM_CreateWindowStruct(size_t ExtraSize)
{
tWindow *ret;
if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
return ;
- _msg.Val = 0;
- WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
- _msg.Val = 1;
- WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
-
+ if( gpWM_FocusedWindow )
+ {
+ _msg.Val = 0;
+ WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
+ }
+ if( Destination )
+ {
+ _msg.Val = 1;
+ WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
+ }
+
WM_Invalidate(gpWM_FocusedWindow);
WM_Invalidate(Destination);
gpWM_FocusedWindow = Destination;
WM_Invalidate(Window);
}
+void WM_SetRelative(tWindow *Window, int bRelativeToParent)
+{
+// _SysDebug("WM_SetRelative: (%p{Parent=%p},%i)", Window, Window->Parent, bRelativeToParent);
+ // No meaning if no parent
+ if( !Window->Parent )
+ return ;
+
+ // Check that the flag is changing
+ if( !!bRelativeToParent == !!(Window->Flags & WINFLAG_RELATIVE) )
+ return ;
+
+ if( bRelativeToParent ) {
+ // Set
+ Window->Flags |= WINFLAG_RELATIVE;
+ WM_MoveWindow(Window, Window->X, Window->Y);
+ }
+ else {
+ // Clear
+ Window->Flags &= ~WINFLAG_RELATIVE;
+ WM_MoveWindow(Window, Window->X - Window->Parent->X, Window->Y - Window->Parent->Y);
+ }
+}
+
int WM_MoveWindow(tWindow *Window, int X, int Y)
{
+// _SysDebug("Move %p to (%i,%i)", Window, X, Y);
// Clip coordinates
if(X + Window->W < 0) X = -Window->W + 1;
if(Y + Window->H < 0) Y = -Window->H + 1;
if(X >= giScreenWidth) X = giScreenWidth - 1;
if(Y >= giScreenHeight) Y = giScreenHeight - 1;
+ // If relative to the parent, extra checks
+ if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
+ {
+ if( X > Window->Parent->W ) return 1;
+ if( Y > Window->Parent->H ) return 1;
+ }
+ // TODO: Re-sanitise
+
Window->X = X; Window->Y = Y;
+ // TODO: Why invalidate buffer?
WM_Invalidate(Window);
return 0;
if(Window->X + W < 0) Window->X = -W + 1;
if(Window->Y + H < 0) Window->Y = -H + 1;
+ if( Window->W == W && Window->H == H )
+ return 0;
+
Window->W = W; Window->H = H;
if(Window->RenderBuffer) {
int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
{
- if(Dest == NULL) return -2;
- if(Length > 0 && Data == NULL) return -1;
+// _SysDebug("WM_SendMessage: (%p, %p, %i, %i, %p)", Source, Dest, Message, Length, Data);
+ if(Dest == NULL) {
+ _SysDebug("WM_SendMessage: NULL destination from %p", __builtin_return_address(0));
+ return -2;
+ }
+ if(Length > 0 && Data == NULL) {
+ _SysDebug("WM_SendMessage: non-zero length and NULL data");
+ return -1;
+ }
if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
{
// TODO: Catch errors from ->HandleMessage
+// _SysDebug("WM_SendMessage: Decorator grabbed message?");
return 0;
}
if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
{
// TODO: Catch errors from ->HandleMessage
+// _SysDebug("WM_SendMessage: Renderer grabbed message?");
return 0;
}
// TODO: Implement message masking
+ // Dispatch to client
if(Dest->Client)
{
uint32_t src_id;
src_id = Source->ID;
}
+// _SysDebug("WM_SendMessage: IPC Dispatch");
IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
}
return 1;
}
+int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Data)
+{
+ IPC_SendReply(Window->Client, Window->ID, Message, Length, Data);
+ return 0;
+}
+
void WM_Invalidate(tWindow *Window)
{
if(!Window) return ;
- _SysDebug("Invalidating %p", Window);
+// _SysDebug("Invalidating %p", Window);
// Don't invalidate twice (speedup)
// if( !(Window->Flags & WINFLAG_CLEAN) ) return;
// Calculate RealW/RealH
if( !(Window->Flags & WINFLAG_NODECORATE) )
{
- _SysDebug("Applying decorations to %p", Window);
+ //_SysDebug("Applying decorations to %p", Window);
Decorator_UpdateBorderSize(Window);
Window->RealW = Window->BorderL + Window->W + Window->BorderR;
Window->RealH = Window->BorderT + Window->H + Window->BorderB;
Window->RealH = Window->H;
}
+ if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
+ {
+ Window->RealX = Window->Parent->X + Window->Parent->BorderL + Window->X;
+ Window->RealY = Window->Parent->Y + Window->Parent->BorderT + Window->Y;
+ }
+ else
+ {
+ Window->RealX = Window->X;
+ Window->RealY = Window->Y;
+ }
+
Window->Renderer->Redraw(Window);
Window->Flags |= WINFLAG_CLEAN;
}
if( !(Window->Flags & WINFLAG_SHOW) )
return ;
-// _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->RealW, Window->RealH);
- Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH);
+// _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer,
+// Window->RealX, Window->RealY, Window->RealW, Window->RealH);
+ Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH);
if( Window == gpWM_FocusedWindow && Window->CursorW )
{
Video_FillRect(
- Window->X + Window->BorderL + Window->CursorX,
- Window->Y + Window->BorderT + Window->CursorY,
+ Window->RealX + Window->BorderL + Window->CursorX,
+ Window->RealY + Window->BorderT + Window->CursorY,
Window->CursorW, Window->CursorH,
0x000000
);
-
}
for( child = Window->FirstChild; child; child = child->NextSibling )
#ifndef _AXWIN3__FRAMEBUFFER_MESSAGES_H_
#define _AXWIN3__FRAMEBUFFER_MESSAGES_H_
-enum
+enum eFrameBuffer_IPCCalls
{
- MSG_FB_COMMIT = 0x1000,
- MSG_FB_NEWBUF,
- MSG_FB_UPLOAD,
- MSG_FB_DOWNLOAD,
- MSG_FB_BLIT,
- MSG_FB_FILL
+ IPC_FB_COMMIT,
+ IPC_FB_NEWBUF,
+ IPC_FB_UPLOAD,
+ IPC_FB_DOWNLOAD, // Replies with requested data
+ IPC_FB_BLIT,
+ IPC_FB_FILL,
+ N_IPC_FB
};
typedef struct
{
uint16_t Buffer;
uint16_t W, H;
-} tFBMsg_NewBuf;
+} tFBIPC_NewBuf;
typedef struct
{
uint16_t W, H;
uint16_t X, Y;
uint32_t ImageData[];
-} tFBMsg_Transfer;
+} tFBIPC_Transfer;
typedef struct
{
uint16_t SrcX, SrcY;
uint16_t DstX, DstY;
uint16_t W, H;
-} tFBMsg_Blit;
+} tFBIPC_Blit;
typedef struct
{
uint16_t X, Y;
uint16_t W, H;
uint32_t Colour;
-} tFBMsg_Fill;
+} tFBIPC_Fill;
#endif
*/
//! Request a return value
#define IPCMSG_FLAG_RETURN 0x01
+//! IPC Message for renderer
+#define IPCMSG_FLAG_RENDERER 0x80
/**
* \}
*/
#include "ipcmessages.h"
-enum eMenuMessages
+// Client->Server IPC methods
+enum eMenuIPCCalls
{
- MSG_MENU_ADDITEM = 0x1000,
- MSG_MENU_SETFLAGS,
-
- MSG_MENU_SELECT
+ IPC_MENU_ADDITEM,
+ IPC_MENU_SETFLAGS
};
typedef struct
uint16_t Flags;
uint32_t SubMenuID;
char Label[];
-} tMenuMsg_AddItem;
+} tMenuIPC_AddItem;
typedef struct
{
uint16_t ID;
uint16_t Value;
uint16_t Mask;
-} tMenuMsg_SetFlags;
+} tMenuIPC_SetFlags;
+
+// Server->Client messages
+enum eMenuMessages
+{
+ MSG_MENU_SELECT = 0x1000
+};
typedef struct
{
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * richtext_messages.h
+ * - Formatted Text Field
+ */
+#ifndef _RICHTEXT_MESSAGES_H_
+#define _RICHTEXT_MESSAGES_H_
+
+enum eRichText_Attrs {
+ _ATTR_DEFBG,
+ _ATTR_DEFFG,
+ _ATTR_SCROLL,
+ _ATTR_LINECOUNT,
+ _ATTR_COLCOUNT,
+ _ATTR_CURSOR,
+ _ATTR_CURSORBLINK,
+ _ATTR_CURSORPOS,
+};
+
+enum eRichText_IPCCalls
+{
+ IPC_RICHTEXT_SETATTR,
+ IPC_RICHTEXT_SETFONT,
+ IPC_RICHTEXT_DELLINE,
+ IPC_RICHTEXT_ADDLINE,
+ IPC_RICHTEXT_WRITELINE, // Set line contents
+ IPC_RICHTEXT_READLINE, // Request line contents
+ N_IPC_RICHTEXT
+};
+
+struct sRichTextIPC_SetAttr
+{
+ uint32_t Attr;
+ uint32_t Value;
+};
+
+struct sRichTextIPC_SetFont
+{
+ uint16_t Size;
+ char Name[];
+};
+
+struct sRichTextIPC_AddDelLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextIPC_ReadLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextIPC_WriteLine
+{
+ uint32_t Line;
+ char LineData[];
+};
+
+enum
+{
+ // Events
+ MSG_RICHTEXT_KEYPRESS = 0x1000,
+ MSG_RICHTEXT_MOUSEBTN,
+
+ // Sent by server to get a line that is not cached (expects IPC WRITELINE)
+ MSG_RICHTEXT_REQLINE,
+ // Response to IPC READLINE
+ MSG_RICHTEXT_LINEDATA,
+};
+
+struct sRichTextMsg_ReqLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextMsg_LineData
+{
+ uint32_t Line;
+ char LineData[];
+};
+
+#endif
+
#ifndef _WIDGET_MESSAGES_H_
#define _WIDGET_MESSAGES_H_
-enum
+enum eWidgetIPCCalls
{
// Control (Client->Server) messages
- MSG_WIDGET_CREATE = 0x1000,
- MSG_WIDGET_DELETE,
- MSG_WIDGET_SETFOCUS,
- MSG_WIDGET_SETFLAGS,
- MSG_WIDGET_SETSIZE,
- MSG_WIDGET_SETTEXT,
- MSG_WIDGET_SETCOLOUR,
+ IPC_WIDGET_CREATE,
+ IPC_WIDGET_CREATESUBWIN,
+ IPC_WIDGET_DELETE,
+ IPC_WIDGET_SETFOCUS,
+ IPC_WIDGET_SETFLAGS,
+ IPC_WIDGET_SETSIZE,
+ IPC_WIDGET_SETTEXT,
+ IPC_WIDGET_SETCOLOUR,
-
- // Request (Client->Server->Client) messages
- MSG_WIDGET_GETTEXT,
-
- // Event (Server->Client) messages
- MSG_WIDGET_FIRE,
- MSG_WIDGET_KEYPRESS,
- MSG_WIDGET_MOUSEBTN,
+ IPC_WIDGET_GETTEXT,
+
+ N_IPC_WIDGET
};
+typedef struct
+{
+ uint32_t Parent;
+ uint32_t NewID;
+ uint32_t Type;
+ uint32_t Flags;
+ char DebugName[];
+} tWidgetIPC_Create;
typedef struct
{
uint32_t NewID;
uint32_t Type;
uint32_t Flags;
+ uint32_t WindowHandle;
char DebugName[];
-} tWidgetMsg_Create;
+} tWidgetIPC_CreateSubWin;
typedef struct
{
uint32_t WidgetID;
-} tWidgetMsg_Delete;
+} tWidgetIPC_Delete;
typedef struct
{
uint32_t WidgetID;
-} tWidgetMsg_SetFocus;
+} tWidgetIPC_SetFocus;
typedef struct
{
uint32_t WidgetID;
uint32_t Value;
uint32_t Mask;
-} tWidgetMsg_SetFlags;
+} tWidgetIPC_SetFlags;
typedef struct
{
uint32_t WidgetID;
uint32_t Value;
-} tWidgetMsg_SetSize;
+} tWidgetIPC_SetSize;
typedef struct
{
uint32_t WidgetID;
char Text[];
-} tWidgetMsg_SetText;
+} tWidgetIPC_SetText;
typedef struct
{
uint32_t WidgetID;
uint32_t Index;
uint32_t Colour;
-} tWidgetMsg_SetColour;
+} tWidgetIPC_SetColour;
+
+enum eWidgetMessages
+{
+ // Event (Server->Client) messages
+ MSG_WIDGET_FIRE = 0x1000,
+ MSG_WIDGET_KEYPRESS,
+ MSG_WIDGET_MOUSEBTN,
+};
+
+
typedef struct
{
LDFLAGS += -lc -soname libaxwin3.so
OBJ = main.o msg.o wm.o r_widget.o r_menu.o
+OBJ += r_richtext.o
BIN = libaxwin3.so
include ../../../Libraries/Makefile.tpl
extern void *AxWin3_int_GetDataPtr(tHWND Window);
extern uint32_t AxWin3_int_GetWindowID(tHWND Window);
+extern void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data);
+extern void *AxWin3_WaitIPCMessage(tHWND Window, int Message, size_t *Length);
#endif
extern tAxWin_IPCMessage *AxWin3_int_AllocateIPCMessage(tHWND Window, int Message, int Flags, int ExtraBytes);
extern void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg);
-extern tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(void);
+extern tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *FDs);
extern tAxWin_IPCMessage *AxWin3_int_WaitIPCMessage(int WantedID);
extern void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg);
while(!bExit)
{
- msg = AxWin3_int_GetIPCMessage();
+ msg = AxWin3_int_GetIPCMessage(0, NULL);
if(!msg) continue;
- _SysDebug("oh look, a message (Type=%i, Window=%i, Len=%i)",
+ _SysDebug("AxWin3_MainLoop - Message (Type=%i, Window=%i, Len=%i)",
msg->ID, msg->Window, msg->Size);
AxWin3_int_HandleMessage( msg );
-
- free(msg);
}
}
+void AxWin3_MessageSelect(int nFD, fd_set *FDs)
+{
+ tAxWin_IPCMessage *msg;
+ msg = AxWin3_int_GetIPCMessage(nFD, FDs);
+ if( msg )
+ AxWin3_int_HandleMessage( msg );
+}
+
// === CODE ===
void AxWin3_Connect(const char *ServerDesc)
{
- _SysDebug("ServerDesc = %s", ServerDesc);
- if( !ServerDesc )
- {
+ _SysDebug("ServerDesc (argument) = %s", ServerDesc);
+ if( !ServerDesc ) {
ServerDesc = gsAxWin3_int_ServerDesc;
}
_SysDebug("ServerDesc = %s", ServerDesc);
case '6': case '7': case '8': case '9': case '0':
giConnectionType = CONNTYPE_SENDMESSAGE;
giConnectionNum = atoi(ServerDesc);
+ if( giConnectionNum == 0 ) {
+ _SysDebug("Invalid server PID");
+ exit(-1);
+ }
break;
case 'u':
while(*ServerDesc && *ServerDesc != ':') ServerDesc ++;
}
}
-tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(void)
+tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *fds)
{
int len;
tAxWin_IPCMessage *ret = NULL;
- switch(giConnectionType)
+ pid_t tid;
+
+ _SysSelect(nFD, fds, NULL, NULL, NULL, THREAD_EVENT_IPCMSG);
+
+ // Clear out IPC messages
+ while( (len = SysGetMessage(&tid, 0, NULL)) )
{
- case CONNTYPE_SENDMESSAGE:
- for( ;; )
+ if( giConnectionType != CONNTYPE_SENDMESSAGE || tid != giConnectionNum )
{
- pid_t tid;
-
- // Wait for a message to arrive
- while( !(len = SysGetMessage(&tid, 0, NULL)) )
- {
- _SysWaitEvent(THREAD_EVENT_IPCMSG);
- }
-
- // Check if the message came from the server
- if(tid != giConnectionNum)
- {
- _SysDebug("%i byte message from %i", len, tid);
- // If not, pass the buck (or ignore)
- if( gAxWin3_MessageCallback )
- gAxWin3_MessageCallback(tid, len);
- else
- SysGetMessage(NULL, 0, GETMSG_IGNORE);
- continue ;
- }
-
- // If it's from the server, allocate a buffer and return it
- ret = malloc(len);
- if(ret == NULL) {
- _SysDebug("malloc() failed, ignoring message");
+ _SysDebug("%i byte message from %i", len, tid);
+ // If not, pass the buck (or ignore)
+ if( gAxWin3_MessageCallback )
+ gAxWin3_MessageCallback(tid, len);
+ else
SysGetMessage(NULL, 0, GETMSG_IGNORE);
- return NULL;
- }
- SysGetMessage(NULL, len, ret);
- break;
+ continue ;
}
- break;
- default:
- // TODO: Implement
- _SysDebug("TODO: Implement AxWin3_int_GetIPCMessage for TCP/UDP");
+
+ // Using CONNTYPE_SENDMESSAGE and server message has arrived
+ ret = malloc(len);
+ if(ret == NULL) {
+ _SysDebug("malloc() failed, ignoring message");
+ SysGetMessage(NULL, 0, GETMSG_IGNORE);
+ return NULL;
+ }
+ SysGetMessage(NULL, len, ret);
break;
}
- // No message?
- if( ret == NULL )
- return NULL;
-
- // TODO: Sanity checks, so a stupid server can't crash us
+ if( giConnectionType == CONNTYPE_TCP || giConnectionType == CONNTYPE_UDP )
+ {
+ // Check fds
+ }
return ret;
}
tAxWin_IPCMessage *msg;
for(;;)
{
- msg = AxWin3_int_GetIPCMessage();
+ msg = AxWin3_int_GetIPCMessage(0, NULL);
if(msg->ID == WantedID) return msg;
AxWin3_int_HandleMessage( msg );
- free(msg);
}
}
ret->SubMenu = SubMenu;
{
- tMenuMsg_AddItem *req;
+ tMenuIPC_AddItem *req;
int data_size;
if(!Label) Label = "";
data_size = sizeof(*req)+strlen(Label)+1;
req->Flags = Flags;
req->SubMenuID = AxWin3_int_GetWindowID(SubMenu);
strcpy(req->Label, Label);
- AxWin3_SendMessage(Menu, Menu, MSG_MENU_ADDITEM, data_size, req);
+ AxWin3_SendIPC(Menu, IPC_MENU_ADDITEM, data_size, req);
free(req);
}
--- /dev/null
+/*
+ * AxWin3 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * r_richtext.c
+ * - Formatted Text window type
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+#include "include/internal.h"
+#include <richtext_messages.h>
+#include <string.h>
+//#include <alloca.h>
+
+// === TYPES ===
+typedef struct sRichText_Window
+{
+ tAxWin3_RichText_KeyHandler KeyCallback;
+ tAxWin3_RichText_MouseHandler MouseCallback;
+ tAxWin3_RichText_LineHandler LineHandler;
+} tRichText_Window;
+
+// === CODE ===
+int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
+{
+ return 0;
+}
+
+static void _SendAttrib(tHWND Window, int Attr, uint32_t Value)
+{
+ struct sRichTextIPC_SetAttr msg;
+ msg.Attr = Attr;
+ msg.Value = Value;
+ AxWin3_SendIPC(Window, IPC_RICHTEXT_SETATTR, sizeof(msg), &msg);
+}
+
+tHWND AxWin3_RichText_CreateWindow(tHWND Parent, int Flags)
+{
+ tHWND ret = AxWin3_CreateWindow(Parent, "RichText", Flags, sizeof(tRichText_Window), AxWin3_RichText_MessageHandler);
+// tRichText_Window *info = AxWin3_int_GetDataPtr(ret);
+ return ret;
+}
+
+void AxWin3_RichText_SetKeyHandler(tHWND Window, tAxWin3_RichText_KeyHandler Handler)
+{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ info->KeyCallback = Handler;
+}
+
+void AxWin3_RichText_SetMouseHandler(tHWND Window, tAxWin3_RichText_MouseHandler Handler)
+{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ info->MouseCallback = Handler;
+}
+
+void AxWin3_RichText_EnableScroll(tHWND Window, int bEnable)
+{
+ _SendAttrib(Window, _ATTR_SCROLL, bEnable);
+}
+void AxWin3_RichText_SetLineCount(tHWND Window, int Lines)
+{
+ _SendAttrib(Window, _ATTR_LINECOUNT, Lines);
+}
+void AxWin3_RichText_SetColCount(tHWND Window, int Cols)
+{
+ _SendAttrib(Window, _ATTR_COLCOUNT, Cols);
+}
+void AxWin3_RichText_SetBackground(tHWND Window, uint32_t ARGB_Colour)
+{
+ _SendAttrib(Window, _ATTR_DEFBG, ARGB_Colour);
+}
+void AxWin3_RichText_SetDefaultColour(tHWND Window, uint32_t ARGB_Colour)
+{
+ _SendAttrib(Window, _ATTR_DEFFG, ARGB_Colour);
+}
+void AxWin3_RichText_SetFont(tHWND Window, const char *FontName, int PointSize)
+{
+ // TODO: Send message
+}
+void AxWin3_RichText_SetCursorType(tHWND Window, int Type)
+{
+ _SendAttrib(Window, _ATTR_CURSOR, Type);
+}
+void AxWin3_RichText_SetCursorBlink(tHWND Window, int bBlink)
+{
+ _SendAttrib(Window, _ATTR_CURSORBLINK, bBlink);
+}
+void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column)
+{
+ if(Row < 0 || Row > 0xFFFFF || Column > 0xFFF || Column < 0)
+ return ;
+ _SendAttrib(Window, _ATTR_CURSORPOS, ((Row & 0xFFFFF) << 12) | (Column & 0xFFF));
+}
+
+void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text)
+{
+ // TODO: Local sanity check on `Line`?
+ struct sRichTextIPC_WriteLine *msg;
+ size_t len = sizeof(*msg) + strlen(Text) + 1;
+ char buffer[len];
+ msg = (void*)buffer;
+ msg->Line = Line;
+ strcpy(msg->LineData, Text);
+ AxWin3_SendIPC(Window, IPC_RICHTEXT_WRITELINE, len, msg);
+}
+
return info->Elements[ID];
}
+uint32_t AxWin3_Widget_int_AllocateID(tWidgetWindowInfo *Info)
+{
+ uint32_t newID;
+ // BUG BUG BUG - Double Allocations! (citation needed)
+ // TODO: Atomicity
+ for( newID = Info->FirstFreeID; newID < Info->nElements; newID ++ )
+ {
+ if( Info->Elements[newID] == NULL )
+ break;
+ }
+ if( newID == Info->nElements )
+ {
+ const int size_step = 4;
+ Info->nElements += 4;
+ Info->Elements = realloc(Info->Elements, sizeof(*Info->Elements)*Info->nElements);
+ newID = Info->nElements - 4;
+ memset( &Info->Elements[newID+1], 0, (size_step-1)*sizeof(Info->Elements));
+ _SysDebug("Widget: Expanded to %i and allocated %i", Info->nElements, newID);
+ }
+ else
+ _SysDebug("Widget: Allocated %i", newID);
+ Info->Elements[newID] = (void*)-1;
+
+ return newID;
+
+}
+
int AxWin3_Widget_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
{
tAxWin3_Widget *widget;
widget = AxWin3_Widget_int_GetElementByID(Window, msg->WidgetID);
if(widget->Fire) widget->Fire(widget);
- return 0; }
+ return 1; }
default:
return 0;
}
info = AxWin3_int_GetDataPtr(Parent->Window);
- // Assign ID
- // BUG BUG BUG - Double Allocations!
- // TODO: Atomicity
- for( newID = info->FirstFreeID; newID < info->nElements; newID ++ )
- {
- if( info->Elements[newID] == NULL )
- break;
- }
- if( newID == info->nElements )
- {
- const int size_step = 4;
- info->nElements += 4;
- info->Elements = realloc(info->Elements, sizeof(*info->Elements)*info->nElements);
- newID = info->nElements - 4;
- memset( &info->Elements[newID+1], 0, (size_step-1)*sizeof(info->Elements));
- _SysDebug("Expanded to %i and allocated %i", info->nElements, newID);
- }
- else
- _SysDebug("Allocated %i", newID);
- info->Elements[newID] = (void*)-1;
+ newID = AxWin3_Widget_int_AllocateID(info);
// Create new widget structure
ret = calloc(sizeof(tAxWin3_Widget), 1);
// Send create widget message
{
- char tmp[sizeof(tWidgetMsg_Create)+1];
- tWidgetMsg_Create *msg = (void*)tmp;
+ char tmp[sizeof(tWidgetIPC_Create)+1];
+ tWidgetIPC_Create *msg = (void*)tmp;
msg->Parent = Parent->ID;
msg->NewID = newID;
msg->Type = Type;
msg->Flags = Flags;
msg->DebugName[0] = '\0';
- AxWin3_SendMessage(ret->Window, ret->Window, MSG_WIDGET_CREATE, sizeof(tmp), tmp);
+ AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATE, sizeof(tmp), tmp);
+ }
+
+ return ret;
+}
+
+tAxWin3_Widget *AxWin3_Widget_AddWidget_SubWindow(tAxWin3_Widget *Parent, tHWND Window, int Flags, const char *DbgName)
+{
+ tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Parent->Window);
+ int newID = AxWin3_Widget_int_AllocateID(info);
+
+ tAxWin3_Widget *ret = calloc(sizeof(tAxWin3_Widget), 1);
+ ret->Window = Parent->Window;
+ ret->ID = newID;
+ info->Elements[newID] = ret;
+
+ // Send message
+ {
+ char tmp[sizeof(tWidgetIPC_CreateSubWin)+1];
+ tWidgetIPC_CreateSubWin *msg = (void*)tmp;
+ msg->Parent = Parent->ID;
+ msg->NewID = newID;
+ msg->Type = ELETYPE_SUBWIN;
+ msg->Flags = Flags; // TODO: Flags
+ msg->WindowHandle = AxWin3_int_GetWindowID(Window);
+ msg->DebugName[0] = '\0';
+ AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATESUBWIN, sizeof(tmp), tmp);
}
return ret;
}
+
void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget)
{
- tWidgetMsg_Delete msg;
+ tWidgetIPC_Delete msg;
tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Widget->Window);
msg.WidgetID = Widget->ID;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_DELETE, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_DELETE, sizeof(msg), &msg);
info->Elements[Widget->ID] = NULL;
if(Widget->ID < info->FirstFreeID)
// --- Manipulation
void AxWin3_Widget_SetFlags(tAxWin3_Widget *Widget, int FlagSet, int FlagMask)
{
- tWidgetMsg_SetFlags msg;
+ tWidgetIPC_SetFlags msg;
msg.WidgetID = Widget->ID;
msg.Value = FlagSet;
msg.Mask = FlagMask;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETFLAGS, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETFLAGS, sizeof(msg), &msg);
}
void AxWin3_Widget_SetSize(tAxWin3_Widget *Widget, int Size)
{
- tWidgetMsg_SetSize msg;
+ tWidgetIPC_SetSize msg;
msg.WidgetID = Widget->ID;
msg.Value = Size;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETSIZE, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETSIZE, sizeof(msg), &msg);
}
void AxWin3_Widget_SetText(tAxWin3_Widget *Widget, const char *Text)
{
- char buf[sizeof(tWidgetMsg_SetText) + strlen(Text) + 1];
- tWidgetMsg_SetText *msg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText) + strlen(Text) + 1];
+ tWidgetIPC_SetText *msg = (void*)buf;
msg->WidgetID = Widget->ID;
strcpy(msg->Text, Text);
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETTEXT, sizeof(buf), buf);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETTEXT, sizeof(buf), buf);
}
char *AxWin3_Widget_GetText(tAxWin3_Widget *Widget)
{
- char buf[sizeof(tWidgetMsg_SetText)];
- tWidgetMsg_SetText *msg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText)];
+ tWidgetIPC_SetText *msg = (void*)buf;
size_t retmsg_size;
msg->WidgetID = Widget->ID;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
- msg = AxWin3_WaitMessage(Widget->Window, MSG_WIDGET_GETTEXT, &retmsg_size);
+ msg = AxWin3_WaitIPCMessage(Widget->Window, IPC_WIDGET_GETTEXT, &retmsg_size);
if( retmsg_size < sizeof(*msg) ) {
free(msg);
return NULL;
void AxWin3_Widget_SetColour(tAxWin3_Widget *Widget, int Index, tAxWin3_Colour Colour)
{
- tWidgetMsg_SetColour msg;
+ tWidgetIPC_SetColour msg;
msg.WidgetID = Widget->ID;
msg.Index = Index;
msg.Colour = Colour;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETCOLOUR, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETCOLOUR, sizeof(msg), &msg);
}
ret = (void*)msg->Data;
if(X) *X = ret->X;
- if(X) *X = ret->Y;
+ if(Y) *Y = ret->Y;
if(Width) *Width = ret->W;
if(Height) *Height = ret->H;
AxWin3_int_SendIPCMessage(msg);
free(msg);
+ _SysDebug("AxWin3_CreateWindow: %i :: '%s'", newWinID, Renderer);
+
// TODO: Detect and handle possible errors
// Return success
gAxWin3_Hotkeys[mi->ID]();
}break;
default:
- _SysDebug("--- Unhandled SENDMSG %i", info->ID);
+ _SysDebug("--- Unhandled SENDMSG 0x%x win %i", info->ID, Msg->Window);
break;
}
}
_SysDebug("Unknow message ID %i", Msg->ID);
break;
}
+
+ free(Msg);
}
void AxWin3_SetWindowTitle(tHWND Window, const char *Title)
}
}
+void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data)
+{
+ tAxWin_IPCMessage *msg;
+
+ msg = AxWin3_int_AllocateIPCMessage(Window, Message, IPCMSG_FLAG_RENDERER, Length);
+ memcpy(msg->Data, Data, Length);
+ AxWin3_int_SendIPCMessage(msg);
+ free(msg);
+}
+
+void *AxWin3_WaitIPCMessage(tHWND Window, int MessageID, size_t *Length)
+{
+ tAxWin_IPCMessage *msg;
+ for( ;; )
+ {
+ msg = AxWin3_int_WaitIPCMessage(MessageID);
+ if( !(msg->Flags & IPCMSG_FLAG_RENDERER) || msg->Window != AxWin3_int_GetWindowID(Window) ) {
+ AxWin3_int_HandleMessage(msg);
+ continue ;
+ }
+
+ *Length = msg->Size;
+ void *ret = malloc(msg->Size);
+ memcpy(ret, msg->Data, msg->Size);
+ free(msg);
+
+ return ret;
+ }
+}
+
void AxWin3_FocusWindow(tHWND Window)
{
tAxWin_IPCMessage *msg;
--- /dev/null
+# Project: [GUI] Acess Text Editor (ATE)
+
+-include ../Makefile.cfg
+
+LDFLAGS += -laxwin3
+
+OBJ = main.o
+BIN = ate
+DIR := Apps/AxWin/3.0
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * edit.c
+ * - File Loading / Manipulation
+ */
+#include <stdio.h>
+#include "include/file.h"
+#include "include/syntax.h"
+
+// === CODE ===
+tFile *File_New(void)
+{
+ tFile *ret = malloc(sizeof(tFile) + 1);
+ ret->Handle = NULL;
+ ret->nLines = 0;
+ ret->Lines = NULL;
+ ret->NameOfs = 0;
+ ret->Path[0] = 0;
+ return ret;
+}
+
+tFile *File_Load(const char *Path)
+{
+ return NULL;
+}
+
+int File_Save(tFile *File)
+{
+
+ //file->bIsDirty = 0;
+ return -1;
+}
+
+int File_Close(tFile *File, int bDiscard)
+{
+ //if( file->bIsDirty && !bDiscard )
+ // return 1;
+ if( file->Handle )
+ fclose(File->Handle);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * include/file.h
+ * - In-memory file structures
+ */
+#ifndef _ATE__FILE_H_
+#define _ATE__FILE_H_
+#include <stdio.h>
+
+typedef struct sFileLine
+{
+ int Num;
+
+ // State data for hilighting
+ int HilightState;
+ char *Rendered;
+
+ int Space;
+ int Length;
+ char Data[];
+} tFileLine;
+
+typedef struct sFile
+{
+ FILE *Handle;
+ int nLines;
+ tFileLine **Lines; // TODO: Handle very large files?
+ int NameOfs;
+ const char Path[];
+} tFile;
+
+#endif
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * include/syntax.h
+ * - Syntax Hilighting / Rendering structures
+ */
+#ifndef _ATE__SYNTAX_H_
+#define _ATE__SYNTAX_H_
+
+#endif
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/widget.h>
+#include <axwin3/menu.h>
+#include <axwin3/richtext.h>
+#include <stdio.h>
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[]);
+ int TextArea_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
+ int TextArea_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+void add_toolbar_button(tAxWin3_Widget *Toolbar, const char *Ident, tAxWin3_Widget_FireCb Callback);
+ int Toolbar_New(tAxWin3_Widget *Widget);
+ int Toolbar_Open(tAxWin3_Widget *Widget);
+ int Toolbar_Save(tAxWin3_Widget *Widget);
+
+// === GLOBALS ===
+tHWND gMainWindow;
+tAxWin3_Widget *gMainWindow_Root;
+tHWND gMainWindow_MenuBar;
+tAxWin3_Widget *gMainWindow_Toolbar;
+tHWND gMainWindow_TextArea;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+ AxWin3_Connect(NULL);
+
+ // --- Build up window
+ gMainWindow = AxWin3_Widget_CreateWindow(NULL, 700, 400, ELEFLAG_VERTICAL);
+ AxWin3_SetWindowTitle(gMainWindow, "Acess Text Editor"); // TODO: Update title with other info
+ gMainWindow_Root = AxWin3_Widget_GetRoot(gMainWindow);
+
+ //gMainWindow_MenuBar = AxWin3_Menu_Create(gMainWindow);
+ //AxWin3_Widget_AddWidget_SubWindow(gMainWindow_Root, gMainWindow_MenuBar);
+ // TODO: Populate menu
+
+ // Create toolbar
+ gMainWindow_Toolbar = AxWin3_Widget_AddWidget(gMainWindow_Root, ELETYPE_TOOLBAR, ELEFLAG_NOSTRETCH, "Toolbar");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnNew", Toolbar_New);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnOpen", Toolbar_Open);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnSave", Toolbar_Save);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnUndo", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnRedo", NULL);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnCut", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnCopy", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnPaste", NULL);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnSearch", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnReplace", NULL);
+
+ // TODO: Tab control?
+
+ gMainWindow_TextArea = AxWin3_RichText_CreateWindow(gMainWindow, 0);
+ AxWin3_Widget_AddWidget_SubWindow(gMainWindow_Root, gMainWindow_TextArea, 0, "TextArea");
+ AxWin3_RichText_SetKeyHandler (gMainWindow_TextArea, TextArea_KeyHandler);
+ AxWin3_RichText_SetMouseHandler (gMainWindow_TextArea, TextArea_MouseHandler);
+ AxWin3_RichText_SetBackground (gMainWindow_TextArea, 0xFFFFFF);
+ AxWin3_RichText_SetDefaultColour(gMainWindow_TextArea, 0x000000);
+ AxWin3_RichText_SetFont (gMainWindow_TextArea, "#monospace", 10);
+ AxWin3_RichText_SetCursorPos (gMainWindow_TextArea, 0, 0);
+ AxWin3_RichText_SetCursorType (gMainWindow_TextArea, AXWIN3_RICHTEXT_CURSOR_VLINE);
+ AxWin3_RichText_SetCursorBlink (gMainWindow_TextArea, 1);
+
+ // <testing>
+ AxWin3_RichText_SetLineCount(gMainWindow_TextArea, 3);
+ AxWin3_RichText_SendLine(gMainWindow_TextArea, 0, "First line!");
+ AxWin3_RichText_SendLine(gMainWindow_TextArea, 2, "Third line! \x01""ff0000A red");
+ // </testing>
+
+ AxWin3_ShowWindow(gMainWindow_TextArea, 1);
+ // TODO: Status Bar?
+
+ AxWin3_MoveWindow(gMainWindow, 50, 50);
+ AxWin3_ShowWindow(gMainWindow, 1);
+ AxWin3_FocusWindow(gMainWindow);
+
+ // Main loop
+ AxWin3_MainLoop();
+
+ return 0;
+}
+
+int TextArea_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
+{
+ return 0;
+}
+
+int TextArea_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
+{
+ return 0;
+}
+
+void add_toolbar_button(tAxWin3_Widget *Toolbar, const char *Ident, tAxWin3_Widget_FireCb Callback)
+{
+ tAxWin3_Widget *btn = AxWin3_Widget_AddWidget(Toolbar, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, Ident);
+ tAxWin3_Widget *txt = AxWin3_Widget_AddWidget(btn, ELETYPE_TEXT, 0, Ident);
+ // TODO: Get image / text using `Ident` as a lookup key
+ AxWin3_Widget_SetText(txt, Ident);
+ AxWin3_Widget_SetFireHandler(btn, Callback);
+}
+
+int Toolbar_New(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+int Toolbar_Open(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+int Toolbar_Save(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+
--- /dev/null
+# Project: [GUI] Terminal
+
+-include ../Makefile.cfg
+
+LDFLAGS += -laxwin3
+
+OBJ = main.o
+BIN = terminal
+DIR := Apps/AxWin/3.0
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.h
+ * - RichText Termianl Translation
+ */
+#ifndef _DISPLAY_H_
+#define _DISPLAY_H_
+
+extern void Display_AddText(int Length, const char *UTF8Text);
+extern void Display_Newline(int bCarriageReturn);
+extern void Display_SetCursor(int Row, int Col);
+extern void Display_MoveCursor(int RelRow, int RelCol);
+extern void Display_ClearLine(int Dir); // 0: All, 1: Forward, -1: Reverse
+extern void Display_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse
+extern void Display_SetForeground(uint32_t RGB);
+extern void Display_SetBackground(uint32_t RGB);
+
+#endif
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * vt100.h
+ * - VT100/xterm emulation
+ */
+#ifndef _VT100_H_
+#define _VT100_H_
+
+/**
+ * Returns either a positive or negative byte count.
+ * Positive means that many bytes were used as part of the escape sequence
+ * and should not be sent to the display.
+ * Negative means that there were that many bytes before the next escape
+ * sequence (and hence those should be displayed).
+ */
+extern int Term_HandleVT100(int Len, const char *Buf);
+
+
+#endif
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/menu.h>
+#include <axwin3/richtext.h>
+#include <stdio.h>
+#include "include/display.h"
+#include "include/vt100.h"
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[], const char **envp);
+ int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
+ int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+
+// === GLOBALS ===
+tHWND gMainWindow;
+tHWND gMenuWindow;
+ int giChildStdin;
+ int giChildStdout;
+
+// === CODE ===
+int main(int argc, char *argv[], const char **envp)
+{
+ AxWin3_Connect(NULL);
+
+ // --- Build up window
+ gMainWindow = AxWin3_RichText_CreateWindow(NULL, 0);
+ AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info
+
+ gMenuWindow = AxWin3_Menu_Create(gMainWindow);
+ AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, 0, NULL);
+ AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, 0, NULL);
+ // TODO: Populate menu
+
+
+ // TODO: Tabs?
+
+ AxWin3_RichText_SetKeyHandler (gMainWindow, Term_KeyHandler);
+ AxWin3_RichText_SetMouseHandler (gMainWindow, Term_MouseHandler);
+ AxWin3_RichText_SetDefaultColour(gMainWindow, 0xFFFFFF);
+ AxWin3_RichText_SetBackground (gMainWindow, 0x000000);
+ AxWin3_RichText_SetFont (gMainWindow, "#monospace", 10);
+ AxWin3_RichText_SetCursorPos (gMainWindow, 0, 0);
+ AxWin3_RichText_SetCursorType (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV);
+ AxWin3_RichText_SetCursorBlink (gMainWindow, 1);
+
+ // <testing>
+ AxWin3_RichText_SetLineCount(gMainWindow, 3);
+ AxWin3_RichText_SendLine(gMainWindow, 0, "First line!");
+ AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red");
+ // </testing>
+
+ AxWin3_ResizeWindow(gMainWindow, 600, 400);
+ AxWin3_MoveWindow(gMainWindow, 50, 50);
+ AxWin3_ShowWindow(gMainWindow, 1);
+ AxWin3_FocusWindow(gMainWindow);
+
+ // Spawn shell
+ giChildStdout = open("/Devices/FIFO/anon", O_RDWR);
+ giChildStdin = open("/Devices/FIFO/anon", O_RDWR);
+
+ {
+ int fds[] = {giChildStdin, giChildStdout, giChildStdout};
+ const char *argv[] = {"CLIShell", NULL};
+ _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ }
+
+ // Main loop
+ for( ;; )
+ {
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(giChildStdout, &fds);
+ AxWin3_MessageSelect(giChildStdout + 1, &fds);
+
+ if( FD_ISSET(giChildStdout, &fds) )
+ {
+ // Read and update screen
+ char buf[32];
+ int len = read(giChildStdout, buf, sizeof(buf));
+ if( len <= 0 ) break;
+
+ //Term_HandleOutput(len, buf);
+ }
+ }
+
+ return 0;
+}
+
+int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
+{
+ static int ctrl_state = 0;
+
+ // Handle modifiers
+ #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=1<<(bit);}while(0)
+ switch(KeySym)
+ {
+ case KEY_LCTRL:
+ _bitset(ctrl_state, 0, bPress);
+ return 0;
+ case KEY_RCTRL:
+ _bitset(ctrl_state, 0, bPress);
+ return 0;
+ }
+ #undef _bitset
+
+ // Handle shortcuts
+ // - Ctrl-A -- Ctrl-Z
+ if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z )
+ {
+ Translated = KeySym - KEY_a + 1;
+ }
+
+ if( Translated )
+ {
+ // Encode and send
+
+ return 0;
+ }
+
+ // No translation, look for escape sequences to send
+ switch(KeySym)
+ {
+ case KEY_LEFTARROW:
+ // str = "\x1b[D";
+ break;
+ }
+ return 0;
+}
+
+int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
+{
+ return 0;
+}
+
+void Term_HandleOutput(int Len, const char *Buf)
+{
+ // TODO: Handle graphical / accelerated modes
+
+ int ofs = 0;
+ int esc_len = 0;
+
+ while( ofs < Len )
+ {
+ esc_len = Term_HandleVT100(Len - ofs, Buf + ofs);
+ if( esc_len < 0 ) {
+ Display_AddText(-esc_len, Buf + ofs);
+ esc_len = -esc_len;
+ }
+ Len -= esc_len;
+ ofs += esc_len;
+ }
+}
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <string.h>
+#include "include/vt100.h"
+#include "include/display.h"
+
+int Term_HandleVT100(int Len, const char *Buf)
+{
+ const int max_length = 16;
+ static char inc_buf[max_length]
+ static int inc_len = 0;
+
+ if( inc_len > 0 || *Buf == '\x1b' )
+ {
+ memcpy(inc_buf + inc_len, Buf, min(max_length - inc_len, Len));
+ // Handle VT100 (like) escape sequence
+
+ inc_len = 0;
+ return 1;
+ }
+
+ switch( *Buf )
+ {
+ case '\b':
+ // TODO: Backspace
+ return 1;
+ case '\t':
+ // TODO: tab
+ return 1;
+ case '\n':
+ Display_Newline(1);
+ return 1;
+ case '\r':
+ // TODO: Carriage return
+ return ;
+ }
+
+ int ret = 0;
+ while( ret < Len )
+ {
+ if( *Buf == '\n' )
+ break;
+ if( *Buf == '\x1b' )
+ break;
+ ret ++;
+ Buf ++;
+ }
+ return -ret;
+}
{
int fds[3] = {clt->stdin, clt->stdout, clt->stdout};
const char *argv[] = {NULL};
- _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds);
+ _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
}
}
@mkdir -p $(dir $(_BIN))
@echo [LD] -o $(BIN) $(OBJ)
@$(LD) $(LDFLAGS) -o $(_BIN) $(OBJ) $(shell $(CC) -print-libgcc-file-name)
- @$(DISASM) -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
+ @$(DISASM) -D -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
$(_OBJPREFIX)%.o: %.c
@echo [CC] -o $@
svc #0x1001
mov pc, lr
-@ DEST
-@ SRC
-@_memcpy:
-@ push rbp
-@ mov rbp, rsp
-@
-@ ; RDI - First Param
-@ ; RSI - Second Param
-@ mov rcx, rdx ; RDX - Third
-@ rep movsb
-@
-@ pop rbp
-@ ret
-@
+
+@ >r0: PC
+@ >r1: Pointer to item count
+@ <r0: Address
+@ STUBBED
+__gnu_Unwind_Find_exidx:
+ mov r0, #0
+ str r0, [r1]
+ mov pc, lr
+
+.section .data
.globl _errno
_errno: .long 0 @ Placed in .text, to allow use of relative addressing
+.section .text
.macro syscall0 _name, _num
.globl \_name
\_name:
push {lr}
svc #\_num
- str r2, _errno
+ @mrc p15, 0, r3, c13, c0, 2
+ ldr r3, =_errno
+ str r2, [r3]
pop {pc}
.endm
push {r4, lr}
ldr r4, [sp,#8]
svc #\_num
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
pop {r4, pc}
.endm
ldr r4, [sp,#12]
ldr r5, [sp,#16]
svc #\_num
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
pop {r4,r5,pc}
.endm
push {r4}
mov r4, r1
svc #SYS_CLONE
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
tst r4, r4
beq _clone_ret
@ If in child, set SP
SYSCALL6(_SysDebug, 0x100)
SYSCALL1(_SysGetPhys, SYS_GETPHYS) // uint64_t _SysGetPhys(uint addr)
SYSCALL1(_SysAllocate, SYS_ALLOCATE) // uint64_t _SysAllocate(uint addr)
+SYSCALL3(SysSetMemFlags, SYS_SETFLAGS) // uint32_t SysSetMemFlags(uint addr, uint flags, uint mask)
// VFS System calls
SYSCALL2(open, SYS_OPEN) // char*, int
SYSCALL3(reopen, SYS_REOPEN) // int, char*, int
// === Library/Symbol Manipulation ==
extern void *LoadLibrary(const char *Filename, const char *SearchDir, char **envp);
extern void AddLoaded(const char *File, void *base);
-extern void *GetSymbol(const char *name, size_t *size);
+extern int GetSymbol(const char *Name, void **Value, size_t *size);
extern int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
// === Library Functions ===
# define DEBUG 0
#endif
+#ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+#endif
+
#include "common.h"
#include <stdint.h>
#include "elf32.h"
int ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
void *Elf32Relocate(void *Base, char **envp, const char *Filename);
int Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
-void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
-void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_unk(uint32_t , uint32_t *, Elf32_Addr , int , int , const char *, intptr_t);
#ifdef SUPPORT_ELF64
void *Elf64Relocate(void *Base, char **envp, const char *Filename);
int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
}
}
-void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type,
+ int bRela, const char *Sym, intptr_t iBaseDiff)
{
- intptr_t val;
+ void *symval;
switch( type )
{
// Standard 32 Bit Relocation (S+A)
case R_386_32:
- val = (intptr_t) GetSymbol(Sym, NULL);
- DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')",
- ptr, val, Sym);
- *ptr = val + addend;
+ if( !GetSymbol(Sym, &symval, NULL) )
+ return 1;
+ DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')",
+ ptr, symval, Sym);
+ *ptr = (intptr_t)symval + addend;
break;
// 32 Bit Relocation wrt. Offset (S+A-P)
case R_386_PC32:
DEBUGS(" elf_doRelocate: '%s'", Sym);
- val = (intptr_t) GetSymbol(Sym, NULL);
- DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x",
- ptr, *ptr, val, (intptr_t)ptr );
- *ptr = val + addend - (intptr_t)ptr;
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x",
+ ptr, *ptr, symval, (intptr_t)ptr );
+ *ptr = (intptr_t)symval + addend - (intptr_t)ptr;
//*ptr = val + addend - ((Uint)ptr - iBaseDiff);
break;
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
DEBUGS(" elf_doRelocate: '%s'", Sym);
- val = (intptr_t) GetSymbol( Sym, NULL );
- DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val);
- *ptr = val;
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval);
+ *ptr = (intptr_t)symval;
break;
// Base Address (B+A)
case R_386_COPY: {
size_t size;
- void *src = GetSymbol(Sym, &size);
- DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, src, size);
- memcpy(ptr, src, size);
+ if( !GetSymbol(Sym, &symval, &size) ) return 1;
+ DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size);
+ memcpy(ptr, symval, size);
break; }
default:
SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
- break;
+ return 2;
}
+ return 0;
}
-void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
{
uint32_t val;
switch(type)
// (S + A) | T
case R_ARM_ABS32:
DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
case R_ARM_GLOB_DAT:
DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
case R_ARM_JUMP_SLOT:
if(!bRela) addend = 0;
DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
// Copy
case R_ARM_COPY: {
size_t size;
- void *src = GetSymbol(Sym, &size);
+ void *src;
+ if( !GetSymbol(Sym, &src, &size) ) return 1;
DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size);
memcpy(ptr, src, size);
break; }
// Delta between link and runtime locations + A
case R_ARM_RELATIVE:
+ DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend);
if(Sym[0] != '\0') {
// TODO: Get delta for a symbol
SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols");
+ return 2;
}
else {
*ptr = iBaseDiff + addend;
break;
default:
SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type);
- break;
+ return 2;
}
+ return 0;
+}
+
+int elf_doRelocate_unk(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+{
+ return 1;
}
void *Elf32Relocate(void *Base, char **envp, const char *Filename)
Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer
char *dynstrtab = NULL; // .dynamic String Table
Elf32_Sym *dynsymtab;
- void (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
- auto void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend);
+ int (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
DEBUGS("ElfRelocate: (Base=0x%x)", Base);
// Adjust "Real" Base
iBaseDiff = (intptr_t)Base - iRealBase;
-
+
// hdr->entrypoint += iBaseDiff; // Adjust Entrypoint
// Check if a PT_DYNAMIC segement was found
SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
}
-
+
+ // Allow writing to read-only segments, just in case they need to be relocated
+ // - Will be reversed at the end of the function
+ for( i = 0; i < iSegmentCount; i ++ )
+ {
+ if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
+ uintptr_t addr = phtab[i].VAddr + iBaseDiff;
+ uintptr_t end = addr + phtab[i].MemSize;
+ for( ; addr < end; addr += PAGE_SIZE )
+ SysSetMemFlags(addr, 0, 1); // Unset RO
+ }
+ }
+
// Adjust Dynamic Table
dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff );
// === Get Symbol table and String Table ===
+ dynsymtab = NULL;
for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
{
switch(dynamicTab[j].d_tag)
DEBUGS(" elf_relocate: Beginning Relocation");
- void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend)
- {
- int type = ELF32_R_TYPE(r_info);
- int sym = ELF32_R_SYM(r_info);
- const char *symname = dynstrtab + dynsymtab[sym].nameOfs;
- do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff);
- }
+ int fail = 0;
switch(hdr->machine)
{
break;
default:
SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine);
+ do_relocate = elf_doRelocate_unk;
+ fail = 1;
break;
}
DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm);
+ #define _doRelocate(r_info, ptr, bRela, addend) \
+ do_relocate(r_info, ptr, addend, ELF32_R_TYPE(r_info), bRela, \
+ dynstrtab + dynsymtab[ELF32_R_SYM(r_info)].nameOfs, iBaseDiff);
+
// Parse Relocation Entries
if(rel && relSz)
{
{
//DEBUGS(" Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset);
ptr = (void*)(iBaseDiff + rel[i].r_offset);
- _doRelocate(rel[i].r_info, ptr, 0, *ptr);
+ fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr);
}
}
// Parse Relocation Entries
for( i = 0; i < j; i++ )
{
ptr = (void*)(iBaseDiff + rela[i].r_offset);
- _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
+ fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
}
}
for(i=0;i<j;i++)
{
ptr = (void*)(iBaseDiff + pltRel[i].r_offset);
- _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
+ fail |= _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
}
}
else
for(i=0;i<j;i++)
{
ptr = (void*)(iRealBase + pltRela[i].r_offset);
- _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
+ fail |= _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
}
}
}
-
+
+ // Re-set readonly
+ for( i = 0; i < iSegmentCount; i ++ )
+ {
+ // If load and not writable
+ if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
+ uintptr_t addr = phtab[i].VAddr + iBaseDiff;
+ uintptr_t end = addr + phtab[i].MemSize;
+ for( ; addr < end; addr += PAGE_SIZE )
+ SysSetMemFlags(addr, 1, 1); // Unset RO
+ }
+ }
+
+ if( fail ) {
+ DEBUGS("ElfRelocate: Failure");
+ return NULL;
+ }
+
+ #undef _doRelocate
+
DEBUGS("ElfRelocate: RETURN 0x%x to %p", hdr->entrypoint + iBaseDiff, __builtin_return_address(0));
return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff );
}
}
// Relocation function
- void _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
+ auto int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend);
+ int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
{
int sym = ELF64_R_SYM(r_info);
int type = ELF64_R_TYPE(r_info);
const char *symname = strtab + symtab[sym].st_name;
+ void *symval;
+ //DEBUGS("_Elf64DoReloc: %s", symname);
switch( type )
{
case R_X86_64_NONE:
break;
case R_X86_64_64:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL) + addend;
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval + addend;
break;
case R_X86_64_COPY: {
size_t size;
- void *symptr = GetSymbol(symname, &size);
- memcpy(ptr, symptr, size);
+ if( !GetSymbol(symname, &symval, &size) ) return 1;
+ memcpy(ptr, symval, size);
} break;
case R_X86_64_GLOB_DAT:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval;
break;
case R_X86_64_JUMP_SLOT:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval;
break;
case R_X86_64_RELATIVE:
*(uint64_t*)ptr = (uintptr_t)Base + addend;
break;
default:
SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type);
- break;
+ return 2;
}
+ //DEBUGS("_Elf64DoReloc: - Good");
+ return 0;
}
+ int fail = 0;
if( rel )
{
DEBUGS("rel_count = %i", rel_count);
for( i = 0; i < rel_count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( rel[i].r_offset + baseDiff );
- _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
+ fail |= _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
}
}
for( i = 0; i < rela_count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( rela[i].r_offset + baseDiff );
- _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
+ fail |= _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
}
}
for( i = 0; i < count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
- _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
+ fail |= _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
}
}
else {
for( i = 0; i < count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
- _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
+ fail |= _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
}
}
}
+ if( fail ) {
+ DEBUGS("Elf64Relocate: Failure");
+ return NULL;
+ }
+
{
void *ret = (void *)(uintptr_t)(hdr->e_entry + baseDiff);
DEBUGS("Elf64Relocate: Relocations done, return %p", ret);
extern uint32_t __udivsi3(uint32_t Num, uint32_t Den);
extern uint32_t __umodsi3(uint32_t Num, uint32_t Den);
-
#define _STR(x) #x
#define STR(x) _STR(x)
#define EXP(sym) {&sym, STR(sym)}
#define __ASSEMBLER__
#include "arch/syscalls.s.h"
#undef __ASSEMBLER__
+
+ #ifdef ARCHDIR_is_armv7
+ {0, "__gnu_Unwind_Find_exidx"},
+ {0, "__cxa_call_unexpected"},
+ {0, "__cxa_type_match"},
+ {0, "__cxa_begin_cleanup"},
+ #endif
#if 0
EXP(__umoddi3),
EXP(__udivdi3),
extern int waittid(int id, int *status);
extern int clone(int flags, void *stack);
extern int execve(char *path, char **argv, char **envp);
-extern int _SysSpawn(const char *Path, const char **argv, const char **envp, int nFDs, int *FDs);
+extern int _SysSpawn(const char *Path, const char **argv, const char **envp, int nFDs, int *FDs, struct s_sys_spawninfo *info);
extern int gettid(void);
extern int getpid(void);
extern int _SysSetFaultHandler(int (*Handler)(int));
// --- MEMORY ---
uint64_t _SysGetPhys(uint vaddr);
uint64_t _SysAllocate(uint vaddr);
+uint32_t SysSetMemFlags(uint vaddr, uint32_t flags, uint32_t mask);
#endif
--- /dev/null
+/*
+ * Acess2 Dynamic Linker
+ * - By John Hodge (thePowersGang)
+ *
+ * acess/syscall_types.h
+ * - Structures used for syscalls
+ */
+
+#ifndef _ACESS__SYSCALL_TYPES_H_
+#define _ACESS__SYSCALL_TYPES_H_
+
+struct s_sysACL {
+ unsigned long object; /*!< Group or user (bit 31 determines) */
+ unsigned long perms; /*!< Inverted by bit 31 */
+};
+struct s_sysFInfo {
+ unsigned int mount;
+ unsigned long long inode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int flags;
+ unsigned long long size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ int numacls;
+ struct s_sysACL acls[];
+} __attribute__((packed));
+typedef struct s_sysFInfo t_sysFInfo;
+typedef struct s_sysACL t_sysACL;
+
+struct s_sys_spawninfo
+{
+ unsigned int flags;
+ unsigned int uid;
+ unsigned int gid;
+};
+
+#endif
+
fd_set_ent_t flags[FD_SETSIZE/16];
} fd_set;
-struct s_sysACL {
- unsigned long object; /*!< Group or user (bit 31 determines) */
- unsigned long perms; /*!< Inverted by bit 31 */
-};
-struct s_sysFInfo {
- unsigned int mount;
- unsigned long long inode;
- unsigned int uid;
- unsigned int gid;
- unsigned int flags;
- unsigned long long size;
- time_t atime;
- time_t mtime;
- time_t ctime;
- int numacls;
- struct s_sysACL acls[];
-} __attribute__((packed));
-typedef struct s_sysFInfo t_sysFInfo;
-typedef struct s_sysACL t_sysACL;
+#include "../acess/syscall_types.h"
extern void FD_ZERO(fd_set *fdsetp);
extern void FD_CLR(int fd, fd_set *fdsetp);
// === PROTOTYPES ===
void *IsFileLoaded(const char *file);
- int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
// === IMPORTS ===
extern const struct {
// Load Symbols
fEntry = DoRelocate( base, envp, filename );
+ if( !fEntry ) {
+ return 0;
+ }
// Call Entrypoint
DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
\fn Uint GetSymbol(const char *name)
\brief Gets a symbol value from a loaded library
*/
-void *GetSymbol(const char *name, size_t *Size)
+int GetSymbol(const char *name, void **Value, size_t *Size)
{
int i;
- void *ret;
//SysDebug("ciNumLocalExports = %i", ciNumLocalExports);
for(i=0;i<ciNumLocalExports;i++)
{
- if( strcmp(caLocalExports[i].Name, name) == 0 )
- return caLocalExports[i].Value;
+ if( strcmp(caLocalExports[i].Name, name) == 0 ) {
+ *Value = caLocalExports[i].Value;
+ if(Size)
+ *Size = 0;
+ return 1;
+ }
}
// Entry 0 is ld-acess, ignore it
for(i = 1; i < MAX_LOADED_LIBRARIES; i ++)
{
- if(gLoadedLibraries[i].Base == 0) break;
+ if(gLoadedLibraries[i].Base == 0)
+ break;
//SysDebug(" GetSymbol: Trying 0x%x, '%s'",
// gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
- if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret, Size)) return ret;
+ if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, Value, Size))
+ return 1;
}
SysDebug("GetSymbol: === Symbol '%s' not found ===", name);
return 0;
#define _AXWIN3_AXWIN_H_
#include <stddef.h> // size_t
+#include <unistd.h>
// === CONSTANTS ===
extern void AxWin3_Connect(const char *ServerDesc);
extern tAxWin3_MessageCallback AxWin3_SetMessageCallback(tAxWin3_MessageCallback Callback);
extern void AxWin3_MainLoop(void);
+extern void AxWin3_MessageSelect(int nFD, fd_set *FDs);
// --- Non-Window based functions
extern int AxWin3_GetDisplayCount(void);
--- /dev/null
+/*
+ * Acess2 GUI Version 3 (AxWin3)
+ * - By John Hodge (thePowersGang)
+ *
+ * richtext.h
+ * - Rich Text line editor
+ */
+#ifndef _AXWIN3_RICHTEXT_H_
+#define _AXWIN3_RICHTEXT_H_
+
+#include <stdint.h>
+
+typedef int (*tAxWin3_RichText_KeyHandler)(tHWND Window, int bPress, uint32_t Sym, uint32_t Unicode);
+typedef int (*tAxWin3_RichText_MouseHandler)(tHWND Window, int bPress, int Button, int Row, int Col);
+typedef int (*tAxWin3_RichText_LineHandler)(tHWND Window, int Row);
+
+#define AXWIN3_RICHTEXT_NOSCROLL 0x0001 // Disables server-side scrolling
+#define AXWIN3_RICHTEXT_READONLY 0x0002 // Disables automatic insertion of translated characters
+enum eAxWin3_RichText_CursorType {
+ AXWIN3_RICHTEXT_CURSOR_NONE,
+ AXWIN3_RICHTEXT_CURSOR_VLINE, // Vertical line
+ AXWIN3_RICHTEXT_CURSOR_ULINE, // Underline
+ AXWIN3_RICHTEXT_CURSOR_INV, // Inverted
+};
+
+extern tHWND AxWin3_RichText_CreateWindow(tHWND Parent, int Flags);
+extern void AxWin3_RichText_SetKeyHandler(tHWND Window, tAxWin3_RichText_KeyHandler Handler);
+extern void AxWin3_RichText_SetMouseHandler(tHWND Window, tAxWin3_RichText_MouseHandler Handler);
+/**
+ * \brief Sets the function called when the server requests an update on a line's contents
+ */
+extern void AxWin3_RichText_SetLineHandler(tHWND Window, tAxWin3_RichText_LineHandler Handler);
+extern void AxWin3_RichText_EnableScroll(tHWND Window, int bEnable);
+extern void AxWin3_RichText_SetLineCount(tHWND Window, int Lines);
+extern void AxWin3_RichText_SetColCount(tHWND Window, int Cols);
+extern void AxWin3_RichText_SetBackground(tHWND Window, uint32_t ARGB_Colour);
+extern void AxWin3_RichText_SetDefaultColour(tHWND Window, uint32_t ARGB_Colour);
+extern void AxWin3_RichText_SetFont(tHWND Window, const char *FontName, int PointSize);
+extern void AxWin3_RichText_SetCursorType(tHWND Window, int Type);
+extern void AxWin3_RichText_SetCursorBlink(tHWND Window, int bBlink);
+extern void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column);
+extern void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text);
+
+#endif
+
// --- Element Creation
extern tAxWin3_Widget *AxWin3_Widget_AddWidget(tAxWin3_Widget *Parent, int Type, int Flags, const char *DebugName);
+extern tAxWin3_Widget *AxWin3_Widget_AddWidget_SubWindow(tAxWin3_Widget *Parent, tHWND Window, int Flags, const char *DebugName);
extern void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget);
// --- Callbacks
-include ../Makefile.cfg\r
\r
CPPFLAGS += \r
-CFLAGS += \r
+CFLAGS += -Werror -Wextra\r
ASFLAGS +=\r
-LDFLAGS += -soname libc.so -Map map.txt -lgcc\r
+LDFLAGS += -soname libc.so -Map map.txt\r
\r
INCFILES := stdio.h stdlib.h\r
\r
OBJ = stub.o heap.o stdlib.o env.o fileIO.o string.o select.o rand.o\r
-OBJ += perror.o\r
+OBJ += perror.o scanf.o signals.o\r
OBJ += arch/$(ARCHDIR).ao\r
# signals.o\r
DEPFILES := $(OBJ:%.o=%.d)\r
///\note Initialised in SoMain\r
\r
// === CODE ===\r
+int _fopen_modetoflags(const char *mode)\r
+{\r
+ int flags = 0;\r
+ \r
+ // Get main mode\r
+ switch(*mode)\r
+ {\r
+ case 'r': flags = FILE_FLAG_MODE_READ; break;\r
+ case 'w': flags = FILE_FLAG_MODE_WRITE; break;\r
+ case 'a': flags = FILE_FLAG_MODE_APPEND; break;\r
+ case 'x': flags = FILE_FLAG_MODE_EXEC; break; // Acess addon\r
+ default:\r
+ return -1;\r
+ }\r
+ mode ++;\r
+\r
+ // Get Modifiers\r
+ for( ; *mode; mode ++ )\r
+ {\r
+ switch(*mode)\r
+ {\r
+ case 'b': flags |= FILE_FLAG_M_BINARY; break;\r
+ case '+': flags |= FILE_FLAG_M_EXT; break;\r
+ default:\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ return flags;\r
+}\r
+\r
/**\r
* \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
*/\r
EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
{\r
int openFlags = 0;\r
- int i;\r
\r
// Sanity Check Arguments\r
if(!fp || !file || !mode) return NULL;\r
\r
- if(fp->Flags) {\r
+ if(fp->FD != -1) {\r
fflush(fp);\r
- } else\r
- fp->FD = -1;\r
- \r
- // Get main mode\r
- switch(mode[0])\r
- {\r
- case 'r': fp->Flags = FILE_FLAG_MODE_READ; break;\r
- case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break;\r
- case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break;\r
- case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break;\r
- default:\r
- return NULL;\r
- }\r
- // Get Modifiers\r
- for(i=1;mode[i];i++)\r
- {\r
- switch(mode[i])\r
- {\r
- case '+': fp->Flags |= FILE_FLAG_M_EXT;\r
- }\r
}\r
+\r
+ // Get stdio flags\r
+ fp->Flags = _fopen_modetoflags(mode);\r
+ if(fp->Flags == -1)\r
+ return NULL;\r
\r
// Get Open Flags\r
- switch(mode[0])\r
+ switch(fp->Flags & FILE_FLAG_MODE_MASK)\r
{\r
// Read\r
- case 'r': openFlags = OPENFLAG_READ;\r
+ case FILE_FLAG_MODE_READ:\r
+ openFlags = OPENFLAG_READ;\r
if(fp->Flags & FILE_FLAG_M_EXT)\r
openFlags |= OPENFLAG_WRITE;\r
break;\r
// Write\r
- case 'w': openFlags = OPENFLAG_WRITE;\r
+ case FILE_FLAG_MODE_WRITE:\r
+ openFlags = OPENFLAG_WRITE;\r
if(fp->Flags & FILE_FLAG_M_EXT)\r
openFlags |= OPENFLAG_READ;\r
break;\r
// Execute\r
- case 'x': openFlags = OPENFLAG_EXEC;\r
+ case FILE_FLAG_MODE_APPEND:\r
+ openFlags = OPENFLAG_APPEND;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_READ;\r
+ break;\r
+ // Execute\r
+ case FILE_FLAG_MODE_EXEC:\r
+ openFlags = OPENFLAG_EXEC;\r
break;\r
}\r
\r
return NULL;\r
}\r
\r
- if(mode[0] == 'a') {\r
+ if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {\r
seek(fp->FD, 0, SEEK_END); //SEEK_END\r
}\r
\r
return freopen(file, mode, retFile);\r
}\r
\r
+EXPORT FILE *fmemopen(void *buffer, size_t length, const char *mode)\r
+{\r
+ FILE *ret;\r
+ \r
+ if( !buffer || !mode ) return NULL;\r
+ \r
+ ret = get_file_struct();\r
+ \r
+ ret->FD = -2;\r
+ ret->Flags = _fopen_modetoflags(mode);\r
+ if(ret->Flags == -1) {\r
+ ret->Flags = 0;\r
+ return NULL;\r
+ }\r
+ \r
+ ret->Buffer = buffer;\r
+ ret->BufferStart = 0;\r
+ ret->BufferSize = length;\r
+ \r
+ return ret;\r
+}\r
+\r
EXPORT int fclose(FILE *fp)\r
{\r
- close(fp->FD);\r
+ fflush(fp);\r
+ if( fp->FD != -1 ) {\r
+ close(fp->FD);\r
+ }\r
fp->Flags = 0;\r
fp->FD = -1;\r
return 0;\r
\r
EXPORT void fflush(FILE *fp)\r
{\r
- ///\todo Implement\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
+ \r
+ if( !(fp->Flags & FILE_FLAG_DIRTY) )\r
+ return ;\r
+ \r
+ // Nothing to do for memory files\r
+ if( fp->FD == -2 )\r
+ return ;\r
}\r
\r
-EXPORT void clearerr(FILE *stream)\r
+EXPORT void clearerr(FILE *fp)\r
{\r
- /// \todo Impliment\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
+ \r
+ // TODO: Impliment clearerr()\r
}\r
\r
-EXPORT int feof(FILE *stream)\r
+EXPORT int feof(FILE *fp)\r
{\r
- return 0; //stream->; // ?\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
+ return !!(fp->Flags & FILE_FLAG_EOF);\r
}\r
\r
-EXPORT int ferror(FILE *stream)\r
+EXPORT int ferror(FILE *fp)\r
{\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
return 0;\r
}\r
EXPORT int fileno(FILE *stream)\r
\r
EXPORT off_t ftell(FILE *fp)\r
{\r
- if(!fp || !fp->FD) return -1;\r
- \r
- return tell(fp->FD);\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 )\r
+ return fp->Pos; \r
+ else\r
+ return tell(fp->FD);\r
}\r
\r
EXPORT int fseek(FILE *fp, long int amt, int whence)\r
{\r
- if(!fp || !fp->FD) return -1;\r
- \r
- return seek(fp->FD, amt, whence);\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ switch(whence)\r
+ {\r
+ case SEEK_CUR:\r
+ fp->Pos += amt;\r
+ break;\r
+ case SEEK_SET:\r
+ fp->Pos = amt;\r
+ break;\r
+ case SEEK_END:\r
+ if( fp->BufferSize < (size_t)amt )\r
+ fp->Pos = 0;\r
+ else\r
+ fp->Pos = fp->BufferSize - amt;\r
+ break;\r
+ }\r
+ if(fp->Pos > (off_t)fp->BufferSize) {\r
+ fp->Pos = fp->BufferSize;\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ }\r
+ return 0;\r
+ }\r
+ else\r
+ return seek(fp->FD, amt, whence);\r
}\r
\r
\r
vsnprintf(buf, size+1, (char*)format, args);\r
\r
// Write to stream\r
- write(fp->FD, buf, size);\r
- \r
- // Free buffer\r
- free(buf);\r
+ fwrite(buf, size, 1, fp);\r
\r
// Return written byte count\r
return size;\r
*/\r
EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
- \r
- ret = write(fp->FD, ptr, size*num);\r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy((char*)fp->Buffer + fp->Pos, ptr, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else { \r
+ ret = write(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
\r
return ret;\r
}\r
*/\r
EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
-\r
- // TODO: Fit the spec better with the return value \r
- ret = read(fp->FD, ptr, size*num);\r
- \r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy(ptr, (char*)fp->Buffer + fp->Pos, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else {\r
+ ret = read(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
+ \r
return ret;\r
}\r
\r
*/\r
EXPORT int fputc(int c, FILE *fp)\r
{\r
- if(!fp || !fp->FD) return -1;\r
- return write(fp->FD, &c, 1);\r
+ return fwrite(&c, 1, 1, fp);\r
}\r
\r
EXPORT int putchar(int c)\r
EXPORT int fgetc(FILE *fp)\r
{\r
char ret = 0;\r
- if(!fp) return -1;\r
- if(read(fp->FD, &ret, 1) == -1) return -1;\r
+ if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+ return -1;\r
return ret;\r
}\r
\r
int i;\r
for(i=0;i<STDIO_MAX_STREAMS;i++)\r
{\r
- if(_iob[i].Flags == 0) return &_iob[i];\r
+ if(_iob[i].Flags & FILE_FLAG_ALLOC)\r
+ continue ;\r
+ _iob[i].Flags |= FILE_FLAG_ALLOC;\r
+ _iob[i].FD = -1;\r
+ _iob[i].Pos = 0;\r
+ return &_iob[i];\r
}\r
return NULL;\r
}\r
{\r
char tmp[65];\r
int c, minSize, precision, len;\r
- int pos = 0;\r
+ size_t pos = 0;\r
char *p;\r
char pad;\r
uint64_t arg;\r
*/\r
EXPORT int printf(const char *format, ...)\r
{\r
- #if 1\r
int size;\r
va_list args;\r
\r
free(buf);\r
// Return\r
return size;\r
- \r
- #else\r
- \r
- int ret;\r
- va_list args;\r
- va_start(args, format);\r
- ret = fprintfv(stdout, (char*)format, args);\r
- va_end(args);\r
- return ret;\r
- #endif\r
}\r
\r
/**\r
DEBUGS("free(%p) : 0x%x bytes", mem, head->size);\r
\r
//Unify Right\r
- if((intptr_t)head + head->size < (intptr_t)_heap_end)\r
+ if((uintptr_t)head + head->size < (uintptr_t)_heap_end)\r
{\r
heap_head *nextHead = (heap_head*)((intptr_t)head + head->size);\r
if(nextHead->magic == MAGIC_FREE) { //Is the next block free\r
}\r
}\r
//Unify Left\r
- if((intptr_t)head - sizeof(heap_foot) > (intptr_t)_heap_start)\r
+ if((uintptr_t)head - sizeof(heap_foot) > (uintptr_t)_heap_start)\r
{\r
heap_head *prevHead;\r
heap_foot *prevFoot = (heap_foot *)((intptr_t)head - sizeof(heap_foot));\r
if(ch == '\n') return 1;
return 0;
}
+// C99
+static inline int isblank(int ch) {
+ if(ch == ' ') return 1;
+ if(ch == '\t') return 1;
+ return 0;
+}
#endif
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
+typedef void (*sighandler_t)(int);
+
#define SIG_DFL ((void*)0)
#define SIG_ERR ((void*)-1)
#define SIGPIPE 1001
#define SIGCHLD 1002
+extern int raise(int sig);
+
#endif
extern int fprintf(FILE *fp, const char *format, ...);
extern int vfprintf(FILE *fp, const char *format, va_list args);
+// scanf
+extern int scanf(const char *format, ...);
+extern int fscanf(FILE *stream, const char *format, ...);
+extern int sscanf(const char *str, const char *format, ...);
+extern int vscanf(const char *format, va_list ap);
+extern int vsscanf(const char *str, const char *format, va_list ap);
+extern int vfscanf(FILE *stream, const char *format, va_list ap);
+
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
extern long strtol(const char *ptr, char **end, int base);\r
extern int atoi(const char *ptr);\r
extern void exit(int status) __attribute__((noreturn));\r
+extern void abort(void);\r
extern void atexit(void (*__func)(void));\r
extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));\r
extern int abs(int j);\r
#define LOCAL\r
#endif\r
\r
+#define UNUSED(type, param) __attribute__((unused)) type UNUSED__##param\r
+\r
extern void *memcpy(void *dest, const void *src, size_t n);\r
\r
typedef struct sCPUID tCPUID;\r
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * scanf.c
+ * - *scanf family of functions
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+
+extern void _SysDebug(const char *format, ...);
+
+enum e_vcscanf_types
+{
+ _VCSCANF_NOTYPE,
+ _VCSCANF_INT,
+ _VCSCANF_REAL,
+};
+
+enum e_vcscanf_sizes
+{
+ _VCSCANF_UNDEF,
+ _VCSCANF_CHAR,
+ _VCSCANF_SHORT,
+ _VCSCANF_LONG,
+ _VCSCANF_LONGLONG,
+ _VCSCANF_INTMAX,
+ _VCSCANF_SIZET,
+ _VCSCANF_PTRDIFF,
+ _VCSCANF_LONGDOUBLE
+};
+
+// === CODE ===
+int _vcscanf_int(int (*__getc)(void *), void (*__rewind)(void*), void *h, int base, int maxlen, long long *outval)
+{
+ char ich;
+ int sgn = 1;
+ long long int ret = 0;
+ int n_read = 0;
+
+ // Initialise output to something sane
+ *outval = 0;
+
+ // First character
+ // - maxlen == 0 means no limit
+ ich = __getc(h);
+ n_read ++;
+
+ // Sign?
+ if( ich == '-' || ich == '+' ) {
+ sgn = (ich == '-' ? -1 : 1);
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ }
+
+ // Determine base
+ if( base == 0 ) {
+ if( ich != '0' ) {
+ base = 10;
+ }
+ else {
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ if( ich != 'x' ) {
+ base = 8;
+ }
+ else {
+ base = 16;
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ }
+ }
+ }
+
+ if( ich == 0 ) {
+ // Oops?
+ return n_read;
+ }
+
+ while( ich )
+ {
+ int next = -1;
+
+ // Get the digit value
+ if( base <= 10 ) {
+ if( '0' <= ich && ich <= '0'+base-1 )
+ next = ich - '0';
+ }
+ else {
+ if( '0' <= ich && ich <= '9' )
+ next = ich - '0';
+ if( 'A' <= ich && ich <= 'A'+base-10-1 )
+ next = ich - 'A' + 10;
+ if( 'a' <= ich && ich <= 'a'+base-10-1 )
+ next = ich - 'a' + 10;
+ }
+ // if it's not a digit, rewind and break
+ if( next < 0 ) {
+ __rewind(h);
+ n_read --;
+ break;
+ }
+
+ // Add to the result
+ ret *= base;
+ ret += next;
+ //_SysDebug("- %i/%i read, 0x%x val", n_read, maxlen, ret);
+
+ // Check if we've reached the limit
+ if( n_read == maxlen )
+ break ;
+
+ // Next character
+ ich = __getc(h);
+ n_read ++;
+ }
+
+ // Apply sign
+ if( sgn == -1 )
+ ret = -ret;
+
+ *outval = ret;
+ return n_read;
+}
+
+int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char *format, va_list ap)
+{
+ char fch, ich;
+ int ret = 0, nch = 0;
+
+ while( (fch = *format++) )
+ {
+ union {
+ void *_void;
+ char *_char;
+ short *_short;
+ int *_int;
+ long *_long;
+ long long *_longlong;
+ } ptr;
+ long long ival;
+ //long double rval;
+ int maxlen = 0, offset = -1;
+ enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
+ enum e_vcscanf_types valtype;
+
+ const char *set_start;
+ int set_len;
+
+ // Whitespace matches any ammount of whitespace (including none)
+ if( isspace(fch) )
+ {
+ while( (ich = __getc(h)) && isspace(ich) )
+ nch ++;
+ continue ;
+ }
+
+ // Any non-whitespace and non-% characters must match exactly
+ if( fch != '%' )
+ {
+ if( __getc(h) != fch )
+ break;
+ nch ++;
+ continue ;
+ }
+
+ // Format specifier
+ fch = *format++;
+ if(!fch) break;
+
+ // Catch '%%' early
+ if( fch == '%' ) {
+ if( __getc(h) != '%' )
+ break;
+ nch ++;
+ continue ;
+ }
+
+ // %n$ - Direct offset selection, shouldn't be mixed with just %
+ for( ; isdigit(fch); fch = *format++ )
+ maxlen = maxlen * 10 + (fch - '0');
+ if( fch == '$' ) {
+ offset = maxlen;
+ maxlen = 0;
+ }
+
+ // Supress assignemnt?
+ if( fch == '*' )
+ {
+ fch = *format++;
+ ptr._void = NULL;
+ ret --;
+ }
+ else
+ ptr._void = va_arg(ap, void*);
+
+ // Max field length
+ while( isdigit(fch) )
+ {
+ maxlen = maxlen * 10 + fch - '0';
+ fch = *format++;
+ }
+
+ // Length modifier
+ switch( fch )
+ {
+ case 'h':
+ // 'short'
+ size = _VCSCANF_SHORT;
+ fch = *format++;
+ if( fch == 'h' ) {
+ // 'char'
+ size = _VCSCANF_CHAR;
+ fch = *format++;
+ }
+ break;
+ case 'l':
+ // 'long'
+ size = _VCSCANF_LONG;
+ fch = *format++;
+ if( fch == 'l' ) {
+ // 'long long'
+ size = _VCSCANF_LONGLONG;
+ fch = *format++;
+ }
+ break;
+ case 'j':
+ // '(u)intmax_t'
+ size = _VCSCANF_INTMAX;
+ fch = *format++;
+ break;
+ case 'z':
+ // 'size_t'
+ size = _VCSCANF_SIZET;
+ fch = *format++;
+ break;
+ case 't':
+ // 'ptrdiff_t'
+ size = _VCSCANF_PTRDIFF;
+ fch = *format++;
+ break;
+ case 'L':
+ // 'long double' (a, A, e, E, f, F, g, G)
+ size = _VCSCANF_LONGDOUBLE;
+ fch = *format++;
+ break;
+ }
+
+ // Format specifiers
+ switch( fch )
+ {
+ // Decimal integer
+ case 'd':
+ nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // variable-base integer
+ case 'i':
+ nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // Octal integer
+ case 'o':
+ nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // Hexadecimal integer
+ case 'x': case 'X':
+ nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // strtod format float
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'g': case 'G':
+ valtype = _VCSCANF_REAL;
+ break;
+ // `maxlen` or 1 characters
+ case 'c':
+ if( maxlen == 0 )
+ maxlen = 1;
+ while( maxlen -- && (ich = __getc(h)) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ // sequence of non-whitespace characters
+ case 's':
+ if( maxlen == 0 )
+ maxlen = -1;
+
+ ich = 0;
+ while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ if( maxlen >= 0 && ich )
+ __rewind(h);
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ // match a set of characters
+ case '[':
+ fch = *format++;
+ if( fch == '^' ) {
+ // Invert
+ fch = *format;
+ }
+ set_start = format;
+ set_len = 0;
+ // if the first character is ']' it's part of the set
+ do {
+ // permissable character
+ set_len ++;
+ fch = *format++;
+ } while( fch && fch != ']' );
+
+ ich = 0;
+ while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ if( maxlen >= 0 && ich )
+ __rewind(h);
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ case 'p': // read back printf("%p")
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ case 'n': // number of read characters to this point
+ if(ptr._int) {
+ *ptr._int = nch;
+ ret --; // negates the ret ++ at the end
+ }
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ default:
+ // Implimentation defined
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ }
+
+ switch(valtype)
+ {
+ case _VCSCANF_NOTYPE:
+ // Used when assignment is done above
+ break;
+ case _VCSCANF_INT:
+ switch(size)
+ {
+ case _VCSCANF_UNDEF: *ptr._int = ival; break;
+ case _VCSCANF_CHAR: *ptr._char = ival; break;
+ case _VCSCANF_SHORT: *ptr._short = ival; break;
+ case _VCSCANF_LONG: *ptr._long = ival; break;
+ case _VCSCANF_LONGLONG: *ptr._longlong = ival; break;
+ default: // ???
+ break;
+ }
+ break;
+ case _VCSCANF_REAL:
+ break;
+ }
+
+ ret ++;
+ }
+
+ return ret;
+}
+
+int _vsscanf_getc(void *h)
+{
+ const char **ibuf = h;
+ return *(*ibuf)++; // Dereference, read for return, increment
+}
+
+void _vsscanf_rewind(void *h)
+{
+ const char **ibuf = h;
+ (*ibuf) --; // NOTE: Breaks if there's a rewind before a getc, but that shouldn't happen
+}
+
+int vscanf(const char *format, va_list ap)
+{
+ return vfscanf(stdin, format, ap);
+}
+
+int vsscanf(const char *str, const char *format, va_list ap)
+{
+ return _vcscanf(_vsscanf_getc, _vsscanf_rewind, &str, format, ap);
+}
+
+int _vfscanf_getc(void *h)
+{
+ return fgetc(h); // TODO: Handle -1 -> 0
+}
+void _vfscanf_rewind(void *h)
+{
+ fseek(h, -1, SEEK_CUR);
+}
+
+int vfscanf(FILE *stream, const char *format, va_list ap)
+{
+ return _vcscanf(_vfscanf_getc, _vfscanf_rewind, stream, format, ap);
+}
+
+int scanf(const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vfscanf(stdin, format, args);
+ va_end(args);
+ return rv;
+}
+int fscanf(FILE *stream, const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vfscanf(stream, format, args);
+ va_end(args);
+ return rv;
+}
+int sscanf(const char *str, const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vsscanf(str, format, args);
+ va_end(args);
+ return rv;
+}
+
* AcessOS Basic C Library
* signals.c
*/
-#include <syscalls.h>
+//#include <acess/sys.h>
#include <stdlib.h>
#include <signal.h>
#include "lib.h"
sighandlers[num] = handler;
return prev;
}
+
+int raise(int signal)
+{
+ if( signal < 0 || signal > NUM_SIGNALS )
+ return 1;
+ switch(signal)
+ {
+ case SIGABRT:
+ abort();
+ break;
+ }
+ return 0;
+}
+
+void abort(void)
+{
+ // raise(SIGABRT);
+ _exit(-1);
+}
* Configuration Options
*/
#ifndef _STDIO_INT_H
-# define _STDIO_INT_H
+#define _STDIO_INT_H
+
+#include <sys/types.h>
+#include <stddef.h>
// === CONSTANTS ===
-#define FILE_FLAG_MODE_MASK 0x07
-#define FILE_FLAG_MODE_READ 0x01
-#define FILE_FLAG_MODE_WRITE 0x02
-#define FILE_FLAG_MODE_EXEC 0x03
-#define FILE_FLAG_MODE_APPEND 0x04
-#define FILE_FLAG_M_EXT 0x10
+#define FILE_FLAG_MODE_MASK 0x0007
+#define FILE_FLAG_MODE_READ 0x0001
+#define FILE_FLAG_MODE_WRITE 0x0002
+#define FILE_FLAG_MODE_EXEC 0x0003
+#define FILE_FLAG_MODE_APPEND 0x0004
+#define FILE_FLAG_M_EXT 0x0010
+#define FILE_FLAG_M_BINARY 0x0020
+#define FILE_FLAG_EOF 0x0100
+#define FILE_FLAG_DIRTY 0x0200
+#define FILE_FLAG_ALLOC 0x1000
// === TYPES ===
struct sFILE {
- int FD;
int Flags;
+ int FD;
+ off_t Pos;
+
#if DEBUG_BUILD
- char *FileName;
- #endif
- #if STDIO_LOCAL_BUFFER
- char *Buffer;
- Uint64 BufferStart;
- int BufferSize;
+ char *FileName; // heap
#endif
+ void *Buffer;
+ off_t BufferStart;
+ size_t BufferSize;
};
#endif
*/\r
EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
{\r
- int i, j, min;\r
+ size_t i, j, min;\r
// With 0 items, there's nothing to do and with 1 its already sorted\r
if(nmemb == 0 || nmemb == 1) return;\r
\r
char *sp = (char *)src;
char *dp = (char *)dest;
// Check if the areas overlap
- if( (intptr_t)src < (intptr_t)dest && (intptr_t)dest < (intptr_t)src+count )
+ if( (uintptr_t)src < (uintptr_t)dest && (uintptr_t)dest < (uintptr_t)src+count )
for(;count--;)
dp[count] = sp[count];
else
* \param argv Unused - Arguments (NULL for current version of ld-acess)\r
* \param envp Environment Pointer\r
*/\r
-int SoMain(unsigned int BaseAddress, int argc, char **argv, char **envp)\r
+int SoMain(UNUSED(uintptr_t, BaseAddress), UNUSED(int, argc), UNUSED(char **, argv), char **envp)\r
{\r
// Init for env.c\r
_envp = envp;\r