Índice de entradas
Esta serie de artículos han sido traducidos a partir del documento "How to
Write ZX Spectrum Games" con permiso de su autor, Jonathan Cauldwell, un gran
desarrollador de juegos para el Spectrum, os recomiendo
visitar su Web donde está
el texto original. El documento original, y por tanto esta traducción, tiene
© Jonathan Cauldwell y solo puede duplicarse con permiso expreso por escrito
de su autor.
Música y efectos AY
NdT: Mira esta entrada que hice sobre el sonido en 8 bits que puede ayudarte a enter esta parte.El AY-3-8912
Introducido con los modelos 128K y prácticamente estándar desde entonces, fue
un chip de sonido muy popular que se utilizaba en otros muchos equipos, por
no hablar de vídeo juegos y máquinas de pinball. Básicamente dispone de 14 registros
que se pueden leer o escribir a través de instrucciones in
y out.
Los primeros seis registros controlan el tono para cada uno de los tres canales,
son parejas en modo little-endian (NdT: primero el byte bajo) como es de esperar, es decir, el registro
0 es para byte bajo para el tono del canal A, el registro 1
es el byte alto del tono del canal A, el registro 2 es el byte
bajo para el tono del canal B, y así sucesivamente. El registro 6
controla el periodo del ruido blanco, con valores válidos de 0 a 31. 0 significa
ruido de las frecuencias más alta, 31 de las más bajas. El registro
7 es el control del mezclador. Los bits D0-D5 seleccionar el ruido
blanco, el tono, ninguno o ambos. Para activar un tono o el ruido blanco, se
debe establecer un bit, siendo 0 salida de los tres canales de tono mas el ruido
blanco, y 63 no pone nada a la salida. Los registros 8, 9 y 10
son para controles de amplitud y envolvente. Un valor de 16 indica al chip utilizar
el generador de envolventes, y 0-15 ajusta el volumen de ese canal directamente.
En la práctica, es mejor controlar el volumen por ti mismo junto con el tono.
Mediante la variación de estos de un cuadro al siguiente es posible producir
una variedad muy buena de efectos de sonido. Si deseas utilizar el generador
de envolventes, los dos siguientes, registros 11 y 12, se emparejan
para formar el período de 16 bits y el registro 13
determina el patrón del envolvente. El manual del 128K explica la lista completa de los patrones,
pero no lo cubro aquí ya que nunca los encontré particularmente útiles.
Para leer un registro, se escribe el número del registro en el puerto 65533,
a continuación se lee ese puerto. Para escribir en un registro, se envía de nuevo el número del registro al puerto 65533, y luego el valor al puerto 49149. Para
los no iniciados, los opcodes del Z80 no parecen ser capaces de escribir direcciones
de puerto de 16 bits. No dejes que te confunda, es sólo que la forma en que
se escriben es engañosa. En realidad out (c),a realiza
out (bc),a, y out (n),a en realidad hace
out (a*256+n),a.
La lectura de un registro del chip de sonido tiene varios usos. Es posible que
desees leer los registros de volumen 8, 9 y 10 y presentar una barra de volumen.
Hice algo similar en Egghead 5 Además, aunque no lo creas,
la pistola de Sinclair se lee a través del registro 14 del chip de sonido. Sí,
de verdad. En realidad solo genera dos informaciones, si se presiona el gatillo
o no, y si el arma está apuntando a una parte brillante de la pantalla (o de
hecho a cualquier objeto brillante). Es responsabilidad del programador lo que
hace con esa información.
Aquí algo de código básico para escribir en el chip de sonido:
;Escribir el contenido de nuestro buffer AY en los registros el AY. w8912 ld hl,snddat ; inicio de los registros del AY-3-8912. ld e,0 ; comenzar con el registro 0. ld d,14 ; escribir 14. ld c,253 ; byte bajo del puerto a escribir. w8912a ld b,255 ; 255*256+253 = puerto 65533 = seleccionar registro. out (c),e ; indicar al chip en que registro estamos escribiendo. ld a,(hl) ; valor a escribir. ld b,191 ; 191*256+253 = puerto 49149 = escribir en registro. out (c),a ; esto es lo que estamos escribiendo allí. inc e ; siguiente registro del chip de sonido. inc hl ; siguiente byte a escribir. dec d ; decrementar contador de bucle. jp nz,w8912a ; repetir hasta completar. ret snddat defw 0 ; registro de tono, canal A. defw 0 ; registro de tono, el canal B. defw 0 ; igual para el canal C. sndwnp defb 0 ; período del ruido blanco. sndmix defb 60 ; Tono/ruido control del mezclador. sndv1 defb 0 ; canal A generador de amplitud/envolvente. sndv2 defb 0 ; canal B amplitud/envolvente. sndv3 defb 0 ; canal C amplitud/envolvente. sndenv defw 600 ; duración de cada nota. defb 0
Llamando a w8912 en cada iteración del bucle principal el
sonido es actualizado constantemente. Tu solo debes actualizar la memoria intermedia,
ya que el sonido cambia de un cuadro al siguiente. Piensa en ello como en un "animador"
del sonido. Sin embargo, sólo porque dejes de actualizar el registro de sonido este no va a dejar de sonar. El chip AY mantendrá sonando tu tono o ruido hasta
que le indiques que se detenga. Una forma rápida de hacer esto es establecer
los tres registros de amplitud a 0. En el ejemplo anterior, escribir un cero
en sndv1, sndv2 y sndv3 y
luego llamar w8912.
Usando drivers para la Música
La mayoría de los driver de música de los 128K (y de algunos 48K), tienen dos
puntos de entrada. Una rutina de inicialización/terminación que detiene todo
sonido y restablece el driver al comienzo de la melodía, y una rutina de servicio
para ser llamada varias veces, por lo general 50 veces por segundo. Un buen
lugar para almacenar música suele ser 49152, el inicio del banco de RAM conmutable.
Si conoces la dirección de inicio del controlador, o puedes determinarla por
ti mismo, el principio general es el de inicializar la dirección en la que se
carga la música. La mayoría de las veces el código en este punto es simplemente
saltar a otra dirección, o bien carga un registro o un par de registros antes de
saltar a otra parte. La rutina de servicio tiende a realizar inmediatamente
este jp. Si el driver no tiene otra documentación, es posible
tener que desmontar el código para encontrar esta dirección, por lo general
en 3-6 Bytes.
Para utilizar un driver de música, llamar a la dirección de inicialización antes
de comenzar y cuando quieras apagarla. Entre esos puntos es necesario llamar
a la rutina de servicio en varias ocasiones. Esto puede hacerse o bien manualmente,
o mediante el establecimiento de una interrupción para hacer el trabajo de forma
automática. Si decides hacerlo de forma manual, por ejemplo en el código de
menú, ten en cuenta que la limpieza de la pantalla, mostrar el menú, la tabla
de puntuación mas alta, las instrucciones, etc. tardarán más de 1/50 de segundo,
así que esto retrasará su rutina y podría sonar de forma extraña. Podría ser
mejor escribir una rutina para borrar la pantalla durante varios cuadros con
algún tipo de efecto especial, marcar cuando se detiene y llama a la rutina
de servicio en cada cuadro.
No hay comentarios:
Publicar un comentario