Jos'b
|
|
« : 26 de Mayo de 2007, 10:35:35 am » |
|
Quiero conseguir las siguientes rutinas:
Rutina 1. Crea un una rutina que produzca un retardo, pero que sea controlable en segundos o fracciones
Rutina 2. Hacer volcado RAM a VRAM, pero que se ejecute cada cierto tiempo. Por ejemplo que se vuelquen los sprites en una tanda, en otra se vuelquen los gráficos, etc. Al estilo de lo que hizo viejo en el Malaika.
En definitiva, lo que quiero saber es como parchear (no sé si se dice así) la memoria para que cada vez que salte una interrupcion se ejecute mi propio codigo. He estado mirando el código del ejemplo que viene en el Caruso, pero no doy de sí para entenderlo bien.
Asi, si no es mucho pedir, explicarmelo como si fuera para torpes. Y gracias al alma caritativa que me ayude
|
|
|
En línea
|
|
|
|
jltursan
|
|
« Respuesta #1 : 26 de Mayo de 2007, 01:01:54 pm » |
|
Rutina 1. Crea un una rutina que produzca un retardo, pero que sea controlable en segundos o fracciones La más sencilla es esta: ld a,[TIMETICKS] ; TIMETICKS = numero de interrupciones a esperar ld b,a @@WAIT: halt djnz @@WAIT
Si TIMETICKS vale 50/60 está rutina esperará 1 segundo según la máquina funcione a una frecuencia o a la otra respectivamente. A partir de aquí es fácil adaptarla para que espere el tiempo que tu quieras ;-) Rutina 2. Hacer volcado RAM a VRAM, pero que se ejecute cada cierto tiempo. Por ejemplo que se vuelquen los sprites en una tanda, en otra se vuelquen los gráficos, etc. Al estilo de lo que hizo viejo en el Malaika. Independientemente del volcado a VRAM tu necesitas instalar tu propio gestor de interrupciones; para ello puedes encontrar diversos ejemplos en la sección de snippets: Utilizando IM1 y el hook $FD9F: Interlaced SC1 with 64 columnsUtilizando IM2: Interlaced SC1 with 64 columns (IM2 example)Utilizando IM1 y el hook $FD9A: FD9APATCHEspero que alguno te proporcione la información que necesitas
|
|
« Última modificación: 28 de Mayo de 2007, 09:58:01 am por jltursan »
|
En línea
|
Doom dee doom dee doom
|
|
|
Jos'b
|
|
« Respuesta #2 : 26 de Mayo de 2007, 05:42:23 pm » |
|
Gracias por la rutina de tiempo, me viene de perlas. Respecto a otra toquiero seguir preguntando. En el código de Sap, viene esto FD9APATCHON: ; --- PARCHEO DE LA INTERRUPCION --- ld hl,FD9APATCHCODE ; Direccion del codigo del path ld [$FD9C],hl ; Puesta en FD9C ld hl,$C3F1 ; HL = Pop AF; JP xxxx ld [$FD9A],hl ; Puesto en FD9A ret ; Volvemos
pues vale, ya he cogido que lo que hace es almacenar en FD9Ch la dirección de mi codigo, pero... esto que es lo que es ld hl,$C3F1 ; HL = Pop AF; JP xxxx ld [$FD9A],hl ; Puesto en FD9A vamos que no sé esto que es. No sé si soy claro Y otra pregunta, en el código sustituyente, osea mi propio código, ¿ hay que tener en cuenta algo fuera de lo normal ? o me limito a escribir mi codigo y ya esta. Lo digo por si esto de parchear las interrupciones tiene algún efecto secundario. Y otra pregunta más. Como haceis para repartir el trabajo, poneís un contador y en función del mismo vais realizando una tarea u otra. Por ejemplo, reservo un byte de ram, y cada vez que se llame al código, voy incrementado su valor y en función de este mismo valor hago en cada llamada una tarea diferente.Lo siento pero no me se explicar mejor. Y otra más. me daría tiempo entre llamada y llamada a volcar, por ejemplo, unos 500 bytes de RAM a VRAM. Y ya esta de momento. Sé que algunas preguntas ya estan más que contestadas en otros post, pero es que soy así, necesito respuestas personalizadas. y como sé que esto os lo sabeis de memoria... y si no os importa contestarme pos lo agradezco. Y para que veaís que soy agradecido os voy a hacer un poco la bola los de Karoshi sois fantasticos :god: :god: los mejores msxeros del mundo :god: :god: que sería del MSX sin vosotros :god: :god: Bueno ya esta por hoy me voy a cmptr:)
|
|
|
En línea
|
|
|
|
kabish
|
|
« Respuesta #3 : 27 de Mayo de 2007, 11:15:42 am » |
|
Y otra pregunta más. Como haceis para repartir el trabajo, poneís un contador y en función del mismo vais realizando una tarea u otra. Por ejemplo, reservo un byte de ram, y cada vez que se llame al código, voy incrementado su valor y en función de este mismo valor hago en cada llamada una tarea diferente.Lo siento pero no me se explicar mejor. Sí, yo hago eso mismo, otra cosa es q haya maneras mejores de hacerlo.
|
|
|
En línea
|
|
|
|
Jos'b
|
|
« Respuesta #4 : 27 de Mayo de 2007, 07:06:31 pm » |
|
Por eso lo pregunté, a mí desde luego no se me ocurre otra forma de hacerlo. Pero no sé, a lo mejor hay formas más sencillas. Y respecto al resto de preguntas, he cogido la indirecta. Buscaré por el foro a ver que encuentro
|
|
|
En línea
|
|
|
|
jltursan
|
|
« Respuesta #5 : 28 de Mayo de 2007, 09:57:22 am » |
|
Pero no sé, a lo mejor hay formas más sencillas Eso ya dependerá de lo que quieras hacer; pero lo de tener una variable para distinguir entre un bloque y otro está perfecto vamos que no sé esto que es. No sé si soy claro Es que la rutina de Sapphire es la más especial de las que te puse como ejemplo. En esa rutina lo que se pretende es abortar por completo la ejecución del ISR oficial de la BIOS, el punto más temprano en el que podemos interceptar su ejecución es el que nos proporciona el hook $FD9A; hasta ahí bien, nosotros podemos instalar nuestra propia rutina de interrupciones donde queramos de igual manera que cuando usamos el $FD9F, el problema que tenemos es que al retornar de nuestra rutina no queremos que continue con el resto de la rutina oficial, para evitarlo lo primero que se hace es extraer de la pila la dirección de retorno a la BIOS y en ese momento ya podemos llamar a nuestro código, que por tanto va a ser lo único que se ejecute. El código del ISR de este ejemplo lo único que hace es proporcionar una salida apropiada para la propia rutina de la BIOS, por eso únicamente consta de POPs. Sapphire comenta todo eso (en inglish) en el propio ejemplo, la utilidad de esta rutina es la de hacer que manteniendo el modo IM1 de interrupciones, quede disponible para el programador el máximo tiempo de "frame". Es un perfecto ejemplo de "MSX extreme programming" :-D De todas formas no se si es un buen ejemplo para que empieces por él...
|
|
|
En línea
|
Doom dee doom dee doom
|
|
|
SapphiRe_MSX
Visitante
|
|
« Respuesta #6 : 28 de Mayo de 2007, 11:19:45 am » |
|
Y otra pregunta más. Como haceis para repartir el trabajo, poneís un contador y en función del mismo vais realizando una tarea u otra. Por ejemplo, reservo un byte de ram, y cada vez que se llame al código, voy incrementado su valor y en función de este mismo valor hago en cada llamada una tarea diferente.Lo siento pero no me se explicar mejor. Eso es lo que hacía antes. Ahora el bucle de juego se basa en un autómata de estados finitos dirigido por eventos, de forma que en cada frame se deben realizar las acciones que están activadas según los eventos que han sido detectados en frames anteriores. Lo cierto es que es muy cómodo a la hora de programar, porque te olvidas de todo si está bien hecho.
|
|
|
En línea
|
|
|
|
Jos'b
|
|
« Respuesta #7 : 28 de Mayo de 2007, 05:30:41 pm » |
|
Gracias JL, pero me temo de que no va a ser tan sencillo como pensaba. Dejame que estudie la jugada un poco y ya comentaré(o preguntaré) en este mismo hilo mi parecer. La idea que tengo pensada, es la siguiente: Este año quiero hacer que el juego haga volcados de la RAM a VRAM, vamos de RAM a pantalla controlables en tiempo. Quiero decir que cada x fracciones de segundo se vuelque los sprites, y que cada x fracciones de segundo se vuelquen los graficos, y para ello creo (y dime lo conrario si me equivoco) que solo se puede a traves del parcheo de interrupciones. Así que intento enterarme bien de como hay que hacerlo. De todas formas intentaré comprender los ejemplos que me has dado y por supuesto sigo aceptando sugerencias y referencias bibliograficas facilmente descargables de internet. Si veo que me supera utilizaré la vieja tecnica de usar retardos con bucles Lo siento. Y otra pregunta más. Como haceis para repartir el trabajo, poneís un contador y en función del mismo vais realizando una tarea u otra. Por ejemplo, reservo un byte de ram, y cada vez que se llame al código, voy incrementado su valor y en función de este mismo valor hago en cada llamada una tarea diferente.Lo siento pero no me se explicar mejor. Eso es lo que hacía antes. Ahora el bucle de juego se basa en un autómata de estados finitos dirigido por eventos, de forma que en cada frame se deben realizar las acciones que están activadas según los eventos que han sido detectados en frames anteriores. Lo cierto es que es muy cómodo a la hora de programar, porque te olvidas de todo si está bien hecho. Respecto a los Automatas de estados finitos, conozco su teoría, ya se utiliza en los circuitos digitales con memoría, basícamente es crear un circuito cuya salida dependa de la variable de entrada y del propio estado de la máquina. Sin embargo no sé como se podría adaptar para de forma simple para un juego, eso si que es verdad que se escapa a mi nivel de CM. Creo que me quedaré con lo del contador Es un poco cutre pero funcional. Bueno en definitiva dejadme que siga investigando a ver como puedo hacer lo de la interrupciones, y sino dentro de poco volveré a dar la brasa de nuevo.
|
|
|
En línea
|
|
|
|
SapphiRe_MSX
Visitante
|
|
« Respuesta #8 : 28 de Mayo de 2007, 05:38:23 pm » |
|
Sin embargo no sé como se podría adaptar para de forma simple para un juego, eso si que es verdad que se escapa a mi nivel de CM. No es tan difícil. Por ejemplo tengo una acción que es "Calcular Scroll" y otra que es "Volcar Scroll a VRAM". Cada una de ellas está controlada por un bit de un byte de estado que tiene cada jugador. En un principio el bit de "Calcular Scroll" está siempre activado (aunque no siempre va a estarlo cuando termine por completo el motor del juego), con lo que la rutina de cálculo del scroll se llama 60 veces por segundo (50 en pal, pero siempre diseño en NTSC, da menos problemas). Esta rutina actualiza el scroll cada cierto número de frames (con un "cutre contador") y cuando ha calculado el siguiente scroll, activa el bit de "Volcar Scroll a VRAM". Dado que el Scroll no va siempre a la misma velocidad, no puedo saber a priori qué acciones se van a realizar en cada frame, sólo lo se cuando se han completado todos los cálculos en el frame inmediatamente anterior. El autómata tiene una serie de estados que se encargan de activar y desactivar los bits de todas las acciones (hay unas 4 ó 5 más), dependiendo del estado en el que se encuentra y de los eventos que han sucedido. Saludos -- Sph.
|
|
|
En línea
|
|
|
|
Jos'b
|
|
« Respuesta #9 : 28 de Mayo de 2007, 08:11:32 pm » |
|
Oye, pues es una idea interesante. yo diría que casi mejor que lo del contador, de esta forma llamando a la funcion, ella misma se encargaría de verificar los bits y realizar las acciones que correspondan en relacion a su estado (si me equivoco dimelo). Me ha gustado mas que lo del contador. Respecto a lo de parchear las interrupciones, he pensado otra cosa. Voy a usar lo que ya se comento hace tiempo respecto al halt y hacer el volcado a VRAM justo despues. En una tanda imprimiré los Sprites y en la otra los graficos. Espero que no se haga muy lento. De todas formas sigo aceptando sugerencias.
|
|
|
En línea
|
|
|
|
kabish
|
|
« Respuesta #10 : 28 de Mayo de 2007, 11:04:27 pm » |
|
El autómata tiene una serie de estados que se encargan de activar y desactivar los bits de todas las acciones (hay unas 4 ó 5 más), dependiendo del estado en el que se encuentra y de los eventos que han sucedido.
Pues yo habia pensado hacer lo mismo para un juego q estoy haciendo. Ya q tengo una serie de eventos los cuales algunos son excluyentes y otros nacen de unos estados iniciales. Lo q pasa q mas cutre, claro. Buena idea, si señor.
|
|
|
En línea
|
|
|
|
SapphiRe_MSX
Visitante
|
|
« Respuesta #11 : 29 de Mayo de 2007, 10:40:03 am » |
|
Oye, pues es una idea interesante. yo diría que casi mejor que lo del contador, de esta forma llamando a la funcion, ella misma se encargaría de verificar los bits y realizar las acciones que correspondan en relacion a su estado (si me equivoco dimelo). No te equivocas, esa es la idea que utilizo. Me ha gustado mas que lo del contador. Es más versátil. Respecto a lo de parchear las interrupciones, he pensado otra cosa. Voy a usar lo que ya se comento hace tiempo respecto al halt y hacer el volcado a VRAM justo despues. En una tanda imprimiré los Sprites y en la otra los graficos. Espero que no se haga muy lento. De todas formas sigo aceptando sugerencias. Vuelca los gráficos/sprites sólo cuando algo haya cambiado, con la idea del autómata es muy fácil hacerlo. Saludos -- Sph.
|
|
|
En línea
|
|
|
|
Jos'b
|
|
« Respuesta #12 : 29 de Mayo de 2007, 06:12:34 pm » |
|
Pues estoy aprovechando esta idea de los estados para modificar una rutina que tengo, pero como llevo toda la tarde dandole vuelta y no doy con la tecla, me gustaria que me confirmarais el efecto de las siguientes instrucciones
set 3,[memoria] -> Pone a uno el bit 3 del contenido de la direccion memoria
res 3,[memoria] -> Pone a cero el idem
bit 3, [memoria] -> produce Z=0 si el bit 3 esta a uno y Z=1 si el bit 3 esta a cero
vamos que si hago esto
set 3,[memoria] bit 3,[memoria] call z,rutina
debería saltar a la rutina ¿verdad?
me vale un si o un no. Es para descartar errores.
|
|
|
En línea
|
|
|
|
SapphiRe_MSX
Visitante
|
|
« Respuesta #13 : 29 de Mayo de 2007, 06:50:38 pm » |
|
Pues estoy aprovechando esta idea de los estados para modificar una rutina que tengo, pero como llevo toda la tarde dandole vuelta y no doy con la tecla, me gustaria que me confirmarais el efecto de las siguientes instrucciones Veamos set 3,[memoria] -> Pone a uno el bit 3 del contenido de la direccion memoria Correcto res 3,[memoria] -> Pone a cero el idem Correcto bit 3, [memoria] -> produce Z=0 si el bit 3 esta a uno y Z=1 si el bit 3 esta a cero Correcto vamos que si hago esto
set 3,[memoria] bit 3,[memoria] call z,rutina
debería saltar a la rutina ¿verdad?
Incorrecto, el bit 3 está a uno, por lo tanto el flag z está a 0, o sea, no se activa. Si quieres saltar a la rutina deberías poner call nz,rutina me vale un si o un no. Es para descartar errores. Si lo llego a leer antes no hubiera escrito tanto...
|
|
|
En línea
|
|
|
|
Jos'b
|
|
« Respuesta #14 : 29 de Mayo de 2007, 07:32:25 pm » |
|
Bueno gracias por la aclaración, si soy sincero es la primera vez que uso las instrucciones de manipulación de bit y me he hecho un poco de lio Voy a probar mis nuevos conocimientos a ver que tal.
|
|
|
En línea
|
|
|
|
|