SUPER UWOL SG-1000

20151225
========

Comienzo el diario de la versión de SG-1000 un poco tarde. Pensaba que sería un camino de rosas pero estoy teniendo problemas de rendimiento.

Por lo visto cc65 es mucho mejor compilador que sdcc. Esto me ha sorprendido... Pensé que un motor que no tenía problemas para moverse bien en un 6502 lo haría en un Z80, y que el código generado para Z80 sería más eficiente por tener este procesador más registros... Pero no es así.

En cuanto hay que actualizar muchas cosas pierdo frames en NTSC. Es un problema porque en SMS hay que copiar incluso más datos a VRAM en cada frame. Creo que es bastante posible que este sea uno de los handicaps junto con el compilador, ya que en NES las copias a VRAM son movimientos normales (la VRAM está en el espacio de direcciones) y en SEGA 8-bit se hacen escribiendo a un puerto. Estoy seguro de que esto limita bastante el ancho de banda.

El tema es que tengo que intentar rediseñar y optimizar todo el tema de movimiento de sprites.

SGlib (basada en SMSlib) proporciona una estructura en memoria que es copiada a VRAM una vez por frame. Yo necesito rellenar esta estructura empleando un orden diferente cada vez para introducir parpadeo y evitar que los sprites desaparezcan cuando se alinean más de 4. En este trasiego estoy perdiendo mucho tiempo y creo que es una de las cosas que tengo que optimizar. Se ve perfectamente como el juego deja de perder frames en cuanto comienzan a desaparecer monedas de la pantalla.

El SAT se copia completamente en cada frame. Ahora mismo tengo un máximo de 21 sprites y quizá pueda empezar por instruir a la biblioteca (que ya he modificado a saco) para que sólo procese 21 sprites. Veamos si esto mejora algo (todo suma).

El siguiente paso será diseñar qué se hace con cada tipo de sprite en pantalla para intentar reducir a la minima expresión las actualizaciones. Por ejemplo, las monedas pasan casi todo el tiempo fijas, y sus gráficos se modifican cambiando los patrones en el SGT. Esto implica 8x4 = 32 bytes a VRAM. Quizá también ahorraría tiempo teniendo todos los gráficos en VRAM y cambiando solo el valor de la SAT, que a fin de cuentas se actualiza cada frame... Eso es cambiar 13 valores cada frame.

Luego haré un estudio de todas las actualizaciones posibles e intentaré rediseñar de nuevo el sprite mixer. También ayudaría que el sprite mixer pudiese escribir directamente en la copia de la SAT en vez de estar haciendo cosas intermedias. Cogeré papel y lápiz luego.

~~

Oh, wait, 21 elementos, no 21 sprites. Tengo:

4x2 para enemigos => 8
2x4 para jugadores => 8
2x2 para items => 4
13 monedas 
13+16+4= 33 - ole mis webs, me estoy colando.

Bueno, voy a coger un papel y ver qué necesita cada objeto en pantalla. Pero antes voy a ver si puedo apañar rápidamente lo de las monedas...

La putada es que SDCC es DESESPERANTEMENTE LENTO. Dios, qué coñazo es esperar varios minutos cada vez que tengo que recompilar para probar algo...

~~ 
De entrada pueden ser incluso más de 33. Hay que tener en cuenta que tanto Uwol como Meemaid pueden desaparecer por el borde de la pantalla y para simular ese efecto hay que duplicar los sprites. 

Tengo que ver de donde recortar. De entrada, Fanty podría pintarlo solo con el reborde, y las camisetas más de lo mismo. Esto me dejaría con:

3x2 enemigos => 6
1 fanty 
2x2x2 jugadores => 8
13 monedas
2 items

2+13+6+16 = 37. Me sigo pasando un HUEVO. Voy a examinar los sprites de Uwol y Meemaid a ver si puedo ahorrar algo.

No. Tengo que pensar en algo.

En modo 1P:
8 enemigos
8 Uwol
13 monedas
2 items

Total 31.

En modo 2P tengo que limitar a 4 por jugador. Esto significa que cuando un jugador esté en el borde no lo puedo duplicar. Esto introducira un glitch con el que tendremos que vivir hasta que se me ocurra algo mejor.

En ese caso lo suyo es manejar yo la SAT manualmente. La copia de la SAT la escribo directamente, y luego la copio yo también en el orden que sea.

El byte de colores no necesito tocarlo en mi copia. Se puede inicializar al principio.

~~~~

Entradas en mi copia de la SAT

Off
0		4 		Uwol
4 		4 		Meemaid
8 		2 		Enem 1
10 		2 		Enem 2
12 		2 		Enem 3
14 		2 		Fanty
16 		1 		Item 1
17 		1 		Item 2
18 		13 		Coins 		

Veamos, los enemigos están cargados a partir del patron 128.
Un enemigo de sprite "s" muestra los metasprites s y s + 1, con s = 0...
Cada metasprite está formado por dos sprites, y cada sprite por 4 patrones
patron = 128 + s * 8

~~~~~~~~~~~~

Mucho más tarde - He reescrito todo mil veces y al final me he quedado con lo primero, pero limpio. Le he metido a SGlib las funciones de metasprites directamente para escribir en el array con la copia de la SAT. He modificado las funciones que añaden sprites para usar un puntero e ir escribiendo a manaca, sin comprobaciones.

Más o menos va bien, pero ahora se jode un registro del VDP cuando enciendo la pantalla a veces. Parece que quizá se corrompa la copia de VDPregs en RAM, o yo qué sé. 

Tendré que hacer algo de debug con el emulicious, pero la verdad es que no sé para qué va a valer... Pero bueno, más se perdió en Roma.

~~

Me estaba escribiendo las estructuras const unsigned char * en RAM. He tenido que hacer la paranoia const unsigned char * const unsigned char a [] = {  para que no lo haga ... y deste entonces parece no fallar.

Mañana más. Este proyecto me está matando.

~~

20151226
========

Tengo que encontrar algo convincente para cuando Uwol o Meemaid mueren. Lo más inmediato es poner el frame de "estoy muelto", pero eso ocuparía ROM... Aunque quizá programar una lógica parecida a la versión de Spectrum (en la que el personaje cae hasta desaparecer de la pantalla) terminaría ocupando más.

El problema es que Uwol / Meemaid muertos es un sprite horizontal, con una disposición diferente. Voy a ver si tengo funciones para remplazar el metasprite de una entrada fija de la lista. En ese caso, meteré los sprites nuevos.

No. Pero es muy fácil hacer un inline void msl_change_meta...

Como aún tengo sitio en la SGT, voy a meter los patrones que necesito. Son en total 32 (16 para Uwol, 16 para Meemaid). Los meto a partir de 0x20 (32).

~~

Todo metido y funcionando. Pero escribí por fin la herramienta para ver la ocupación de la ROM y se nos han caido los cojones al suelo. Está casi petada, a falta del final y de casi toda la OGT. Llevamos todo el día haciendo cuentas y recortando.

Sé que al final lo lograremos - pero ahora mismo queda menos de 1Kb (700 y pico bytes a lo más, diría yo). Por ahora lo más importante es que ya está la música ingame y todos los sonidos metidos. Haría falta al menos una música de fanty y meter los finales de algún modo. Yo voy mirando aquí y allá recortando de donde puedo.

SITIOS DE DONDE AHORRAR
=======================

Si las cosas se ponen chungas, se puede ahorrar espacio quitando / modificando algunas cosas:

- Cuando acabas un nivel, hay un bucle en el que se va sumando 10 puntos por cada segundo restante. Queda muy arcade, pero se puede quitar (y directamente sumar el tiempo por 10 y que ya se vea el resultado en la pirámide).
- Pantalla de Game Over. Queda chuli, pero tampoco se va a morir nadie.

He optimizado algo más. He ahorrado algo de memoria del tileset (seguía cargando el tile de la moneda, misteriosamente) y más cosas. He metido los finales (sin probar) y me he quedado igual que antes XD

Venga, que lo vamos a conseguir.

20151228
========

Me cago y me queda.

Ahora resulta que la SG-1000 admite 48K de ROM sin mappers. Eso me pasa por no preguntar y confiar en el documento mierder que leí en tiempos.

Voy a volver a meter el frame que quité, a hacer los gráficos para el final, y a decirle a David que haga una OGT en condiciones y que no me mate.

20151229
========

Sverx ha integrado aPlib con las modificaciones de Maxim para que descomprima ROM->VRAM, y voy a ver qué resultados obtengo comprimiendo los patrones de las pantallas del final, una imagen bonita para el VS, los patrones del tileset principal, los patrones de los sprites de los enemigos y las monedas, y demás patraña que no se tenga que actualizar cada frame.

Esto me introduce una nueva necesidad: que mkts exporte en binario. Puedo hacer que detecte la éxtensión del fichero de salida (.h o .bin) y que saque código o datos (para los patrones, se entiende) según convenga.

Pero antes voy a terminar un par de dibujines.

Otra cosa para MKTS: Modo tilemap para imagenes completas. Como aquí no es como en NES que hay que estar pendiente de los atributos, ahorro bastante sacando las imagenes como tilemaps completos basados en patrones y repetición.
