theNestruo
|
|
« : 03 de Abril de 2012, 07:38:26 pm » |
|
Hola! Bueno, pues gracias principalmente al tutorial de Pepe Vila, ya he conseguido dar mis primeros pasos en ensamblador. Una vez cogido el flujo de trabajo, me he propuesto un minireto para ver qué era capaz de conseguir fuera de lo aprendido en el tutorial. Para saber qué instrucciones se puede usar y cuáles no he ido tirando de opcodes.asm (de los ejemplos del asMSX) y de otro par de tutoriales de speccy.org y no sé qué otra página. Al final he conseguido programar un mini-pang supercutre (tan cutre que ni te matan ni se acaba el juego xDDD). Y aquí es donde entrais vosotros. Voy a pediros que, como teneis más rodaje que yo, le echeis un vistazo a la sarta de barbaridades que he hecho y me lleveis al buen camino del ensamblador De la parte de MUEVE_JUGADOR estoy razonablemente satisfecho. Pero la parte de MUEVE_BOLAS creo que no ha quedado tan bien: - Utilizo IX e IY y he leído que debería intentar minimizarlos... lo que no he sabido es cómo organizar el código sin llenarlo de PUSHs y POPs. Tampoco sé cuál de las dos opciones es mejor
- ¿Es normal que COMPRUEBA_PINCHO, que simplemente mira una colisión, ocupe 25 líneas?
- Para dividr las bolas, reduzco la actual, copio la reducida y le cambio el dx a la copia... en 60+ farragosas líneas :S ¿Ideas para mejorar esto?
- Utilizo la copia de SPRATR que tengo en la RAM como variables del juego, ¿esto habitualmente se hace así? (para las bolas tengo además otra tabla separada para saber si están activas, desplazamiento, etc.)
No busco una optimización a tope... simplemente que me indiqueis si estoy haciendo cochinadas muy gordas y cómo podría mejorarlas. ¡Muchas gracias!
|
|
|
En línea
|
theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
|
|
|
pitpan
|
|
« Respuesta #1 : 14 de Abril de 2012, 09:59:45 pm » |
|
Pues está francamente bien para ser tu primera prueba en ensamblador!
No he abierto aún el código, pero el resultado en pantalla es bueno.
Gracias.
|
|
|
En línea
|
|
|
|
cybernoid
|
|
« Respuesta #2 : 15 de Abril de 2012, 08:51:26 pm » |
|
Aunque no soy un crack del ensamblador me parece que vas por muy buen camino, y si conseguiste hacer en basic el Perez, no quiero imaginarme de lo que seras capaz en ASM. mucho animo! por cierto, ya me contareis un día de donde narices sacáis el tiempo los que sois papis...
|
|
|
En línea
|
|
|
|
theNestruo
|
|
« Respuesta #3 : 21 de Abril de 2012, 12:18:55 pm » |
|
Bueno, pues aquí vuelvo; ahora con dudas más concretas: Imaginaos que estoy volcando un cacho de mapa a una línea horizontal de la pantalla. Tengo hl apuntando al próximo caracter a leer, de a donde lo quiero escribir y b el número de caracteres que quiero copiar: @@LOOP: ld a, [hl] ; ...toqueteo a (por eso no uso ldir)... ld [de], a inc hl inc de djnz @@LOOP
Todo muy fácil, sencillo y para toda la familia. Ahora viene lo gordo: si lo que quiero copiar es una columna tengo que andar con push/ex/ex/pop para poder incrementar tanto hl como de. ¿Esto normalmente se hace así? ¿Es suficientemente rápido o cuando empiece a añadir elemento se ralentizará el asunto? @@LOOP: ld a, [hl] ; ...toqueteo a (por eso no uso ldir)... ld [de], a push bc ; preservo bc (b es el contador) ld bc, ANCHO_MAPA ; 64 add hl, bc ld bc, ANCHO_PANTALLA ; 32 ex hl, de add hl, bc ex hl, de pop bc ; restauro bc (b es el contador) djnz @@LOOP
Estoy pensando en hacer una alternativa que sea tener un buffer_columna, apuntar ahí de (con lo que en el bucle sólo tendría que hacer inc de) y luego, cuando esté lleno, volcarlo al búfer de pantalla con otro bucle diferente (en el que para la parte de hl sólo haría inc hl). Estoy un poco perdido porque tampoco sé cómo medir cuánto tardo en preparar un frame. Intenté cambiar el color del borde justo después del halt y cambiarlo otra vez justo al acabar de pintar, que me sonaba haber leído que se podía hacer así, pero no me ha funcionado... ¡Muchas gracias por los ánimos! @cybernoid: yo no tengo niños, pero imagino que pasar la noche despierto + netbook = entradas para la MSXDev P.D.: Adjunto como quedó al final el experimento del minipang
|
|
|
En línea
|
theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
|
|
|
Mortimer
|
|
« Respuesta #4 : 24 de Abril de 2012, 09:27:24 pm » |
|
Al código que has puesto seguramente se le pueden arañar algunos ciclos, pero para saber si te cabrá en el frame dependerá también de cuantos caracteres transfieras junto al resto de cosas que tengas que hacer.... La técnica de cambiar el color del borde es buena, bonita, barata y muy efectiva, yo uso esta rutinilla ; Cambio color de borde que llega en A ColorBorde: ; ret push bc ld b,a ld a,[vdpregisterwrite] ld c,a out [c], b ld b, 087h out [c], b pop bc ret
|
|
|
En línea
|
|
|
|
theNestruo
|
|
« Respuesta #5 : 27 de Abril de 2012, 03:08:38 pm » |
|
Pues ya lo he metido en el código. Para desarrollar estoy tirando de emulador; creía que el meisei me iba a representar bien lo del borde, pero no se ve nada. En el BlueMSX sin embargo sí que lo veo, aunque siempre me llega hasta la mitad de la pantalla más o menos. Tengo que meterle alguna ñapa al código a ver si efectivamente sube o baja, no vaya a ser que me fíe y en realidad no pueda usarlo en el emulador.
Transferir transfiero... todos, los 768 (¿o a qué te refieres?). Básicamente tengo un búfer y un valor offset que varía según se mueve el scroll (derecha +1, arriba -32, etc.). Copio offset bytes de buffer+offset a NAMTBL y luego copio 768-offset bytes de buffer a NAMTBL+offset. La movida viene a la hora de pintar la nueva parte expuesta, que varía dónde he de escribir según el offset y hay que andar verificando que no me salga del búfer... De hecho, estoy pensando si no sería más eficiente (sobre todo en el algoritmo de pintado de parte expuesta) mover los datos del búfer con ldir/lddr para hacer el scroll, luego pintar (sin preocuparme del offset) y luego hacer el LDIRVM... a ver si puedo hacer la prueba sin destrozar mucho el código que ya tengo :S
|
|
|
En línea
|
theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
|
|
|
Mortimer
|
|
« Respuesta #6 : 28 de Abril de 2012, 09:41:15 am » |
|
Yo para mirar lo del color del borde mientras desarrollo uso el Blue, y luego los resultados son iguales que en un MSX real donde lo pruebo cada mucho menos.
Sobre los tiempos, durante el retrazado te da tiempo a enviar los 768 caracteres, eso sí, sin usar la BIOS, y luego tienes el resto del frame para preparar el siguiente buffer a enviar en el siguiente retrazo... Quizás fuera mejor manipular el mapa en memoria, y luego volcar la parte que te interese directamente a vram, que la doble transferencia que es lo que entiendo que intentas hacer.
|
|
|
En línea
|
|
|
|
cybernoid
|
|
« Respuesta #7 : 30 de Abril de 2012, 02:03:54 pm » |
|
Hola chicos, para que sirve lo de cambiar el color del borde (aparte de para cambiar el color del borde)? ¿? me tiene intrigado ¿para medir el tiempo del retrazo? me podeis explicar por encima como funciona todo el tema del retrazo de pantalla? gracias
|
|
|
En línea
|
|
|
|
pitpan
|
|
« Respuesta #8 : 30 de Abril de 2012, 02:18:54 pm » |
|
La idea es medir de una forma gráfica "cuánto tarda" el bucle de un juego. ¿Qué importancia tiene esto? Pues para sincronizarlo respecto del retrazado de pantalla y que el movimiento sea más fluido. Además, durante el retrazado vertical la VDP dispone de mayor ancho de banda para lectura/escritura, por lo que es el momento óptimo para realizar actualizaciones de VRAM (copiar datos, principalmente).
|
|
|
En línea
|
|
|
|
cybernoid
|
|
« Respuesta #9 : 30 de Abril de 2012, 04:35:18 pm » |
|
y como sabes cuando comienza ese retrazo? hay alguna variable de sistema que lo indique?
|
|
|
En línea
|
|
|
|
theNestruo
|
|
« Respuesta #10 : 30 de Abril de 2012, 04:53:41 pm » |
|
No sé si se podrá saber cuando empieza, pero puedes esperarlo con halt (o eso creo). Mira, mi bucle principal es así: MAIN_LOOP: ; parte gráfica halt ld a, 4 call DEBUG_BDRCLR ; parte grafica call BLIT_RAM_TO_VRAM ld a, 6 call DEBUG_BDRCLR ; logica del juego ; fin de la parte gráfica call GET_STICK call UPDATE_SCROLL ; fin del bucle ld a, 12 call DEBUG_BDRCLR ; parte libre del frame jr MAIN_LOOP
De esta forma, el borde de la pantalla se pinta de azul hasta la mitad (el LDIRVM de la NAMTBL), luego hay un fragmento rojo durante los cálculos del scroll (más gordo cuando hay más cosas que hacer, por ejemplo al moverme en diagonal) y luego ya veo verde hasta abajo del todo. ^_^ Y a todo esto, he descubierto una cosa muy curiosa: el LDIRVM de C-Bios es SALVAJEMENTE más rápido que el de la BIOS normal (al menos en BlueMSX). ¿Alguien me puede confirmar esto? Si es así... ¿Por qué? ¿Podría traerme el LDIRVM de C-Bios a mi programa para evitar andar pillado? ¿Cómo? ¿De dónde lo saco?
|
|
|
En línea
|
theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
|
|
|
Mortimer
|
|
« Respuesta #11 : 30 de Abril de 2012, 07:55:20 pm » |
|
Pues ahora que lo dices... la BIOS original hace esto: LDIRVM: ; EX DE,HL CALL SETWRT LDIVM1: LD A,(DE) OUT (VDP.DRW),A INC DE DEC BC LD A,C OR B JR NZ,LDIVM1 RET Es decir, un bucle 'manual' de un porrón de ciclos para cada byte enviado, en cambio la C-BIOS hace esto: ;-------------------------------- ; $005C LDIRVM ; Function : Block transfer from memory to VRAM ; Input : BC - blocklength ; DE - Start address of VRAM ; HL - Start address of memory ; Note : the routine doesn't change IM ; Registers: All ldirvm: ex de,hl IF VDP = TMS99X8 call setwrt ELSE ld a,(SCRMOD) cp 4 jr nc,ldirvm_new call setwrt jr ldirvm_cont ldirvm_new: call nsetwr ldirvm_cont: ENDIF ex de,hl dec bc inc c ld a,b ld b,c inc a ld c,VDP_DATA ldirvm_lp: otir dec a jr nz,ldirvm_lp ; Note: Without this, Quinpl shows glitches. ; TODO: Investigate why. ex de,hl ret
Que envía con OTIR, bastante más rápido. Pero ya que te vas a saltar el BIOS, si sabes que vas a escribir durante el retrazado es más rápido todavía encadenar unos cuantos OUTIs
|
|
|
En línea
|
|
|
|
pitpan
|
|
« Respuesta #12 : 30 de Abril de 2012, 07:57:39 pm » |
|
Y por eso probablemente C-BIOS no funciona correctamente en ordenadores MSX reales. O no en todos, vamos.
Por cierto, que es totalmente cierto: un montón de OUTIs son siempre más rápidos que un OTIR.
|
|
|
En línea
|
|
|
|
Mortimer
|
|
« Respuesta #13 : 30 de Abril de 2012, 08:24:56 pm » |
|
Pues teniendo en cuenta que oficialmente la espera mínima en el peor de los casos es de 28 ciclos y OTIR sólo espera 22... Y además de no cumplir el estándar, tampoco le veo mucho sentido que C-BIOS hagan la transferencia mucho más rápido porque puede hacer que juegos funcionen más rápidos, o incluso que no funcionen
|
|
|
En línea
|
|
|
|
theNestruo
|
|
« Respuesta #14 : 01 de Mayo de 2012, 12:07:00 am » |
|
Buh, pues me da a mí que de momento voy a seguir utilizando LDIRVM. Así me aseguro compatibilidad... y "me obligo" a hacer código eficiente para el resto de cosas. Si cuando esté todo montado veo que necesito un poco más de velocidad, pues entonces ya me contareis lo de la espera mínima, los OTIR y cómo hacer una transferencia más rápida...
|
|
|
En línea
|
theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
|
|
|
|