diff --git a/src/Core.h b/src/Core.h index 67fe182d4..439cb5e5e 100644 --- a/src/Core.h +++ b/src/Core.h @@ -286,6 +286,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_BEARSSL #define CC_BUILD_LOWMEM #define CC_BUILD_CONSOLE + #define CC_BUILD_TOUCH #undef CC_BUILD_FREETYPE #elif defined GEKKO #define CC_BUILD_GCWII diff --git a/src/Graphics.h b/src/Graphics.h index f0513fe50..16af4c859 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -238,6 +238,9 @@ void Gfx_OnWindowResize(void); /* NOTE: Each line is separated by \n */ void Gfx_GetApiInfo(cc_string* info); +void Gfx_3DS_DrawToTopScreen(void); +void Gfx_3DS_DrawToBottomScreen(void); + /* Raises ContextLost event and updates state for lost contexts */ void Gfx_LoseContext(const char* reason); /* Raises ContextRecreated event and restores internal state */ diff --git a/src/Graphics_3DS.c b/src/Graphics_3DS.c index 13d7d4065..2c90aa33a 100644 --- a/src/Graphics_3DS.c +++ b/src/Graphics_3DS.c @@ -106,7 +106,8 @@ static void SwitchProgram(void) { /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* *#########################################################################################################################*/ -static C3D_RenderTarget* target; +static C3D_RenderTarget* topTarget; +static C3D_RenderTarget* bottomTarget; static void AllocShaders(void) { Shader_Alloc(&shaders[0], coloured_shbin, coloured_shbin_size); @@ -129,9 +130,16 @@ static void SetDefaultState(void) { static void InitCitro3D(void) { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); - target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + topTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(topTarget, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + + // Even though the bottom screen is 320 pixels wide, we use 400 here so that the same ortho matrix + // can be used for both screens. The output is clipped to the actual screen width, anyway. + bottomTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(bottomTarget, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + + gfxSetDoubleBuffering(GFX_TOP, true); SetDefaultState(); AllocShaders(); } @@ -173,6 +181,14 @@ void Gfx_FreeState(void) { Gfx_DeleteTexture(&white_square); } +void Gfx_3DS_DrawToTopScreen(void) { + C3D_FrameDrawOn(topTarget); +} + +void Gfx_3DS_DrawToBottomScreen(void) { + C3D_FrameDrawOn(bottomTarget); +} + /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ @@ -355,11 +371,12 @@ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { void Gfx_BeginFrame(void) { int flags = gfx_vsync ? C3D_FRAME_SYNCDRAW : 0; C3D_FrameBegin(flags); + C3D_FrameDrawOn(topTarget); } void Gfx_Clear(void) { - C3D_RenderTargetClear(target, C3D_CLEAR_ALL, clear_color, 0); - C3D_FrameDrawOn(target); + C3D_RenderTargetClear(topTarget, C3D_CLEAR_ALL, clear_color, 0); + C3D_RenderTargetClear(bottomTarget, C3D_CLEAR_ALL, 0, 0); } void Gfx_EndFrame(void) { @@ -780,4 +797,4 @@ void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color) { C3D_ImmSendAttrib(v[0].U, v[0].V, 0.0f, 0.0f); C3D_ImmDrawEnd(); } -#endif \ No newline at end of file +#endif diff --git a/src/Gui.c b/src/Gui.c index 9844dbfcd..4824c5039 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -21,7 +21,9 @@ struct _GuiData Gui; struct Screen* Gui_Screens[GUI_MAX_SCREENS]; static cc_uint8 priorities[GUI_MAX_SCREENS]; - +#ifdef __3DS__ +static struct Texture touchBgTex; +#endif /*########################################################################################################################* *----------------------------------------------------------Gui------------------------------------------------------------* @@ -32,10 +34,14 @@ static CC_NOINLINE int GetWindowScale(void) { /* Use larger UI scaling on mobile */ /* TODO move this DPI scaling elsewhere.,. */ +#ifndef __3DS__ if (!Input_TouchMode) { +#endif widthScale /= DisplayInfo.ScaleX; heightScale /= DisplayInfo.ScaleY; +#ifndef __3DS__ } +#endif return 1 + (int)(min(widthScale, heightScale)); } @@ -137,12 +143,16 @@ void Gui_LayoutAll(void) { struct Screen* s; int i; + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + for (i = 0; i < Gui.ScreensCount; i++) { s = Gui_Screens[i]; s->VTABLE->Layout(s); s->dirty = true; } + + Window_3DS_SetRenderScreen(scr); } void Gui_RefreshAll(void) { @@ -152,10 +162,14 @@ void Gui_RefreshAll(void) { } void Gui_Refresh(struct Screen* s) { + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + s->VTABLE->ContextLost(s); s->VTABLE->ContextRecreated(s); s->VTABLE->Layout(s); s->dirty = true; + + Window_3DS_SetRenderScreen(scr); } static void Gui_AddCore(struct Screen* s, int priority) { @@ -179,6 +193,8 @@ static void Gui_AddCore(struct Screen* s, int priority) { priorities[i] = priority; Gui.ScreensCount++; + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + s->dirty = true; s->VTABLE->Init(s); s->VTABLE->ContextRecreated(s); @@ -189,6 +205,8 @@ static void Gui_AddCore(struct Screen* s, int priority) { { s->VTABLE->HandlesPointerMove(s, i, Pointers[i].x, Pointers[i].y); } + + Window_3DS_SetRenderScreen(scr); } /* Returns index of the given screen in the screens list, -1 if not */ @@ -283,6 +301,12 @@ void Gui_RenderGui(double delta) { struct Screen* s; int i; + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + +#ifdef __3DS__ + Texture_Render(&touchBgTex); +#endif + /* Draw back to front so highest priority screen is on top */ for (i = Gui.ScreensCount - 1; i >= 0; i--) { @@ -292,6 +316,8 @@ void Gui_RenderGui(double delta) { if (s->dirty) { s->VTABLE->BuildMesh(s); s->dirty = false; } s->VTABLE->Render(s, delta); } + + Window_3DS_SetRenderScreen(scr); } @@ -449,22 +475,26 @@ int Screen_DoPointerDown(void* screen, int id, int x, int y) { struct Screen* s = (struct Screen*)screen; struct Widget** widgets = s->widgets; int i, count = s->numWidgets; + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); /* iterate backwards (because last elements rendered are shown over others) */ for (i = count - 1; i >= 0; i--) { struct Widget* w = widgets[i]; if (!w || !Widget_Contains(w, x, y)) continue; - if (w->flags & WIDGET_FLAG_DISABLED) return i; + if (w->flags & WIDGET_FLAG_DISABLED) break; if (w->MenuClick) { w->MenuClick(s, w); } else { Elem_HandlesPointerDown(w, id, x, y); } - return i; + break; } - return -1; + + Window_3DS_SetRenderScreen(scr); + + return i; } int Screen_Index(void* screen, void* widget) { @@ -568,7 +598,6 @@ static void TouchPngProcess(struct Stream* stream, const cc_string* name) { } static struct TextureEntry touch_entry = { "touch.png", TouchPngProcess }; - static void OnFontChanged(void* obj) { Gui_RefreshAll(); } static void OnKeyPress(void* obj, int cp) { @@ -612,6 +641,19 @@ static void OnInit(void) { TextureEntry_Register(&icons_entry); TextureEntry_Register(&touch_entry); +#ifdef __3DS__ + struct Context2D ctx; + Context2D_Alloc(&ctx, 32, 32); + Gradient_Noise(&ctx, BitmapColor_RGB(0x40, 0x30, 0x20), 6, 0, 0, ctx.width, ctx.height); + Context2D_MakeTexture(&touchBgTex, &ctx); + Context2D_Free(&ctx); + // Tile the texture to fill the entire screen + int tilesX = (320 + ctx.width - 1) / ctx.width; + int tilesY = (240 + ctx.height - 1) / ctx.height; + touchBgTex.Width *= tilesX; touchBgTex.Height *= tilesY; + touchBgTex.uv.U2 *= tilesX; touchBgTex.uv.V2 *= tilesY; +#endif + Event_Register_(&ChatEvents.FontChanged, NULL, OnFontChanged); Event_Register_(&GfxEvents.ContextLost, NULL, OnContextLost); Event_Register_(&GfxEvents.ContextRecreated, NULL, OnContextRecreated); diff --git a/src/Launcher.c b/src/Launcher.c index 1e2b389c8..335ccde6e 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -114,6 +114,7 @@ cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const if (res) { Logger_SysWarn(res, "starting game"); return false; } Launcher_ShouldExit = Platform_SingleProcess || Options_GetBool(LOPT_AUTO_CLOSE, false); + return true; } @@ -235,6 +236,8 @@ void Launcher_Run(void) { } #endif + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + Drawer2D_Component.Init(); SystemFonts_Component.Init(); Drawer2D.BitmappedText = false; @@ -295,6 +298,8 @@ void Launcher_Run(void) { if (Window_Main.Exists) Window_RequestClose(); #endif + + Window_3DS_SetRenderScreen(scr); } @@ -527,17 +532,43 @@ void Launcher_DrawTitle(struct FontDesc* font, const char* text, struct Context2 cc_string title = String_FromReadonly(text); struct DrawTextArgs args; int x; + int y; /* Skip dragging logo when very small window to save space */ if (Window_Main.Height < 240) return; +#ifdef __3DS__ + /* Put title on top screen */ + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); + struct Bitmap bmp; + struct Context2D topCtx; + + ctx = &topCtx; + bmp.width = max(Window_Main.Width, 1); + bmp.height = max(Window_Main.Height, 1); + Window_AllocFramebuffer(&bmp); + Context2D_Wrap(ctx, &bmp); + Launcher_DrawBackgroundAll(ctx); +#endif + DrawTextArgs_Make(&args, &title, font, false); x = ctx->width / 2 - Drawer2D_TextWidth(&args) / 2; + y = 0; + +#ifdef __3DS__ + // vertically center the title + y = ctx->height / 2 - Drawer2D_TextHeight(&args) / 2; +#endif Drawer2D.Colors['f'] = BITMAPCOLOR_BLACK; - Context2D_DrawText(ctx, &args, x + Display_ScaleX(4), Display_ScaleY(4)); + Context2D_DrawText(ctx, &args, x + Display_ScaleX(4), y + Display_ScaleY(4)); Drawer2D.Colors['f'] = BITMAPCOLOR_WHITE; - Context2D_DrawText(ctx, &args, x, 0); + Context2D_DrawText(ctx, &args, x, y); + +#ifdef __3DS__ + Window_DrawFramebuffer((Rect2D){ 0, 0, bmp.width, bmp.height }); + Window_3DS_SetRenderScreen(scr); +#endif } void Launcher_MakeTitleFont(struct FontDesc* font) { diff --git a/src/Platform_3DS.c b/src/Platform_3DS.c index d5c4ab7b4..fad6b52f5 100644 --- a/src/Platform_3DS.c +++ b/src/Platform_3DS.c @@ -56,6 +56,10 @@ void Platform_Log(const char* msg, int len) { write(STDOUT_FILENO, msg, len); write(STDOUT_FILENO, "\n", 1); + + // output to debug service (visible in Citra with log level set to "*:Debug", or on console via remote gdb) + svcOutputDebugString(msg, len); + svcOutputDebugString("\n", 1); } #define UnixTime_TotalMS(time) ((cc_uint64)time.tv_sec * 1000 + UNIX_EPOCH + (time.tv_usec / 1000)) diff --git a/src/Screens.c b/src/Screens.c index 0bc607ddb..343391c86 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -202,9 +202,11 @@ static void HUDScreen_ContextRecreated(void* screen) { } static int HUDScreen_LayoutHotbar(void) { + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); struct HUDScreen* s = &HUDScreen_Instance; s->hotbar.scale = Gui_GetHotbarScale(); Widget_Layout(&s->hotbar); + Window_3DS_SetRenderScreen(scr); return s->hotbar.height; } @@ -337,6 +339,7 @@ static void HUDScreen_BuildCrosshairsMesh(struct VertexTextured** ptr) { /* Only top quarter of icons.png is used */ static struct Texture tex = { 0, Tex_Rect(0,0,0,0), Tex_UV(0.0f,0.0f, 15/256.0f,15/64.0f) }; int extent; + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); extent = (int)(CH_EXTENT * Gui_Scale(Window_Main.Height / 480.0f)); tex.x = (Window_Main.Width / 2) - extent; @@ -345,6 +348,8 @@ static void HUDScreen_BuildCrosshairsMesh(struct VertexTextured** ptr) { tex.Width = extent * 2; tex.Height = extent * 2; Gfx_Make2DQuad(&tex, PACKEDCOL_WHITE, ptr); + + Window_3DS_SetRenderScreen(scr); } static void HUDScreen_BuildMesh(void* screen) { @@ -369,6 +374,8 @@ static void HUDScreen_Render(void* screen, double delta) { struct HUDScreen* s = (struct HUDScreen*)screen; if (Game_HideGui) return; + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); Gfx_BindDynamicVb(s->vb); if (Gui.ShowFPS) Widget_Render2(&s->line1, 4); @@ -382,15 +389,18 @@ static void HUDScreen_Render(void* screen, double delta) { /* TODO swap these two lines back */ } - if (Gui_GetBlocksWorld()) return; - Gfx_BindDynamicVb(s->vb); - Widget_Render2(&s->hotbar, 12); + if (!Gui_GetBlocksWorld()) { + Gfx_BindDynamicVb(s->vb); + Widget_Render2(&s->hotbar, 12); - if (Gui.IconsTex && !tablist_active) { - Gfx_BindTexture(Gui.IconsTex); - Gfx_BindDynamicVb(s->vb); /* Have to rebind for mobile right now... */ - Gfx_DrawVb_IndexedTris(4); + if (Gui.IconsTex && !tablist_active) { + Gfx_BindTexture(Gui.IconsTex); + Gfx_BindDynamicVb(s->vb); /* Have to rebind for mobile right now... */ + Gfx_DrawVb_IndexedTris(4); + } } + + Window_3DS_SetRenderScreen(scr); } static const struct ScreenVTABLE HUDScreen_VTABLE = { @@ -494,6 +504,8 @@ static void TabListOverlay_Layout(void* screen) { int i, x, y, width = 0, height = 0; int columns = Math_CeilDiv(s->usedCount, LIST_NAMES_PER_COLUMN); + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); + for (i = 0; i < columns; i++) { width += TabListOverlay_GetColumnWidth(s, i); @@ -530,6 +542,8 @@ static void TabListOverlay_Layout(void* screen) { s->title.horAnchor = ANCHOR_CENTRE; s->title.yOffset = s->y + paddingY / 2; Widget_Layout(&s->title); + + Window_3DS_SetRenderScreen(scr); } static void TabListOverlay_AddName(struct TabListOverlay* s, EntityID id, int index) { @@ -804,6 +818,9 @@ static void TabListOverlay_Render(void* screen, double delta) { PackedCol bottomCol = PackedCol_Make(50, 50, 50, 205); if (Game_HideGui || !IsOnlyChatActive()) return; + + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); + Gfx_Draw2DGradient(s->x, s->y, s->width, s->height, topCol, bottomCol); Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); @@ -818,6 +835,8 @@ static void TabListOverlay_Render(void* screen, double delta) { Gfx_DrawVb_IndexedTris_Range(4, offset); offset += 4; } + + Window_3DS_SetRenderScreen(scr); } static void TabListOverlay_Free(void* screen) { @@ -1152,9 +1171,11 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) { #ifdef CC_BUILD_TOUCH if (!Input_TouchMode) return; + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); Elem_Render(&s->more, delta); Elem_Render(&s->send, delta); Elem_Render(&s->cancel, delta); + Window_3DS_SetRenderScreen(scr); #endif } } @@ -1218,6 +1239,8 @@ static void ChatScreen_BuildMesh(void* screen) { } static void ChatScreen_Layout(void* screen) { + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); + struct ChatScreen* s = (struct ChatScreen*)screen; if (ChatScreen_ChatUpdateFont(s)) ChatScreen_Redraw(s); @@ -1248,6 +1271,8 @@ static void ChatScreen_Layout(void* screen) { s->smallAnnouncement.yOffset = Window_Main.Height / 20; Widget_Layout(&s->smallAnnouncement); + Window_3DS_SetRenderScreen(scr); + #ifdef CC_BUILD_TOUCH if (Window_Main.SoftKeyboard == SOFT_KEYBOARD_SHIFT) { Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MAX, 10, 60); @@ -1456,17 +1481,19 @@ static void ChatScreen_Init(void* screen) { static void ChatScreen_Render(void* screen, double delta) { struct ChatScreen* s = (struct ChatScreen*)screen; + enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN); if (Game_HideGui && s->grabsInput) { Elem_Render(&s->input.base, delta); } - if (Game_HideGui) return; + if (!Game_HideGui) { + if (s->grabsInput && !Gui.ClassicChat) { + ChatScreen_DrawChatBackground(s); + } - if (s->grabsInput && !Gui.ClassicChat) { - ChatScreen_DrawChatBackground(s); + ChatScreen_DrawChat(s, delta); } - - ChatScreen_DrawChat(s, delta); + Window_3DS_SetRenderScreen(scr); } static void ChatScreen_Free(void* screen) { diff --git a/src/Widgets.c b/src/Widgets.c index 64766450d..acf9a615a 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -448,16 +448,21 @@ static void HotbarWidget_RenderEntries(struct HotbarWidget* w, int offset) { } static int HotbarWidget_Render2(void* widget, int offset) { + enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN); + struct HotbarWidget* w = (struct HotbarWidget*)widget; HotbarWidget_RenderOutline(w, offset ); HotbarWidget_RenderEntries(w, offset + 8); #ifdef CC_BUILD_TOUCH - if (!Input_TouchMode) return HOTBAR_MAX_VERTICES; - w->ellipsisTex.x = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.Width / 2; - w->ellipsisTex.y = w->y + (w->height / 2) - w->ellipsisTex.Height / 2; - Texture_Render(&w->ellipsisTex); + if (Input_TouchMode) { + w->ellipsisTex.x = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.Width / 2; + w->ellipsisTex.y = w->y + (w->height / 2) - w->ellipsisTex.Height / 2; + Texture_Render(&w->ellipsisTex); + } #endif + + Window_3DS_SetRenderScreen(scr); return HOTBAR_MAX_VERTICES; } diff --git a/src/Window.h b/src/Window.h index 24499d084..f5c182a3c 100644 --- a/src/Window.h +++ b/src/Window.h @@ -233,4 +233,14 @@ void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs); /* Gets OpenGL context specific graphics information. */ void GLContext_GetApiInfo(cc_string* info); #endif + +enum Screen3DS { TOP_SCREEN, BOTTOM_SCREEN }; +#ifdef __3DS__ +/* Selects which screen on the 3DS to render to. Returns the previous screen */ +enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen); +#else +static inline +enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen) { return TOP_SCREEN; } +#endif + #endif diff --git a/src/Window_3DS.c b/src/Window_3DS.c index e4d8b8ae5..7c49c0855 100644 --- a/src/Window_3DS.c +++ b/src/Window_3DS.c @@ -12,9 +12,9 @@ #include "ExtMath.h" #include <3ds.h> -static int touchActive, touchBegX, touchBegY; static cc_bool launcherMode; static Result irrst_result; +static enum Screen3DS renderScreen = TOP_SCREEN; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; @@ -32,7 +32,7 @@ void Window_Init(void) { gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false); //gfxInit(GSP_RGBA8_OES,GSP_RGBA8_OES,false); - consoleInit(GFX_BOTTOM, NULL); + //consoleInit(GFX_BOTTOM, NULL); u16 width, height; gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height); @@ -48,6 +48,7 @@ void Window_Init(void) { Window_Main.Focused = true; Window_Main.Exists = true; + Input_SetTouchMode(true); Input.Sources = INPUT_SOURCE_GAMEPAD; irrst_result = irrstInit(); @@ -58,6 +59,21 @@ void Window_Init(void) { void Window_Free(void) { irrstExit(); } +enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen) { + enum Screen3DS prev = renderScreen; + if (screen != prev) + { + renderScreen = screen; + DisplayInfo.Width = (screen == TOP_SCREEN) ? 400 : 320; + WindowInfo.Width = DisplayInfo.Width; + if (screen == TOP_SCREEN) + Gfx_3DS_DrawToTopScreen(); + else + Gfx_3DS_DrawToBottomScreen(); + } + return prev; +} + void Window_Create2D(int width, int height) { launcherMode = true; } void Window_Create3D(int width, int height) { launcherMode = false; } @@ -112,27 +128,27 @@ static void ProcessJoystickInput(circlePosition* pos, double delta) { } static void ProcessTouchInput(int mods) { + static int currX, currY; // current touch position touchPosition touch; hidTouchRead(&touch); - touchActive = mods & KEY_TOUCH; - - if (touchActive) { - // rescale X from [0, bottom_FB_width) to [0, top_FB_width) - int x = touch.px * Window_Main.Width / GSP_SCREEN_HEIGHT_BOTTOM; - int y = touch.py; - Pointer_SetPosition(0, x, y); + if (hidKeysDown() & KEY_TOUCH) { // stylus went down + currX = touch.px; + currY = touch.py; + Input_AddTouch(0, currX, currY); } - // Set starting position for camera movement - if (hidKeysDown() & KEY_TOUCH) { - touchBegX = touch.px; - touchBegY = touch.py; + else if (mods & KEY_TOUCH) { // stylus is down + currX = touch.px; + currY = touch.py; + Input_UpdateTouch(0, currX, currY); + } + else if (hidKeysUp() & KEY_TOUCH) { // stylus was lifted + Input_RemoveTouch(0, currX, currY); } } void Window_ProcessEvents(double delta) { hidScanInput(); - /* TODO implement */ - + if (!aptMainLoop()) { Window_Main.Exists = false; Window_RequestClose(); @@ -141,8 +157,7 @@ void Window_ProcessEvents(double delta) { u32 mods = hidKeysDown() | hidKeysHeld(); HandleButtons(mods); - - Input_SetNonRepeatable(CCMOUSE_L, mods & KEY_TOUCH); + ProcessTouchInput(mods); if (Input.RawMode) { @@ -163,33 +178,29 @@ void Cursor_SetPosition(int x, int y) { } // Makes no sense for 3DS void Window_EnableRawMouse(void) { Input.RawMode = true; } void Window_DisableRawMouse(void) { Input.RawMode = false; } -void Window_UpdateRawMouse(void) { - if (!touchActive) return; - - touchPosition touch; - hidTouchRead(&touch); - - Event_RaiseRawMove(&PointerEvents.RawMoved, - touch.px - touchBegX, touch.py - touchBegY); - touchBegX = touch.px; - touchBegY = touch.py; -} - +void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *------------------------------------------------------Framebuffer--------------------------------------------------------* *#########################################################################################################################*/ -static struct Bitmap fb_bmp; +static struct Bitmap top_fb_bmp; +static struct Bitmap bottom_fb_bmp; void Window_AllocFramebuffer(struct Bitmap* bmp) { bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); - fb_bmp = *bmp; + if (renderScreen == TOP_SCREEN) { + top_fb_bmp = *bmp; + } + else { + bottom_fb_bmp = *bmp; + } } void Window_DrawFramebuffer(Rect2D r) { u16 width, height; - gfxSetDoubleBuffering(GFX_TOP, false); - u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height); - + gfxScreen_t screen = (renderScreen == TOP_SCREEN) ? GFX_TOP : GFX_BOTTOM; + gfxSetDoubleBuffering(screen, false); + u8* fb = gfxGetFramebuffer(screen, GFX_LEFT, &width, &height); + struct Bitmap *bmp = (renderScreen == TOP_SCREEN) ? &top_fb_bmp : &bottom_fb_bmp; // SRC y = 0 to 240 // SRC x = 0 to 400 // DST X = 0 to 240 @@ -198,7 +209,7 @@ void Window_DrawFramebuffer(Rect2D r) { for (int y = r.y; y < r.y + r.Height; y++) for (int x = r.x; x < r.x + r.Width; x++) { - BitmapCol color = Bitmap_GetPixel(&fb_bmp, x, y); + BitmapCol color = Bitmap_GetPixel(bmp, x, y); int addr = (width - 1 - y + x * width) * 3; // TODO -1 or not fb[addr+0] = BitmapCol_B(color); fb[addr+1] = BitmapCol_G(color); @@ -209,10 +220,12 @@ void Window_DrawFramebuffer(Rect2D r) { gfxFlushBuffers(); //gfxSwapBuffers(); // TODO: tearing?? + /* gfxSetDoubleBuffering(GFX_TOP, false); gfxScreenSwapBuffers(GFX_TOP, true); gfxSetDoubleBuffering(GFX_TOP, true); gfxScreenSwapBuffers(GFX_BOTTOM, true); + */ } void Window_FreeFramebuffer(struct Bitmap* bmp) {