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!

Replying to:RGamesOffical
It seems that by using SmileBASIC 4, somebody can make a Mock OS that uses a real keyboard and mouse.
Be sure it's two separate devices, eg two usb dongles, though. I bought a lovely keyboard with a trackpad attached (Logitech K400+) and though the keyboard works, the trackpad doesn't.

Replying to:MZ952
Could GRP-1 be the FADE sprite?
You can use it for any sprite you want.
I might be behind the times, are you saying we can set individual sprites to different GRPs at the same time?

Replying to:MZ952
Could GRP-1 be the FADE sprite?
Yep!

Replying to:RGamesOffical
It seems that by using SmileBASIC 4, somebody can make a Mock OS that uses a real keyboard and mouse.
(I really need to get my hands on this fine-sounding piece of software called SmileBASIC 4)

Replying to:MZ952
Could GRP-1 be the FADE sprite?
Hot sandwich that's great news! I can stop leaving giant holes in my spritesheet to draw on

Replying to:MZ952
Could GRP-1 be the FADE sprite?
wait what

Replying to:MZ952
Could GRP-1 be the FADE sprite?
This is why the GSPRITE is automatically set to draw in the top left of GRP0

Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
I don't know the answer, but microseconds are more precise.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
The performance commands indeed use microseconds (1/1000000 of a second), not milliseconds (1/1000 of a second). Keep in mind these commands are meant to be used for very fine performance measurements within a single frame. If they used milliseconds, they would be much less useful, since a frame is only about 16.6667 milliseconds in the first place.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
Doesn't the Switch use 30 FPS though?

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
No, it does 60 fps. Looks pretty nice on the switch, too.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
The fact that a $23 programming application is in 60 FPS but $60 games on the same system are in 30 FPS hurts me.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
Fail.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
@IAmRalsei It's because some games--especially graphically demanding ones--run better at 30 FPS. If you removed the 30 FPS lock from those games, the FPS would be a lot less consistent and you would get a lot of frame drops. Please don't be ignorant when posting comments like that.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
There would be no reason to have the PERF functions count in millis because we already have MILLISEC(). Most basic operations are fast enough to register as 0ms so for performance measurement it's basically useless. The perf timers show up on a gauge that appears when you press the PrintScreen key so they need to be highly accurate.

Replying to:IAmRalsei
Regarding the performance-based commands, do they actually measure in microseconds or do they actually measure in milliseconds? Because I see no reason why they should use microseconds instead of milliseconds.
cool

Been using FUZE a little for some time and wanted to port my MM2 PTC project to it, but to be honest, it has a lot of problems. Frequent crashes with what I do is the main one. Not only that, but much of what I could do in PTC on a DS via functions and features would have to be done manually in FUZE, including an MML Player, eating up precious process cycles. With SB4, I get most of what I could do in PTC plus a lot more. Only question now is whether they'd allow uploaded content based on copyright, which I am kinda doubting. .

Replying to:Discostew
Been using FUZE a little for some time and wanted to port my MM2 PTC project to it, but to be honest, it has a lot of problems. Frequent crashes with what I do is the main one. Not only that, but much of what I could do in PTC on a DS via functions and features would have to be done manually in FUZE, including an MML Player, eating up precious process cycles. With SB4, I get most of what I could do in PTC plus a lot more. Only question now is whether they'd allow uploaded content based on copyright, which I am kinda doubting. .
I don't think SmileBoom would allow a direct port like MM2 PTC, I would assume same rules as 3DS SmileBasic. However, if you changed the names, graphics, sounds and levels to your own, there should be no problem. Basically like megaman but not megaman. I for one would look forward to playing something like that. Fuze dissapoints me on so many levels. They go around giving educational lectures yet can't make something with a debugger or read eval print loop, let alone terminal mode for a simple 80s programs with scrolling text. I am still waiting for a help file fix on strBegins/strContains to see if I can find a instr equivalent. Actually on the topic of Megaman, I was thinking, you could break Megaman up into multiple sprites, one for the face that doesn't change, and another for the body in grayscale Then you could use the spcolor (tint) commands for his color swap on weapon change.

Replying to:Discostew
Been using FUZE a little for some time and wanted to port my MM2 PTC project to it, but to be honest, it has a lot of problems. Frequent crashes with what I do is the main one. Not only that, but much of what I could do in PTC on a DS via functions and features would have to be done manually in FUZE, including an MML Player, eating up precious process cycles. With SB4, I get most of what I could do in PTC plus a lot more. Only question now is whether they'd allow uploaded content based on copyright, which I am kinda doubting. .
You'd need a couple layers for the body, since a few of the weapon color palettes can't be made with a simple hue shift. SB4 has practically infinite sprite space so just storing all of them separately is actually the easier approach (consider: how do you handle collision in this situation?)