Karoshi MSX Community
05 de Julio de 2021, 07:27:04 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1] 2 3
  Imprimir  
Autor Tema: Rincón del novato en ASM  (Leído 17022 veces)
0 Usuarios y 1 Visitante están viendo este tema.
theNestruo
Karoshi Lover
***
Mensajes: 236


Email
« : 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. Wink
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 Grin
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
Karoshi Forum's Guru
*******
Mensajes: 1812


« 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
Karoshi Maniac
****
Mensajes: 368



WWW
« 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.

Smiley 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
Karoshi Lover
***
Mensajes: 236


Email
« 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:
Código:
@@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?
Código:
@@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 Wink

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
Karoshi Lover
***
Mensajes: 216


WWW
« 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

Código:
; 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
Karoshi Lover
***
Mensajes: 236


Email
« 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
Karoshi Lover
***
Mensajes: 216


WWW
« 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
Karoshi Maniac
****
Mensajes: 368



WWW
« 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 Tongue  ¿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
Karoshi Forum's Guru
*******
Mensajes: 1812


« 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
Karoshi Maniac
****
Mensajes: 368



WWW
« 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
Karoshi Lover
***
Mensajes: 236


Email
« 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í:
Código:
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
Karoshi Lover
***
Mensajes: 216


WWW
« Respuesta #11 : 30 de Abril de 2012, 07:55:20 pm »

Pues ahora que lo dices... la BIOS original hace esto:

Código:
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:

Código:
;--------------------------------
; $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
Karoshi Forum's Guru
*******
Mensajes: 1812


« 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
Karoshi Lover
***
Mensajes: 216


WWW
« 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...  Sad

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  Huh
En línea
theNestruo
Karoshi Lover
***
Mensajes: 236


Email
« 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...
Cheesy
En línea

theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
Páginas: [1] 2 3
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!