cursos:ensamblador:interrupciones

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
Última revisiónAmbos lados, revisión siguiente
cursos:ensamblador:interrupciones [19-01-2024 12:08] – [La ISR de IM 1] sromerocursos:ensamblador:interrupciones [21-01-2024 11:20] – [Utilizar un JP como ISR] sromero
Línea 1103: Línea 1103:
  
 waitkeyticks_loop:            ; bucle de espera, la ISR lo ira decrementando waitkeyticks_loop:            ; bucle de espera, la ISR lo ira decrementando
-    xor a +    xor a                     ; A = 0 => leer todas las semifilas del teclado 
-    in a,(254+    in a, ($fe              ; Leer teclado 
-    or 224 +    or %11100000              ; Poner a 1 los 3 bits más altos 
-    inc a                     ; Comprobamos el estado del teclado +    inc a                     ; A=A+1. Comprobamos el estado del teclado 
-    ret nz                    ; Si hay tecla pulsadasalimos+    ret nz                    ; Si A=0  => ZF = 1 => no hay tecla pulsada 
 +                              ; Si A!=0 => ZF = 0 => hay alguna tecla => salimos
  
     ld hl, (timer)     ld hl, (timer)
Línea 1116: Línea 1117:
     ret     ret
 </code> </code>
 +
 +
 +\\
 +===== Utilizar un JP como ISR =====
 +
 + En muchos juegos comerciales y homebrew, la rutina de ISR no es una rutina en sí misma sino un ''jp'' a la rutina real, de modo que podamos tenerla junto al resto de nuestro código, y no en una ubicación específica de memoria:
 +
 +
 +<code z80>
 +; Rutina de ISR ubicada junto a nuestro programa, y no en dirección tipo $XYXY
 +    ORG 40000
 +
 +    ; Generamos una tabla de 257 valores "$a2" desde $a000 a $a101
 +    ld hl, $a000
 +    ld a, $a2                     ; A = $a2
 +    ld (hl), a                    ; Cargamos $a2 en $fe00
 +    ld de, $fe01                  ; Apuntamos DE a $fe01
 +    ld bc, 256                    ; Realizamos 256 ldi para copiar $a2
 +    ldir                          ; en toda la tabla de vectores de int.
 +
 +    ; Activamos im2 con nuestra ISR
 +    di
 +    ld a, $fe                     ; Definimos la tabla a partir de $fe00.
 +    ld i, a
 +    im 2                          ; Saltamos a im2
 +    ei
 +
 +    ; Nuestro programa
 +    ; (...)
 +
 +Rutina_ISR:
 +    ; La rutina ISR
 +    (...)
 +    ei
 +    reti
 +
 +    ; Guardamos en una variable de preprocesador la posicion
 +    ; de este punto en el proceso de ensamblado ($)
 +    PUNTO_ENSAMBLADO EQU $
 +
 +    ;-------------------------------------------------------------
 +    ; Nuestra rutina de ISR ensamblada en $A2A2: JP a rutina real
 +    ;-------------------------------------------------------------
 +    ORG $A2A2
 +
 +PUNTO_ENTRADA_ISR:
 +    jp Rutina_ISR
 +</code>
 +
 +De esta forma, la tabla de vectores de interrupción y la rutina ISR (un simple ''jp'' a la rutina real) están prácticamente juntas en memoria y sabemos que acaba 3 bytes después de **$a2a2**, por lo que podemos poner código a continuación sin tener que calcular cuánto ocupa la rutina de ISR. De esta forma también podemos tener la rutina de ISR junto al resto del código, con la única penalización de 3 bytes y 10 ciclos de reloj del ''jp NN''.
  
  
Línea 1167: Línea 1218:
  
 Necesitaremos buscar un hueco en nuestro programa, para colocar un ORG adecuado delante de la ISR, como por ejemplo $a1a1 (41377), o cualquier otra dirección donde el byte alto y el bajo coincidan, y que nos venga bien según el mapa de memoria de nuestro juego. Necesitaremos buscar un hueco en nuestro programa, para colocar un ORG adecuado delante de la ISR, como por ejemplo $a1a1 (41377), o cualquier otra dirección donde el byte alto y el bajo coincidan, y que nos venga bien según el mapa de memoria de nuestro juego.
 +
 +Por citar ejemplos de direcciones, podemos ver las obtenidas en el artículo "//Disassemble Interrupt Mode on some popular ZX Spectrum 128k Games//", de Andy Dansby, quien estudió la ubicación de la rutina de ISR en diferentes juegos de Spectrum comerciales:
 +
 +\\ 
 +|< 90% >|
 +^ Juego ^ Ubicación tabla vectores ^ Ubicación ISR ^ Tipo de ISR (rutina o\\ salto a rutina real) ^ Notas ^
 +| La Familia Addams (The Addams Family) | $b900-$ba00 | $5b5b | ISR es ''jp $ba6e'' | - |
 +| Where Time Stood Still | $8400-$8500 | $bebe | Rutina ISR | - |
 +| Demo 7th Reality | $6300-$6400 | $6464 | ISR es ''jp $624d'' | - |
 +| La Abadia Del Crimen | $be00-$bf00 | $bfbf | Rutina ISR | - |
 +| Chase HQ 2 | $9b00-$9c00 | $fdfd | ISR es ''jp $ba6e'' | ISR en bloque paginable | 
 +| Grand Prix Circuit | $8200-$8300 | $6363 | ISR es ''jp $a07a'' | - |
 +| Robocop 2 | $7700-$7800 | $5b5b | ISR es ''jp $9cb4'' | - |
 +| Robocop 3 | $7700-$7800 | $7676 | ISR es ''jp $8225'' | - |
 +| Spacegun | $be00-$bf00 | $bfbf | ISR es ''jp $a07a'' | - |
 +| Desafio Total (Total Recall) | $9100-$9200 | $5d5d | ISR es ''jp $71ff'' | - |
 +| Carrier Command | $8300-$8400 | $8585 | Rutina ISR | - |
 +| El Gran Halcón (Hudson Hawk) | $9000-$8100 | $8181 | Rutina ISR | - |
 +| NARC | $be00-$bf00 | $bfbf | ISR es ''jp $de38'' | - |
 +| Navy Seals | $9100-$9200 | $5d5d | ISR es ''jp $6dfd'' | - |
 +| Pang | $8000-$8101 | $8181 | ISR es ''jp $6286'' | - |
 +\\ 
 +
 +Varias curiosidades:
 +
 +  * Como se puede ver, no hay un estándar sobre dónde ubicar la tabla de vectores de interrupción, ni la ISR, es una cuestión de elegir las direcciones deseadas según diferentes criterios (como el mapa de memoria de nuestro programa).
 +
 +  * Sólo 2 juegos de la lista (**Grand Prix Circuit** y **Pang**) tienen una tabla de 257 bytes, teniendo el resto de juegos una tabla de 1 página (256 bytes), con lo que técnicamente, había una posibilidad "baja" de que el juego se colgase al arrancar si IM2 cogía $FF y $FF+1. Estos dos juegos implementan IM2 correctamente técnicamente hablando.
 +
 +  * Sólo 4 juegos de la lista implementan la rutina directamente en la dirección apuntada por el vector de interrupciones, mientras que el resto simplemente tienen un ''JP'' a la rutina de ISR real.
 +
  
 \\ \\
  • cursos/ensamblador/interrupciones.txt
  • Última modificación: 21-01-2024 11:23
  • por sromero