minor corrections

This commit is contained in:
sejo 2021-12-14 18:46:28 -06:00
parent b44b7413aa
commit c81deee7ea
1 changed files with 99 additions and 85 deletions

View File

@ -30,9 +30,9 @@ how do we deal with them?
## the short mode
counting from right to left, the 6th bit of a byte that encodes an instruction for the uxn computer is a binary "flag" that corresponds to what is called the short mode.
counting from right to left, the 6th bit of a byte that encodes an instruction for the uxn computer is a binary flag that indicates if the short mode is set or not.
whenever this flag is set, i.e. when that bit is 1 instead of 0, the uxn cpu will perform the instruction given by the first 5 bits (the opcode) but using pairs of bytes instead of single bytes.
whenever the short mode is enabled, i.e. when that bit is 1 instead of 0, the uxn cpu will perform the instruction given by the first 5 bits (the opcode) but using pairs of bytes instead of single bytes.
the byte that is deeper inside the stack will be the "high" byte of the short, and the byte that is closer to the top of the stack will be the "low" byte of the short.
@ -44,19 +44,18 @@ let's see some examples!
### LIT2
first of all, let's recap. the following code will push number 02 down onto the stack, then it will push number 30 (in hexadecimal) down onto the stack, and finally add them together, leaving number 32 in the stack:
first of all, let's recap. the following code will push number 02 down onto the stack, then it will push number 30 (hexadecimal) down onto the stack, and finally add them together, leaving number 32 in the stack:
```
#02 #30 ADD
```
final state of the stack:
this would be the final state of the stack:
```
32 <- top
```
in the previous section we said that this was equivalent to using the LIT instruction instead of the literal hex rune (#)
in the previous day we mentioned that the literal hex rune (#) is a shorthand for the LIT instruction. therefore we could have written our code as follows:
```
LIT 02 LIT 30 ADD ( assembled code: 80 02 80 30 18 )
@ -68,7 +67,7 @@ now, if we add the '2' suffix to the LIT instruction, we could write instead:
LIT2 02 30 ADD ( assembled code: a0 02 30 18 )
```
instead of pushing one byte, LIT2 is pushing the next short (two bytes) in memory, down onto the stack.
instead of pushing one byte, LIT2 is pushing the short (two bytes) that follows in memory, down onto the stack.
we can use the literal hex rune (#) with a short (four nibbles) instead of a byte (two nibbles), and it will work as a shorthand for LIT2:
@ -78,7 +77,7 @@ we can use the literal hex rune (#) with a short (four nibbles) instead of a byt
### ADD2
now let's see what happens with the ADD instruction and the short mode.
now let's see what happens with the ADD instruction when we use the short mode.
what would be the state of the stack after executing this code?
@ -99,7 +98,6 @@ now, let's compare with what happens with ADD2:
```
in this case we are pushing the same 4 bytes down onto the stack, but ADD2 is doing the following actions:
* take the top element of the stack (08), and store it as the low byte of the first short
* take the new top element of the stack (00), and store it as the high byte of the first short, that is now 0008
* take the new top element of the stack (04), and store it as the low byte of the second short
@ -114,13 +112,13 @@ the stack ends up looking as follows:
00 0c <- top
```
we might not need to think too much about the per-byte manipulations of arithmetic operations, as we can think that they are doing "the same as before", but using pairs of bytes instead of single bytes; not really changing their order.
we might not need to think too much about the per-byte manipulations of arithmetic operations, because normally we can think that they are doing the same operation as before, but using pairs of bytes instead of single bytes. their order not really changes.
in any case, it's useful to keep them in mind for some behaviors we might need later :)
in any case, it's useful to keep in mind how they work for some behaviors we might need later :)
### DEO2, DEI, DEI2
let's talk now about the DEO (device out) instruction we discussed, as its short mode implies something special.
let's talk now about the DEO (device out) instruction we discussed in the previous day, as its short mode implies something special.
the DEO instruction needs a value (1 byte) to output, and an i/o address (1 byte) in the stack, in order to output that value to that address.
@ -128,38 +126,38 @@ the DEO instruction needs a value (1 byte) to output, and an i/o address (1 byte
DEO ( value address -- )
```
now that we are at it, let's mention its counterpart instruction: DEI (device in).
this instuction has a counterpart: DEI (device in).
this instruction needs an i/o address (1 byte) in the stack, and it will push down onto the stack the value (1 byte) that corresponds to reading that input.
the DEI instruction takes an i/o address (1 byte) from the stack, and it will push down onto the stack the value (1 byte) that corresponds to reading that input.
```
DEI ( address -- value )
```
what would DEO2 and DEI2 do?
what do you think that DEO2 and DEI2 would do?
in the case of the short mode of DEO and DEI, the short aspect applies to the value to output or input and not to the address.
in the case of the short mode of DEO and DEI, the short aspect applies to the value to output or input, and not to the address.
remember that the 256 i/o addresses are covered using one byte only already, so using one short for them would be redundant: the high byte would be always 00.
considering this, the following are the behaviors that we can expect:
the DEO2 instruction needs a value (1 short) to output, and an i/o address (1 byte) in the stack, in order to output that value to that address.
the DEO2 instruction needs a value (1 short) to output, and an i/o address (1 byte) in the stack, in order to output that value to that address. therefore it needs a total of 3 bytes in the stack to operate.
on the other hand, the DEI2 instruction needs an i/o address (1 byte) in the stack, and it will push down onto the stack the value (1 short) that corresponds to that input.
we will see next some examples where we'll be able to use these instructions.
in the following section we will see some examples where we'll be able to use these instructions.
the 'write' output of the console device has a size of 1 byte, so we can't really use with it these instructions in a meaningful way .
the 'write' port of the console device that we used last time has a size of 1 byte, so we can't really use these new instructions in a meaningful way with it.
# system device and colors
the system device is the varvara device with an address of 00. its output addresses (starting at address 08) correspond to three different shorts: one called red, the other one green, and the last one blue.
the system device is the varvara device with an address of 00. its output ports (starting at address 08) correspond to three different shorts: one called red (r), the other one green (g), and the last one blue (b).
in uxntal examples we can see its labels defined as follows:
```
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
```
we will ignore the first elements for the moment, and focus on the color components.
@ -170,11 +168,11 @@ the varvara screen device can only show a maximum of four colors at a time.
these four colors are called color 0, color 1, color 2 and color 3.
each color has a depth of 12 bits: 4 bits for the red component, 4 bits for the green component, and 4 bits for the blue component.
each color has a total depth of 12 bits: 4 bits for the red component, 4 bits for the green component, and 4 bits for the blue component.
we can define the values of these colors setting the r, g, b values of the system device.
the way we could write that would be as follows:
we could write that as follows:
```
( hello-screen.tal )
@ -190,18 +188,18 @@ the way we could write that would be as follows:
#2ce5 .System/b DEO2
```
what do the shorts mean?
how would we read what those literal shorts mean?
we can read them vertically, from left to right:
we can read each of the colors vertically, from left to right:
* color 0 would be red: 2, green: 0, blue: 2 ( #220022 in hex color notation, dark purple )
* color 1 would be red: c, green: 1, blue: c ( #cc11cc in hex color notation, magenta )
* color 2 would be red: e, green: c, blue: e ( #eeccee in hex color notation, light pink )
* color 3 would be red: 9, green: 0, blue: 5 ( #990055 in hex color notation, dark red )
if we run the program now, we'll see a dark purple screen, instead of black as before.
if we run the program now we'll see a dark purple screen, instead of black as what we had before.
try changing the values of color 0, and see what happens :)
try changing the values of color 0, i.e. the first column, and see what happens :)
# on-screen debugger
@ -226,7 +224,7 @@ now that you have some system colors set, run your program and press the F2 key:
remember: you can use the F1 key to switch between different zoom levels.
take a look at the representation of the stack: if you didn't change the values i suggested above, you'll the the following numbers at the top left:
take a look at the representation of the stack: if you didn't change the values i suggested above, you'll see the following numbers at the top left:
``` 2c e5 0c
[2c] e5 0c
@ -234,7 +232,9 @@ take a look at the representation of the stack: if you didn't change the values
what are these numbers?
2ce5 is the short we assigned to the blue components of the system colors, and 0c is the i/o address of the short corresponding to .System/b ! (can you say what are the numerical addresses of each of the color components in the system device?)
2ce5 is the short we assigned to the blue components of the system colors, and 0c is the i/o address of the short corresponding to .System/b ! (can you calculate and enumerate what are the numerical addresses of each of the color components in the system device?)
those values are the leftovers from the last operation on our program, the DEO2 that set the blue component of the system colors.
we can think of the highlight in the leftmost 2c, as an arrow pointing leftwards to the "top" of the stack. it current position implies that the stack is empty, as there are no more elements to its left.
@ -258,7 +258,7 @@ if everything went alright, you'll see:
00 0c [00] 08
```
if we think of the highlight as an arrow pointing left towards the top of the stack, we'll see that its position corresponds with the result that we wrote before!
if we think of the highlight as an arrow pointing left towards the top of the stack, we'll see that its position corresponds with the result that we would have expected!
```
00 0c <- top
@ -275,17 +275,16 @@ otherwise, it means that our operations with the stack were left unbalanced: the
# the screen device
we mentioned already that the screen device can only show four different colors at a given time, and that these colors are numbered from 0 to 3. we set these colors already with the system device.
let's discuss further and start using the screen device!
as a recap: we mentioned that the screen device can only show four different colors at a given time, and that these colors are numbered from 0 to 3. we set these these colors using the corresponding ports in the system device.
now let's discuss the screen device further and start using it!
## inputs and outputs
in uxntal programs for the varvara computer you will be able to find the labels corresponding to this device as follows:
```
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
```
the inputs that we can read from this device are:
@ -294,7 +293,7 @@ the inputs that we can read from this device are:
* width of the screen (2 bytes)
* height of the screen (2 bytes)
the output fields of this device are:
and the output ports of this device are:
* x coordinate (2 bytes)
* y coordinate (2 bytes)
@ -312,9 +311,9 @@ in the beginning the foreground layer is completey transparent: a process of alp
# drawing a pixel
the first and simpler way to draw into the screen, is drawing a single pixel.
the first and simpler way to draw into the screen is drawing a single pixel.
in order to do this, we need to set a pair of x,y coordinates where we want the pixel to be drawn, and we need to set the pixel byte to a value to actually perform the drawing.
in order to do this we need to set a pair of x,y coordinates where we want the pixel to be drawn, and we need to set the 'pixel' byte to a specific value to actually perform the drawing.
## setting the coordinates
@ -340,16 +339,16 @@ a question for you: if we wanted to set the coordinates as ( x: 4, y: 8 ), which
## setting the color
sending a byte to .Screen/pixel will perform the drawing in the screen.
sending a single byte to .Screen/pixel will perform the drawing in the screen.
the high nibble of that byte will determine the layer in which we'll draw:
the high nibble of that byte, i.e. the hexadecimal digit at the left, will determine the layer in which we'll draw:
* 0: draw a single pixel in the background
* 4: draw a single pixel in the foreground
and the low nibble of the byte will determine its color.
the low nibble of the byte, i.e. the hexadecimal digit at the right, will determine its color.
the 8 possible combinations of the pixel byte that we have for drawing a pixel are:
the 8 possible combinations of the 'pixel' byte that we have for drawing a pixel are:
+ <table>
+ <tr><th>pixel byte</th><th>layer</th><th>color</th></tr>
@ -387,8 +386,8 @@ the complete program would look as follows:
( hello-pixel.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( main program )
|0100
@ -400,7 +399,7 @@ the complete program would look as follows:
( draw a pixel in the screen )
#0008 .Screen/x DEO2
#0008 .Screen/y DEO2
#41 .Screen/pixel DEO
#41 .Screen/pixel DEO ( fg layer, color 1 )
```
woohoo!
@ -437,9 +436,9 @@ for example, we can draw multiple pixels in an horizontal line, setting the y co
#11 .Screen/pixel DEO
```
note that we have to set the color for each pixel we draw; that operation signals the drawing.
note that we have to set the color for each pixel we draw; that operation signals the drawing and has to be repeated.
we can define a macro to make it easier to repeat that:
we can define a macro to make this process easier to write:
```
%DRAW-PIXEL { #41 .Screen/pixel DEO } ( -- )
@ -471,7 +470,9 @@ you guessed it right, i hope!
* the second line pushes number 0001, adds it to the previous short, and pushes the result down onto the stack.
* the third line takes that result from the stack and writes it as the new x coordinate.
as that set of instructions increments the screen x coordinate by one, we could save it as a macro as well:
that set of instructions increments the screen x coordinate by one :)
they seem handy, so we could save them as a macro as well:
```
%INC-X { .Screen/x DEI2 #0001 ADD2 .Screen/x DEO2 } ( -- )
@ -509,8 +510,8 @@ using these macros we defined above, our code could end up looking as following:
( hello-pixels.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( macros )
%DRAW-PIXEL { #41 .Screen/pixel DEO } ( -- )
@ -535,19 +536,25 @@ using these macros we defined above, our code could end up looking as following:
DRAW-PIXEL
```
nice, isn't it?
nice, isn't it? the operations now look clearer! and if we wanted to have this line available for use in other positions, we could define a macro for it:
we'll see now how to leverage the built-in support for "sprites" in the uxn screen device, in order to draw many pixels at once!
```
%DRAW-LINE { } ( -- )
```
try writing the macro and using it in different positions of the screen!
# drawing sprites
now, we'll see now how to leverage the built-in support for "sprites" in the varvara screen device in order to draw many pixels at once!
the varvara screen device allows us to use and draw tiles of 8x8 pixels, also called sprites.
there are two posible modes: 1bpp (1 bit per pixel), and 2bpp (2 bits per pixel).
1bpp tiles use two colors, and they are encoded using 8 bytes; using one bit per pixel means that we can only encode if that pixel is using one color, or the other.
2bpp tiles use four colors and they are encoded using 16 bytes; using two bits per pixel we can encode one color out of four.
2bpp tiles use four colors and they are encoded using 16 bytes; using two bits per pixel means we can encode which one of the four available colors the pixel has.
we will be storing and accessing these tiles from the main memory.
@ -591,7 +598,7 @@ based on that, we could encode our square as follows:
## storing the sprite
in uxntal, we need to write and label the data corresponding to the sprite into the main memory, going from top to bottom:
in uxntal, we need to label and write into main memory the data corresponding to the sprite. we write the bytes going from top to bottom of the sprite:
```
@square ff81 8181 8181 81ff
@ -599,11 +606,11 @@ in uxntal, we need to write and label the data corresponding to the sprite into
note that we are not using the literal hex (#) rune here: we want to use the raw bytes in memory, and we don't need to push them down onto the stack.
to make sure that these bytes are not read as instructions by the uxn cpu, it's a good practice to precede them with the BRK instruction: this will interrupt the execution of the program before arriving here, leaving uxn "waiting" for inputs.
to make sure that these bytes are not read as instructions by the uxn cpu, it's a good practice to precede them with the BRK instruction: this will interrupt the execution of the program before arriving here, leaving uxn in a state where it's waiting for inputs.
## setting the address
in order to draw the sprite, we need to set its address in memory to the screen device, and we need to assign an appropriate sprite byte.
in order to draw the sprite, we need to send its address in memory to the screen device, and we need to assign an appropriate sprite byte.
to achieve the former, we write the following:
@ -623,11 +630,11 @@ similar to what we saw already with the pixel, sending a byte to .Screen/sprite
### sprite high nibble for 1bpp
as in the case of drawing pixels, the high nibble of that byte will determine the layer in which we'll draw.
the high nibble of the 'sprite' byte will determine the layer in which we'll draw, just like when we were drawing using the 'pixel' byte.
however, in this case we'll have other possibilities: we can flip the sprite in the horizontal (x) and/or the vertical (y) axis.
the possible values of this high nibble, used for drawing a 1bpp sprite, are:
the eight possible values of this high nibble, used for drawing a 1bpp sprite, are:
+ <table>
+ <tr><th>high nibble</th><th>layer</th><th>flip-y</th><th>flip-x</th></tr>
@ -664,10 +671,13 @@ the following shows the meaning of each of these bits in the high nibble, assumi
& * bit 6: layer (0 is background, 1 is foreground)
& * bit 7: mode (0 is 1bpp, 1 is 2bpp)
as an example, when the 'sprite' high nibble is 0, that in binary is 0000, it means that all the flags are off: that's why it draws a 1bpp (0) sprite in the background (0), not flipped neither vertically (0) nor horizontally (0).
a high nible of 1, i.e. 0001 in binary, has the last flag on, so that's why it's flipped horizontally, and so on.
### sprite low nibble for 1bpp
the low nibble of the sprite byte will determine the colors that are used to draw the "on" and "off" pixels of the tiles.
the low nibble of the 'sprite' byte will determine the colors that are used to draw the "on" and "off" pixels of the tiles.
+ <table>
+ <tr><th>low nibble</th><th>"on" color</th><th>"off" color</th></tr>
@ -718,8 +728,8 @@ let's do this! the following program will draw our sprite once:
( hello-sprite.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( main program )
|0100
@ -728,7 +738,7 @@ let's do this! the following program will draw our sprite once:
#01c0 .System/g DEO2
#2ce5 .System/b DEO2
( set x,y coordinates )
( set x,y coordinates )
#0008 .Screen/x DEO2
#0008 .Screen/y DEO2
@ -754,8 +764,8 @@ the following code will draw our square sprite with all 16 combinations of color
( hello-sprites.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( macros )
%INIT-X { #0008 .Screen/x DEO2 } ( -- )
@ -825,7 +835,7 @@ in 2bpp sprites each pixel can have one of four possible colors.
we can think that, in order to assign these colors, we will encode one out of four states in each of the pixels of the sprite.
each one of these states can be encoded with a combination of two bits. these states can be assigned different combination of the four system colors, by using appropriate values in the screen color byte.
each one of these states can be encoded with a combination of two bits. these states can be assigned different combination of the four system colors by using appropriate values in the screen 'sprite' byte.
a single 2bpp tile of 8x8 pixels needs 16 bytes to be encoded. these bytes are ordered according to a format called chr.
@ -859,7 +869,7 @@ in this way, we could think of our sprite as follows:
(01) (01) (01) (01) (01) (01) (01) (01)
```
the chr encoding needs some interesting manipulation of those bits: we can think of each pair of bits as having a high bit in the left and a low bit in the right.
the chr encoding requires some interesting manipulation of those bits: we can think of each pair of bits as having a high bit in the left and a low bit in the right.
we separate our tile into two different squares, one for the high bits and the other for the low bits:
@ -874,7 +884,7 @@ we separate our tile into two different squares, one for the high bits and the o
00000000 11111111
```
now we can take each of these squares as 1bpp sprites, and encode them in hexadecimal as he did before:
now we can think of each of these squares as 1bpp sprites, and encode them in hexadecimal as he did before:
``` the two previous 8x8 squares with their corresponding hexadecimal encoding
00000000: 00 00000001: 01
@ -892,7 +902,7 @@ now we can take each of these squares as 1bpp sprites, and encode them in hexade
in order to write this sprite into memory, we first store the square corresponding to the low bits, and then the square corresponding to the high bits. each of them, from top to bottom:
```
@new-square 017f 7b73 6343 7fff 007c 7c7c 7c7c 0000
@new-square 017f 7b73 6343 7fff 007c 7c7c 7c7c 0000
```
we can set this address in the screen device the same as before:
@ -901,7 +911,7 @@ we can set this address in the screen device the same as before:
;new-square .Screen/addr DEO2
```
the screen device will use treat this address as a 2bpp sprite when we use the appropriate color byte.
the screen device will treat this address as a 2bpp sprite when we use the appropriate color byte.
## setting the color
@ -909,7 +919,9 @@ let's see how to use the sprite byte in order to draw 2bpp tiles!
### sprite high nibble for 2bpp
the high nibble for 2bpp sprites will allow us to choose the layer we want it to be drawn, and the flip direction, if any:
the high nibble for 2bpp sprites will allow us to choose the layer we want it to be drawn, and the flip direction.
the eight possible values for this nibble are:
+ <table>
+ <tr><th>high nibble</th><th>layer</th><th>flip-y</th><th>flip-x</th></tr>
@ -932,6 +944,8 @@ the high nibble for 2bpp sprites will allow us to choose the layer we want it to
& * e: draw a 2bpp sprite in the foreground, flipped vertically
& * f: draw a 2bpp sprite in the foreground, flipped horizontally and vertically
note that these eight values all have a leftmost bit in 1: this bit signals that we will be drawing a 2bpp sprite. the other three bits of the nibble behave as described above in the 1bpp case.
### sprite low nibble for 2bpp
the low nibble will allow us to choose between many combinations of colors assigned to each different states of the pixels.
@ -983,8 +997,8 @@ the following code will show our sprite in the 16 different combinations of colo
( hello-2bpp-sprite.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( macros )
%INIT-X { #0008 .Screen/x DEO2 } ( -- )
@ -1042,7 +1056,7 @@ the screen.tal example in the uxn repo consists of a table showing all possible
=> https://git.sr.ht/~rabbits/uxn/tree/main/item/projects/examples/devices/screen.tal screen.tal code
compare them with everything we have said before about the sprite byte!
compare them with everything we have said about the 'sprite' byte!
## designing sprites
@ -1062,7 +1076,7 @@ the last thing we'll cover today has to do with the assumptions varvara makes ab
in short, there's not a standard screen size!
by default, the screen of the varvara emulator is 512x320 pixels (or 64x40 tiles).
by default, the screen of the varvara emulator has a size of 512x320 pixels (or 64x40 tiles).
however, and for example, the virtual computer also runs in the nintendo ds, with a resolution of 256x192 pixels (32x24 tiles), and in the teletype with a resolution of 128x64 pixels (16x8 tiles)
@ -1070,9 +1084,9 @@ as programmers, we are expected to decide what to do with these: our programs ca
## changing the screen size
we can change the varvara screen size by writing to the .Screen/width and .Screen/height fields.
additionaly, we can change the varvara screen size by writing to the .Screen/width and .Screen/height ports.
for example, the following would change it to a 640x480 resolution:
for example, the following code would change the screen to a 640x480 resolution:
```
#0280 .Screen/width DEO2 ( width of 640 )
@ -1087,7 +1101,7 @@ it would be important to keep in mind the responsiveness aspects that are discus
originally, the way of changing the screen size in uxnemu implied editing its source code.
in the uxn repo we downloaded, inside the src/ directory, there's uxnemu.c, with a couple of lines that look like the following:
if you downloaded the repository with the source code, you'll see that inside the src/ directory there's uxnemu.c, with a couple of lines that look like the following:
```
#define WIDTH 64 * 8
@ -1100,7 +1114,7 @@ you can change those, save the file, and then re-run the build.sh script to have
## reading and adapting to the screen size (the basics)
as you may recall from the device addresses mentioned above, the screen allows us to read its width and height, as shorts.
as you may recall from the screen device ports mentioned above, the screen allows us to read its width and height as shorts.
if we wanted to, for example, draw a pixel in the middle of the screen regardless of the screen size, we can translate to uxntal an expression like the following:
@ -1128,9 +1142,9 @@ using DIV, our translated expression for the case of the x coordinate, could loo
if what we want is to divide over or multiply by powers of two (like in this case), we can also use the SFT instruction.
this instruction takes a number and a "shift value" that indicates the amount of bits to shift to the right, and/or to the left.
this instruction takes a number and a "shift value" that indicates the amount of bit positions to shift to the right, and/or to the left.
the low nibble of the shift value tells uxn how many bits to shift to the right, and the high nibble expresses how many bits to shift to the left.
the low nibble of the shift value tells uxn how many positions to shift to the right, and the high nibble expresses how many bits to shift to the left.
in order to divide a number over 2, we'd need to shift its bits one space to the right.
@ -1140,17 +1154,17 @@ for example, dividing 10 (in decimal) over 2 could be expressed as follows:
#0a #01 SFT ( result: 05 )
```
0a is 0000 1010 in binary, and 05 is 0000 0101 in binary.
0a is 0000 1010 in binary, and 05 is 0000 0101 in binary: the bits from 0a were shifted one position to the right, and a zero was brought in as the leftmost bit.
to multiply times 2, we shift one space to the left:
to multiply by 2, we shift one space to the left:
```
#0a #10 SFT ( result: 14 in hexadecimal )
```
14 in hexadecimal (20 in decimal), is 0001 0100 in binary.
14 in hexadecimal (20 in decimal), is 0001 0100 in binary: the bits from 0a were shifted one position to the left, and a zero was brought in as the rightmost bit.
in short mode, the number to shift is a short, but the shift value is still a byte.
when in short mode, the number to shift is a short, but the shift value is still a byte.
for example, the following will divide the screen width over two, by using bitwise shifting:
@ -1188,13 +1202,13 @@ note that the HALF2 macro using SFT2 would require one byte less than the one us
## drawing sprites in specific positions
as an exercise for you, i invite you to write the code in order to do some or all of the following:
as an exercise for you, i invite you to write the code that would achieve some or all of the following:
* draw an 8x8 tile completely centered in the screen
* draw an 8x8 tile in each of the corners of the screen
* draw an 8x8 tile touching each of the screen borders, centered in each of them
do the same, but using an image composed of multiple tiles (e.g. 2x2 tiles, 1x2 tiles, etc).
once you have it, i invite you to do the same, but using an image composed of multiple tiles (e.g. 2x2 tiles, 1x2 tiles, etc).
# instructions of day 2