LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

SmileBASIC 4 for SmileBASIC 3 geezers

Root / Submissions / [.]

niconiiCreated:
Now that we have a ton of solid information on SmileBASIC 4, I think it's a good time for a guide to get people prepared! I've been thinking of ways to try and summarize the changes in the SmileBASIC 4 reference, but there's really a ton of stuff in there. I would highly recommend looking through it thoroughly, because a lot has changed! But even for those who have looked through it, there may be stuff you've missed! It's hard to really digest the big picture information from an API reference. Which is exactly why I have digested it down for you, and am fully prepared to regurgitate this information for you like a bird to her young! So, in this guide, I'm gonna go over the biggest changes I've noticed. I'll assume you're fairly familiar with SmileBASIC 3 for this breakdown. I'm also gonna be talking more about the big picture concepts, rather than specific functions, because I'm sure you'll be able to find this stuff in the reference once you know what you're looking for.

Table of contents

Language

So, to start off, let's look at SmileBASIC 4's language changes, as well as some function changes and additions.

Backwards compatibility

The first thing to understand here is that SmileBASIC 4 is not backwards compatible with SmileBASIC 3 (the 3DS version) or BIG (the Japan-only Wii U version). 3 and BIG managed to keep some level of cross-compatibility with each other with the aid of the XON statement, but SmileBASIC 4 makes a clean break from that. XON no longer exists at all, and even VERSION has been moved to a constant called #VERSION. Due to these and other major incompatible changes, it's not very feasible to write programs that work with both SmileBASIC 3 and SmileBASIC 4 without a large amount of system-specific code. It is possible in SmileBASIC 4 to download SmileBASIC 3 projects from public keys. This is intended to aid porting efforts from SB3 to SB4. It is not possible to do the reverse, however.

Types

In SmileBASIC 3, variable names have suffixes that determine their type. In SmileBASIC 4, however, suffixes are basically meaningless. In fact, the only effect they have now on a variable is which default value it has (0.0, 0, or "") if you access it without assigning anything to it first (e.g. PRINT A without first doing A=123, assuming OPTION STRICT isn't set). Thus, in SmileBASIC 4, only values themselves have types; any value can be assigned to any variable. In other words, this is now perfectly valid:
A$=123
A$="Hello!"
A$=4.5
To some of you this may seem like a lawless hellscape from which we can never escape, but this isn't much different from any other scripting language. To compensate for variables being untyped, we now have more tools for dealing with value types:
  • TYPEOF(value) returns the type of any given value, including arrays.
  • INT(value), FLOAT(value), and STR$(value) convert the given value to that particular type. (STR$ isn't new, but it's here for completeness.)
  • INSPECT value, or ??value for short, gives you detailed information about a value, including what type it is, its contents if it happens to be an array, and so on.
However, if you were hoping for user-defined types, no luck, I'm afraid. The full list of types is the same as in SmileBASIC 3: the null type, integers, floats (or "real numbers"), strings, integer arrays, float arrays, and string arrays. (If you're wondering about null, it's not really important. The main cases you'll see it are if you don't pass a parameter you're supposed to (FOO A,,C instead of FOO A,B,C) or don't return a value when you're supposed to (DEF FOO():RETURN:END).) In SmileBASIC 4, however, the rules work like this:
  • Decimal number literals with a decimal point (like 123.), or scientific notation syntax (like 5E10), are always floats regardless of value.
  • Other decimal number literals (like 123) are ints, or floats if they can't fit in an int.
  • Hexadecimal or binary number literals (&H123 or &B1000) are always ints. If they cannot fit in an int, a syntax error occurs.
  • If both operands are ints, the +, -, and * operators result in an int, or a float if overflow would occur. If either operand is a float, they always result in a float.
  • The / operator always results in a float.
  • Unary - and ! always result in the same type they're used on.
  • All other operators always result in an int.
  • Ints and floats are never implicitly converted to each other when assigning to a variable except when assigning to an array of the other number type.

Arrays

One thing SmileBASIC 4 does add is that arrays are a bit nicer to initialize:
VAR MY_ARRAY[]=[1,2,3,4,5]
This is special syntax for VAR/DIM, rather than an actual array literal, though. LAST(array) is equivalent to LEN(array)-1. It's a small thing, but it makes iterating over arrays a little nicer:
FOR I=0 TO LAST(MY_ARRAY)
 PRINT MY_ARRAY[I]
NEXT
It is now possible to determine the number of dimensions of an array, as well as the size of each dimension:
VAR MY_ARRAY[4,7,2]
PRINT DIM(MY_ARRAY)   '3
PRINT DIM(MY_ARRAY,1) '7
Multi-dimensional arrays can now be referenced as if they were one-dimensional. However, functions that resize an array, like PUSH, cannot be used with them. They can be explicitly resized with the new RESIZE command, however. The new INSERT and REMOVE commands allow you to insert and remove elements from a one-dimensional array. The new function form of COPY lets you copy a portion of an array without having to declare a new variable. It works on strings as well, where it's equivalent to MID$.
VAR MY_ARRAY[]=[0,1,2,3,4,5,6]
INSPECT COPY(MY_ARRAY,2,3) '[2,3,4]
The ARRAY#, ARRAY%, and ARRAY$ functions create arrays of a specified size, filled with the default value for that type. For example, ARRAY%(5,5) makes a two-dimensional 5 by 5 array, filled with 0.

Variadic functions

Another new thing SmileBASIC 4 has is variadic functions, which can take any number of arguments, and return any number of values. Among other things, this allows you to make functions that take optional arguments!
DEF DOUBLE_ALL * OUT *
 IF DEFARGC() != DEFOUTC() THEN
  STOP "Number of inputs and outputs must match"
 END
 FOR I=0 TO DEFOUTC()-1
  DEFOUT I, DEFARG(I)*2
 NEXT
END

DOUBLE_ALL 1,2,3 OUT A,B,C
PRINT A,B,C '2 4 6
Arguments and return values are accessed like this:
  • DEFARGC() gets the number of arguments passed in.
  • DEFARG(n) gets the nth argument.
  • DEFOUTC() gets the number of return values expected.
  • DEFOUT n, value sets the nth return value.

Control flow

A couple of new control flow statements have been added:
CASE N
 WHEN 3:
  PRINT "N is three!"
 WHEN 7:
 WHEN 8:
  PRINT "N is seven or eight!"
 OTHERWISE:
  PRINT "N isn't three, seven, or eight."
ENDCASE

LOOP
 'Loop forever
ENDLOOP

Constants and enums

It's now possible to define your own constants and enums:
CONST #MY_CONST=1000

ENUM #A=100,#B,#C,#D=200,#E
'#A=100, #B=101, #C=102, #D=200, #E=201

Line continuation

Lines can be continued onto a new line by adding a backslash to the end of the line:
FOO A,B,C, \
    D,E
'is equivalent to
FOO A,B,C,D,E
For that matter, backslash is now an actual backslash character, not a yen symbol like you might see above.

ON BREAK

ON BREAK GOTO @LABEL allows you to jump to a label when the user attempts to close a program with the + Button. Although they can still force a program to close by holding the + Button, this allows you to do things like confirm whether the user wants to save a file first.

Performance measurement

The new functions PERFBEGIN and PERFEND allow you to measure the amount of time elapsed between them, in microseconds. Up to eight measurements can run at once, and these measurements can be drawn on a performance graph.

Files

Loading and saving files is a bit different now. LOAD and SAVE have each been split into three different variants:
  • LOAD/SAVE is for moving programs between files and slots. This replaces LOAD/SAVE "PRGn:name".
  • LOADG/SAVEG is for moving graphics between files and GRPs. This replaces LOAD/SAVE "GRPn:name".
  • LOADV/SAVEV is for moving data between files and variables. This replaces LOAD/SAVE "type:name".
Filename prefixes in SmileBASIC 3 did double duty as targets for LOAD/SAVE ("PRGn:" and "GRPn:") as well as signifying file types ("TXT:", "DAT:", and "GRP:"). In SmileBASIC 4, file types are the only filename prefixes. Another interesting thing to note is that GRP files no longer have to be the size of an entire graphics page. Also, DAT and GRP files are automatically compressed when saved. Considering that a full uncompressed graphics page would weigh in at 16 MB, these are very welcome changes! In SB3, there was the SYS project, which contains built-in files like the default spritesheet. In SB4, there are instead multiple system projects, like #SYS or #GUIDE, with names starting with #. Any file in a system project can be loaded or executed from any other project (e.g. LOADG "#SYS/DEFFONT",5).

Subprograms

Subprograms are the replacement for SB3's tool programs. Only one subprogram can be running at a time, but unlike in SB3, they can display stuff in their own window, overlapping the screen, and run in parallel with the editor or main program. They're able to read and write the GRPs and program slots of the main program, and can get some basic status information, like whether the editor is open, or whether the program has reached an error, and so on. Subprograms can be run at any time using the F9-F11 keys on a USB keyboard, by using the Smile buttons in the software keyboard, or by binding a button combination to them. They can even be started while a program is running. For example, this means that the graphics editor can be used to modify the graphics of a program while it's still running! ENOCODE, a Scratch-like editor tool, is an example of a subprogram. In fact, it seems like components of the UI itself are special subprograms, such as the software keyboard! Whether the main program or subprogram receives input depends on which one has focus. When a subprogram starts, it is given focus, and it can give and take it away at will. However, the main program does not have this power; it can't take focus from the subprogram, nor give it back once given it. This does pose a problem, if you need a subprogram that needs to stay open to preserve state, but also need to be able to switch focus between the main and subprograms freely. After all, the subprogram can give focus to the main program, but how will it know to take focus back if it can't get any input? Well, it turns out that's not entirely true. At least for the time being, subprograms can still read the USB keyboard and mouse cursor position (though not the mouse buttons). There's also some undocumented special character codes PUSHKEY can use to switch focus from the main program, but I wouldn't rely on that. Of course, if you don't need to preserve state, you can simply close and open the subprogram as needed, without having to use any dodgy undocumented behavior.

Miscellaneous functions

METALOAD, METAEDIT, and METASAVE allow you to edit the title, description, and icon of the current project.

System variables

System variables are now completely gone. Specifically:
  • TRUE and FALSE are now #TRUE and #FALSE (which already existed in SB3).
  • FREEMEM, RESULT, MAINCNT, MILLISEC, TIME$, DATE$, CALLIDX, and PCMPOS are now functions of the same name.
  • VERSION and HARDWARE are now #VERSION and #HARDWARE.
  • TABSTEP and SYSBEEP are now accessed via SYSPARAM.
  • CSRX, CSRY are now accessed via LOCATE OUT X,Y.
  • CSRZ is now the Z-coordinate returned from TOFS OUT X,Y,Z.
  • ERRNUM, ERRLINE, and ERRPRG are removed, perhaps because programs couldn't really use them anyway, and LIST ERR already makes the editor jump to the location of the error. Subprograms can get this information with ENVSTAT.
  • MICPOS and MICSIZE are removed because SmileBASIC 4 has no support for microphones.
  • MPCOUNT, MPHOST, and MPLOCAL are removed because SmileBASIC 4 has no support for local wireless multiplayer, instead opting for multiple controllers on a single console.

Special constants

The special constants #_LINE, #_SLOT, and #_FILENAME give the current line number, slot, and filename where they are used.

Putting stuff on the screen

Alright, so let's look at how things have changed since SmileBASIC 3 when it comes to displaying stuff, because there's a lot more than you might think!

Graphics pages

Graphics pages, or GRPs for short, are still pretty much the same. Instead of being 512x512, they're 2048x2048, and instead of RGBA1555 color, it's ARGB8888. That means you have the full RGB(0,0,0) to RGB(255,255,255) range of color, plus a proper alpha channel this time! In SmileBASIC 3, you have six normal pages, GRP0 through GRP5, and then you have a special one called GRPF for the font. In SmileBASIC 4, you have six normal pages, GRP0 through GRP5, but this time GRPF is actually just another name for GRP5. In addition, there's GRP-1 (that's negative one) which can't be written to and is completely white (specifically, &HFFFFFFFF). To tell you the truth, I'm actually not entirely sure where GRP-1 would come in handy... but hey, it's there if you need it for something!

Display elements

So, in SmileBASIC 3, there are four main ways to put stuff on the screen:
  • The graphics screen, which displays the contents of a graphics page, by default GRP0.
  • Backgrounds, or BGs for short, which are made up of tiles, which by default come from GRP4. There are four BGs in all.
  • Sprites. Everyone knows what sprites are, right? By default, their graphics come from GRP5. There are 512 sprites in all.
  • The text screen, where text is printed. The font comes from GRPF.
Well, in SmileBASIC 4, it's pretty different. There are only two main ways:
  • Sprites. They're no longer tied to a single graphics page; each sprite can choose a region from any page. However, by default, they all come from GRP4, starting at coordinates (0, 0). There are 4096 in all.
  • The text screens. Yep, screens. There's five of them now. Most of the font comes from GRPF, which is now just another name for GRP5, but there's also 4096 "user-defined characters" from &HE800 to &HF7FF. By default, these also come from GRP4, starting at coordinates (1024, 0).
"Huh?" you might be asking. "Where'd the graphics screen go? Where's the backgrounds? Are they just... gone?" Well... not exactly. I mean, yeah, they are, but only because they're not needed in the first place! Let me explain:
  • The "graphics screen" is now just a huge sprite covering the entire screen. Specifically, sprite 4095, which also has a handy constant, #GSPRITE. That sprite is set to use (0, 0) to (w, h) of GRP0, where w and h are the screen width and height. In other words, if you want to put something on the screen, you just... draw to GRP0. Just like you always did!
  • The four "backgrounds" are now just text screens 0-3, and the one you normally print text to is text screen 4. Yep, the text screen was basically just a crappier BG anyway, so why not? Naturally, to compensate, text screens can now do everything BGs used to do, so you can rotate them, scale them, and so on, and you can choose between 8x8 and 16x16 fonts for each. Those "user-defined characters" I told you about earlier? Yep, those are your tileset!
So, just to summarize, in bold letters for those people in the back: The graphics screen and BGs have been merged with sprites and text screens respectively, and thus have been rendered obsolete. Pretty crazy, right? BG tiles are just text now! You could stick 'em in strings if you wanted to! Maybe even put a whole map in DATA statements? The graphics screen is just a sprite, so you can rotate and scale it as much as you want! Something else to be aware of is that just because there's only 4096 "user-defined characters" doesn't mean you only have 4096 tiles to work with! After all, you have the whole rest of the font to work with. If you want to sacrifice stuff like kanji for more tiles, you can do that! Anyway, adjusting from SmileBASIC 3 to SmileBASIC 4 isn't too bad here. A lot of the BG* functions have T* equivalents, and you'll still use the same old G* functions to draw to GRP0.

Layers

But that's not all! We've also got layers! What's a layer? Well... There are 8 layers, from 0 to 7. Like the name implies, they're drawn stacked over each other, with layer 0 being the top layer, and layer 7 being the bottom layer. Each sprite and text screen can be assigned to one of these layers. Regardless of Z-coordinate, the stuff in layer 0 will always be drawn over the stuff in layer 1, and so on. But, of course, that's not all layers are good for. For starters, you can move an entire layer as a single unit. But not just moving it--with LMATRIX, you can apply an entire 4x4 transformation matrix to each layer! That's right, not just translation, but rotation, scaling, and skewing, all in 3D space! Mode 7-like effects are a breeze now! But that's not all! With LFILTER, you can pixelate, blur, and change the hue, saturation, and value of the entire layer! But that's not all! LFILTER also lets you create raster effects by changing the X scroll, Y scroll, X scale, and Y scale of every individual row or column of the layer's pixels! Wavy effects? No problem! And sorry, did I say Mode 7-like effects earlier? Sorry, I meant just straight-up Mode 7! That spinny cylinder room in Super Castlevania IV that was really cool but also made you a bit nauseous? Yeah, you can do that now. Then there's color blending with LAYER, which lets you do composition by adding or multiplying colors! Finally, clipping is now part of layers, via LCLIP, rather than sprites or text screens. So, the screen is made up of layers, and the layers are made up of sprites and text screens! Neat! What's next?

The screen itself

Well, now that you understand how the screen is put together, let's finish things up by talking about the screen itself! Good old XSCREEN is still around, but it works a little differently now: The first two parameters are the width and height of the screen. Width can be from 128 to 1280, and height can be from 128 to 720. You can choose any number divisible by 4 that's within those ranges. The default resolution is 400x240, the same resolution as the 3DS's top screen. Actually, everything after this is optional, so you could just write XSCREEN 1280,720 if you wanted to, but let's take a look at the rest of them anyway! The next parameter is sample magnification. What does that do? Well, think about this: Say you want a real low-resolution game, something crazy like the Game Boy's 160x144 resolution. But of course, you still want those fancy sprite rotation and scaling effects. So you rotate a sprite a few degrees... and it turns into a mess of pixels. Well, of course it does, you're rendering at 160x144! But maybe you didn't necessarily want to render everything at 160x144. Maybe you still wanted rotation and scaling to be buttery-smooth, even if it's not totally sticking true to that resolution. Well, that's what sample magnification is for! If you set it to, say, 3, everything will still be as if it were rendered at 160x144. But when you start rotating and scaling stuff, you'll see that it's actually rendering at 3x that resolution, at 480x432. That said, you can't get a resolution greater than 1280x720 this way, nor can you set the magnification lower than 1. The next parameter is the screen's texture filtering. 0 is bilinear filtering (blurry pixels), 2 is nearest neighbor (sharp pixels), and 1 is somewhere between the two. Finally, the last parameter is the aspect ratio. This lets you stretch the screen, if you're in the mood for some rectangular pixels! So, that about covers it! If you thought there wasn't much of a change when it comes to putting stuff on the screen, you haven't been digging deep enough!

Input

Well, now that we've covered output, the next thing we should cover is input! A lot has changed here too, though a bit of it might be familiar if you ever used SmileBASIC BIG.

Buttons and sticks

The 3DS has built-in buttons, but the Switch has controllers to worry about. Are you playing with a Pro Controller? Or maybe two Joy-Cons? What about a single Joy-Con? And what about multiple players? Because of that, a lot has changed here, so if you try and use BUTTON like you used to, things aren't going to work like you expect. It's hard to explain the differences in text, so let's look at some code. Now, in SmileBASIC 3, if you wanted to check if A was pressed this frame, you'd do something like this:
IF BUTTON(2) AND #A THEN
 PRINT "A was pressed!"
ENDIF
In SmileBASIC 4, however, it's like this:
IF BUTTON(0,#B_RRIGHT,2) THEN
 PRINT "A was pressed!"
ENDIF
Now, what on Earth is that? Well, let's look at what's changed: The first parameter is the controller ID. 0 is the "default controller", whereas 1-4 are players 1 through 4. We'll get back to this later on when we talk about setting up controllers, but for now, sticking with 0 is fine. Also, the constants for buttons have changed. The first thing to be aware of is that these constants don't refer to specific physical buttons, but rather how these buttons are used while playing. For example, when you play with a single right Joy-Con, you hold it horizontally, so you move with the "left stick", and you press the "A button" to confirm things, even if physically speaking these are technically the right stick and X button.
  • #B_LUP, #B_LDOWN, #B_LLEFT, and #B_LRIGHT represent the buttons you'd use as a D-Pad for your particular controller. If you're playing with a single Joy-Con, you don't have these at all, since you only have a stick to move with.
  • #B_RUP, #B_RDOWN, #B_RLEFT, and #B_RRIGHT represent the buttons you'd use as X, B, Y, and A respectively. These directions are according to how you'd hold the controller while playing, so for a single right Joy-Con held horizontally, #B_RRIGHT would actually be the button labeled as X, and so on.
  • Update: #B_X, #B_B, #B_Y, and #B_A now also work as aliases for the above.
  • #B_L1, #B_R1, #B_L2, and #B_R2 represent L, R, ZL, and ZR on the two Joy-Cons or a Pro Controller. Yeah, I know, L1 and L2... weird, right? This ain't no PS4!
  • #B_SL, #B_SR, #B_S1, and #B_S2 represent SL, SR, L/R, and ZL/ZR on a single left or right Joy-Con. These are actually aliases for the previous set of constants, in the same order.
  • #B_LSTICK represents clicking the left stick. Both single Joy-Cons have this, since the stick is at the left when you hold it while playing.
  • #B_RSTICK represents clicking the right stick. Single Joy-Cons don't have this at all.
  • #B_RANY represents pressing any of the ABXY buttons.
  • #B_LANY represents pressing any of the directional buttons.
  • #B_ANY represents pressing any button, except for clicking the sticks.
The last thing to be aware of is that these constants aren't bitmasks, they're button IDs counting from 0, 1, 2, 3, and so on. There is still a way to use bitmasks, though, which we'll get to shortly, and getting the bitmask for a button is as simple as 1<<#B_RRIGHT, so don't worry too much. The last parameter should be pretty familiar, since it's the same as SmileBASIC 3.
  • 0 checks if the button is currently held. This is the default if you omit the parameter.
  • 1 checks if the button was pressed this frame, including BREPEAT.
  • 2 checks if the button was pressed this frame, without BREPEAT.
  • 3 checks if the button was released this frame.
So, probably the most notable part of this change is that you don't really have to understand bitmasks anymore to deal with buttons. If you want to check if both ZL and ZR are being held down:
IF BUTTON(0,#B_L2) && BUTTON(0,#B_R2) THEN
 PRINT "ZL and ZR are being held!"
ENDIF
Of course, some of you probably like getting a bitmask of all of the buttons at once, and you can still do that by passing in -1 instead of a button:
IF BUTTON(0,-1,2) AND 1<<#B_RRIGHT THEN
 PRINT "A was pressed!"
ENDIF
Also, BUTTON(controller, -1, 0) can be shortened to simply BUTTON(controller):
IF BUTTON(0) AND (1<<#B_L2 OR 1<<#B_R2) THEN
 PRINT "ZL and ZR are being held!"
ENDIF
Next, there's BREPEAT, which is basically the same as in SmileBASIC 3. For some reason, you actually can't set BREPEAT on individual controllers. If you set it, it applies to all connected controllers, as explicitly noted in the reference. Now, in SmileBASIC 3, BREPEAT had its own weird set of button IDs you had to use, which were different from the button constants. Since the constants are now IDs instead of bitmasks, can you just use the constants now? Well, I don't know! The reference doesn't say. Finally, let's talk about the analog sticks. They haven't really changed much. STICK OUT X, Y is now STICK controller[, stick] OUT X, Y. Stick 0 is the left stick, and 1 is the right stick, so EXSTICK is gone now. If you leave it out, it'll default to 0. And of course, just like the button constants, this takes the type of controller into account, so the stick will work as you expect when holding a Joy-Con sideways. Anyway, that's how buttons and sticks work. Whew! Who knew they could be so troublesome?

Setting up controllers

So, that's all well and good, and if you're not doing anything special, you can get away with using the default controller. However, special features like motion controls, vibration, and the IR camera require that you use controllers 1-4, rather than 0, and of course they will fail if the controller you happen to be using doesn't have those functions. So, let's talk about detecting controllers, as well as requesting a specific style of controller. So, there's a few different kinds of controllers, but they all fit into four different styles:
  • Full controller. Handheld mode, a pair of Joy-Cons, or a Pro Controller can all be used as full controllers. All buttons and both sticks are available, as well as motion controls and vibration. However, they are considered a single unit, so in the case of a pair of Joy-Cons, the two gyroscopes and accelerometers cannot be accessed independently.
  • Pair of controllers. Only a pair of Joy-Cons can be used as a pair of controllers. Pairs of controllers can do everything full controllers can, as well as access the two gyroscopes and accelerometers independently.
  • Sideways controller. Only a single Joy-Con or a Pro Controller can be used as a sideways controller. Only the left stick, ABXY buttons, and all four trigger buttons can be accessed, as well as the gyroscope, accelerometer, and vibration.
  • Sideways controller (strict). Same as the above, but only a single Joy-Con is permitted.
XCTRLSTYLE lets you request a specific controller style, and the Switch's controller connection screen will appear automatically if the wrong style of controller is connected. It also lets you enable use of the gyroscope/accelerometer and the IR camera. You can also get information about connected controllers using the CONTROLLER function. This is useful if you want to support different kinds of controllers, falling back gracefully instead of demanding a specific style. CONTROLLER(controller) can tell you whether the given controller is disconnected, Joy-Cons connected to the Switch in portable mode, a Pro Controller, a pair of Joy-Cons, a single left Joy-Con, or a single right Joy-Con. Not only that, you can even get the colors of each controller! CONTROLLER(0) will always appear as portable mode, though.

Motion controls and vibration

Accessing the gyroscope and accelerometer isn't much different from SmileBASIC 3. There's no more XON and XOFF, since motion controls are enabled and disabled via XCTRLSTYLE now. GYROA, GYROV, ACCEL, and GYROSYNC are all still here, but now they all take a controller ID (and optionally a sensor number) as arguments. The sensor number is used to access the left and right Joy-Con sensors independently, where applicable. Vibration is accessed with the VIBRATE command. It lets you change the frequency and amplitude of both the left and right vibration motor, or both, in the case of a sideways controller.

The IR camera

The IR camera is pretty complicated. Basically, there are three modes:
  • In clustering mode, up to 16 bright areas are recognized and returned as variable-sized rectangular regions called clusters. The position, size, number of pixels, average brightness and center of gravity is given for each cluster.
  • In shooting mode, images are taken. However, probably for the same reason that SmileBASIC 3 couldn't use the 3DS cameras, the actual image data cannot be accessed by a BASIC program. Instead, using IRSPRITE, a sprite can be assigned to a special GRP containing this data, which cannot otherwise be accessed. The image can be displayed on-screen this way.
  • In moment mode, the camera's view is split into 8 by 6 equal-sized regions called blocks. Average brightness and center of gravity is given for each block.
Other parameters like camera gain, exposure, and so on can be adjusted.

The touch screen

There's two key differences when it comes to the touch screen in SmileBASIC 4. The first is that it's not always available, because the touch screen is inaccessible while docked. The second is that the touch screen supports multitouch this time around! Up to 10 points can be tracked at once.

Keyboard and mouse

Yet another thing SmileBASIC 4 supports is USB keyboards and mice. If you just want text input, you can still use INPUT, LINPUT, and INKEY$ like in SmileBASIC 3. However, if you want to access the keyboard state directly, that can be done with KEYBOARD, using scan codes from the table starting on page 53 of the USB HID Usage Tables. Using KEYBOARD, you can check whether each individual key is being held down, or was pressed or released this frame. For example, you can check if the A key was pressed this frame like so:
IF KEYBOARD(4,2) THEN
 PRINT "The A key was pressed!"
ENDIF
Accessing the mouse is done using MOUSE for the mouse and wheel position, and MBUTTON for the state of up to five mouse buttons. Again, you can determine whether each button is being held down, or was pressed or released this frame.

Nintendo Labo Toy-Cons

Yep. There's support for that too! I'm not gonna go into much detail about these, since these are probably especially niche, and this section's kinda dragging as it is, but just know that there's special support for the Piano, House, Motorbike, Fishing Rod, Robot, and Visor Toy-Cons. And I believe those are all of the ways to get input in SmileBASIC 4. That was even longer than the graphics section!

To be... or not to be?

Really, at this point, the only thing left to cover is audio, and I don't think much has changed there. For that matter, it's not really my strongest subject... So, this might be the end!

"In other words, you could potentially have over 60000 tiles!" seems suspicious. Most characters don't have symbols assigned to them, I'm pretty sure.

Replying to:12Me21
"In other words, you could potentially have over 60000 tiles!" seems suspicious. Most characters don't have symbols assigned to them, I'm pretty sure.
Yeah, alright. I was already a bit iffy on that figure already because of surrogate pairs and other potential weirdness, but I'll just remove it until I can test that out myself.

This looks great!

will it an update for 3Ds ?

Replying to:LBWdvQW5k6V9T98X4
will it an update for 3Ds ?
No, it's for the Switch.

Replying to:LBWdvQW5k6V9T98X4
will it an update for 3Ds ?
Nope, SmileBASIC 3 is the 3DS version, while SmileBASIC 4 is the upcoming Switch version.

Replying to:LBWdvQW5k6V9T98X4
will it an update for 3Ds ?
IAmRalsei 41 seconds ago: No, it's for the Switch. niconii 40 seconds ago: Nope, SmileBASIC 3 is the 3DS version, while SmileBASIC 4 is the upcoming Switch version. I knew you were the copy robot from Mega Man 1.

There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
The layer system is something completely separate from the GRP system. It's a heirarchy system to organize text sheets, sprites, and GRPs into separate "layers" in the display space. Layers can have filters and transformations applied to them, which seems to be the motivation behind the change.

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
So, like a more-advanced GPRIO thing? Are sprites really separate from the GRPs? In my imagination, I'm seeing the text sheet with sprites superimposed over it (or vice versa) acting as the graphics display page, but this would make GPAGE obsolete, which leads me to believe that you can display a GRP without defining it with some sprite mumbo-jumbo, like in SB3. I might never understand this until I actually play with the damn thing lol

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
The way GRP layers are handled is that the currently displayed GRP layer is actually just displayed with sprite ID 4095. I guess they figured it was more efficient to just handle it in a way that was more homogenous since using sprites as a mirror of a GRP was a common trick in SB3. The GRP display layer concept found in SB3 and PTC isn't a thing anymore, it's just an automatically initialized sprite.

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
Okay, so you may have gotten a bit mixed up because I mention "graphics pages" and the "graphics screen". These are not synonyms, but two distinct concepts. So, a graphics page or GRP is just a texture you draw to, using GLINE, GBOX, and so on. The graphics pages are not displayed on the screen by themselves; rather, they provide graphics for the display elements. In SmileBASIC 3, the graphics screen is a display element covering the entire screen, which shows the contents of GRP0 by default. That's why, when you draw to GRP0, it shows up on the screen. However, there's already a way to show part of a GRP on the screen. It's called using a sprite. In SmileBASIC 3, each sprite takes its graphics from part of GRP4. If SmileBASIC 3 let you set the GRP for each sprite, you could have a sprite the size of the whole screen taking graphics from GRP0, put it on the screen, and it would be exactly the same as having a graphics screen. After all, when you draw to GRP0, that'd change the graphics the sprite is using, and it'd appear on the screen. So, in SmileBASIC 4, that's what they did. They got rid of the graphics screen. That doesn't mean GRPs are gone, or that GRPs are the same thing as sprites. It just means one of the sprites takes its graphics from GRP0 by default, now, and it's set to be the size of the entire screen. Each sprite can be set to use any GRP you want. There is no longer a dedicated sprite GRP. As for what you're saying about GPAGE... that function isn't in SmileBASIC 4. Only GTARGET exists, and that sets the manipulation page. There's no such thing as a "display page" anymore. If you want to change the page displayed on the screen, you just have to change which page that sprite is using. As for layers, each individual sprite and each individual text screen can be assigned to one of those 8 layers. So, that's 4096 sprites and 5 text screens that can be assigned to any of those 8 layers. The fact that there's 6 GRPs has nothing to do with it, because GRPs aren't displayed on their own. They only provide graphics for the sprites and text screen font. So, snail_'s comment is mostly right, but the one nitpick I'll make is the fact that layers organize text screens and sprites, but not GRPs. Again, GRPs simply provide the graphics for sprites and text screen font. They can't be assigned to layers themselves.

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
Ahhh, okay, that makes much more sense. (I swear I read about GPAGE in the SB4 reference though... Come to think of it, it might've been in the SB3 vs SB4 section. Oops.) I'm guessing the parameters for XSCREEN adjust how the auto-initialized sprite at 4095 initializes itself?

Replying to:MZ952
There are 8 layers but 6 GRPs? And each GRP is a sprite page? Okay, so, how does this work? Do you assign sprites a layer to exist on? Also, I'm a bit confused about how the whole display page thing works. I think they've eliminated the display/manipulation page relationship, because the new GPAGE function changes (or returns) the display page (I think?) and GTARGET changes the manipulation page. But this doesn't seem to fit with the idea that the GRPs are now sprites. I'm trying to reconcile the ideas of the display page, the displayed sprites, and the layers.
Yes, running ACLS or XSCREEN will initialize sprite 4095 to be the size of the screen, and use a screen-sized area in GRP0.

Resources can be sticki- oh. I forgot there was a promoted feature.

I think it would be better play it on the 3DS. (Because you have to program more, and more with that buttons...)

Will objects, if they exist in sb4, be gone over next time?

Replying to:spaceturtles
Will objects, if they exist in sb4, be gone over next time?
Sprites are still the closest things we've got to objects. SPVAR has been enhanced to support strings as both keys and values, instead of just having keys from 0 to 7 and numeric values. So you can do things like SPVAR 0,"NAME","VALUE" Still not sure why they didn't just straight-up include map/dictionary types.

This might be a silly question but I can't find anything solid on it: in what ways can you connect a keyboard & mouse combo to the switch? Do you need a USB Type C adapter?

Replying to:MZ952
This might be a silly question but I can't find anything solid on it: in what ways can you connect a keyboard & mouse combo to the switch? Do you need a USB Type C adapter?
The dock has USB A ports, and I assume the USB C port on the device will work as well