; --------------------- ; --- PASOS PREVIOS --- ; --------------------- ; Dependiendo de la máquina, los puertos del VDP son diferentes. Asumamos que existen dos direcciones: ; VDPDATAREAD almacena el puerto #0 de lectura del VDP ; VDPDATAWRITE almacena el puerto #0 de escritura del VDP ; ; Estas direcciones deberán ser inicializadas antes de utilizar estas rutinas: ; En MSX lo copiamos desde (o usamos) las direcciones $0006 y $0007 respectivamente ; En Colecovision/Sega Master System ambas direcciones deben guardar el valor $BE ; ; Dado que los registros del VDP sólo son de lectura, deberemos tener almacenada en RAM una copia de sus valores ; Esa copia estará accesible desde la dirección VDPREGSAV ; Se asume que a partir de esa dirección se almacenan consecutivamente los valores de R#0 en adelante CHECKREFRESH: ; --- RUTINA QUE COMPRUEBA LA VELOCIDAD DE REFRESCO DEL VDP --- ; Paso 1: Desconectamos interrupciones ; Dependiendo de la máquina, el código es diferente: ; Instrucción para MSX/Sega Master System: di ; Desconectamos interrupciones ; En Colecovision debemos escribir un 0 en el bit 5 de R#1 (también funcionaría en MSX y Sega Master System) ; call VBLANKDI ; Desconectamos interrupción VBLANK directamente en el VDP ; Paso 2: Inicializamos un registro de 16 bits a 0 ld hl,0 ; hl:=0 ; Paso 3: Eliminamos posibles interrupciones VBLANK que estuviesen pendientes ld a,[VDPDATAREAD] ; a = puerto #0 de lectura del VDP ld c,a ; c = puerto #0 de lectura del VDP inc c ; c = puerto #1 de lectura del VDP in a,[c] ; Leemos el puerto y así borramos el bit de interrupción (si estuviera activado) ; Paso 4: Nos sincronizamos con el VBLANK @@sync: in a,[c] ; Leemos el puerto and a ; Comprobamos si el bit está activo jp p,@@sync ; Y si no lo está cerramos el bucle ; Paso 5: Medimos el número de incrementos que podemos hacer entre dos VBLANK @@bench: inc hl ; Incrementamos contador in a,[c] ; Leemos el puerto and a ; Comprobamos si el bit está activo jp p,@@bench ; Y si no lo está cerramos el bucle ; Paso 6: Utilizamos un umbral que esté entre los valores NTSC y PAL de la máquina ; Dependiendo de la máquina, el umbral es diferente ; Umbral para MSX/Coleco: $071D ld de,$071D ; de:=$071D (MSX/Coleco) ; Umbral para Sega Master System: $081D ; ld de,$081D ; de:=$071D (Sega Master System) ; Paso 7: Si HL > DE es que estamos a 50hz, si no, estamos a 60hz sbc hl,de ; hl:=hl-de jr c,@@set60hz ; Si el flag C se activa estamos a 60hz ; Si llegamos aquí estamos a 50hz ... ; Lo que sea que quieras hacer si es 50hz jr @@checkEND ; Volvemos @@set60hz: ; Si llegamos aquí estamos a 60hz ... ; Lo que sea que quieras hacer si es 60hz @@checkEND: ; Paso 8: Reactivamos las interrupciones ; Dependiendo de la máquina, el código es diferente: ; Instrucciones para MSX/Sega Master System: ei ; Reactivamos las interrupciones ret ; Volvemos ; En Colecovision debemos escribir un 0 en el bit 5 de R#1 (también funciona en MSX y Sega Master System) ; jp VBLANKEI ; Reconectamos la interrupción VBLANK directamente en el VDP y volvemos ; -------------------------------------- ; --- RUTINAS AUXILIARES PARA COLECO --- ; -------------------------------------- ; También funcionan en MSX y Sega Master System, aunque en estas máquinas no sea necesario su uso para este caso concreto VBLANKDI: ; --- Desactivamos la interrupcion del VDP --- push af push bc ld a,[VDPREGSAV+1] ; Valor actual de R#1 and $DF ; Desactivamos el bir 5 (No generar interrupción VBLANK) jp VBLANKCOM ; Vamos a VBLANKCOM VBLANKEI: ; --- Activamos la interrupcion del VDP --- push af push bc ld a,[VDPREGSAV+1] ; Valor actual de R#1 or $20 ; Activamos el bit 5 (Generar interrupción VBLANK) VBLANKCOM: ld b,a ; Valor a escribir ld c,1 ; Registro R#1 call FWRTVDP ; Lo escribimos y guardamos el valor del registro pop bc pop af ret FWRTVDP: ; --- Escritura en un puerto del VDP guardando su valor --- ; --- Entrada: B = Valor a escribir --- ; --- C = Puerto del VDP --- push hl ; Guardamos hl ld hl,VDPREGSAV ; Zona donde guardamos una copia de los registros del VDP ld a,c ; a:=Registro del VDP call ADDHLA ; Apuntamos a la variable que guarda el registro ld [hl],b ; Guardamos el valor que vamos a escribir pop hl ; Recuperamos hl ; --- Escritura en un puerto del VDP --- ; --- Entrada: B = Valor a escribir --- ; --- C = Puerto del VDP --- push de ld d,c ; d:=Registro del VDP ld a,[VDPDATAWRITE] ; a:=puerto #0 de escritura del VDP ld c,a ; c:=puerto #0 de escritura del VDP inc c ; c:=puerto #1 de escritura del VDP out [c],b ; Valor a escribir en el VDP ld a,d ; a:=Registro del VDP and $3F ; Limpiamos los dos bits superiores or $80 ; Encendemos el bit superior out [c],a ; Escrito el registro del VDP pop de ret ; Volvemos ADDHLA: ; --- RUTINA QUE SUMA HL + A --- ; --- SALIDA: HL := HL + A --- push af ; Guardamos AF add a,l ; a:=a+l jp nc,@@NOCARRY ; Si no hay acarreo saltamos la siguiente instruccion inc h ; Incrementamos el byte superior @@NOCARRY: ld l,a ; hl:=hl+a pop af ; Recuperamos AF ret ; Volvemos