🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.demos
Article #3028

N-Buffer menudo cayo. _SiN_

#3028
From: Luis Angel Rodil Fernandez
Date: Mon, 02 Jun 1997 00:00
402 lines
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-mail

Show 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