Karoshi MSX Community
24 de Septiembre de 2017, 11:21:14 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 Calendario Ingresar Registrarse  
Páginas: [1]
  Imprimir  
Autor Tema: FD9APATCH.ASM  (Leído 8120 veces)
0 Usuarios y 1 Visitante están viendo este tema.
SapphiRe
Visitante
« : 09 de Abril de 2006, 04:29:04 pm »

Hi all!!

  There's a routine to patch FD9A hook and save some extra raster lines in our games (sorry, commentaries in Spanish):

Código:
                di                                      ; Desactivamos las interrupciones
                call    FD9APATCHON                     ; Parcheamos la interrupcion
                IM      1                               ; Modo de interrupcion 1
                ei                                      ; Reactivamos las interrupciones
                ld      hl,$0303                        ; COLOR ,3,3
                ld      [$F3EA],hl                      ; actualizamos las variables RAM
                call    INIGRP                          ; SCREEN 2
test:           halt                                    ; Sincronizamos con la interrupcion
                ld      bc,$0407                        ; Color azul...
                call    WRTVDP                          ; ...de borde
                ld      b,8                             ; 8 loops completos
waitext:        ld      c,b                             ; Guardamos el contador exterior
                ld      b,0                             ; 256 loops internos
waitint:        djnz    waitint                         ; cerramos el bucle interior
                ld      b,c                             ; Recuperamos el contador exterior
                djnz    waitext                         ; cerramos el bucle exterior
                ld      bc,$0F07                        ; Color blanco...
                call    WRTVDP                          ; ...de borde
                jp      test                            ; Cerramos el test
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
FD9APATCHOFF:   ; --- DESACTIVAMOS EL PARCHEO ---
                ld      a,$C9                           ; A = Ret
                ld      [$FD9A],a                       ; Colocamos un RET en FD9A
                ret                                     ; Volvemos
FD9APATCHCODE:  ; --- RUTINA DE RESTAURACION RAPIDA DE INTERRUPCION ---
                in      a,[$99]                         ; Reseteamos el bit de interrupcion
                pop     IX                              ; Restauramos IX
                pop     IY                              ; Restauramos IY
                pop     af                              ; Restauramos AF'
                pop     bc                              ; Restauramos BC'
                pop     de                              ; Restauramos DE'
                pop     hl                              ; Restauramos HL'
                ex      af,af'                          ; Cambiamos a los registros normales
                exx                                     ; Cambiamos a los registros normales
                pop     af                              ; Restauramos AF
                pop     bc                              ; Restauramos BC
                pop     de                              ; Restauramos DE
                pop     hl                              ; Restauramos HL
                ei                                      ; Reactivamos las interrupciones
                ret                                     ; Volvemos

Explanation:

On every VDP interruption the RST#38 routine first pushes all registers and after that calls to FD9A. If the path is on, before call FD9APATCHCODE, we pop the return address stored in stak. The first line of the routine clears interrupt bit. After that, pops all registers (in the correct order), and finally enables interrupts again and returns. I've tested this routine in several MSX configurations and it works perfectly, also with C-Bios.

There' also an example code to visualize the effect of the path (copy the code and test it with and without the second line). I've made two screenshoots of the result:

First image: path is off



Second image: path is on



Image explanation:

Green: screen area
Blue: time used by our code
White: time used by BIOS
Red (hand-added): interrupt free time

As you can see, there are around 16 extra free lines when path is on.

I also made an additional test: patch the BIOS to avoid the PUSH's and POP's. The minimum code needed is:

Código:
                push    af                              ; Guardamos AF
                in      a,[$99]                         ; Reseteamos el bit de interrupcion
                pop     af                              ; Restauramos AF
                ei                                      ; Reactivamos las interrupciones
                ret                                     ; Volvemos

This code gives us two additional extra lines when compared to the proposed one, but you need to have (and find) RAM on page 0 to copy and patch the BIOS.

Regards
--
SapphiRe
« Última modificación: 09 de Abril de 2006, 04:46:59 pm por SapphiRe » En línea
jltursan
Karoshi Forum's Guru
*******
Mensajes: 1516


¿Que es lo que has aprendido hoy?


Ver Perfil WWW Email
« Respuesta #1 : 09 de Abril de 2006, 05:40:26 pm »

¡Great work!
En línea

Doom dee doom dee doom
SapphiRe
Visitante
« Respuesta #2 : 09 de Abril de 2006, 06:19:03 pm »

¡Great work!
Thanks!

Additionally if you want to use FD9F hook you need to patch this patching routine inserting two new lines as follows:

Código:
                in      a,[$99]                         ; Reseteamos el bit de interrupcion
                bit     7,a                             ; If bit 7 is off...
                call    z,$FD9F                         ; ...call FD9F
@@POPS:         pop     IX                              ; Restauramos IX



Obviously you can change $FD9F and place here your favourite routine Grin

Regards
--
SapphiRe
« Última modificación: 09 de Abril de 2006, 06:33:54 pm por SapphiRe » En línea
SapphiRe
Visitante
« Respuesta #3 : 16 de Abril de 2006, 12:50:44 pm »

Hi again!

  There's another patch to the patching routine to get a better halt synchronization:

Código:
FD9APATCHCODE:  ; --- FAST INTERRUPT ROUTINE, HALT SYNCHRONIZATION UPDATE ---
                in      a,[$99]                         ; Reset interrupt bit
                bit     7,a                             ; If bit 7 is off...
                jp      z,@@ISVDP                       ; ...is a VDP interrupt
@@NOVDP:        call    @@POPS                          ; pops all registers
                ei                                      ; Reactivate interrupts
                halt                                    ; Resyncrhonization (wait till the next interrupt)
                ret                                     ; Return
@@ISVDP:        call    $FD9F                           ; ...call FD9F (you can call to your favourite routine)
                call    @@POPS                          ; pops all registers
                ei                                      ; Reactivate interrupts
                ret                                     ; Return
@@POPS:         pop     IX                              ; Pop IX
                pop     IY                              ; Pop IY
                pop     af                              ; Pop AF'
                pop     bc                              ; Pop BC'
                pop     de                              ; Pop DE'
                pop     hl                              ; Pop HL'
                ex      af,af'                          ; Normal registers
                exx                                     ; Normal registers
                pop     af                              ; Pop AF
                pop     bc                              ; Pop BC
                pop     de                              ; Pop DE
                pop     hl                              ; Pop HL
                ret                                     ; Return

[2006-04-17] A minor update: the code may fail if an interrupt occurs just between the RET and the HALT, so I have modified the routine and now should work well... anyone can take a look?

If an interrupt not due to the VDP occurs, the routine will execute another HALT before return to the main program. So this routine ensures HALT's in the main program will wait till a VDP interrupt occurs.
« Última modificación: 17 de Abril de 2006, 03:59:10 pm por SapphiRe » En línea
SapphiRe
Visitante
« Respuesta #4 : 04 de Mayo de 2006, 04:06:46 pm »

Ok, no one took a look at the previous routine. Why I know? Because the routine doesn't work properly Grin (lesson: please test the code on your MSX, not on your mind).

Here is a routine that actually works well:

Código:
FD9APATCHCODE:  ; --- FAST INTERRUPT ROUTINE, HALT SYNCHRONIZATION UPDATE. THIS CODE WORKS ON RAM/ROM!! ---
                in      a,[$99]                         ; Reset interrupt bit
                bit     7,a                             ; If bit 7 is on...
                jp      nz,@@ISVDP                      ; ...is a VDP interrupt
@@NOVDP:        pop     IX                              ; Pop IX
                pop     IY                              ; Pop IY
                pop     af                              ; Pop AF'
                pop     bc                              ; Pop BC'
                pop     de                              ; Pop DE'
                pop     hl                              ; Pop HL'
                ex      af,af'                          ; Normal registers
                exx                                     ; Normal registers
                pop     af                              ; Pop AF
                pop     bc                              ; Pop BC
                pop     de                              ; Pop DE
                pop     hl                              ; Pop HL
                ei                                      ; Reactivate interrupts
                halt                                    ; Resyncrhonization (wait till the next interrupt)
                ret                                     ; Return
@@ISVDP:        call    $FD9F                           ; ...call FD9F (you can call to your favourite routine)
                pop     IX                              ; Pop IX
                pop     IY                              ; Pop IY
                pop     af                              ; Pop AF'
                pop     bc                              ; Pop BC'
                pop     de                              ; Pop DE'
                pop     hl                              ; Pop HL'
                ex      af,af'                          ; Normal registers
                exx                                     ; Normal registers
                pop     af                              ; Pop AF
                pop     bc                              ; Pop BC
                pop     de                              ; Pop DE
                pop     hl                              ; Pop HL
                ei                                      ; Reactivate interrupts
                ret                                     ; Return

What was the problem? Well: you can't call a routine that only performs POPs. Obvious, isn't it? Spank

I will continue investigating... cmptr:)

Regards
--
SapphiRe
« Última modificación: 05 de Mayo de 2006, 11:37:46 am por SapphiRe » En línea
jltursan
Karoshi Forum's Guru
*******
Mensajes: 1516


¿Que es lo que has aprendido hoy?


Ver Perfil WWW Email
« Respuesta #5 : 04 de Mayo de 2006, 07:37:34 pm »

It's really a good one!! Shocked. A routine doing only POPs,.....what a... Embarrassed

...but now, looking such a space used doing POPs, why not write a self modifying one? (only for RAM of course). Grin
En línea

Doom dee doom dee doom
SapphiRe
Visitante
« Respuesta #6 : 05 de Mayo de 2006, 11:37:00 am »

It's really a good one!! Shocked. A routine doing only POPs,.....what a... Embarrassed

...but now, looking such a space used doing POPs, why not write a self modifying one? (only for RAM of course). Grin

Easy...

Código:
FD9APATCHCODE:  ; --- FAST INTERRUPT ROUTINE, HALT SYNCHRONIZATION UPDATE. THIS CODE ONLY WORKS ON RAM!! ---
                in      a,[$99]                         ; Reset interrupt bit
                bit     7,a                             ; If bit 7 is off...
                jp      z,@@NOVDP                       ; ...is not a VDP interrupt
                call    $FD9F                           ; ...call FD9F (you can call to your favourite routine)
                xor     a                               ; a = NOP code
@@POPS:         ld      [@@HALTNOP],a                   ; Correct instruction for resyncrhonization or to do nothing
                pop     IX                              ; Pop IX
                pop     IY                              ; Pop IY
                pop     af                              ; Pop AF'
                pop     bc                              ; Pop BC'
                pop     de                              ; Pop DE'
                pop     hl                              ; Pop HL'
                ex      af,af'                          ; Normal registers
                exx                                     ; Normal registers
                pop     af                              ; Pop AF
                pop     bc                              ; Pop BC
                pop     de                              ; Pop DE
                pop     hl                              ; Pop HL
                ei                                      ; Reactivate interrupts
@@HALTNOP:      halt                                    ; Resyncrhonization (wait till the next interrupt) or DO NOTHING
                ret                                     ; Return
@@NOVDP:        ld      a,$76                           ; a = HALT code
                jp      @@POPS                          ; goto @@POPS

  I can't test this routine now. Can anyone take a look or (better) test it? JL? What do you think?

Regards
--
SapphiRe
« Última modificación: 05 de Mayo de 2006, 02:04:46 pm por SapphiRe » En línea
jltursan
Karoshi Forum's Guru
*******
Mensajes: 1516


¿Que es lo que has aprendido hoy?


Ver Perfil WWW Email
« Respuesta #7 : 05 de Mayo de 2006, 05:25:24 pm »

Works fine!. To be easily relocated in RAM (if the source is a ROM) the following changes could be applied:

Código:
FD9APATCHCODE:  ; --- FAST INTERRUPT ROUTINE, HALT SYNCHRONIZATION UPDATE. THIS CODE ONLY WORKS ON RAM!! ---
                in      a,[$99]                         ; Reset interrupt bit
                bit     7,a                             ; If bit 7 is off...
                jr      z,@@NOVDP                       ; ...is not a VDP interrupt
                call    $FD9F                           ; ...call FD9F (you can call to your favourite routine)
                xor     a                               ; a = NOP code
@@POPS:         ld hl,INITPATCH+(HALTNOP-FD9APATCHCODE)
                ld      [hl],a                          ; Correct instruction for resyncrhonization or to do nothing
                pop     IX                              ; Pop IX
                pop     IY                              ; Pop IY
                pop     af                              ; Pop AF'
                pop     bc                              ; Pop BC'
                pop     de                              ; Pop DE'
                pop     hl                              ; Pop HL'
                ex      af,af'                          ; Normal registers
                exx                                     ; Normal registers
                pop     af                              ; Pop AF
                pop     bc                              ; Pop BC
                pop     de                              ; Pop DE
                pop     hl                              ; Pop HL
                ei                                      ; Reactivate interrupts
HALTNOP:        halt                                    ; Resyncrhonization (wait till the next interrupt) or DO NOTHING
                ret   
@@NOVDP:        ld      a,$76                           ; a = HALT code
                jr      @@POPS                          ; goto @@POPS               

Where INITPATH is the RAM addres where this routine will be moved from ROM using an LDIR during the initialization of our program (the routine is 35 bytes long).

I'll use it for sure! Wink
En línea

Doom dee doom dee doom
SapphiRe
Visitante
« Respuesta #8 : 05 de Mayo de 2006, 05:48:12 pm »

I'll use it for sure! Wink

Yeah! I'm currently using the ROM version Cheesy
En línea
SapphiRe_MSX
Visitante
« Respuesta #9 : 16 de Noviembre de 2007, 07:49:31 pm »

Ooook, the routine is stupid Grin Grin the BIOS returns after FD9A jump if the interrupt was not VDP generated, so:

Código:
FD9APATCHON:     ; --- PARCHEO DE LA INTERRUPCION ---
                ld      hl,INTERRUPT                    ; Direccion del codigo del path
                ld      [$FD9B],hl                      ; Puesta en FD9B
                ld      a,$C3                           ; A JP xxxx
                ld      [$FD9A],a                       ; Puesto en FD9A
                ret                                     ; Volvemos
FD9APATCHOFF:   ; --- DESACTIVAMOS EL PARCHEO ---
                ld      a,$C9                           ; A = Ret
                ld      [$FD9A],a                       ; Colocamos un RET en FD9A
                ret                                     ; Volvemos
INTERRUPT:      call    RDVDP                           ; Leemos el byte de interrupcion del VDP
                bit     7,a                             ; Si la interrupcion fue provocada por el VDP
                ret     nz                              ; Volvemos
                ei                                      ; Si no, reactivamos interrupciones
                halt                                    ; Esperamos a la siguiente
                ret                                     ; Y volvemos

Using this routine, the HALTs in the main program will wait till a VDP interrupt occurs, preventing bad syncs in our code. Of course you can change the RET NZ for a JP NZ,XXXX to do more things on a VDP interruption.

Comments, please
--
Sph.

P.D. Thanks to GuyveR800 for the tip Cheesy
« Última modificación: 16 de Noviembre de 2007, 07:53:27 pm por SapphiRe » En línea
Páginas: [1]
  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!