here we will generalize a similar procedure into a draw-tiles subroutine that draws a rectangle filled with a given tile. it will receive the x,y coordinates of the top left corner of the rectangle, its width and height in pixels, and the address of the tile:
a reminder that we are using the convention of adding a caret (^) after the name of a value to indicate it's a short, and an asterisk (*) to indicate it's a short working as a pointer (i.e. an address in program memory)
we will detail how to get to two versions of this subroutine, one that relies on heavy stack wrangling, and other one that uses variables. this in order to compare both approaches and give us a broader view of the possibilities within uxntal.
now, let's say we want to have the previous code work with any given initial x and width, present in the stack before starting.
we can even think of it as a subroutine by itself with the following signature:
```
@draw-tiles-in-a-row ( x^ width^ -- )
```
let's assume for the moment that the address of the sprite was already set, in order to focus in x and width.
when starting the subroutine, the width is at the top of the stack, followed by initial x.
we can use these two values to calculate the limit, that we can stash in the return stack.
one way of achieving that, noting the state of the working stack after each instruction, could be:
```
( initial state: ws: x^ width^ )
OVR2 ( ws: x^ width^ x^ )
ADD2 ( ws: x^ limit^ )
STH2 ( ws: x^ / rs: limit^ )
```
another one:
```
( initial state: ws: x^ width^ )
ADD2k ( ws: x^ width^ limit^ )
STH2 ( ws: x^ width^ / rs: limit^ )
POP2 ( ws: x^ / rs: limit^ )
```
remember that we are showing the top of the stacks at their right.
after these steps, the initial x is at the top of the stack, so we can send it directly to the screen.
the last change that we would need is to replace our hardcoded limit with a STH2kr instruction (copy limit from the return stack into the working stack), and end our routine with a POP2r (remove limit from return stack).
our subroutine would then look as follows:
```
@draw-tiles-in-a-row ( x^ width^ -- )
( calculate and save limit )
OVR2 ( ws: x^ width^ x^ )
ADD2 ( ws: x^ limit^ )
STH2 ( ws: x^ / rs: limit^ )
.Screen/x DEO2 ( set initial x )
&loop-x
#03 .Screen/sprite DEO ( draw sprite with color 3 and 0 )
.Screen/x DEI2 #0008 ADD2 DUP2 ( add 8 to x )
.Screen/x DEO2 ( store new x )
STH2kr ( copy limit from rs into ws )
LTH2 ,&loop-x JCN ( jump if x is less than the limit )
similar to what we just did: what's a procedure we could follow to repeat vertically a row starting from y, and ending at a limit corresponding to y+height?
in the case of x, let's start at 0000 and have a width corresponding to the screen width.
as the address wouldn't change in the process, we can set it up at the top and forget about it.
the following code is based on the previous x loop, but it now draws a row in a given y coordinate, adds 8 to it and then checks if it's less than the limit:
```
;tile-background .Screen/addr DEO2 ( set tile address )
#0008 .Screen/y ( set initial y )
&loop-y
( prepare and draw row )
#0000 ( initial x )
.Screen/width DEI2 ( get screen width )
;draw-tiles-in-a-row JSR2
.Screen/y DEI2 #0008 ADD2 DUP2 ( add 8 to y )
.Screen/y DEO2 ( store new y )
#0108 ( put limit in top of the stack )
LTH2 ,&loop-y JCN ( jump if x is less than the limit )
now, before jumping right into emulating the solution for drawing the row, let's note that in this case it is not that easy.
why? because the idea for our draw-tiles subroutine is that it should be able to receive the initial x and the width of the rectangle, and right now these values are hardcoded inside the loop.
this should be the signature for our subroutine:
```
@draw-tiles ( x^ y^ width^ height^ addr* -- )
```
we can approach this problem either with some "stack wrangling", or with "variables".
if we just wanted to cover all the screen with a sprite, we have all the required code already: we would only need to adapt the vertical limit of the loop to correspond to the height of the screen, and that would be it!
we could then just jump to the section regarding the paddles. however, what follows can be interesting as a way of looking at possible approach to write more complex uxntal code :)
thinking about the vertical loop, we need to calculate its limit adding height to y, and we need to set the initial y.
we could do the following:
```
ROT2 ( ws: x^ width^ height^ y^ )
DUP2 ( ws: x^ width^ height^ y^ y^ )
( set initial y: )
.Screen/y DEO2 ( ws: x^ width^ height^ y^ )
( calculate and stash vertical limit )
ADD2 ( ws: x^ width^ limit-y^ )
STH2 ( ws: x^ width^ / rs: limit-y^ )
```
now, we might be able to stash also the width and 'x', as we need them afterwards in their original order (first x, then width )
```
STH2 ( ws: x^ / rs: limit-y^ width^ )
STH2 ( ws: / rs: limit-y^ width^ x^ )
```
in theory, the first part of our subroutine could look like:
```
@draw-tiles ( x^ y^ width^ height^ addr* -- )
( set tile address )
.Screen/addr DEO2 ( ws: x^ y^ width^ height^ )
ROT2 ( ws: x^ width^ height^ y^ )
DUP2 ( ws: x^ width^ height^ y^ y^ )
( set initial y )
.Screen/y DEO2 ( set initial y, ws: x^ width^ height^ y^ )
( calculate and stash limit-y )
ADD2 ( ws: x^ width^ limit-y^ )
STH2 ( ws: x^ width^ / rs: limit-y^ )
( stash width and x )
STH2 STH2 ( ws: / rs: limit-y^ width^ x^ )
&loop-y
( prepare and draw row )
( retrieve x )
STH2r ( ws: x^ / rs: limit-y^ width^ )
( retrieve width )
STH2r ( ws: x^ width^ / rs: limit-y^ )
;draw-tiles-in-a-row JSR2
```
the problem is that inside the loop, both STH2r instructions retrieve and consume the values for x and width from the return stack. therefore, in the next iteration we wouldn't be able to use them again, as they would be lost.
we can think we could replace these instructions with STH2kr:
```
&loop-y
( prepare and draw row )
( retrieve x )
STH2kr ( ws: x^ / rs: limit-y^ width^ x^ )
```
but then we can't retrieve the width because the x is still at the top of the return stack!
oh, many difficulties, but for the sake of the stack wrangling example, let's continue solving this (?)
how can we put the width at the top of the return stack? maybe with a swap applied to the return stack:
but ah, before doing the comparison and jumping, we should rearrange the return stack so that it corresponds to the ordering we had at the beginning of the loop:
maybe the vertical limit can be stashed in the return stack like in the draw-tiles-in-a-row loop, or maybe the variable for the height and for the initial y are not needed.
i'll let you figure them out :)
note that this subroutine as-is, requires 24 bytes of program memory more than the stack wrangling version.
in our case that's not much of a problem, but it's a good way of evaluating our priorities: super readable but probably inefficient code (like this last subroutine), super optimized but probably unreadable code (write-only code, they say), or something in the middle.