Revisión pausada del Día 7 y Apéndice A, y correciones de otros Días.

This commit is contained in:
jota 2022-01-14 12:03:51 -03:00
parent bb7925f997
commit b16a6c8045
7 changed files with 107 additions and 105 deletions

View File

@ -121,7 +121,7 @@ ADD2 ( ptra: x^ límite^ )
STH2 ( ptra: x^ / pret: límite^ )
```
otra:
otra más:
```
( estado inicial: ptra: x^ ancho^ )
@ -284,15 +284,15 @@ DUP2 ( ptra: x^ ancho^ altura^ y^ y^ )
.Pantalla/y DEO2 ( ptra: x^ ancho^ alto^ y^ )
( calcular y almacenar el límite vertical )
ADD2 ( ptra: x^ ancho^ límite-y^ )
STH2 ( ptra: x^ ancho^ / pret: límite-y^ )
ADD2 ( ptra: x^ ancho^ limite-y^ )
STH2 ( ptra: x^ ancho^ / pret: limite-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 )
ahora, podríamos también almacenar el ancho y `x`, ya que las necesitamos después en su orden original (primero x, luego el ancho )
```
STH2 ( ptra: x^ / pret: límite-y^ ancho^ )
STH2 ( ptra: / pret: límite-y^ ancho^ x^ )
STH2 ( ptra: x^ / pret: limite-y^ ancho^ )
STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
```
en teoría, la primera parte de nuestra subrutina podría verse como:
@ -305,23 +305,23 @@ en teoría, la primera parte de nuestra subrutina podría verse como:
ROT2 ( ptra: x^ ^ altura^ y^ )
DUP2 ( ptra: x^ ^ altura^ y^ )
( fijar y inicial )
.Pantalla/y DEO2 ( fijar y inicial, ptra: x^ ^ altura^ y^ )
( fijar `y` inicial )
.Pantalla/y DEO2 ( fijar `y` inicial, ptra: x^ ^ altura^ y^ )
( calcular y guardar límite-y )
ADD2 ( ptra: x^ ^ límite-y^ )
STH2 ( ptra: x^ ^ / pret: límite-y^ )
( calcular y guardar limite-y )
ADD2 ( ptra: x^ ^ limite-y^ )
STH2 ( ptra: x^ ^ / pret: limite-y^ )
( almacenar anchura y `x` )
STH2 STH2 ( ptra: / pret: límite-y^ ancho^ x^ )
( almacenar ancho y `x` )
STH2 STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2r ( ptra: x^ / pret: límite-y^ ancho^ )
STH2r ( ptra: x^ / pret: limite-y^ ancho^ )
( recuperar la anchura )
STH2r ( ptra: x^ ancho^ / pret: límite-y^ )
( recuperar el ancho )
STH2r ( ptra: x^ ancho^ / pret: limite-y^ )
;dibuja-tiles-en-fila JSR2
```
@ -333,7 +333,7 @@ podemos pensar que podríamos reemplazar estas instrucciones con STH2kr:
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2kr ( ptra: x^ / pret: límite-y^ ancho^ x^ )
STH2kr ( ptra: x^ / pret: limite-y^ ancho^ x^ )
```
¡pero entonces no podemos recuperar el ancho porque la x sigue en la parte superior de la pila de retorno!
@ -343,35 +343,35 @@ oh, muchas dificultades, pero por el bien del ejemplo de la pila, vamos a seguir
¿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 ( ptra: x^ / pret: límite-y^ x^ ancho^ )
SWP2r ( ptra: x^ / pret: limite-y^ x^ ancho^ )
```
entonces podemos recuperar el ancho y utilizarlo:
```
STH2kr ( ptra: x^ ancho^ / pret: límite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: límite-y^ x^ ancho^ )
STH2kr ( ptra: x^ ancho^ / pret: limite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: limite-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; ptra: y^ y^ / pret: límite-y^ x^ ancho^ )
.Pantalla/y DEO2 ( almacenar nueva `y`; ptra: y^ / pret: límite-y^ x^ ancho^ )
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a `y`; ptra: y^ y^ / pret: limite-y^ x^ ancho^ )
.Pantalla/y DEO2 ( almacenar nueva `y`; ptra: y^ / pret: limite-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 ( ptra: y^ / pret: x^ ancho^ límite-y^ )
STH2kr ( ptra: y^ límite-y^ / pret: x^ ancho^ límite-y^ )
ROT2r ( ptra: y^ / pret: x^ ancho^ limite-y^ )
STH2kr ( ptra: y^ limite-y^ / pret: x^ ancho^ limite-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 ( ptra: y^ límite-y^ / pret: x^ límite-y^ ancho^ )
ROT2r ( ptra: y^ límite-y^ / pret: límite-y^ ancho^ x^ )
SWP2r ( ptra: y^ limite-y^ / pret: x^ limite-y^ ancho^ )
ROT2r ( ptra: y^ limite-y^ / pret: limite-y^ ancho^ x^ )
```
ahora podemos hacer la comparación y saltar:
@ -396,36 +396,36 @@ después de todo esto, nuestra subrutina tendría el siguiente aspecto:
ROT2 ( ptra: x^ ^ altura^ y^ )
DUP2 ( ptra: x^ ^ altura^ y^ )
( fijar y inicial )
.Pantalla/y DEO2 ( fijar y inicial, ptra: x^ ^ altura^ y^ )
( fijar `y` inicial )
.Pantalla/y DEO2 ( fijar `y` inicial, ptra: x^ ^ altura^ y^ )
( calcular y almacenar límite-y )
ADD2 ( ptra: x^ ^ límite-y^ )
STH2 ( ptra: x^ ^ / pret: límite-y^ )
( calcular y almacenar limite-y )
ADD2 ( ptra: x^ ^ limite-y^ )
STH2 ( ptra: x^ ^ / pret: limite-y^ )
( almacenar anchura y `x` )
STH2 STH2 ( ptra: / pret: límite-y^ ancho^ x^ )
( almacenar ancho y `x` )
STH2 STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
&bucle-y
( preparar y dibujar la fila )
( recuperar x )
STH2kr ( ptra: x^ / pret: límite-y^ ancho^ x^ )
STH2kr ( ptra: x^ / pret: limite-y^ ancho^ x^ )
( recuperar la anchura )
SWP2r ( ptra: x^ / pret: límite-y^ x^ ancho^ )
STH2kr ( ptra: x^ ancho^ / pret: límite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: límite-y^ x^ ancho^ )
( recuperar el ancho )
SWP2r ( ptra: x^ / pret: limite-y^ x^ ancho^ )
STH2kr ( ptra: x^ ancho^ / pret: limite-y^ x^ ancho^ )
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: limite-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 ( ptra: y^ / pret: x^ ^ límite-y^ )
STH2kr ( ptra: y^ límite-y^ / pret: x^ ancho^ límite-y^ )
( recuperar limite-y )
ROT2r ( ptra: y^ / pret: x^ ^ limite-y^ )
STH2kr ( ptra: y^ limite-y^ / pret: x^ ancho^ limite-y^ )
( reordenar la pila de retorno )
SWP2r ( ptra: y^ límite-y^ / pret: x^ límite-y^ ancho^ )
ROT2r ( ptra: y^ límite-y^ / pret: límite-y^ ancho^ x^ )
SWP2r ( ptra: y^ limite-y^ / pret: x^ limite-y^ ancho^ )
ROT2r ( ptra: y^ limite-y^ / pret: limite-y^ ancho^ x^ )
LTH2 ,&bucle-y JCN ( salta si x es menor que el límite )
@ -436,7 +436,7 @@ RTN
podemos entonces llamarlo de la siguiente manera para obtener un cuadrado de 256x256 lleno de tiles:
```
#0008 #0008 ( x y `y` )
#0008 #0008 ( `x` y `y` )
#0100 #0100 ( ancho y alto )
;tile-fondo
;dibuja-tiles JSR2
@ -454,7 +454,7 @@ declararemos las siguientes etiquetas para nuestras variables, después del RTN
```
( variables )
&alto $2 &ancho $2 &y $2 &x $2 &límite-y $2
&alto $2 &ancho $2 &y $2 &x $2 &limite-y $2
```
ahora, iniciamos la subrutina de la misma manera que antes, estableciendo la dirección para nuestro sprite:
@ -480,21 +480,21 @@ 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 )
( establecer `y` inicial )
,&y LDR2 DUP2 ( ptra: y^ y^ )
.Pantalla/y DEO2 ( ptra: y^ )
( calcular límite-y )
( calcular limite-y )
,&alto LDR2 ( ptra: y^ alto^ )
ADD2 ( ptra: límite-y^ )
,&límite-y STR2 ( ptra: )
ADD2 ( ptra: limite-y^ )
,&limite-y STR2 ( ptra: )
```
nuestro bucle ahora tendría el siguiente aspecto:
```
&bucle-y
( recuperar x y ancho )
( recuperar `x` y ancho )
,&x LDR2
&ancho LDR2
( dibujar fila )
@ -504,7 +504,7 @@ nuestro bucle ahora tendría el siguiente aspecto:
.Pantalla/y DEO2 ( almacenar la nueva y )
( recuperar el límite vertical )
,&límite-y LDR2
,&limite-y LDR2
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
```
@ -526,17 +526,17 @@ la subrutina completa tendría el siguiente aspecto:
&y STR2
,&x STR2
( establecer y inicial )
( establecer `y` inicial )
,&y LDR2 DUP2 ( ptra: y^ y^ )
.Pantalla/y DEO2 ( ptra: y^ )
( calcular el límite vertical )
,&alto LDR2 ( ptra: y^ alto^ )
ADD2 ( ptra: límite-y^ )
,&límite-y STR2 ( ptra: )
ADD2 ( ptra: limite-y^ )
,&limite-y STR2 ( ptra: )
&bucle-y
( recuperar x y anchura )
( recuperar `x` y ancho )
,&x LDR2
,&ancho LDR2
( dibujar fila )
@ -546,13 +546,13 @@ la subrutina completa tendría el siguiente aspecto:
.Pantalla/y DEO2 ( almacenar la nueva y )
( recuperar el límite vertical )
,&límite-y LDR2
,&limite-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
&alto $2 &ancho $2 &y $2 &x $2 &limite-y $2
```
como he dicho antes, podemos encontrar aquí algunas oportunidades de optimización.
@ -561,7 +561,7 @@ tal vez el límite vertical puede ser escondido en la pila de retorno como en el
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.
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.
@ -584,7 +584,8 @@ RTN
que podemos llamar simplemente desde nuestra subrutina de iniciación:
```
dibuja-fondo JSR2
;dibuja-fondo JSR2
;dibuja-fondo JSR2
```
=> ./img/screenshot_uxn-background-full.png captura de pantalla mostrando la pantalla varvara cubierta de líneas diagonales.

View File

@ -269,7 +269,7 @@ ok, ahora nuestros programas pueden identificar y almacenar en banderas si un va
en modo byte, las direcciones que utilizan estas instrucciones son de un byte.
estas direcciones de un byte son relativas y contienen signos: indican cuántos bytes hay que saltar en la memoria principal desde la posición actual del contador de programa, ya sea hacia delante (positivo) o hacia atrás (negativo). el rango de estas direcciones relativas es de -128 a 127 inclusive.
estas direcciones de un byte son relativas y pueden considerarse positivas y negativas: indican cuántos bytes hay que saltar en la memoria principal desde la posición actual del contador de programa, ya sea hacia delante (positivo) o hacia atrás (negativo). el rango de estas direcciones relativas es de -128 a 127 inclusive.
en modo corto, las direcciones que toman estas instrucciones son absolutas (es decir, de dos bytes de longitud), pero el valor que toma JCN para decidir sigue siendo un byte.

View File

@ -292,7 +292,7 @@ otra posibilidad que tenemos en uxn y que podría ser más apropiada para las "v
de forma similar a las variables de la página cero, para direccionar estas variables sólo necesitamos un byte.
sin embargo, como estas direcciones se dan como desfases ("offsets") relativos y con signo, sólo se pueden alcanzar si están dentro de los 256 bytes que rodean a la instrucción que las carga o almacena.
sin embargo, como estas direcciones se dan como desfases ("offsets") relativos y pueden considerarse positivas y negativas, sólo se pueden alcanzar si están dentro de los 256 bytes que rodean a la instrucción que las carga o almacena.
### instrucciones: LDR, STR
@ -491,7 +491,7 @@ el siguiente programa nos permite controlar la posición horizontal de nuestro c
¡nótese las similitudes entre el programa anterior, y lo que cubrimos en el {tutorial de uxn día 3}!
```
( hola-sprite-enmovimiento.tal )
( hola-sprite-en-movimiento.tal )
( dispositivos )
|00 @Sistema [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Pantalla [ &vector $2 &ancho $2 &alto $2 &pad $2 &x $2 &y $2 &direc $2 &pixel $1 &sprite $1 ]

View File

@ -488,7 +488,7 @@ habiendo introducido la pila de retorno y el modo de retorno, se nos abre otro m
para lograr esto, uxn tiene una instrucción llamada STH, "stash" o almacenar.
¡esta es la última instrucción de uxn que teníamos en mente cubrir en esta serie de tutoriales! :)
¡esta es la última instrucción de uxn que teníamos en mente cubrir en este tutorial! :)
## STH

View File

@ -372,7 +372,7 @@ he dibujado el sprite usando el modo de mezcla 85 como indica nasu, pero lo camb
construyamos una subrutina que dibuje las 6 fichas de la pala en el orden correspondiente.
podríamos tener la subrutina recibiendo como argumentos la posición x e `y` de su esquina superior izquierda:
podríamos escribirffff la subrutina recibiendo como argumentos la posición x e `y` de su esquina superior izquierda:
```
@dibuja-pala ( x^ y^ -- )
@ -660,7 +660,7 @@ donde COLOR-BORRAR en este caso sería:
### actualizar posición
para actualizar la posición de nuestras palas, podemos recurrir al ejemplo hola-sprite-enmovimiento.tal del {tutorial de uxn día 4}.
para actualizar la posición de nuestras palas, podemos recurrir al ejemplo hola-sprite-en-movimiento.tal del {tutorial de uxn día 4}.
podemos usar las flechas arriba y abajo para cambiar la posición de la pala izquierda, y los botones ctrl y alt (A y B) para cambiar la posición de la pala derecha.
@ -873,7 +873,7 @@ un enfoque podría ser tener una bandera para cada x e `y` que indique si debemo
otro enfoque podría ser tener una variable de velocidad para cada x e `y`, que se cambia de acuerdo a la dirección que queremos que la pelota vaya.
utilizaremos este último enfoque con la velocidad, ya que nos ayudará a discutir algunas ventajas de la aritmética de enteros sin signo.
utilizaremos este último enfoque de la variable velocidad, ya que nos ayudará a discutir algunas ventajas de la aritmética de enteros sin signo.
incluimos estas variables en nuestra página cero, complementando las x e `y` que ya teníamos:
@ -1237,7 +1237,8 @@ para la pala derecha haremos lo mismo que arriba, pero cambiando las comparacion
&verif-pala-der
.pelota/x LDZ2 TAM-PELOTA ADD2 ( pelota-x + tamaño-pelota )
.Pantalla/ancho DEI2 MARGEN SUB2 ANCHO-PALA SUB2
GTH2 ( ¿es la coordenada derecha de la pelota mayor que el ancho de la pantalla - margen - ancho-palaf? )
( ¿es la coordenada derecha de la pelota mayor que el ancho de la pantalla - margen - ancho-pala? )
GTH2
,&x-en-derecha JCN
&fin JMP
@ -1471,7 +1472,8 @@ RTN
&verif-pala-der
.pelota/x LDZ2 TAM-PELOTA ADD2
.Pantalla/ancho DEI2 MARGEN SUB2 ANCHO-PALA SUB2
GTH2 ( ¿es pelota-x + tamaño-pelota mayor que la anchura de la pantalla - margen - ancho-pala? )
( ¿es pelota-x + tamaño-pelota mayor que la anchura de la pantalla - margen - ancho-pala? )
GTH2
,&x-en-derecha JCN
,&fin JMP

View File

@ -20,7 +20,7 @@ sus puertos se definen normalmente de la siguiente manera:
* 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
* el corto nombre es para la dirección de memoria donde se almacena el nombre del archivo (terminado en cero, es decir, con un 00)
* 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 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 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.
@ -28,31 +28,30 @@ sus puertos se definen normalmente de la siguiente manera:
una operación de lectura se inicia cuando se escribe en el corto `leer`, y una operación de escritura se inicia cuando se escribe en el corto `escribir`.
¡estos pueden parecer muchos campos para manejar, pero veremos que no son demasiado problema!
¡estos pueden parecer muchos detalles para manejar, pero veremos que no son demasiado problema!
## leer un archivo
para leer un archivo, necesitamos saber lo siguiente:
* la ruta del archivo, escrita como una cadena de texto etiquetada en la memoria del programa y terminada por un 00 - esta ruta sería relativa a la ubicación donde se ejecuta uxnemu.
* la cantidad de bytes que queremos leer del archivo: no pasa nada si este número no es igual al tamaño del archivo; puede ser menor o incluso mayor.
* la etiqueta para una sección reservada de la memoria del programa donde se almacenarán los datos leídos
¡y eso es todo!
podemos usar una estructura como la siguiente, donde el nombre del archivo y la memoria reservada están bajo una etiqueta, y la subrutina de carga del archivo bajo otra:
podemos usar una estructura como la siguiente, donde el nombre del archivo y la memoria reservada están bajo una etiqueta, y la subrutina carga-archivo bajo otra:
```
@carga-archivo ( -- )
;archivo/nombre .Archivo/nombre DEO2 ( dirección de la ruta del archivo )
#00ff .Archivo/largo DEO2 ( intentará leer 255 bytes )
( establecer la dirección de los datos a leer y hacer la lectura )
( establecer la dirección de los datos a leer y hacer lectura )
;archivo/datos .Archivo/lectura DEO2
( comprobar el byte éxito y saltar según corresponda )
Archivo/exito DEI2 #0000 EQU2 ,&failed JCN
Archivo/exito DEI2 #0000 EQU2 ,&fallo JCN
&exito
LIT 'Y .Consola/escribir DEO
@ -69,9 +68,9 @@ RTN
nótese que para el nombre del archivo estamos usando la runa de cadena cruda o `raw` (") que nos permite escribir varios caracteres en la memoria del programa hasta encontrar un espacio en blanco.
en este ejemplo estamos escribiendo un carácter en la consola en función de que el corto `exito` sea cero o no, pero podríamos decidir realizar cualquier acción que consideremos oportuna.
en este ejemplo estamos escribiendo un carácter en la consola en función de que el corto `exito` sea cero o no, pero podríamos decidir realizar cualquier acción que consideremos apropiada.
además, en este ejemplo no nos preocupa realmente cuántos bytes se han leído realmente: ¡tenga en cuenta que esta información se almacena en `Archivo/exito` hasta que se produzca otra lectura o escritura!
además, en este ejemplo no nos preocupa realmente cuántos bytes se han leído realmente: ¡tenga en cuenta que esta información se almacena en Archivo/exito hasta que se produzca otra lectura o escritura!
es importante recordar que, como siempre en este contexto, estamos tratando con bytes crudos.
@ -115,7 +114,7 @@ RTN
¡observe lo similar que es a la subrutina cargar-archivo!
las únicas diferencias, además del uso de `Archivo/escribir` en lugar de `Archivo/leer`, son la longitud del archivo y la comparación para el corto éxito: en este caso sabemos con seguridad cuántos bytes deberían haberse escrito.
las únicas diferencias, además del uso de Archivo/escribir en lugar de Archivo/leer, son la longitud del archivo y la comparación para el corto éxito: en este caso sabemos con seguridad cuántos bytes deberían haberse escrito.
## un breve estudio de caso: el archivo de temas
@ -136,7 +135,7 @@ podríamos adaptar nuestra subrutina anterior para cargar el archivo de temas y
;tema/nombre .Archivo/nombre DEO2 ( establecer la dirección de la ruta del archivo )
#0006 .Archivo/largo DEO2 ( intentará leer 6 bytes )
( establecer la dirección de los datos a leer y hacer la lectura )
( establecer la dirección de los datos a leer y hacer lectura )
;tema/datos .Archivo/cargar DEO2
( comprobar el byte éxito y saltar según corresponda )
@ -192,9 +191,9 @@ RTN
=> https://git.sr.ht/~rabbits/nasu/tree/main/item/src/main.tal código fuente de nasu
# el dispositivo fechahora o "datetime"
# el dispositivo fechahora
el dispositivo fechahora puede ser útil para el cronometraje de baja precisión y/o para las visualizaciones del tiempo.
el dispositivo fechahora (o "datetime") puede ser útil para el cronometraje de baja precisión y/o para las visualizaciones del tiempo.
tiene varios campos que podemos leer, todos ellos basados en la hora del sistema actual y la zona horaria:
@ -205,10 +204,10 @@ tiene varios campos que podemos leer, todos ellos basados en la hora del sistema
* el byte año corresponde al número de año de la llamada era común
* el byte mes cuenta los meses desde enero (es decir, enero es 0, febrero 1, etc.)
* el byte día cuenta los días del mes a partir del 1
* Los bytes hora, minuto y segundo corresponden a lo que se espera: sus valores van de 0 a 23, o de 0 a 59 respectivamente.
* ddls (día de la semana) es un byte que cuenta los días desde el domingo (es decir, el domingo es 0, el lunes es 1, el martes es 2, etc.).
* los bytes hora, minuto y segundo corresponden a lo que se espera: sus valores van de 0 a 23, o de 0 a 59 respectivamente
* ddls (día de la semana) es un byte que cuenta los días desde el domingo (es decir, el domingo es 0, el lunes es 1, el martes es 2, etc.)
* dda (día del año) es un byte que cuenta los días desde el 1 de enero (es decir, el 1 de enero es 0, el 2 de enero es 1, etc.)
* eshdv ( es horario de verano) es una bandera, 01 si es horario de verano y 00 si no lo es.
* eshdv (es horario de verano) es una bandera, 01 si es horario de verano y 00 si no lo es.
basándonos en esto, debería ser sencillo utilizarlos. por ejemplo, para leer la hora del día en la pila, haríamos:
@ -235,10 +234,10 @@ por fin, ¡el dispositivo de audio! o debería decir, ¡los dispositivos de audi
varvara tiene cuatro dispositivos estéreo idénticos (o "canales"), que se mezclan antes de pasar a los altavoces/auriculares:
```
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|40 @Audio1 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|50 @Audio2 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|60 @Audio3 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
|40 @Audio1 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
|50 @Audio2 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
|60 @Audio3 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
```
de forma similar a como en el dispositivo de pantalla podemos dibujar apuntando a direcciones con datos de sprite, en los dispositivos de audio podremos reproducir sonidos apuntando a direcciones con datos de audio (muestras o "samples").
@ -381,17 +380,17 @@ de forma similar a como hemos tratado los sprites, y de forma parecida al dispos
#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.
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 tono.
## pitch
## tono
el byte pitch hace que la muestra comience a reproducirse cada vez que le escribimos, de forma similar a como el byte de sprite realiza el dibujo del sprite cuando le escribimos.
el byte tono hace que la muestra comience a reproducirse cada vez que le escribimos, de forma similar a como el byte de sprite realiza el dibujo del sprite cuando le escribimos.
los primeros 7 bits (de derecha a izquierda) del byte corresponden a una nota midi, y por tanto a la frecuencia a la que se reproducirá la muestra.
el octavo bit es una bandera: cuando es 0 la muestra se reproducirá en bucle, y cuando es 1 la muestra se reproducirá sólo una vez.
normalmente querremos hacer un bucle de la muestra para generar un tono basado en ella. sólo cuando la muestra sea lo suficientemente larga tendrá sentido no hacer un bucle y reproducirla una vez.
normalmente querremos hacer un bucle de la muestra para generar un tono basado en ella. sólo cuando la muestra sea lo suficientemente larga tendrá sentido no hacer un bucle y reproducirla una vez.
con respecto a los bits para la nota midi, es una buena idea tener una tabla midi alrededor para ver los valores hexadecimales correspondientes a las diferentes notas.
@ -407,20 +406,20 @@ en teoría, parecería que el siguiente programa debería reproducir nuestra mue
( hola-sonido.tal )
( dispositivos )
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
( programa principal )
|0100
;sierra-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 pitch como Do medio )
#3c .Audio0/tono DEO ( establecer el tono como Do medio )
BRK
```
¡no realmente!
para poder escuchar el sonido, necesitamos dos cosas más: ajustar el volumen del dispositivo y ajustar la envolvente ADSL.
¡pero ya casi! para poder escuchar el sonido, necesitamos dos cosas más: ajustar el volumen del dispositivo y ajustar la envolvente ADSL.
## volumen
@ -467,13 +466,13 @@ ok, ¡ahora estamos listos para reproducir el sonido!
## reproduciendo la muestra
¡el siguiente programa tiene ahora los cinco componentes que necesitamos para reproducir un sonido: una dirección de muestra, su longitud, las duraciones de adsr, el volumen, y su pitch!
¡el siguiente programa tiene ahora los cinco componentes que necesitamos para reproducir un sonido: una dirección de muestra, su longitud, las duraciones de adsr, el volumen, y su tono!
```
( hola-sonido.tal )
( dispositivos )
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &pitch $1 ]
|30 @Audio0 [ &vector $2 &posicion $2 &salida $1 &pad $3 &adsr $2 &largo $2 &direc $2 &volumen $1 &tono $1 ]
( programa principal )
|0100
@ -482,17 +481,17 @@ ok, ¡ahora estamos listos para reproducir el sonido!
#ffff .Audio0/adsr DEO2 ( establecer la envolvente )
#ff .Audio0/volumen DEO ( establecer el volumen máximo )
#3c .Audio0/pitch DEO ( establecer el pitch como Do central )
#3c .Audio0/tono DEO ( establecer el tono como Do central )
BRK
```
nota (!) que sólo se reproducirá el sonido una vez, y lo hace cuando se inicia el programa.
### algunos experimentos sugeridos
te invito a que experimentes modificando los valores del ADSR: ¿cómo cambia el sonido cuando sólo hay uno de ellos? ¿o cuando todos son números pequeños o con diferentes combinaciones de duraciones?
también, prueba a cambiar el byte pitch: ¿corresponden con tus oídos los valores midi que esperas?
también, prueba a cambiar el byte tono: ¿corresponden con tus oídos los valores midi que esperas?
¿y cómo cambia el sonido cuando usas una muestra diferente? ¿puedes encontrar o crear otras diferentes?
@ -500,10 +499,10 @@ también, prueba a cambiar el byte pitch: ¿corresponden con tus oídos los valo
una vez que hemos configurado nuestro dispositivo de audio con una muestra, longitud, envolvente ADSR y volumen, podríamos reproducirlo una y otra vez (re)escribiendo un tono en un momento diferente; los demás parámetros pueden dejarse intactos.
por ejemplo, una macro como la siguiente podría permitirnos reproducir una nota de nuevo según el pitch dado en la parte superior de la pila:
por ejemplo, una macro como la siguiente podría permitirnos reproducir una nota de nuevo según el tono dado en la parte superior de la pila:
```
%REPR-NOTA { .Audio0/pitch DEO } ( pitch -- )
%REPR-NOTA { .Audio0/tono DEO } ( tono -- )
```
cuando ocurriera un evento específico, podrías llamarlo:
@ -512,13 +511,13 @@ cuando ocurriera un evento específico, podrías llamarlo:
#3c REPR-NOTA ( reproducir Do central )
```
ten en cuenta que cada vez que escribes un pitch, la reproducción de la muestra y la forma de la envolvente vuelve a empezar, independientemente de dónde se encuentre.
ten en cuenta que cada vez que escribes un tono, la reproducción de la muestra y la forma de la envolvente vuelve a empezar, independientemente de dónde se encuentre.
### algunas ideas
¿qué tal si implementas la reproducción de diferentes tonos presionando diferentes teclas en el teclado? podrías usar nuestros ejemplos anteriores, pero escribiendo un tono en el dispositivo en lugar de, por ejemplo, incrementar una coordenada :)
¿o qué tal si complementas nuestro programa pong de {tutorial de uxn día 6} con efectos de sonido, haciendo que el dispositivo toque una nota cada vez que la pelota rebote?
¿o qué tal si complementas nuestro programa pong del {tutorial de uxn día 6} con efectos de sonido, haciendo que el dispositivo toque una nota cada vez que la pelota rebote?
¿o qué tal si utilizas el vector de la pantalla para cronometrar la reproducción repetitiva de una nota? ¿o qué tal si haces que toque una melodía siguiendo una secuencia de notas? ¿podría venir esta secuencia de un archivo de texto? :)
@ -551,7 +550,7 @@ en cualquier caso, ¡no dudes en compartir lo que crees! :)
aunque no lo creas, ¡este es el final!
¡has llegado al final de la serie del tutorial! ¡felicidades!
¡has llegado al final de este tutorial! ¡felicidades!
¡espero que lo hayas disfrutado y que lo veas como el comienzo de tu viaje uxn!

View File

@ -20,7 +20,7 @@ let's start with the following program as a template. it includes the data for a
( hello-background.tal )
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|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 )