viernes, 30 de abril de 2010

Estado del proyecto

Quiero hacer una pausa para poneros al día de la situación del proyecto. En la actualidad ya dispongo de una versión operativa. La interfaz esta bastante evolucionada. Se puede controlar con teclado y joystick, y le he añadido funcionalidades que no tenia pensadas.

Sobre el problema en el ajuste de los campos con valores grandes, he seguido la idea que me dio Andrear de utilizar aceleración. Quiero puntualizar, que para resolver este problema he conseguido 4 posibles soluciones: el numpad modal de JamQue, el segundo botón de Neuroflip, la aceleración de Andrear y el slider por mi. Al final he optado por la que he encontrado más óptima para esta aplicación, aunque es muy probable que implemente alguna en futuras aplicaciones.

También he añadido aceleración en el control del puntero, para agilizar el movimiento por la pantalla. Otros novedades seria la sustitución del campo que controla el tempo, por el valor de las pulsaciones por minuto (BPM), y la función de "mute" independiente para cada canal, accionable desde el teclado.

El control por potenciometros lo he dejado parado hasta que termine una primera versión. Ahora quiero centrarme en el acceso a disco y el control por ratón. He encontrado unos tutoriales de Ramones en la página de Konamito que me pueden ayudar en la tarea:
Os dejo una demo de un patrón, para que os hagáis una idea de como suena.
PSGed demo001 by aorante

domingo, 25 de abril de 2010

Mostrar números en Screen 2

Para resolver esta tarea, tendremos que convertir el valor de nuestra variable a una cadena de caracteres y luego mostrarlo en la pantalla de forma similar a como lo hicimos con la función vprint del post anterior. Para la conversión he adaptado una función en assembler de baze (Z80bits Collection of Z80 routines). La he llamado Num2Dec16 y como parámetros se le pasa un valor de tipo entero y la cadena donde se ha de escribir el resultado.

/*
16-bit Integer to ASCII (decimal)
by baze
Input: HL = number to convert, DE = location of ASCII string
Output: ASCII string at (DE)
*/
void Num2Dec16(unsigned int aNumber, char *address)
{
aNumber;
address;
__asm
ld l,4(ix)
ld h,5(ix)

ld e,6(ix)
ld d,7(ix)

ld bc,#-10000
call $Num1
ld bc,#-1000
call $Num1
ld bc,#-100
call $Num1
ld c,#-10
call $Num1
ld c,b
call $Num1
jr $Num3
$Num1:
ld a,#47
$Num2:
inc a
add hl,bc
jr c,$Num2
sbc hl,bc
ld (de),a
inc de
ret
$Num3:

__endasm;
}

La función que tenemos que utilizar se llama vprintNumber y le pasaremos como parámetros la posición de la pantalla, el valor y el número de cifras a mostrar (máximo 5). Para desempeñar su tarea, llama a la función de conversión y luego utiliza getAddress para obtener la dirección VRAM correspondiente a la posición que le hemos dado. Seguidamente, realizará un bucle para mostrar con vpoke la cadena que contiene el valor.

// vprintNumber: muestra un numero en la pantalla
// column = numero de columna (0 a 31)
// line = numero de fila (0 a 23)
// aNumber = valor a mostrar
// aLength = numero de cifras a mostrar
void vprintNumber(char column, char line, unsigned int aNumber, char aLength)
{
char pos=5;
unsigned int tiladdre=0;
char strBuff[5];

Num2Dec16(aNumber, strBuff);

// proporciona la direccion de la VRAM a partir de una posicion
tiladdre = getAddress(column, line);

//coloca el contador en la posicion donde se ha de empezar a mostrar
pos = 5-aLength;

// muestra el numero en la pantalla
while (aLength-->0){ vpoke(tiladdre++,strBuff[pos++]);}
}

Ejemplo de uso:
unsigned int valor=1024;
vprintNumber(9, 14, valor, 4);

viernes, 23 de abril de 2010

Mostrar textos en Screen 2

Para facilitar la tarea de mostrar textos en el modo gráfico Screen 2, he programado una serie de funciones. Si quieres conocer como se programa el VDP de los MSX (TMS9918), podéis encontrar el datasheet en EmuDocs.

La primera función necesaria, es una que nos permita escribir en la VRAM (igual que la instrucción de basic VPOKE). Está programada en assembler y es muy sencilla, ya que utiliza la función WRTVRM de la BIOS. En el registro HL se le pasa la dirección, y en el registro A el valor a escribir.

// address = direccion de memoria VRAM
// value = valor a escribir
void vpoke(unsigned int address, unsigned char value)
{
  address;
  value;
__asm
  ld l,4(ix)
  ld h,5(ix)
  ld a,6(ix)
  call 0x004d
__endasm;
}

La siguiente función es la que nos mostrará el texto en la pantalla.

// posx = numero de columna (0 a 31)
// posy = numero de fila (0 a 23)
// text = cadena de caracteres
void vprint(unsigned char posx, unsigned char posy, char* text)
{
  int longi = strLength(text); // tamaño de la cadena
  unsigned int address = 6144 + (posy * 32) + posx; // calcula la posicion en la VRAM
  while (longi-->0)
  {
   vpoke(address++,*(text++)); // escribe en la VRAM
  }
}

Veréis que lo primero que se hace, es identificar el tamaño de la cadena. En vez de utilizar la función de la librería del SDCC, he creado una que la he llamado strLength:

int strLength(char *str)
{
    int i = 0;
    while(*(str++))  i++;
    return i;
}

Luego se calcula la posición en la memoria de vídeo donde se ha de escribir la cadena, en base a la posición dada. El valor 6144 se refiere a la posición de la tabla de nombre de patrones, en la VRAM. Por último se hace un bucle que escribe los caracteres utilizando la función vpoke.

Para finalizar un ejemplo de uso:
vprint(9, 14, "VERSION 0.21B");

martes, 20 de abril de 2010

Cambios en la GUI

He empezado a programar la interfaz y al probarla me he encontrado con un problema. Al modificar valores grandes como la frecuencia de tono o la frecuencia de la envolvente, los botones para incrementar y reducir, resultan muy lentos. Es necesario añadir un sistema que permita modificar el valor de forma más rápida.

JamQue me ha dado la idea de mostrar a través de un botón, una ventana modal con un teclado numérico que permita introducir el valor. A raíz de esta idea se me ha ocurrido mostrar una modal con un control tipo deslizador. Así que me he puesto con el nMSXtiles y he creado el botón y he diseñado las dos posibles ventanas. Cuando lo implemente veré cual de las dos soluciones es la más ágil.

Tendré que hacer una función que gestione las ventanas modales, para que antes de mostrarse guarde los tiles que se ocultan para luego recuperarlos. Para el caso del "slider", sera necesario utilizar un sprite para el cursor.

También he modificado el control del conmutador (checkbox), ya que no quedaba muy claro cuando estaba activo o inactivo. Para ello he añadido una simulación de un led, que se muestra de color verde cuando esta activo.

lunes, 19 de abril de 2010

Pantalla de presentación


Me he entretenido haciendo la pantalla de presentación, que incluye el logo, mi nombre, la versión y un menú donde se podrá seleccionar el dispositivo de control (teclas de cursor, joystick o mouse).

Para el logo me basado en una fuente TrueType, que he adaptado para que se mostrará con la forma adecuada. Para diferenciar las dos partes que se compone el nombre, he utilizado dos colores. Para acabar, lo he adornado con tres líneas de diferentes grosores, que simbolizan los tres canales con tonos de forma cuadrada del PSG. Esta dibujado con Gimp, y he necesitado utilizar tres sprites de 8x8, para que se mostraran correctamente el color de algunas partes del logo.

También he utilizado un sprite, para la flecha usada como cursor en el menú.

martes, 13 de abril de 2010

Hello World


Para mi primer programa con SDCC, me he propuesto hacer el clásico "Hello World" en una ROM. Primeramente he de agradecer el tutorial de Nerlaska para la creación de ROMs y la información de Andrear. En el código podéis encontrar funciones de acceso al VDP, de ambos. También he usado el nMSXtiles de Pentacour, para crear el tileset de la fuente, que para su conversión a código C, me he apoyado de una utilidad que he creado. Para simplificar la compilación y del proceso de creación de la ROM, también he desarrollado una utilidad con una interfaz gráfica. Cuando estén más estables las compartiré con vosotros.

En el desarrollo me encontré con problemas al insertar los datos de la fuente utilizando muchos arrays de chars. El fichero resultante era muy grande y además al ejecutarlo daba errores. He aprendido que cuando se trabaja con bloques muy grandes de datos, como es el caso de los gráficos, es mejor añadirlo en un único array de char (uno para los patrones, otro para los colores y otro para los nombres de patrones). Además para mi sorpresa, el compilador SDCC comprime los datos repetidos, que para este caso se aprovecha bastante. Es un sistema similar al RLE, pero que afecta únicamente a series de valores repetidos.

El programa es muy simple. Primero llena la pantalla del tile 32, para que no se vea como se escriben los gráficos en la VRAM, que aunque es rápido no es tanto como en assembler. Luego lleno la tabla de colores con el color que uso para la fuente (blanco con fondo azul). Para estas dos tareas utilizo una sencilla función en assembler de Nerlaska que es muy rápida (VDP_FillVRAM). Después copio los datos gráficos (del tileset), a los tres bancos de la pantalla (con vpoke_block). En el siguiente paso pongo los textos en la pantalla con una función a la cual indico la posición de la pantalla y el texto (vprint, esta es mía ;D ). Para finalizar espero la pulsación de una tecla (llamada a la bios CHGET-h009F), y después reinicio el ordenador.

Para compilar, he utilizado la siguiente sentencia (al resultado faltaría aplicarle el hex2bin y convertirlo en una ROM de 16k):
sdcc -mz80 --no-std-crt0 --code-loc 0x4010 --data-loc 0xC000 HelloSC2.c

viernes, 9 de abril de 2010

Elección de lenguaje y herramientas de desarrollo

He investigando como programar la aplicación y he llegado a las siguientes conclusiones:
  • La opción más optima es el Assembler. Es el más utilizado por que permite ante una CPU de 3,58 MHz, aprovechar los recursos al máximo. Encontraremos mucha información y es el que dispone más herramientas y soporte de usuarios expertos. Lo malo es que es mucho más complicado programar y mantener el código.
  • Otra opción interesante es el C. Este lenguaje es menos complicado y más legible. Al compilarse se obtiene una velocidad de ejecución aceptable para determinadas tareas. Como punto negativo, nos encontramos que el fichero compilado puede ser muy grande.
Por los pros y contras de estos lenguajes, he decidido combinar los dos. Dependiendo de como evolucione, continuaré con este sistema o trabajaré únicamente con Assembler.

Como entorno de desarrollo he decidido utilizar el SDCC (Small Device C Compiler), sobre Windows. Se trata de un compilador cruzado de Z80 (y otros microprocesadores), open source, para windows y Linux. Para la edición utilizo PSpad y para completar el kit, estoy creando herramientas para facilitar la compilación y transformación de datos gráficos.
Como comentaba, con el uso de algunas de sus librerias, podemos obtener ficheros excesivamente grandes, por lo que es mejor evitarlas. Se puede compensar, gracias a que permite introducir código assembler, con el que podemos crear librerías para acceso al hardware de los MSX (VDP, PSG, etc...), o con funciones más optimas.

Más info: