[Preview] New 3DS Web Browser web app

Discussion in '3DS - Homebrew Development and Emulators' started by jsa, Dec 6, 2015.

  1. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    UPDATE: Bookmark this page - http://jsa.x10host.com/newTab.php - instead of the actual thing - it does the stuff needed (open in a clean tab) to make it work properly

    Also REMOVED the symbols (letters/arrows) on A/B/X/Y buttons and the D-Pad, makes it look clean and modern. Buttons become coloured on-screen when pressed! (actually that was done before) A/B/X/Y match the colours of the buttons on a standard N3DS (which is also the colour of the letters on the buttons on a N3DSXL which is less rainbow-y)

    TL;DR: A tech demo for using almost all of the New 3DS's hardware buttons/sticks via the browser.

    --Just realized I forgot to add Start and Select. Will update asap.--

    So, seeing as I can't get on my computer that much to write C homebrew for the 3DS, I figured I'd make some web-based homebrew instead.

    I actually wrote all 300 lines of code with the New 3DS browser as my family tend occupy the laptop a lot. (That's why HomebreWWW/Koopa Cruiser development is slow, guys!)

    Basically, what this is is a HTML5/JavaScript web app which, when opened, shows you what buttons you may be pressing (including Circle Pad/C-Stick position) using the HTML5 Gamepad API. (nb, not related to the Wii U gamepad though I believe the Wii U supports that API too).

    The code's a bit of a mess (what did you expect, it being written entirely with the New 3DS) but it works.

    I hope to clean this up a bit in future and release a framework/library for making web-based games for the New 3DS, once I've got Koopa Cruiser/HomebreWWW in a usable state.

    This supports reading the states of all the buttons on the New 3DS barring the HOME button. Please note that ZL and ZR are practically unusable (they change the tab) and B cannot be held down for more than 500ms (half a second) without the tab being closed (it's the shortcut to close the tab). Though popping up a JavaScript alert stops the tab closing, "hold B" is not usable. L and R are usable providing the page is opened via the "Open in New Tab" option when you tap and hold on a link. This is because if there are items in the tab's history it will go back and forward, therefore it needs to be programmatically opened in a tab, or via the context menu (for lack of a better word). I will make a small poster page to do this automatically.

    Also, Start and Select are mapped to the browser menu and bookmarks/history respectively, so are unusable.

    All other buttons are usable: D-pad, Circle Pad, C-Stick, A, B (partial), X and Y.

    Also, though I haven't yet implemented it, you can read the touch screen position, a really simple thing to do if you spend 10 minutes with Google.

    Please note this is only for the New Nintendo 3DS browser and consequently will NOT work with older DS and 3DSes, though it may work with the Wii U and possibly a game controller connected to a PC. ;)

    http://jsa.x10host.com/n3ds_gamepad.html (tap and hold then select "Open in New Tab")
     
    Last edited by jsa, Dec 6, 2015
  2. TamDanny

    TamDanny GBATemp 3DS Fanatic

    Member
    314
    215
    Aug 20, 2015
    Mexico
    Wow. I tested this out on my system, and it works pretty well! Pretty impressive that you typed this all in the 3DS. :)
     
  3. MyLegGuy

    MyLegGuy Moron

    Member
    531
    325
    Nov 26, 2014
    United States
    It's too bad that a lot of people (including me) have their browsers disabled.
     
  4. Voxel

    Voxel Fable Junkie

    Member
    GBAtemp Patron
    Voxel is a Patron of GBAtemp and is helping us stay independent!

    Our Patreon
    5,209
    5,956
    Jun 27, 2015
    United Kingdom
    England, UK
    This is looking really good, bro! :)

    I will test it out, later!
     
  5. DarkRioru

    DarkRioru Dream Beeeeeaaaammmm!!!

    Member
    1,993
    423
    Aug 29, 2015
    United States
    looking up at the stars
    nice!!! i'm keeping this bookmarked just in case I need to test my buttons :yay3ds:
     
  6. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    yeah you have a slight issue there as you need to open it in a "clean" tab for the buttons to work. I made a splash page that basically has JavaScript that will open the tab "properly" (window.open)

    http://jsa.x10host.com/newTab.php

    tl;dr: bookmark that link to make everything work properly when launching it from bookmarks
     
  7. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    @jsa do you think it's possible to use the touch screen. The 3DS does not support Touch Events API. Maybe another technic might work? What do you think?
     
  8. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    Actually, the New 3DS does support the Touch Events API! :D
    For the Old 3DS, however, you could use mouseDown events and such. (I believe it is window.onMouseDown)

    By the way, every HTML5 standard API supported on the Wii U browser will work on the New 3DS browser. Their HTML5 te
     
  9. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    I thought it was not supported because it's not on their list of Web Standards:
    • HTML 4.01
    • HTML 5
    • XHTML 1.1
    • Fullscreen API
    • Gamepad API
    • SVG
    • WebSocket
    • Video Subtitle
    • WOFF
    • Web Messaging
    • Server-Sent Events
    • Web Storage (elements used)
    • XMLHttpRequest
    • Canvas
    • Video
    • DOM Levels 1-3
    • ECMAScript
    • CSS 1
    • CSS 2.1
    • CSS 3 (elements used)
    The Wii U support Device Orientation, so you think it's available on the New 3DS?

    For the Wii U Gamepad I mostly use their custom API.
     
  10. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    I tried the Device Orientation API, but it is non functional. It's just locked in a single position.
     
  11. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    Thanks for testing it.
     
  12. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    I've also made a demo for Touch Events, http://jsa.x10host.com/n3ds/ (<- the new landing page for the N3DS HTML5 demos)

    See if it and/or the buttond test work on Wii U
     
  13. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    I have just tested on the Wii U Gamepad and it seems to work. I'm going to check the documentation and try to be familiar with this new API.
    The Gamepad API does not seem to Work with the Wii U.
     
  14. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    Perhaps we could create a kind of abstraction layer which translates wiiu.* to standard HTML5 APIs.
     
  15. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    Actually I have the exact opposite :)

    Here is my code for the untested beta 4 with touch support:
    HTML:
    <!doctype html>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8" />
            <meta name="viewport" content="width=400 user-scalable=no" />
            <link rel="shortcut icon" href="favicon.ico" type="image/vnd.microsoft.icon" />
            <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css" />
            <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap-theme.min.css">
            <link rel="stylesheet" type="text/css" href="usendmii.css" />
            <title>UsendMii</title>
            <script type="text/javascript">
                const STICK_PRESSED = 0.06;
                var MySocket = new WebSocket("ws://" + window.location.host);
                var interval;
                var tpTouch = 0, tpX = 0, tpY = 0;
    
                MySocket.onopen = function()
                {
                    document.getElementById("out").innerHTML = "Connected";
    
                    var el = document.getElementsByTagName("canvas")[0];
                    el.addEventListener("touchmove", handleMove, false);
                    el.addEventListener("touchstart", handleStart, false);
                    el.addEventListener("touchend", handleEnd, false);
    
                    setInterval('update()', 10);
                };
    
                MySocket.onmessage = function(evt)
                {
                    document.getElementById("out").innerHTML = evt.data;
                };
    
                MySocket.onclose = function()
                {
                    document.getElementById("out").innerHTML = "Disconnected";
                    clearInterval(interval);
                };
    
                function handleMove(evt) {
                    evt.preventDefault();
                    var touch = evt.changedTouches[0];
                    tpX = touch.pageX;
                    tpY = touch.pageY;
                }
    
                function handleStart(evt) {
                    evt.preventDefault();
                    tpTouch = 1;
                }
    
                function handleEnd(evt) {
                    evt.preventDefault();
                    tpTouch = 0;
                }
    
                function update()
                {
                    if(MySocket.bufferedAmount > 0) {
                        return; // There is data in the queue
                    }
    
                    var gp = navigator.webkitGetGamepads()[0];
                    var gamepadState = {tpTouch:0, tpX:0, tpY:0, hold:0, lStickX:0, lStickY:0, rStickX:0, rStickY:0};
                    var hold = 0;
    
                    if(gp.buttons[0] == 1) {
                        hold |= 0X00004000; // B
                    }
                    if(gp.buttons[1] == 1) {
                        hold |= 0X00008000; // A
                    }
                    if(gp.buttons[2] == 1) {
                        hold |= 0X00001000; // Y
                    }
                    if(gp.buttons[3] == 1) {
                        hold |= 0X00002000; // X
                    }
                    if(gp.buttons[4] == 1) {
                        hold |= 0X00000020; // L
                    }
                    if(gp.buttons[5] == 1) {
                        hold |= 0X00000010; // R
                    }
                    if(gp.buttons[6] == 1) {
                        hold |= 0X00000080; // ZL
                    }
                    if(gp.buttons[7] == 1) {
                        hold |= 0X00000040; // ZR
                    }
                    if(gp.buttons[8] == 1) {
                        hold |= 0X00000008; // Start
                    }
                    if(gp.buttons[9] == 1) {
                        hold |= 0X00000004; // Select
                    }
                    if(gp.buttons[10] == 1) {
                        hold |= 0X00040000; // Circle Pad Click
                    }
                    if(gp.buttons[11] == 1) {
                        hold |= 0X00020000; // C Stick Click
                    }
                    if(gp.buttons[12] == 1) {
                        hold |= 0X00000200; // Up
                    }
                    if(gp.buttons[13] == 1) {
                        hold |= 0X00000100; // Down
                    }
                    if(gp.buttons[14] == 1) {
                        hold |= 0X00000800; // Left
                    }
                    if(gp.buttons[15] == 1) {
                        hold |= 0X00000400; // Right
                    }
                    if(gp.axes[0] < -STICK_PRESSED) {
                        hold |= 0X40000000; // Circle Pad Left
                    }
                    else if(gp.axes[0] > STICK_PRESSED) {
                        hold |= 0X20000000; // Circle Pad Right
                    }
                    if(gp.axes[1] < -STICK_PRESSED) {
                        hold |= 0X10000000; // Circle Pad Up
                    }
                    else if(gp.axes[1] > STICK_PRESSED) {
                        hold |= 0X08000000; // Circle Pad Down
                    }
                    if(gp.axes[2] < -STICK_PRESSED) {
                        hold |= 0X04000000; // C Stick Left
                    }
                    else if(gp.axes[2] > STICK_PRESSED) {
                        hold |= 0X02000000; // C Stick Right
                    }
                    if(gp.axes[3] < -STICK_PRESSED) {
                        hold |= 0X01000000; // C Stick Up
                    }
                    else if(gp.axes[3] > STICK_PRESSED) {
                        hold |= 0X00800000; // C Stick Down
                    }
                    gamepadState.hold = hold;
                    gamepadState.tpTouch = tpTouch;
                    gamepadState.tpX = tpX * 854 / 320;
                    gamepadState.tpY = tpY * 480 / 212;
    
                    gamepadState.lStickX = gp.axes[0]; // Circle Pad X
                    gamepadState.lStickY = gp.axes[1]; // Circle Pad Y
                    gamepadState.rStickX = gp.axes[2]; // C Stick X
                    gamepadState.rStickY = gp.axes[3]; // C Stick Y
    
                    MySocket.send("gamepadstate=" + JSON.stringify(gamepadState));
                }
            </script>
        </head>
        <body>
            <div id="out"></div>
            <canvas id="canvas" width="320" height="212"></canvas>
        </body>
    </html>
    By the way, I was thinking of giving you credits in UsendMii for helping me with the New Nintendo 3DS. Do you prefer if I put jsa or your real name?
     
  16. jsa
    OP

    jsa GBAtemp Regular

    Member
    213
    196
    Oct 21, 2015
    United Kingdom
    Devon, UK
    Either just jsa or both.
     
  17. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    @jsa someone reported a problem with my touch API implementation on the New Nintendo 3DS with my application. The major problem is scrolling. Did you do any tricks on your Touch Events Demo to prevent that? I know that on 3DBrew they recommend calling scrollTo frequently. What do you think?
     
  18. Shubshub

    Shubshub The Shubinator

    Member
    902
    482
    Oct 16, 2009
    New Zealand
    The dark part of your house
    Would it at all be possible to make one that supports Old 3DS? or not? Just curious
     
  19. Crayon2000

    Crayon2000 GBAtemp Regular

    Member
    107
    74
    Feb 4, 2013
    Canada
    The Old 3DS does not support Gamepad API and Touch Events API. Only up/down/left/right and A buttons can be used with the Internet Browser.
     
  20. Shubshub

    Shubshub The Shubinator

    Member
    902
    482
    Oct 16, 2009
    New Zealand
    The dark part of your house
    alright thanks for letting me know =P