Traducción terminada del Día 7 y Apéndice A. Revisión breve de demases.

This commit is contained in:
jota 2022-01-12 15:33:35 -03:00
parent 2f7ea7474c
commit 04273debea
5 changed files with 623 additions and 22 deletions

View File

@ -68,6 +68,14 @@ este debería ser un final ligero y tranquilo de nuestro recorrido, ya que tiene
{tutorial de uxn día 7}
## apéndices
# apéndice a: repetir un tile dentro de un rectángulo
aquí generalizaremos un procedimiento similar en una subrutina dibuja-tiles que dibuje un rectángulo relleno con un tile dado.
{tutorial de uxn apéndice a}
# índice tentativo
este índice está aquí y ahora como referencia de la estructura general del tutorial.

View File

@ -1,3 +1,596 @@
# apéndice A
# tutorial uxn apéndice a: repetir un tile dentro de un rectángulo
¡proximamente! traducción en proceso. :)
en la primera parte del {tutorial de uxn día 6} hablamos de cómo cubrir el fondo de la pantalla con un tile dado.
aquí generalizaremos un procedimiento similar en una subrutina dibuja-tiles que dibuje un rectángulo relleno con un tile dado. recibirá las coordenadas x,y de la esquina superior izquierda del rectángulo, su anchura y altura en píxeles, y la dirección del tile:
```
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
```
un recordatorio de que estamos utilizando la convención de añadir un signo de intercalación (^) después del nombre de un valor para indicar que es un corto, y un asterisco (*) para indicar que es un corto que funciona como un puntero (es decir, una dirección en la memoria del programa)
vamos a detallar cómo llegar a dos versiones de esta subrutina, una que se basa en una fuerte manipulación de la pila, y otra que utiliza variables. esto con el fin de comparar ambos enfoques y darnos una visión más amplia de las posibilidades dentro de uxntal.
## configuración
comencemos con el siguiente programa como plantilla. incluye los datos para un sprite de 1bpp compuesto por líneas diagonales.
```
( hola-fondo.tal )
( dispositivos )
|00 @Sistema [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Pantalla [ &vector $2 &ancho $2 &alto $2 &auto $1 &pad $1 &x $2 &y $2 &direc $2 &pixel $1 &sprite $1 ]
( macros )
%RTN { JMP2r }
( programa principal )
|0100
@configuracion
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
BRK
@tile-fondo 1122 4488 1122 4488
```
## repetir un tile en una fila
¿qué procedimiento podríamos seguir para repetir el dibujo de un tile empezando por x, y terminando en un límite correspondiente a x+ancho?
una forma sería algo así como:
* dibujar tile en x
* añadir 8 (el tamaño del tile) a x
* ¿es x menor que el límite? si lo es, repite el procedimiento, si no, termina
### versión concreta
antes de abstraerlo, recomiendo que lo escribamos con números concretos.
digamos que nuestra x inicial es 0008, nuestro ancho es 0100, y el tile que estamos dibujando es tile-fondo.
el límite, x+ancho, sería 0108.
el primer paso, dibujar el tile en x sería:
```
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
#0008 .Pantalla/x DEO2 ( establecer la x inicial )
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
```
añadiendo 8 a x, ya sabemos:
```
.Pantalla/x DEI2 #0008 ADD2 ( añadir 8 a x )
.Pantalla/x DEO2 ( guardar la nueva x )
```
comprobar si x es menor que el límite, saltando si lo es, sería algo así:
```
.Pantalla/x DEI2
#0108 ( el límite )
LTH2 ,&bucle JCN ( saltar si x es menor que el límite )
```
integrando todo ello, podríamos obtener:
```
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
#0008 .Pantalla/x DEO2 ( establecer la x inicial )
&bucle-x
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
.Pantalla/x DEO2 ( almacenar la nueva x )
#0108 LTH2 ,&bucle-x JCN ( salta si x es menor que el límite )
```
nótese el uso de DUP2 para evitar releer el valor de x.
### abstrayendo
ahora, digamos que queremos que el código anterior funcione con cualquier x inicial y ancho inicial dados, presentes en la pila antes de empezar.
podemos incluso pensar en ello como una subrutina por sí misma con la siguiente firma:
```
@dibuja-tiles-en-fila ( x^ ancho^ -- )
```
asumamos por el momento que la dirección del sprite ya fue establecida, para enfocarnos en `x` y en el ancho.
al iniciar la subrutina, el ancho está en la parte superior de la pila, seguido de la x inicial.
podemos utilizar estos dos valores para calcular el límite, que podemos almacenar en la pila de retorno.
una forma de conseguirlo, anotando el estado de la pila de trabajo después de cada instrucción, podría ser:
```
( estado inicial: ptr: x^ ancho^ )
OVR2 ( ptr: x^ ancho^ x^ )
ADD2 ( ptr: x^ límite^ )
STH2 ( ptr: x^ / pre: límite^ )
```
otra:
```
( estado inicial: ptr: x^ ancho^ )
ADD2k ( ptr: x^ ancho^ límite^ )
STH2 ( ptr: x^ ancho^ / pre: límite^ )
POP2 ( ptr: x^ / pre: límite^ )
```
recuerda que estamos mostrando la parte superior de las pilas a su derecha.
después de estos pasos, la x inicial está en la parte superior de la pila, por lo que podemos enviarla directamente a la pantalla.
el último cambio que necesitaríamos es reemplazar nuestro límite codificado por una instrucción STH2kr (copiar el límite de la pila de retorno a la pila de trabajo), y terminar nuestra rutina con una POP2r (eliminar el límite de la pila de retorno).
nuestra subrutina se vería entonces de la siguiente manera:
```
@dibuja-tiles-en-fila ( x^ ancho^ -- )
( calcular y guardar el límite )
OVR2 ( ptr: x^ ancho^ x^ )
ADD2 ( ptr: x^ límite^ )
STH2 ( ptr: x^ / pre: límite^ )
.Pantalla/x DEO2 ( fijar x inicial )
&bucle-x
#03 .Pantalla/sprite DEO ( dibujar sprite con color 3 y 0 )
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
.Pantalla/x DEO2 ( guardar la nueva x )
STH2kr ( copiar límite de rs en ws )
LTH2 ,&bucle-x JCN ( saltar si x es menor que el límite )
POP2r ( hacer POP en límite de rs )
RTN
```
### programa completo
lo siguiente muestra nuestro programa en contexto, llenando completamente la primera fila de nuestra pantalla con nuestro tile:
=> ./img/screenshot_uxn-background-row.png captura de pantalla mostrando la primera fila de la pantalla varvara rellenada con líneas diagonales
```
( hola-fondo.tal )
( dispositivos )
|00 @Sistema [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Pantalla [ &vector $2 &ancho $2 &alto $2 &auto $1 &pad $1 &x $2 &y $2 &direc $2 &pixel $1 &sprite $1 ]
( macros )
%RTN { JMP2r }
( programa principal )
|0100
@configuracion
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
#0000 ( x inicial )
.Pantalla/ancho DEI2 ( obtener el ancho de la pantalla )
;dibuja-tiles-en-fila JSR2
BRK
@dibuja-tiles-en-fila ( x^ ancho^ -- )
OVR2 ( ptr: x^ límite^ x^ )
ADD2 ( ptr: x^ límite^ )
STH2 ( ptr: x^ / pre: límite^ )
.Pantalla/x DEO2 ( fijar x inicial )
&bucle-x
#03 .Pantalla/sprite DEO ( dibujar sprite con color 3 y 0 )
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
.Pantalla/x DEO2 ( guarda la nueva x )
STH2kr ( copiar límite de rs en ws )
LTH2 ,&bucle-x JCN ( saltar si x es menor que el límite )
POP2r ( sacar el límite de rs )
RTN
@tile-fondo 1122 4488 1122 4488
```
## repetir una fila
similar a lo que acabamos de hacer: ¿cuál es el procedimiento que podríamos seguir para repetir verticalmente una fila empezando por `y`, y terminando en un límite correspondiente a y+altura?
siguiendo la misma estrategia, podríamos hacer:
* dibujar la fila en y
* añadir 8 (el tamaño del tile) a y
* ¿es `y` menor que el límite? si lo es, repetir el procedimiento, en caso contrario terminar
### versión concreta
utilicemos los mismos números que antes, suponiendo que nuestra `y` inicial es 0008, nuestra altura es 0100, y por tanto nuestro límite siendo 0108.
en el caso de x, comencemos en 0000 y tengamos un ancho correspondiente al ancho de la pantalla.
como la dirección no cambiaría en el proceso, podemos establecerla al principio y olvidarnos de ella.
el siguiente código se basa en el bucle anterior de x, pero ahora dibuja una fila en una coordenada `y` dada, le suma 8 y luego comprueba si es menor que el límite:
```
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
#0008 .Pantalla/y ( establecer y inicial )
&bucle-y
( preparar y dibujar fila )
#0000 ( x inicial )
.Pantalla/ancho DEI2 ( obtener el ancho de la pantalla )
;dibuja-tiles-en-fila JSR2
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
.Pantalla/y DEO2 ( guardar la nueva y )
#0108 ( poner límite en la parte superior de la pila )
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
```
### versión abstracta
ahora, antes de saltar directamente a la emulación de la solución para dibujar la fila, vamos a notar que en este caso no es tan fácil.
¿por qué? porque la idea de nuestra subrutina dibuja-tiles es que debe ser capaz de recibir la x inicial y el ancho del rectángulo, y ahora mismo estos valores están codificados dentro del bucle.
esta debería ser la firma de nuestra subrutina:
```
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
```
podemos abordar este problema bien con alguna "manipulación de la pila ", o bien con "variables ".
también hay que tener en cuenta que lo haremos porque estamos tratando de llegar a una subrutina generalizada.
si sólo quisiéramos cubrir toda la pantalla con un sprite, ya tenemos todo el código necesario: sólo tendríamos que adaptar el límite vertical del bucle para que se corresponda con la altura de la pantalla, ¡y ya está!
entonces podríamos pasar a la sección relativa de las paletas. sin embargo, lo que sigue puede ser interesante como una forma de ver un posible enfoque para escribir un código uxntal más complejo :)
### usando la manipulación de la pila
en principio podríamos simplemente manipular los elementos dados en la pila, almacenándolos cuando sea apropiado, para adaptar nuestra subrutina a su firma.
en primer lugar, la dirección del tile es el valor de la parte superior de la pila. podemos consumirlo y olvidarnos de él:
```
( ws inicial: x^ y^ ancho^ alto^ direc* )
.Pantalla/direc DEO2 ( ptr: x^ y^ ancho^ alto^ )
```
pensando en el bucle vertical, necesitamos calcular su límite sumando la altura a `y`, y necesitamos establecer la `y` inicial.
podríamos hacer lo siguiente:
```
ROT2 ( ptr: x^ ancho^ altura^ y^ )
DUP2 ( ptr: x^ ancho^ altura^ y^ y^ )
( establecer y inicial: )
.Pantalla/y DEO2 ( ptr: x^ ancho^ alto^ y^ )
( calcular y almacenar el límite vertical )
ADD2 ( ptr: x^ ancho^ límite-y^ )
STH2 ( ptr: x^ ancho^ / pre: límite-y^ )
```
ahora, podríamos también almacenar el ancho y `x`, ya que las necesitamos después en su orden original (primero x, luego anchura )
```
STH2 ( ptr: x^ / pre: límite-y^ ancho^ )
STH2 ( ptr: / pre: límite-y^ ancho^ x^ )
```
en teoría, la primera parte de nuestra subrutina podría verse como:
```
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
( establecer la dirección del tile )
.Pantalla/direc DEO2 ( ptr: x^ y^ ancho^ alto^ )
ROT2 ( ptr: x^ ^ altura^ y^ )
DUP2 ( ptr: x^ ^ altura^ y^ )
( fijar y inicial )
.Pantalla/y DEO2 ( fijar y inicial, ptr: x^ ^ altura^ y^ )
( calcular y guardar límite-y )
ADD2 ( ptr: x^ ^ límite-y^ )
STH2 ( ptr: x^ ^ / pre: límite-y^ )
( almacenar anchura y `x` )
STH2 STH2 ( ptr: / pre: límite-y^ ancho^ x^ )
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2r ( ptr: x^ / pre: límite-y^ ancho^ )
( recuperar la anchura )
STH2r ( ptr: x^ ancho^ / pre: límite-y^ )
;dibuja-tiles-en-fila JSR2
```
el problema es que dentro del bucle, ambas instrucciones STH2r recuperan y consumen los valores de `x` y ancho de la pila de retorno. por tanto, en la siguiente iteración no podríamos volver a utilizarlos, ya que se perderían.
podemos pensar que podríamos reemplazar estas instrucciones con STH2kr:
```
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2kr ( ptr: x^ / pre: límite-y^ ancho^ x^ )
```
¡pero entonces no podemos recuperar el ancho porque la x sigue en la parte superior de la pila de retorno!
oh, muchas dificultades, pero por el bien del ejemplo de la pila, vamos a seguir resolviendo esto (?)
¿cómo podemos poner el ancho en la parte superior de la pila de retorno? tal vez con un intercambio aplicado a la pila de retorno:
```
SWP2r ( ptr: x^ / pre: límite-y^ x^ ancho^ )
```
entonces podemos recuperar el ancho y utilizarlo:
```
STH2kr ( ptr: x^ ancho^ / pre: límite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptr: / pre: límite-y^ x^ ancho^ )
```
¿qué sigue? añadir 8 a `y`, y comprobar si es menor que el límite. la primera parte va sin problemas:
```
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y; ptr: y^ y^ / pre: límite-y^ x^ ancho^ )
.Pantalla/y DEO2 ( almacenar nueva `y`; ptr: y^ / pre: límite-y^ x^ ancho^ )
```
para conseguir el límite en la pila de trabajo para la comparación, tenemos que girar la pila de retorno:
```
ROT2r ( ptr: y^ / pre: x^ ancho^ límite-y^ )
STH2kr ( ptr: y^ límite-y^ / pre: x^ ancho^ límite-y^ )
```
pero ah, antes de hacer la comparación y el salto, debemos reordenar la pila de retorno para que se corresponda con la ordenación que teníamos al principio del bucle:
```
SWP2r ( ptr: y^ límite-y^ / pre: x^ límite-y^ ancho^ )
ROT2r ( ptr: y^ límite-y^ / pre: límite-y^ ancho^ x^ )
```
ahora podemos hacer la comparación y saltar:
```
LTH2 ,&bucle-y JCN ( salta si x es menor que el límite )
```
después debemos limpiar la pila de retorno:
```
POP2r POP2r POP2r
```
después de todo esto, nuestra subrutina tendría el siguiente aspecto:
```
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
( establecer la dirección del tile )
.Pantalla/direc DEO2 ( ptr: x^ y^ ancho^ alto^ )
ROT2 ( ptr: x^ ^ altura^ y^ )
DUP2 ( ptr: x^ ^ altura^ y^ )
( fijar y inicial )
.Pantalla/y DEO2 ( fijar y inicial, ptr: x^ ^ altura^ y^ )
( calcular y almacenar límite-y )
ADD2 ( ptr: x^ ^ límite-y^ )
STH2 ( ptr: x^ ^ / pre: límite-y^ )
( almacenar anchura y `x` )
STH2 STH2 ( ptr: / pre: límite-y^ ancho^ x^ )
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2kr ( ptr: x^ / pre: límite-y^ ancho^ x^ )
( recuperar la anchura )
SWP2r ( ptr: x^ / pre: límite-y^ x^ ancho^ )
STH2kr ( ptr: x^ ancho^ / pre: límite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptr: / pre: límite-y^ x^ ancho^ )
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añadir 8 a y )
.Pantalla/y DEO2 ( almacenar la nueva y )
( recuperar límite-y )
ROT2r ( ptr: y^ / pre: x^ ^ límite-y^ )
STH2kr ( ptr: y^ límite-y^ / pre: x^ ancho^ límite-y^ )
( reordenar la pila de retorno )
SWP2r ( ptr: y^ límite-y^ / pre: x^ límite-y^ ancho^ )
ROT2r ( ptr: y^ límite-y^ / pre: límite-y^ ancho^ x^ )
LTH2 ,&bucle-y JCN ( salta si x es menor que el límite )
POP2r POP2r POP2r ( limpiar la pila de retorno )
RTN
```
podemos entonces llamarlo de la siguiente manera para obtener un cuadrado de 256x256 lleno de tiles:
```
#0008 #0008 ( x y `y` )
#0100 #0100 ( ancho y alto )
;tile-fondo
;dibuja-tiles JSR2
```
=> ./img/screenshot_uxn-background-square.png captura de pantalla que muestra un gran cuadrado en la pantalla varvara compuesto por líneas diagonales
### usando variables
comparemos el enfoque anterior con el uso de variables relativas.
iremos "con todo" de una manera relativamente derrochadora, sin optimizar los procedimientos que podrían beneficiarse de la manipulación de la pila.
declararemos las siguientes etiquetas para nuestras variables, después del RTN que termina la subrutina:
```
( variables )
&alto $2 &ancho $2 &y $2 &x $2 &límite-y $2
```
ahora, iniciamos la subrutina de la misma manera que antes, estableciendo la dirección para nuestro sprite:
```
( ws inicial: x^ y^ ancho^ alto^ direc* )
.Pantalla/direc DEO2 ( ptr: x^ y^ ancho^ alto^ )
```
entonces, simplemente almacenamos los siguientes valores en direcciones relativas:
```
,&alto STR2
,&ancho STR2
&y STR2
&x STR2
```
nótese que vamos en orden inverso.
después de estas operaciones las pilas están vacías.
entonces podemos fijar la `y` inicial y calcular el límite vertical, utilizando los valores almacenados en las variables:
```
( establecer y inicial )
,&y LDR2 DUP2 ( ptr: y^ y^ )
.Pantalla/y DEO2 ( ptr: y^ )
( calcular límite-y )
,&alto LDR2 ( ptr: y^ alto^ )
ADD2 ( ptr: límite-y^ )
,&límite-y STR2 ( ptr: )
```
nuestro bucle ahora tendría el siguiente aspecto:
```
&bucle-y
( recuperar x y ancho )
,&x LDR2
&ancho LDR2
( dibujar fila )
;dibuja-tiles-en-fila JSR2
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
.Pantalla/y DEO2 ( almacenar la nueva y )
( recuperar el límite vertical )
,&límite-y LDR2
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
```
¡y eso es todo!
compara esto con la versión "concreta" que desarrollamos anteriormente, ¡es muy similar en su estructura!
la subrutina completa tendría el siguiente aspecto:
```
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
( establecer la dirección del tile )
.Pantalla/direc DEO2 ( ptr: x^ y^ ancho^ alto^ )
( almacenar valores )
,&altura STR2
,&ancho STR2
&y STR2
,&x STR2
( establecer y inicial )
,&y LDR2 DUP2 ( ptr: y^ y^ )
.Pantalla/y DEO2 ( ptr: y^ )
( calcular el límite vertical )
,&alto LDR2 ( ptr: y^ alto^ )
ADD2 ( ptr: límite-y^ )
,&límite-y STR2 ( ptr: )
&bucle-y
( recuperar x y anchura )
,&x LDR2
,&ancho LDR2
( dibujar fila )
;dibuja-tiles-en-fila JSR2
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
.Pantalla/y DEO2 ( almacenar la nueva y )
( recuperar el límite vertical )
,&límite-y LDR2
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
RTN
( variables )
&alto $2 &ancho $2 &y $2 &x $2 &límite-y $2
```
como he dicho antes, podemos encontrar aquí algunas oportunidades de optimización.
tal vez el límite vertical puede ser escondido en la pila de retorno como en el bucle dibuja-tiles-en-fila, o tal vez la variable para la altura y para la `y` inicial no son necesarios.
dejo que lo resuelvas :)
nota que esta subrutina tal como está, requiere 24 bytes de memoria de programa más que la versión de la pila.
en nuestro caso eso no es un gran problema, pero es una buena manera de evaluar nuestras prioridades: código súper legible pero probablemente ineficiente (como esta última subrutina), código súper optimizado pero probablemente ilegible (código de sólo escritura, dicen), o algo en el medio.
## dibuja-fondo
ahora que tenemos estas bonitas subrutinas, podemos simplemente envolverlas en otra que cubrirá todo el fondo con nuestro tile elegido.
por ejemplo:
```
@dibuja-fondo ( -- )
#0000 #0010 ( x e `y` iniciales )
.Pantalla/ancho DEI2
.Pantalla/alto DEI2 #0010 SUB2
;tile-fondo
;dibuja-tiles JSR2
RTN
```
que podemos llamar simplemente desde nuestra subrutina de iniciación:
```
dibuja-fondo JSR2
```
=> ./img/screenshot_uxn-background-full.png captura de pantalla mostrando la pantalla varvara cubierta de líneas diagonales.
¡bonito! te recomiendo que te tomes un pequeño descanso; ¡esto ha sido pesado!
# apoyo
si te ha gustado este tutorial y te ha resultado útil, considera compartirlo y darle tu {apoyo} :)

View File

@ -13,7 +13,8 @@ el dispositivo de archivo en el ordenador varvara nos permite leer y escribir en
sus puertos se definen normalmente de la siguiente manera:
```
|a0 @Archivo [ &vector $2 &exito $2 &estad $2 &borrar $1 &adjuntar $1 &nombre $2 &largo $2 &leer $2 &escribir $2 ]```
|a0 @Archivo [ &vector $2 &exito $2 &estad $2 &borrar $1 &adjuntar $1 &nombre $2 &largo $2 &leer $2 &escribir $2 ]
```
* el corto vector no se utiliza actualmente
* el corto éxito almacena la longitud de los datos que se han leído o escrito con éxito, o cero si ha habido un error
@ -21,7 +22,7 @@ sus puertos se definen normalmente de la siguiente manera:
* el corto largo es la cantidad de bytes a leer o escribir: ¡no olvidemos que la memoria del programa es ffff más 1 byte de largo, y que el programa mismo se almacena allí!
* el short leer es para la dirección de memoria inicial donde los datos de lectura deben ser almacenados
* el corto escribir es para la dirección de memoria inicial donde se almacenan los datos a escribir
* el corto estad es similar al de cargar, pero lee la entrada del directorio para el nombre del archivo
* el corto estad es similar al de leer, pero lee la entrada del directorio para el nombre del archivo
* el byte borrar borra el archivo cuando se escribe cualquier valor en él.
* establecer el byte adjuntar a 01 hace que `escribir` añada datos al final del archivo. cuando el byte adjuntar tiene el valor por defecto, 00, `escribir` sobrescribe el contenido desde el principio
@ -90,7 +91,7 @@ el siguiente programa escribirá "hola" y una nueva línea (0a) en un archivo ll
```
@guardar-archivo ( -- )
;archivo/nombre .Archivo/nombre DEO2 ( establecer nombre de archivo )
;archivo/nombre .Archivo/nombre DEO2 ( establecer el nombre de archivo )
#0006 .Archivo/largo DEO2 ( intentará escribir 6 bytes )
( establecer la dirección de inicio de los datos, y hacer la escritura )
@ -376,8 +377,8 @@ saw-pcm:
de forma similar a como hemos tratado los sprites, y de forma parecida al dispositivo de archivo comentado anteriormente, para fijar una muestra en el dispositivo de audio sólo tenemos que escribir su dirección y su longitud:
```
;saw-pcm .Audio0/direc DEO2 ( establecer dirección de muestra )
#0100 .Audio0/largo DEO2 ( establecer longitud de muestra )
;saw-pcm .Audio0/direc DEO2 ( establecer la dirección de la muestra )
#0100 .Audio0/largo DEO2 ( establecer la longitud de la muestra )
```
la frecuencia a la que se reproduce esta muestra (es decir, a la que la amplitud de la onda toma el valor del siguiente byte) viene determinada por el byte pitch.
@ -410,10 +411,10 @@ en teoría, parecería que el siguiente programa debería reproducir nuestra mue
( programa principal )
|0100
;saw-pcm .Audio0/direc DEO2 ( establecer dirección de muestra )
#0100 .Audio0/largo DEO2 ( establecer longitud de muestra )
;saw-pcm .Audio0/direc DEO2 ( establecer la dirección de la muestra )
#0100 .Audio0/largo DEO2 ( establecer la longitud de la muestra )
#3c .Audio0/pitch DEO ( establecer el tono como Do medio )
#3c .Audio0/pitch DEO ( establecer el pitch como Do medio )
BRK
```
@ -430,7 +431,7 @@ por lo tanto, cada canal tiene 16 niveles posibles: 0 es el mínimo, y f el máx
lo siguiente establecería el volumen máximo en el dispositivo:
```
#ff . Audio0/volumen DEO ( establecer volumen máximo en izquierda y derecha )
#ff . Audio0/volumen DEO ( establecer el volumen máximo en izquierda y derecha )
```
¡aunque las muestras son mono, podemos panoramizarlas con el byte de volumen para obtener un sonido estéreo!
@ -476,12 +477,12 @@ ok, ¡ahora estamos listos para reproducir el sonido!
( programa principal )
|0100
;saw-pcm .Audio0/direc DEO2 ( establecer dirección de muestra )
#0100 .Audio0/largo DEO2 ( establecer longitud de muestra )
#ffff .Audio0/adsr DEO2 ( establecer envolvente )
#ff .Audio0/volumen DEO ( establecer volumen máximo )
;saw-pcm .Audio0/direc DEO2 ( establecer la dirección de la muestra )
#0100 .Audio0/largo DEO2 ( establecer la longitud de la muestra )
#ffff .Audio0/adsr DEO2 ( establecer la envolvente )
#ff .Audio0/volumen DEO ( establecer el volumen máximo )
#3c .Audio0/pitch DEO ( establecer pitch como Do central )
#3c .Audio0/pitch DEO ( establecer el pitch como Do central )
BRK
```

View File

@ -1,4 +1,4 @@
# uxn tutorial appendix b: repeating a tile inside a rectangle
# uxn tutorial appendix a: repeating a tile inside a rectangle
in the first part of {uxn tutorial day 6} we discuss how to cover the background of the screen with a given tile.
@ -34,7 +34,6 @@ let's start with the following program as a template. it includes the data for a
#01c0 .System/g DEO2
#2ce5 .System/b DEO2
BRK
@tile-background 1122 4488 1122 4488
@ -167,8 +166,8 @@ the following shows our program in context, completely filling the first row of
( hello-background.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1 &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 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
( macros )
%RTN { JMP2r }
@ -209,7 +208,7 @@ RTN
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?
following the same strategy, we could do
following the same strategy, we could do:
* draw row in y
* add 8 (the size of the tile) to y

View File

@ -22,7 +22,7 @@ its ports are normally defined as follows:
* the length short is the amount of bytes to read or write: don't forget that the program memory is ffff plus 1 bytes long, and that the program itself is stored there!
* the read short is for the starting memory address where the read data should be stored
* the write short is for the starting memory address where the data to be written is stored
* the stat short is similar to load, but reads the directory entry for the filename
* the stat short is similar to read, but reads the directory entry for the filename
* the delete byte deletes the file when any value is written to it
* setting the append byte to 01 makes write append data to the end of the file. when the append byte has the the default value, 00, write overwrites the contents from the start