domingo, 30 de mayo de 2010

Sincronizando!

Un punto importante un cualquier programa donde se reproduzca música, es que esta se escuche siguiendo sus tiempos, si no el resultado podría ser algo desagradable... :P

Para conseguir esto, necesitamos sincronizar la ejecución de nuestro programa y en MSX se utilizan las interrupciones del Z80.

He investigado un poco el tema, y he encontrado unas funciones en la web de Avelino (interrupt.s), pensadas para cuando se trabaja en MSX-DOS. Estas se puede adaptar para el caso de trabajar en formato ROM, con la solución dada por SapphiRe (FD9APATCH.ASM), en los foros de desarrollo de Karoshi. Todavía no lo he probado, ya que he dado con una solución más propicia para la forma en la que esta programado el PSGed.

Al principio utilicé una función de Andrear llamada wait_retrace:
   di
$3:
   in a,(0x99)
   and #0x80
   cp #0x00
   jr z, $3
   ei
Esta espera a que finalice el redibujado de la pantalla, para dejar continuar el flujo de ejecución. Haciendo pruebas, vi que en los emuladores y en el onechip, funcionaba perfectamente, pero al probarlo en un MSX real, al reproducir una secuencia, no se escuchaba correctamente.

Estudiando el articulo de SapphiRe, descubrí una instrucción del z80 (no se mucho de assembler), que podía servirme en sustitución de la función wait_retrace, me refiero a la instrucción "halt". Esta pone en espera la ejecución hasta que se dispara una interrupción. Así que me puse manos a la obra. Primero definí una función en assembler con esta instrucción:
#define HALT __asm halt __endasm
y luego lo coloqué en el inicio del bucle que controla el play y la interfaz gráfica de la pantalla principal.
while(1)
{
   HALT;

   //resto del codigo
}
Lo he probado en un MSX y ha funcionado perfectamente! :)

viernes, 28 de mayo de 2010

Acceso a funciones Asm desde C


Además del "assembler in line" que permite añadir directamente código ensamblador de Z80 en nuestras funciones en C, podemos acceder a funciones incluidas en fuentes totalmente en assembler. Si este código esta creado para compiladores como el asMSX, antes tendremos que adaptarlo para que lo acepte el compilador de SDCC. Algunos de estos cambios son:
Los valores deberán de preceder del caracter almohadilla.
0ffh --> #0xFF

Los corchetes de las instrucciones que apuntan a direcciones de memoria, habrá que cambiarlo por paréntesis.
ld a,[#FAFE] --> ld a,(#0xFAFE)

Las variables con la instrucción "equ" por un igual.
initmem equ 0E000h --> initmem = #0xE000

En mi caso, lo he necesitado para utilizar las rutinas de Ramones para el control de ratón.

Una vez adaptado el código, el siguiente paso, sera marcar de alguna forma, que funciones son a las que queremos acceder desde C. Para ello tendremos que poner al inicio de la etiqueta usada, un subrayado y al final dos veces el caracter de dos puntos.
_checkmouse::

Una vez hecho todo esto compilaremos el fuente, obteniendo un fichero object (".rel"):
sdasz80 -o mouse.asm

Luego desde nuestro editor, crearemos un fichero "header" donde definiremos las funciones que acceden a las de assembler. Utilizaremos la instrucción "extern" y pondremos el nombre de la etiqueta sin los caracteres añadidos (el tema parámetros, en estos momentos desconozco como funciona).
extern void checkmouse(void);

Incluiremos el include en nuestro fuente y llamaremos a la función utilizando el nombre dado en la definición.
checkmouse();

Para finalizar, compilaremos nuestro proyecto incluyendo el objet:
sdcc -mz80 -o --no-std-crt0 --code-loc 0x4010 --data-loc 0xC000 mouse.rel PSGed_v06a.c

Para conseguir este "item", quiero agradecer la ayuda de Andrear, Ramones y Avelino.

domingo, 23 de mayo de 2010

Utilizar datos en assembler

Este caso específico, lo comento, ya que me encontré con un problema con la forma de trabajar con las etiquetas en el "assembler in line", que no estaba descrito (o no lo localicé) , en la documentación del SDCC (manual + ASxxxx Cross Assembler Documentation).

En mi caso, para mostrar el texto de ayuda, necesito que se aloje en un área de la memoria, que luego voy copiando a la VRAM, creando un efecto de scroll. Lo que estaba haciendo, hasta el momento, era utilizar un array de char, que luego volcaba en la RAM. Mi intención es situarlo en la ROM y acceder directamente a la dirección donde se aloje. Para ello he utilizado el "assembler in line", añadiendo los datos con la instrucción "db".

Nota: Esta técnica nos sirve para añadir cualquier tipo de dato, como por ejemplo gráficos, con lo que conseguiríamos mucha más velocidad al volcarlos a la VRAM, utilizando directamente una rutina en ensamblador.

Para conseguir esto, necesitaríamos averiguar en que dirección apuntan nuestros datos. En assembler utilizaremos una etiqueta, pero nos encontramos con el problema de que en C no podemos acceder a esta. Para solucionarlo, tendremos que usar un puente: escribiremos la dirección en la RAM. Para ello, ejecutaremos un programita en ensamblador. Fijaos que al hacer el "load" de la etiqueta al registro HL, hay que añadirle el caracter de la almohadilla "#" (este es el problema que comentaba al inicio).

void setData()
{
__asm

ld hl,#ALABEL
ld (#0xE007),hl
ret

ALABEL:
.db 0x50,0x53,0x47,0x65,0x64,0x20,0x56,0x30
.db 0x2E,0x34,0x42,0x20,0x20,0x20,0x20,0x20
.db 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
.db 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
__endasm;
}

Nota: En el ejemplo se puede observar que los datos utilizan el formato típico de SDCC ("0xFF"), ya que no acepta el común en algunos compiladores de asm ("0FFh").

Club Sprite Chiptune Stage

Ayer pase la tarde con el Club Sprite, en uno de sus stages, esta vez dedicado al chiptune.
Había un MSX onechip, un Amiga 1200 y un portátil, donde escuchamos un buen puñado de módulos de los trackers más variados.
MsxKun trajo un Music Module (MSX Audio), y pudimos apreciar la calidad de sus 9 canales FM + su canal PCM de 8 bits.
Neuroflip, mostró algunos de sus trabajos (tanto soft como temas musicales), junto al nst0002 (el player de SIDs). TPM mostró unos nuevos temas en el ZMA player y yo pude hacer la primera demo al publico del PSGed (la v0.5b), en un MSX onechip!!!
También pudimos ver el nuevo Mega Flash ROM SCC+ pero no lo llegamos a probar...

domingo, 16 de mayo de 2010

Control con ratón



Ya he añadido el control de ratón. Para ello he utilizado las funciones de Ramones, para identificar y leer los datos del ratón. Primero he compilado con asMSX las funciones y el binario resultante lo he incrustado en el ROM que creado con SDCC. Por otro lado, he programado unas funciones en C, que llaman a las rutinas de Ramones. Es verdad que no es una solución elegante, pero he tenido que optar por esta, ya que no sabia como resolverlo totalmente con SDCC. Afortunadamente, Andrear, me ha facilitado una forma de hacerlo, que seguramente lo pondré en practica la semana que viene.

He creado un vídeo de demo con blueMSX, para que podáis ver el funcionamiento del PSGed con el ratón. Como observaréis, he cambiado algunos elementos de la interfaz. Esto ha sido debido a que al probar el ratón, he visto algunos puntos a mejorar para aprovechar el manejo con este.

viernes, 7 de mayo de 2010

El registro 13


Programando la función del player del PSGed, me he dado cuenta de una peculiaridad del AY-3-8910 que desconocía, que repercute en el funcionamiento del secuenciador.

El PSG tiene dos formas de operar. Si no utilizamos la envolvente, lo que determina que suene el PSG, es principalmente el valor del volumen y del mixer, pero si la utilizamos la cosa cambia. Lo que provoca que se disparen los sonidos, es cuando damos un valor al registro 13 (la forma de envolvente). Eso quiere decir que si queremos disparar sonidos independientes en cada canal, con el mismo envolvente, no lo podremos hacer, ya que al tocar este registro, nos sonarán los tres a la vez.

Una posible solución es apagar el sonido del resto de canales, poniendo el valor 0 en los registros de amplitud (con el mixer suena un beep extraño). Como deduciréis, dependiendo del periodo y el tipo de envolvente que usemos, nos cortará el sonido de los otros canales.

La mejor solución seria crear envolventes modificando los valores del volumen mediante programación. Esto nos permitiría utilizar diferentes envolventes en cada canal, o asignarlas a instrumentos. En el caso del PSGed, como la intención es usar directamente los registros del PSG, he utilizado la primera solución.

A continuación un ejemplo para probar lo explicado en este post:
Nota: Suena el tono de los canales A y C, y el ruido del canal B.
100 ' frecuencias de los 3 canales
110 '
120 SOUND 0,100
130 SOUND 1,10
140 SOUND 2,200
150 SOUND 3,100
160 SOUND 4,200
170 SOUND 5,20
180 ' frecuencia de ruido
190 SOUND 6,10
200 ' registros de amplitud
210 ' activamos la envolvente
220 SOUND 8,16
230 SOUND 9,16
240 SOUND10,16
250 ' mixer
260 SOUND 7,&B00101010
270 ' periodo de la envolvente
280 SOUND 11,100
290 SOUND 12,10
300 '
310 IF INKEY$="" THEN 310
320 ' forma de la envolvente
330 ' y dispara el sonido
340 SOUND 13,1
350 GOTO 310

domingo, 2 de mayo de 2010

Pantalla de ayuda

Ya he terminado la pantalla de ayuda!

Para mostrarla antes guardo la pantalla anterior (tabla de nombre de patrones), en un buffer de memoria para luego recuperarla al salir. Utilizo dos funciones de la BIOS (LDIRVM y LDIRMV), para copiar de VRAM a RAM y viceversa. Se nota la velocidad, comparado cuando utilizo un bucle y vpoke desde C.

Luego muestro el texto que lo he alojado en una zona de la memoria y que se desplaza pulsando en los botones correspondientes. He programado la funcionalidad para mostrar la posición de la barra de scroll. Se ajusta automáticamente, por lo que es totalmente reutilizable. Lo que no tiene es la función de arrastrarla con el puntero.

He modificado el diseño de la barra de scroll original, haciéndola más fina (2 columnas en vez de 3). He utilizado dos sprites para las flechas para que se muestren con el color azul, utilizado en todos los botones de las pantallas.

He tenido que cambiar el tileset, y también le he añadido más caracteres que faltaban en la fuente de color negro, necesario para que se mostrará correctamente los textos.

Si os fijáis en la imagen, vereis que no hay minúsculas. Estas se corresponden a la fuente de color magenta, y la utilizo para poder resaltar títulos y otras palabras. Pensé en cambiar el tileset en esta pantalla y añadirle las minúsculas y una fuente completa en otro color para resaltar las teclas, pero no he querido complicarlo hasta ver si tendré suficiente memoria (se trata de una ROM de 32k).