Article View: es.comp.demos
Article #3028N-Buffer menudo cayo. _SiN_
From: Luis Angel Rodil Fernandez
Date: Mon, 02 Jun 1997 00:00
Date: Mon, 02 Jun 1997 00:00
402 lines
11607 bytes
11607 bytes
Hola jefes!
Este post es muy denso, pero si logramos solucionarlo puede q los q no
tengan un sistema de NBuffer puedan tener uno en breve.
Hace una burrada de tiempo, despues de la EP4 empez� a programar un
peque�o sistema de NBuffer (modo 13h) en mi viejo 386, la cosa acab� a medias,
pq funcionar, funcionaba, pero la VBI estaba mal sincronizada, este error se
deb�a a q no calculaba bien la frequencia de refresco para la VBI. Ahora
vuelvo a necesitar ese c�digo y he metido todas las rutinas en una clase
(C++) pero en mi nuevo P5, se tosta nada m�s empezar (con el ensamblador no
pasaban estas cosas). Sorprendido, volv� al c�digo en C viejo y tampoco
funcionaba. He revisado, trazado, desensamblado, etc... el c�digo una
decena de veces sin obtener resultado alguno. Se q es un co�azo, pero
pegar� aqui el c�digo y el q quiera q lo mire y si lo consigue arreglar q
lo use como si fuera suyo (q me pida el resto, q yo se lo mando)... Lo
�nico q pido a cambio es q el q lo descubra q haga p�blico el BUG y ponga
de nuevo el c�digo en este grupo para q lo use todo el mundo (incluso yo :)
Unas cuantas explicaciones:
La cabecera QUEUE.H contiene el c�digo relaccionado con la estructura
de datos COLA. La implement� en forma de clase y se trata de un array
circular.
Para calcular el valor de FlopTime pongo una VBISR q lo �nico q hace es
incrementar una variable, espero al retrazo y si la variable ha sido
incrementada quiere decir q la VBISR es m�s r�pida q el retrazo as� q
decremento el valor de FlopTime unos 13Hz y vuelvo a probar. Considero
q la VBISR est� sincronizada con el retrazo cuando entre retrazo y
retrazo la variable q la VBISR incrementa no ha variado, esto quiere
decir q entre retrazo y retrazo no se ha disparado la VBISR. Se q
existen otras maneras de calcular la frecuencia de interrupci�n de una
ISR, pero lamentablemente las desconozco. (JARE si estas ah�
agradecer�a un cable :)
VBISR. Vertical Blank Interrupt Service Routine
Ejemplo de como lo usar�a desde un proggy cualquiera:
scr1, scr2 y scr3 son punteros a zonas de memoria q contienen distintas
imagenes con las q quiero flashear la pantalla.
El tipo evento ser�a una cosa as�:
typedef struct {
void *pointer;
dword size;
} tEvent;
;--[ Loop de prueba ]---------------------
SetupVBI();
for (int cnt = 0; cnt < 100000; cnt++)
{
if (!QUEUE.IsFull()) // Si la cola no esta llena.
// Mete ese puntero en la cola, para la la VBISR
// haga el Dump. Push introduce un evento en la
// cola.
// Cada evento consta de un puntero y de un
// n�mero de bytes q utilizar� la VBISR para hacer
// un dump a pantalla.
QUEUE.Push((void *)scr1, 64000); // BBACK.PCX
if (!QUEUE.IsFull())
QUEUE.Push((void *)scr2, 64000); // XOR Pattern
if (!QUEUE.IsFull())
QUEUE.Push((void *)scr3, 64000); // Blank
}
ShutDownVBI();
;--[ Fin de loop de prueba ]----------------
A aquellos q se pregunten si quizas es el c�digo de la cola el q falla
les dir� q ya lo he usado en muchos otros programas y q nunca me ha fallado
as� q no creo q el fallo venga de ahi.
Predonad q los comentarios del proggy est�n en "ingl�s" (si a eso se le
puede llamar ingl�s). Perosq es una mala costumbre q tengo. ;)
gracias por adelantado...
_SiN_
(pego solo el c�digo de la VBI, lo de las colas y el resto de lo
relaccionado con el NBuffer lo omito por brevedad, pero el q lo quiera, q
lo pida)
;--[ VBI.CPP begin]--------------------------------------------------------
// Vertical Blank Interrupt Service Routine library.
// Written by Luis Angel Rodil Fernandez
// better known a SiN of ELECTRA Productions 1996
// Got some info from Yakka/Xography docs about FakeMode setup, thanks man!
//
// $Id: VBI.CPP, v0.1, 11/10/96, 20:14, sin$
//
// Development notes:
//
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <types.h>
#include "queue.h"
#include "vbi.h"
static volatile bool AlreadyOnInt;
static volatile dword LapsusCounter;
static word FlopTime;
static volatile word SysTimer;
void (__interrupt __far *OldHandler)();
volatile dword FrameCount;
cQueue QUEUE;
tEvent where;
///////////////////////////////////////////////////////////////////////
// ASM Stuff.
///////////////////////////////////////////////////////////////////////
void EOI( void );
#pragma aux EOI = \
" mov al,20h ",\
" out 20h,al ",\
modify exact [eax];
void CLI ( void );
#pragma aux CLI = \
" cli ",\
modify exact [];
void STI ( void );
#pragma aux STI = \
" sti ",\
modify exact [];
void OUTP(word port, byte value);
#pragma aux OUTP = \
" out dx,al ",\
parm [dx] [al] \
modify exact [];
byte INP(word port);
#pragma aux OUTPW = \
" xor eax,eax ",\
" in al,dx ",\
parm [dx] \
value [al] \
modify exact [eax];
void WaitVBEnd ( void );
#pragma aux WaitVBEnd = \
" mov dx,3dah ",\
"s1: ",\
" in al,dx ",\
" and al,8 ",\
" jnz s1 ",\
modify exact [dx ax];
void WaitVB ( void );
#pragma aux WaitVB = \
" mov dx,3dah ",\
"s2: ",\
" in al,dx ",\
" and al,8 ",\
" jz s2 ",\
modify exact [dx ax];
void WaitNextVB ( void );
#pragma aux WaitNextVB = \
" mov dx,3dah ",\
"l1: ",\
" in al,dx ",\
" and al,8 ",\
" jnz l1 ",\
"l2: ",\
" in al,dx ",\
" and al,8 ",\
" jz l2 ",\
modify exact [dx ax];
void ResetTimer ( void );
#pragma aux ResetTimer = \
" mov al,36h ",\
" out 43h,al ",\
" xor ax,ax ",\
" out 40h,al ",\
" out 40h,al ",\
modify exact [ax];
void SetFreq ( word freq );
#pragma aux SetFreq = \
" mov al,34h ",\
" out 43h,al ",\
" mov ax,dx ",\
" out 40h,al ",\
" mov al,ah ",\
" out 40h,al ",\
parm [dx] \
modify exact [ax];
void CallOldHandler ( void );
#pragma aux CallOldHandler = \
" pushfd ",\
" call fword OldHandler ",\
modify exact [];
void ESequDS ( void );
#pragma aux ESequDS = \
" push ds ",\
" pop es ",\
modify exact [];
word GimmeAX ( void );
#pragma aux GimmeAX = value [ax];
void Dump ( byte *s, byte *d, dword size );
#pragma aux Dump = \
" shr ecx,2 ",\
" rep movsd ",\
parm [esi] [edi] [ecx];
////////////////////////////////////////////////////////////////////////////////
// DummySynchro. Is a dummy function to synchronice the timer with the vertical
// blank. It only increments a variable.
// On entry: Interrupt
// On exit : Interrupt
// Notes :
////////////////////////////////////////////////////////////////////////////////
void __interrupt __far DummySynchro ()
{
ESequDS();
++LapsusCounter;
EOI();
}
///////////////////////////////////////////////////////////////////////////////
// TestVBISR. Model for an VB ISR.
// On entry: Interrupt.
// On exit : Interrupt
// Notes :
///////////////////////////////////////////////////////////////////////////////
void __interrupt __far TestVBISR ()
{
byte *screen = (byte *)0xA0000;
byte tmp;
word calc, oldSys;
ESequDS(); // Becoz of the stoopid watcom.
++FrameCount; // For new wait retrace.
if (AlreadyOnInt) { EOI(); return; };
AlreadyOnInt = TRUE; // Avoid nested calls
if (QUEUE.HasEntry()) // Is the queue empty?
{
where = QUEUE.GetEntry(); // If not, get a source pointer.
Dump((byte *)where.pointer, screen, where.size);
// And dump its contents onto screen.
}
WaitVB(); // Wait NEXT retrace
SetFreq(FlopTime); // Avoid desync
//*** HE PROBADO A NO LLAMAR A LA INT VIEJA, PERO SE TOSTA IGUAL!
tmp = GimmeAX(); // Now tmp = AX, after SetFreq
oldSys = SysTimer;
SysTimer += tmp;
if (SysTimer <= oldSys)
CallOldHandler();
AlreadyOnInt = FALSE;
EOI();
}
///////////////////////////////////////////////////////////////////////////////
// New wait-retrace-like routine.
// On entry: Nothing
// On exit : Nothing
// comments: Do not use it from the VBI! Or you'll cause nested int calls. :(
///////////////////////////////////////////////////////////////////////////////
void WaitFrame ( void )
{
dword old;
old = FrameCount;
while( old == FrameCount ) ; // While no screen update, do nothing.
}
///////////////////////////////////////////////////////////////////////////////
// SetupVBI. Sets up the whole thing... This function works by finding a
// synchro value and putting a new VB service routine to the synchro frequency
// in order to trigger a timer interrupt on every screen update.
// On entry: Nothing
// On exit : VBISR working, no return values.
// Notes : Uses the DummySynchro function to find the synchro value.
///////////////////////////////////////////////////////////////////////////////
void SetupVBI ( void ) //( void (__interrupt __far *VBISR)())
{
dword tmpLapsus;
// We start with a very high interrupt frequency. Say 256Hz, so...
// 1193180 / 256 = 4660 = 0x1234;
// Yakka's method.
FlopTime = 0x1234;
OldHandler = _dos_getvect(0x08);
_dos_setvect(0x08, DummySynchro);
WaitNextVB();
do {
FlopTime += 25; // Step down 13.8Hz every loop (for example :)
SetFreq(FlopTime); // Set the interrupt rate.
LapsusCounter = 0;
WaitNextVB();
tmpLapsus = LapsusCounter;
} while ((tmpLapsus > 0) || (FlopTime < 22000));
if (tmpLapsus > 0)
{
printf("Screen syncin' Problems!!!");
ShutDownVBI();
}
// Now we have our synchronization value in FlopTime. This is the value
// we need to put in the timer to trigger an interrupt on every screen
// update. But we need to decrement a bit the FlopTime variable, due to
// interruption latency, our interrupt takes a little amount of execution
// time... isn't it? :)
FlopTime -= 100; // We need to decrement it a bit more (this is C++ ;)
SetFreq(FlopTime);
// Just before Vertical Retrace starts the VBISR will be called.
// _dos_setvect(0x08, VBISR);
_dos_setvect(0x08, TestVBISR);
}
void ShutDownVBI( void )
{
ResetTimer();
_dos_setvect(0x08, OldHandler);
}
;--[ VBI.CPP end ]---------------------------------------------------------
-----
"El arbol del mal da frutos amargos"
Luis Angel Rodil Fernandez
email: luis@bbs.mrbit.es
i1444108@petra.euitio.uniovi.es
SiN/Coder
CopyWrong-AnarchyRights (A) ELECTRA Productions 1997
Technical Details
Message-ID:
<5mu0io$e9a$4@sci.cpd.uniovi.es>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Language: SPANISH,ASCII X-Google-Thread: fdc65,e609e025181495b,start X-Google-Attributes: gidfdc65,public From: i1444108@petra.euitio.uniovi.es (Luis Angel Rodil Fernandez) Subject: N-Buffer menudo cayo. _SiN_ Date: 1997/06/02 Message-ID: <5mu0io$e9a$4@sci.cpd.uniovi.es> X-Deja-AN: 245587677 Organization: Universidad de Oviedo Newsgroups: es.comp.demos