# Dusk Tour

The idea of a Dusk tutorial is a bit weird because if you don't know your way
around Forth and Dusk, you won't be able to make good use of it. Therefore,
if you want to begin using Dusk, you should learn about it using the serious
path, which begins at [doc/operator] followed by [doc/usage].

However, if what you want is to have an idea of Dusk's capabilities without
having to invest time learning about Forth and Dusk semantics too much, then
this tour walks you through a couple of interesting places. All you need to do
is to type the commands.

Explanations are minimal, because it's useless to understand what you're typing
if you don't have a good understanding of Dusk's underpinnings. See this tour
more like a show and tell.

If something doesn't work as expected during the tour, check whether you're
running it from a release tag (example "v11") or from the master branch. This
tour is checked for correctness before releases but not after each commit.

## Requirements

The first part of the tour has no particular requirement. Any flavor of Dusk
will work. For the "Grid" part, you'll need either a "curses" or "sdl" (or bare
metal, of course) flavor of Dusk, either under the POSIX VM or under Usermode.
For the "Graphics" part of the tour, you'll need the "sdl" flavor.

It's better if you begin the tour with the "best" flavor you can manage to build
right away, because the tour builds on memory artifacts built previously. If you
switch flavor in the middle, you'll have to rebuild those artifacts.

See the root README for details about how to build those flavors.

The POSIX VM version is easier to build than Usermode, but runs slower. If you
decide to run on this, you shouldn't judge Dusk's speed by this tour. Dusk is
much faster than this.

## Let's go

  Dusk OS
  183KB used 31MB free ok

That's the welcome prompt. Dusk is waiting for a command. Typing on the keyboard
will make letters appear on the screen. Execution of the typed line only happens
when you press Return. Backspace can be used to erase characters.

So what's those 31MB free? It's your system memory. It's a contiguous area of
memory and "here" is where you're "currently at" in it. Where is that? Let's
find out:

  here .x
  0002e4a0 ok

That's your playground. Any address within "here" and 31MB is good to play with.
Let's dump what we have in front of us:

  here dump
  :0002e4a0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4b0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4c0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4d0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4e0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4f0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e500 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e510 0000 0000 0000 0000 0000 0000 0000 0000 ................

What a nice bunch of zeroed out bits. What about those 183KB used? What do they
look like?

  here $100 - dump
  :0002e3a0 ff0c 90e2 ff08 90e2 ff04 90e2 0000 8de5 ................
  :0002e3b0 0c00 000a 08b0 9de5 0280 a0e3 0800 9de5 ................
  :0002e3c0 0800 90e0 0800 8de5 0490 2ae5 0190 dbe5 ..........*.....
  :0002e3d0 0490 2ae5 0090 dbe5 df63 ffeb de63 ffeb ..*......c...c..
  :0002e3e0 635d ffeb ebff ffea 01df 9de2 0490 8de5 c]..............
  :0002e3f0 0490 9ae4 0490 2ae5 019e a0e3 0190 99e2 ......*.........
  :0002e400 0490 2de5 0490 9ae4 0000 9de5 ff00 90e2 ..-.............
  :0002e410 ff0c 90e2 ff08 90e2 ff04 90e2 0000 8de5 ................

Ok. You can play with that memory. For example, write to it:

  $cafebabe here !
   ok
  here @ .x
  cafebabe ok
  here dump
  :0002e4a0 beba feca 0000 0000 0000 0000 0000 0000 ................
  :0002e4b0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4c0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4d0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4e0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e4f0 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e500 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :0002e510 0000 0000 0000 0000 0000 0000 0000 0000 ................

As you can see, that's a little endian system. In fact, I'm going to tell you,
this is an ARM system. How about we flex our assembler muscles?

  needs asm/arm
  code add42 add) rW rdn) 42 imm) ,) ret,
  5 add42 .
  47 ok

ALTERNATE REALITY: if you run the tour on a system that isn't ARM (the regular
POSIX VM emulates ARM, so it's ARM), "add42" will crash your system. What you
can do, however, is to use the HAL, which will assemble the same thing in your
native architecture:

  code add42 42 i) +, exit,
  5 add42 . \ works on any CPU
  47 ok

What we did here is that we created a new native word, right "here". Let's look
at what's in "add42".

  ' add42 dump
  :00031918 2a90 89e2 1eff 2fe1 0000 0000 0000 0000 *...../.........
  :00031928 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031938 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031948 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031958 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031968 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031978 0000 0000 0000 0000 0000 0000 0000 0000 ................
  :00031988 0000 0000 0000 0000 0000 0000 0000 0000 ................

Keen eyes among you will recognize ARM binary format. But we aren't all nerdy
weirdos, right? Let's use a disassembler.

  needs asm/armd
  ' add42 dis
  00031918    ADD  r9  r9  0000002a e289902a
  0003191c    BX   r14              e12fff1e
  00031920 EQ AND  r0  r0  r0       00000000
  00031924 EQ AND  r0  r0  r0       00000200
  00031928 EQ AND  r0  r0  r8       00000008
  0003192c EQ AND  r0  r1  r12      0001064c
  00031930 EQ AND  r0  r1  r8       00010678
  00031934 EQ MUL                   000126bc
  00031938 EQ AND  r0  r0  r10      0000021a
  0003193c EQ AND  r12 r0  r4       0000ce54
  00031940 EQ AND  r12 r0  r0       0000cf20
  00031944 EQ AND  r13 r0  r8       0000d0a8
  00031948 EQ AND  r0  r0  r0       00000000
  0003194c EQ AND  r0  r0  r1       00000e01
  00031950 EQ AND  r0  r0  r1       00000e01
  00031954 EQ AND  r1  r1  r8       00011328

Only the first two lines, until the BX, are relevant. The rest is non-code
garbage because the disassembler can't know when to stop disassembling, so it
spits a pre-defined number of lines.

That's pretty much what we've assembled right? Of course it is.

What about compiling some C code now?

  needs comp/c
  :c int add54(int n) { return n+54; }
  5 add54 .
  59 ok

Good stuff. What does it look like, code wise?

  ' add54 dis
  000450f8    STR  r14 r13 -04 !    e52de004
  000450fc    STR  r9  r10 -04 !    e52a9004
  00045100    MOV  r9  00000036     e3a09036
  00045104    LDR  r0  r10          e59a0000
  00045108    ADDS r9  r9  r0       e0999000
  0004510c    ADDS r10 r10 00000004 e29aaf01
  00045110    LDR  r15 r13 +04 !p   e49df004
  00045114 EQ AND  r0  r0  r0       00000000
  00045118 EQ AND  r0  r0  r0       00000000
  0004511c EQ AND  r0  r0  r0       00000000
  00045120 EQ AND  r0  r0  r0       00000000
  00045124 EQ AND  r0  r0  r0       00000000
  00045128 EQ AND  r0  r0  r0       00000000
  0004512c EQ AND  r0  r0  r0       00000000
  00045130 EQ AND  r0  r0  r0       00000000
  00045134 EQ AND  r0  r0  r0       00000000

A bit looser than the straight assembler version, but not that bad heh?

## Grid

At this point of the tour, you need either the "curses" or "sdl" flavors of
Dusk.

I haven't told you about the Grid yet. Your console is a Grid (see
[doc/io/grid.txt]), which means the characters you see are arranged in a matrix
of glyphs that are easy to address individually. In the UNIX world, the "curses"
library provides this, but it uses terminal escapes to do so. In Dusk, hardware
drivers provide this capability natively, no need to jump through VT100 hoops.
Example:

  needs io/grid
  : line COLS 2/ over - over at-xy 2* 0 do '#' emit loop ;
  : tri LINES COLS 2/ min 0 do i line loop ;
  clear tri key drop

So far, all you've used is "dump". How about something more powerful?

  needs bin/gbe
  gbe

The interface you see will look familiar if you've ever used what we call Hex
Editors in the UNIX world. But what you're seeing here is not a file, it's
directly the system memory. You can move around with h/j/k/l and page up and
down with [ and ].

*NOTE: if you are using a different Dusk in this Grid section of the tour than
in its first section, you'll have to repeat the steps that lead to the creation
of "add54".*

How about looking at your "add54" again? Type "J", followed by "' add54",
followed by Return. The binary contents under the cursor will be the same as
the disassembled one above. If you press "z", current position will be "zoomed"
to the middle of the screen allowing you to see the dictionary entry for "add54"
directly preceding your binary contents.

Doesn't this give you a devious little idea? What about unleashing that "we'll
do it live!" energy and modify the "add54" string directly in memory? Yesss, I
knew you'd have the same idea.

With h/j/k/l, move the cursor until it sits on the "a" of "add54". Then press
"T", followed by "add99" followed by Return. Press "W", then "q" to quit the
application.

Back on the console, what happens if you type "5 add54 ."? ... and " 5 add99 ."?
You've modified your system dictionary directly in memory!

## Graphics

From that point on, we need graphical capabilities. usermode/dusk-sdl gives you
that, but other Dusk port can give it to you too. If you have a blue 8x8 square
that moves around with the mouse, you're good.

  100 100 screen pixdst! 255 0 0 >screencolor 60 80 fillpixels key drop

This should show a 60x80 pixels red square on the screen. Yes, this code above
needs to be typed on a single line. Why? Press "return" a few times. See how the
console overwrites the red square? That's because the concept of "screen" is as
simple as it sounds: a framebuffer plugged to the screen. When you draw to it,
you do it directly. Refreshingly simple right? Yes, but it's a shared resource
that the console also uses. Whenever a character is drawn to the screen, it is
using the same [gr/pix] API, which has global states. Therefore, your draw
operation need to happen without the console drawing a character in between.

Dusk doesn't have a vector drawing API yet, so drawing is mostly about moving
pixels around, but that doesn't mean we can't have fun with that. It has a
sprite based API in [gr/varvara] and we can test that it works with:

  needs gr/varvara
  vscreentest key drop

This should draw a rectangle along with a few hearts and diamonds here and
there. This shows you that the varvara screen system works. At the heart of this
API is the concept of sprite, which is a 8x8 bitmap, which can have 2 or 4
colors. Let's look at an example sprite:

  heart 16 cspit[]
  00 66 ff ff ff 7e 3c 18 00 00 00 18 18 00 00 00 ok

The "heart" array comes from gr/varvara and is the sprite we use for our little
test we've just drawn. Each byte represents a 8 pixels row, with each bit
representing a pixel, b7 being leftmost and b0 being rightmost. The first 8
bytes are the first color channel and the following 8 bytes are the second color
channel. Therefore, a 1bpp sprite is 8 bytes long and a 2bpp sprite is 16 bytes
long and its first 8 bytes is the same as a 1bpp sprite.

So, hum, what kind of fun could we have with this. Let's draw a whole bunch of
those hearts.

  10 to X 10 to Y heart to sprite
  1 2bpp) X+) 10 times) drawsprite
  refreshscreen key drop

You should see 10 hearts being drawn in a vertical line (why vertical when we
use X+)? see [gr/varvara] for details). We don't need to type everything in a
single line because this unit uses a separate buffer, which we draw to screen
using "refreshscreen". What about a horizontal line of flipped hearts using
another color blend?

  2 2bpp) Y+) flipY) 12 times) drawsprite
  refreshscreen key drop

Wait, I just had an idea. What about this blue cursor we move around with the
mouse. Is that a pixbuf? Can I play with it? Of course you can!

  0 0 cursor pixdst! rgbblack >screencolor rgbwhite >screencolor heart drawicn

Tadaa! your mouse cursor is now a heart (move it to see)!

So that's it for the Dusk Tour, with the hopes that it titillated your thirst
for power. This power doesn't come for free though. Significant efforts have to
be invested in learning Forth, then Dusk. You can begin at [doc/usage].
