Appunti per Scuola e Università
humanisticheUmanistiche
Appunti e tesine di tutte le materie per gli studenti delle scuole medie riguardanti le materie umanistiche: dall'italiano alla storia riguardanti le materie umanistiche: dall'italiano alla storia 
sceintificheScientifiche
Appunti, analisi, compresione per le scuole medie suddivisi per materie scientifiche, per ognuna troverai appunti, dispense, esercitazioni, tesi e riassunti in download.
tecnicheTecniche
Gli appunti, le tesine e riassunti di tecnica amministrativa, ingegneria tecnico, costruzione. Tutti gli appunti di AppuntiMania.com gratis!
Appunti
informatica
CComputerDatabaseInternetJava
Linux unixReti


AppuntiMania.com » Informatica » Appunti di c » Catturare il contenuto del video

Catturare il contenuto del video




Visite: 1682Gradito:apreciate 4-stela [ Medio appunti ]
Leggi anche appunti:

Scrivere funzioni di libreria


Scrivere funzioni di libreria La scrittura di un programma C implica sempre

Il flusso elaborativo


Il flusso elaborativo Qualsiasi programma può venire codificato in un linguaggio

Numeri a caso


Numeri a caso La libreria C include alcune funzioni per la generazione di
immagine di categoria

Scarica gratis Catturare il contenuto del video

Catturare il contenuto del video

In questo esempio presentiamo un programma TSR che consente di scrivere in un file specificato dall'utente il contenuto del video (in modo testo) quando vengano premuti contemporaneamente i due tasti di shift. Il testo del buffer video è aggiunto ai dati eventualmente già presenti nel file indicato; al termine di ogni riga (e prima di quella iniziale) è aggiunta una sequenza CR LF; in coda al buffer è inserito un carattere ASCII  FormFeed o salto pagina), rendendo in tal modo il tutto particolarmente idoneo al successivo editing mediante programmi di videoscrittura.



Barninga_Z! - 1991


SHFVWRIT.C - TSR che scrive su un file il buffer video CGA, EGA,

VGA in modo testo formattato mediante l'aggiunta di

CR+LF in testa e a fine riga, e di FF in coda. Il nome

del file deve essere specificato sulla command line.


I bit del byte attributo (eccetto il bit del blink)

sono invertiti per segnalare lo svolgimento

dell'operazione e sono nuovamente invertiti al termine

della scrittura su file (effettuata in append). Se

l'applicazione interrotta 'ridisegna' una parte del

video durante la scrittura, i bit dei bytes attibuto

di tale porzione del video non vengono invertiti al

termine dell'operazione. Il TSR si attiva premendo

contemporaneamente i due SHIFT.


Compilato sotto TURBO C++ 1.01


tcc -O -d -rd -k- -Tm2 shfvwrit.c



#pragma  inline

#pragma  option -k-


#include <stdio.h>

#include <stdlib.h>

#include <dos.h>


#define PRG       'SHFVWRIT'

#define YEAR                 '1991'

#define _BLANK_              ((char)32)

#define _FF_                 ((char)12)

#define _LF_                 ((char)10)

#define _CR_                 ((char)13)

#define _NROW_               25

#define _NCOL_               80

#define _VBYTES_             _NROW_*_NCOL_

#define _NCR_                (_NROW_+1)

#define _NLF_                _NCR_

#define _NFF_                1

#define _BUFDIM_             (_VBYTES_+_NCR_+_NLF_+_NFF_)

#define _MONO_VIDADDR_       ((char far *)0xB0000000L)

#define _COLR_VIDADDR_       ((char far *)0xB8000000L)

#define _SHFMASK_            ((char)3)

#define _MASK_               ((char)127)

#define _TSR_TEST_           0x97 /* shfvwrit e' residente ? */

#define _TSR_YES_        0xABFE /* risposta = si, e' residente */

#define _PSPENVOFF_          0x2C /* off del seg ptr all'env.in psp */

#define _FNMLEN_             80 /* lungh. max path con NULL finale */


#define  int09h ((void (interrupt *)())(*((long *)TSRdata))) /*dd*/

#define  int28h ((void (interrupt *)())(*(((long *)TSRdata)+1))) /*dd*/

#define  int2Fh ((void (interrupt *)())(*(((long *)TSRdata)+2))) /*dd*/

#define  fnameptr ((char far *)(*(((long *)TSRdata)+3))) /*dd*/

#define  strptr ((char far *)(*(((long *)TSRdata)+4))) /*dd*/

#define  shfflag (*(((int *)TSRdata)+10)) /*dw*/

#define  exeflag (*(((int *)TSRdata)+11)) /*dw*/

#define  shfstat (*((char far *)(*(((int *)TSRdata)+12)))) /*dw*/

#define  vidstr (((char *)TSRdata)+26) /*arr*/

#define  vidatr (((char *)TSRdata)+26+_BUFDIM_) /*arr*/

#define  fname (((char far *)TSRdata)+26+_BUFDIM_+_VBYTES_) /*arr*/


#define  int09h_asm TSRdata

#define  int28h_asm TSRdata+4

#define  int2Fh_asm TSRdata+8

#define  fnameptr_asm TSRdata+12

#define  strptr_asm TSRdata+16


#define  clear_stack() asm


void TSRdata(void); /* consente l'uso del nome prima della definiz. */


void filewrit(void)


_OPENED:

asm




void vidstrset(void)


switch(_AL)

vidstop = (vidptr += (_BH*_VBYTES_));

strptr = vidstr;

*strptr++ = _CR_;

*strptr++ = _LF_;

for(i = 0;i < _NROW_;i++)

*strptr++ = _CR_;

*strptr++ = _LF_;

}

*strptr++ = _FF_;

filewrit();

for(;vidptr > vidstop;vidptr--)

*vidptr = (*(--vidptr) == (*(--atrptr) ^= _MASK_)) ? *vidptr :

*atrptr;




void interrupt newint28h(void)


clear_stack(); /* macro per uscire da funzione interrupt */

asm jmp dword ptr int28h_asm;




void interrupt newint09h(void)




void far newint2Fh(void)        /* non interrupt: non serve salvare regs */


_CHAIN:

asm jmp dword ptr int2Fh_asm;

_ANSWER:

asm




void TSRdata(void)





int tsrtest(void)


_RESIDENT:

return(_AX);




void release_env(void)





void install(void)





int filetest(char *argv1)


_OPENED_NEW:

asm

_FNAME_OK:

asm xor ax,ax;

_EXITFUNC:

asm pop ds;

return(_AX);




void main(int argc,char **argv)



La struttura del programma non è particolarmente complessa. La main() controlla che sia stato fornito, via command line, un nome di file per l'output: in caso negativo l'elaborazione viene interrotta. La funzione tsrtest() verifica l'eventuale presenza in RAM del TSR, utilizzando l'int 2Fh (la tecnica è descritta a pag.  ). Se il programma non è già residente, filetest() controlla la validità del nome di file specificato dall'utente: il servizio 60h dell'int 21h (vedere anche pag.  ) è utilizzato per ricavarne il pathname completo, onde evitare che variazioni dei default relativi a drive e directory di lavoro determinino la scrittura dei dati in luoghi imprevisti. La main() invoca poi install(), che completa la fase di installazione: essa, in primo luogo, salva i vettori degli interrupt utilizzati dal programma e sostituisce ad essi quelli dei nuovi gestori; in seguito invoca release_env(), che libera la RAM occupata dall'environment fornito dal DOS al TSR (vedere pag.  ), dal momento che questo non ne fa uso. Infine install() calcola il numero di paragrafi che devono rimanere residenti (l'algoritmo di calcolo è descritto a pag.  ) e installa SHFVWRIT mediante l'int 21h, servizio 31h, 'cuore' della funzione di libreria keep() (pag.  ), qui invocato direttamente per rendere il codice più compatto.

Tutti i dati globali necessari al programma sono gestiti nello spazio ad essi riservato, all'interno del code segment, dalla funzione jolly TSRdata(), che chiude il gruppo delle routine residenti. Le macro atte a facilitare i riferimenti a detti dati sono definite, nel sorgente, al termine delle direttive #define relative alle costanti manifeste. Disorientati? Niente paura: vedere a pag. 

La funzione newint2Fh() è il nuovo gestore dell'int 2Fh: essa è dichiarata far in quanto la semplicità della sua struttura rende inutile il salvataggio automatico dei registri. Il concatenamento al gestore originale (nel caso in cui SHFVWRIT non sia ancora installato) è effettuato mediante una istruzione JMP; il ritorno al processo chiamante (SHFVWRIT installato) mediante una IRET. In entrambi i casi è indispensabile ripristinare lo stack quale esso appare al momento dell'ingresso nella funzione: a seconda della versione del compilatore può essere necessario, a tal fine, effettuare una POP del registro BP

La funzione newint09h() è il nuovo gestore dell'int 09h: esso si occupa semplicemente di analizzare il byte di stato degli shift per intercettare lo hotkey. Se l'utente preme i due shift e, al tempo stesso, il TSR non è attivo (exeflag ) viene posto a  il flag indicante la richiesta di popup, cioè di attivazione. Anche in questo caso il concatenamento al gestore originale è effettuato con una JMP; lo stack è ripristinato dalla macro clear_stack(), precedentemente definita. La newint09h() è dichiarata interrupt per sicurezza. Essa, infatti, gestisce un interrupt hardware che viene invocato da un evento asincrono; inoltre contiene quasi esclusivamente codice C, con la conseguenza che non è possibile sapere a priori quali registri vengano da essa modificati. In questo caso appare prudente (e comodo) lasciare al compilatore il compito di salvare in modo opportuno i registri della CPU.

La newint28h() gestisce l'int 28h: essa è pertanto invocata dal DOS quando questo è in attesa di un input dalla tastiera. Se è stato richiesto il popup e il TSR non è attivo, viene posto a  il flag che ne indica l'attivazione ed è invocata vidstrset(). Al rientro sono azzerati i flag e viene concatenato il gestore originale. Anche newint28h() è scritta quasi interamente in linguaggio C, pertanto è dichiarata interrupt

La funzione vidstrset() pilota le operazioni di lettura del buffer video e di preparazione alla scrittura nel file. Essa verifica la modalità video attuale mediante il servizio 0Fh dell'int 10h: se è grafica o testo a 40 colonne il controllo è restituito a newint28h() senza intraprendere alcuna azione, altrimenti viene opportunamente determinato l'indirizzo del buffer video.

Mediante indirezioni e incrementi di puntatori, il testo contenuto nel buffer è copiato nello spazio ad esso riservato nella TSRdata(), inserendo al tempo stesso i caratteri necessari per dare al testo il formato voluto; inoltre gli ASCII  sono trasformati in ASCII  (spazio). I byte attributo del buffer, e dunque i colori del testo visualizzato, dopo essere stati anch'essi salvati in un array collocato nella TSRdata(), sono modificati tramite un'operazione di XOR con un byte che funge da maschera: lo scopo è segnalare visivamente che SHFVWRIT è in azione. Al termine di queste operazioni è invocata filewrit() e al rientro da questa una nuova operazione di XOR, identica alla precedente, ripristina i colori originali del testo nelle sole aree di video non modificate da altre applicazioni durante l'attività di filewrit()

Quest'ultima si occupa delle operazioni di output nel file specificato dall'utente: dal momento che il testo deve essere aggiunto al contenuto del file, è necessario che esso sia creato se non esiste, ma non distrutto se è già presente. Il servizio 5Bh dell'int 21h tenta l'apertura di un nuovo file: se questo esiste l'operazione fallisce (il servizio 3Ch ne avrebbe troncato a  la lunghezza) e il file può essere aperto con il servizio 3Dh. Dopo l'operazione di scrittura il file viene chiuso: in tal modo il DOS aggiorna correttamente FAT e directory. La filewrit() è scritta quasi per intero in assmbly inline non solo per ragioni di velocità e compattezza del codice, ma anche (e soprattutto) per evitare l'uso di funzioni di libreria e, di conseguenza, i problemi descritti a pag. 

Concludiamo il commento al codice di SHFVWRIT evidenziandone le carenze, dovute alla necessità di presentare un esempio di facile comprensione. Le routine residenti non segnalano all'utente il verificarsi di eventuali errori (modalità video non prevista, disco pieno, etc.) e mancano gestori per gli int 23h e 1Bh (CTRL‑C CTRL‑BREAK) e per l'int 24h (errore critico), la gestione dei quali è quindi lasciata all'applicazione interrotta. Il limite più evidente è però l'utilizzo dell'int 28h come punto di attivazione: detto interrupt è infatti generato dal DOS nei loop interni alle funzioni 01h‑0Ch dell'int 21h, cioè, in prima approssimazione, quando esso è in attesa di un input da tastiera. Se l'applicazione interrotta non si avvale del DOS per gestire la tastiera ma, piuttosto, del BIOS (int 16h), newint09() può ancora registrare nell'apposito flag la richiesta di popup, ma questo non avviene sino al termine dell'applicazione stessa.

Presentiamo di seguito il listato del programma VIDEOCAP, che rappresenta una evoluzione di SHFVWRIT. In particolare VIDEOCAP utilizza ancora quale punto di attivazione l'int 28h, ma incorpora un gestore dell'int 16h (newint16h()), il quale simula con un loop sul servizio 01h/11h le richieste di servizio 00h/10h; in tale loop viene invocato un int 28h (se non sono in corso servizi DOS) consentendo così l'attivazione anche sotto programmi che gestiscono la tastiera via int 16h. La routine di copia del buffer video individua il modo video attuale (ammessi testo 80 colonne colore o mono), il numero di righe video attuali e la pagina corrente, risultando così più flessibile e completa di quella incorporata da SHFVWRIT. L'offset della pagina video corrente nel buffer video è determinato moltiplicando 160 (80 % 2) per il numero di righe correnti e sommando un correttivo (individuato empiricamente) descritto in una tabella hard-coded, alla quale è riservato spazio dalla funzione fittizia rowFactors()

Si noti che le funzioni fittizie sono dichiarate DUMMY, così come il tipo di parametro richiesto. L'identificatore di tipo DUMMY è, in realtà, definito e reso equivalente a void dalla riga

typedef void DUMMY;

Si tratta dunque di uno stratagemma volto ad aumentare la leggibilità del programma (lo specificatore typedef definisce sinonimi per i tipi di dato; vedere pag. 

VIDEOCAP, a differenza di SHFVWRIT, impiega una funzione fittizia per ogni variabile globale residente: in tal modo è più semplice referenziarle mediante operazioni di cast e si evitano alcune #define

Anche la modalità in cui il programma segnala di avere eseguito il proprio compito è radicalmente diverso: invece di modificare il colore dei caratteri a video durante l'operazione, VIDEOCAP emette un breve beep a 2000 Hz non appena chiuso il file. La funzione beep2000Hz() esemplifica come pilotare l'altoparlante del PC in una routine residente.



VIDEOCAP.C - Barninga_Z! - 09/11/92


Utility TSR per salvataggio del video su file. Invocare con un nome

di file per installare in memoria. Il dump su file si ottiene

premendo contemporaneamente i due tasti di shift. Per disinstallare

invocare con un asterisco come parametro sulla command line.


Compilato sotto BORLAND C++ 3.1:


bcc -Tm2 -O -d -rd -k- videocap.c



#pragma inline

#pragma warn -pia


#include <stdio.h>          // la #include <io.h> deve essere DOPO tutte le

#include <dos.h>              // funzioni DUMMY contenenti asm dup()

#include <string.h> // perche' in io.h e' definita int dup(int)


#define PRG            'VIDEOCAP'

#define VER            '1.0'

#define YEAR           '1992'

#define CRLF           0A0Dh // backwords

#define UNINSTALL      '*' // opzione disinstallazione

#define BLANK          32

#define FORMFEED       12

#define _NCOL_         80

#define _MAXROW_       50

#define _BUFDIM_ ((_NCOL_*_MAXROW_)+(2*_MAXROW_)+3) // b*h+b*CRLF+CRLFFF

#define _MONO_V_SEG_   0B000h

#define _COLOR_V_SEG_  0B800h

#define _SHFMASK_      3

#define _TSR_TEST_     0xA1 // videocap e' residente ?

#define _TSR_YES_      0xFF16 // risposta = si, e' residente

#define _FNAMELEN_     81 // lungh. max pathname compreso NULL finale

#define  BADCHARS ';,:|><' // caratteri illeciti nei nomi di file


typedef     void DUMMY;


int pathname(char *path,char *src,char *badchrs);

char far *getInDOSaddr(void);


DUMMY resPSP(DUMMY)



DUMMY inDosFlagPtr(DUMMY)



DUMMY old09h(DUMMY)



DUMMY old16h(DUMMY)



DUMMY old28h(DUMMY)



DUMMY old2Fh(DUMMY)



DUMMY opReq(DUMMY)



DUMMY inOp(DUMMY)



DUMMY rowFactors(DUMMY)        // fattori di offset per pagine video su VGA



DUMMY fileName(DUMMY)



DUMMY bufVid(DUMMY)



#include <io.h>   // definisce dup(int); va incluso DOPO tutte le asm XX dup(Y)


void beep2000Hz(void)



void writebufVid(int rows)



int getOffsetByRow(void)



int setbufVid(void)



void far new09h(void)



void far new16h(void)



void interrupt new28h(void)



void s2Funinstall(void)



void far new2Fh(void)



void releaseEnv(void)



void install(void)



int tsrtest(void)



int filetest(char *fname)



void uninstall(void)



void main(int argc,char **argv)


VIDEOCAP chiama due funzioni delle quali, per brvità, il codice comprende esclusivamente i prototipi: si tratta di pathname(), utilizzata per ricavare il path completo del file fornito come parametro sulla riga di comando, e di getInDOSaddr(), che restituisce l'indirizzo dell'InDOS Flag (pag.  ). I listati completi e commentati delle due funzioni si trovano, rispettivamente, a pag.  e pag. 

Infine, si noti che lo header file IO.H è incluso dopo la definizione di tutte le funzioni fittizie, per evitare che il compilatore interpreti come chiamate alla funzione dup(), in esso dichiarata, le direttive assembly DUP utilizzate per riservare spazio alle variabili globali residenti (vedere pag. 




 Scrivendo la funzione in puro linguaggio C sarebbe stato necessario utilizzare, al minimo, la int86x() e la segread()

Scarica gratis Catturare il contenuto del video
Appunti su:



Scarica 100% gratis e , tesine, riassunti



Registrati ora

Password dimenticata?
  • Appunti superiori
  • In questa sezione troverai sunti esame, dispense, appunti universitari, esercitazioni e tesi, suddivisi per le principali facoltà.
  • Università
  • Appunti, dispense, esercitazioni, riassunti direttamente dalla tua aula Universitaria
  • all'Informatica
  • Introduzione all'Informatica, Information and Comunication Tecnology, componenti del computer, software, hardware ...