<commit_before>#include "DRAWOBJ.H"

#include "SPECIFIC.H"
#include "LIBGPU.H"
#include "EMULATOR.H"
#include "GPU.H"

void MakeMono(unsigned short* s, unsigned char* d)//7F9E4
{
	S_Warn("[MakeMono] - Unimplemented!\n");
}

void InitObjGTE()
{
	S_Warn("[InitObjGTE] - Unimplemented!\n");
}

void DrawClippedMesh(int vertcache, short* mesh, MMTEXTURE* text, char* ot, char* prim, char* prim_lim, long fp, long prim_len, long num_tri)
{
	UNIMPLEMENTED();
}

void DrawSubDivMesh()
{
	UNIMPLEMENTED();
}

void initialise_light_matrix()
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_normal(short* mesh, short clip)
{
	initialise_light_matrix();

	mesh_header* mptr = (mesh_header*)mesh;

#if GLTEST
	Emulator_TestDrawVertices(mesh, RoomTextInfo);
#endif
	UNIMPLEMENTED();
}

void phd_PutPolygons_pickup(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_seethrough(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_train(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons(short* mesh, short clip)
{
	phd_PutPolygons_normal(mesh, clip);
}<commit_msg>Attempt to fix PSXPC_N compile.<commit_after>#include "DRAWOBJ.H"

#include "SPECIFIC.H"
#include "LIBGPU.H"
#include "EMULATOR.H"
#include "GPU.H"

void MakeMono(unsigned short* s, unsigned char* d)//7F9E4, 81A28
{
	//at = 0x421
#if 0
	ctc2    $at, $29
	lw      $t0, 0($a0)
	li      $v0, 0x3FFF
	li      $v1, 0xD371F947
	li      $t4, 0x41C64E6D

	 loc_7FA04:
			 mult    $v1, $t4
				 srl     $t3, $t0, 26
				 srl     $t2, $t0, 21
				 srl     $t1, $t0, 16
				 andi    $t3, 0x1F
				 andi    $t2, 0x1F
				 andi    $t1, 0x1F
				 mtc2    $t3, $17
				 mtc2    $t2, $18
				 mtc2    $t1, $19
				 addi    $a0, 4
				 cop2    0x158002D
				 srl     $t2, $t0, 10
				 srl     $t1, $t0, 5
				 andi    $t2, 0x1F
				 andi    $t1, 0x1F
				 andi    $t0, 0x1F
				 mtc2    $t2, $17
				 mtc2    $t1, $18
				 mtc2    $t0, $19
				 mfc2    $t1, $7
				 cop2    0x158002D
				 mflo    $v1
				 addiu   $v1, 0x3039
				 lw      $t0, 0($a0)
				 mfc2    $at, $7
				 srl     $t3, $v1, 16
				 srl     $t5, $v1, 24
				 andi    $t3, 1
				 andi    $t5, 1
				 sltiu   $t2, $t1, 0xF
				 bnez    $t2, loc_7FA8C
				 sltiu   $t2, $at, 0xF
				 li      $t1, 0xF

				 loc_7FA8C:
			 bnez    $t2, loc_7FA98
				 sub     $t1, $t3
				 li      $at, 0xF

				 loc_7FA98 :
				 bgez    $t1, loc_7FAA4
				 sub     $at, $t5
				 move    $t1, $zero

				 loc_7FAA4 :
			 bgez    $at, loc_7FAB0
				 sll     $t1, 4
				 move    $at, $zero

				 loc_7FAB0 :
			 or $t1, $at
				 sb      $t1, 0($a1)
				 addi    $a1, 1
				 bnez    $v0, loc_7FA04
				 addi    $v0, -1
				 li      $v0, 0xAA
				 ctc2    $v0, $29
				 jr      $ra
				 nop
#endif
	S_Warn("[MakeMono] - Unimplemented!\n");
}

void InitObjGTE()
{
	S_Warn("[InitObjGTE] - Unimplemented!\n");
}

void DrawClippedMesh(int vertcache, short* mesh, MMTEXTURE* text, char* ot, char* prim, char* prim_lim, long fp, long prim_len, long num_tri)
{
	UNIMPLEMENTED();
}

void DrawSubDivMesh()
{
	UNIMPLEMENTED();
}

void initialise_light_matrix()
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_normal(short* mesh, short clip)
{
	initialise_light_matrix();

	mesh_header* mptr = (mesh_header*)mesh;

#if GLTEST
	Emulator_TestDrawVertices(mesh, RoomTextInfo);
#endif
	UNIMPLEMENTED();
}

void phd_PutPolygons_pickup(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_seethrough(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_train(short* mesh, short clip)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons(short* mesh, short clip)
{
	phd_PutPolygons_normal(mesh, clip);
}

void phd_PutPolygons_pickup(short* meshp, long unk)
{
	UNIMPLEMENTED();
}

void phd_PutPolygons_seethrough(short* meshp, long unk)
{
	UNIMPLEMENTED();
}
<|endoftext|>


<commit_before>/*
Demonstration of Modified Nodal Analysis
Originally by Antonio Carlos M. de Queiroz (acmq@coe.ufrj.br)
Modified by Dhiana Deva, Felipe de Leo, Silvino Vieira
*/

/*
Elementos aceitos e linhas do netlist:

Resistor:  R<nome> <no+> <no-> <resistencia>
VCCS:            G<nome> <io+> <io-> <vi+> <vi-> <transcondutancia>
VCVC:            E<nome> <vo+> <vo-> <vi+> <vi-> <ganho de tensao>
CCCS:            F<nome> <io+> <io-> <ii+> <ii-> <ganho de corrente>
CCVS:            H<nome> <vo+> <vo-> <ii+> <ii-> <transresistencia>
Fonte I:     I<nome> <io+> <io-> <corrente>
Fonte V:     V<nome> <vo+> <vo-> <tensao>
Amp. op.:  O<nome> <vo1> <vo2> <vi1> <vi2>

As fontes F e H tem o ramo de entrada em curto
O amplificador operacional ideal tem a saida suspensa
Os nos podem ser nomes
*/

#include "matrix/solve.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdlib>
#include <cmath>

using namespace std;

#define DEBUG

static const int MAX_LINHA = 80;
static const int MAX_NOME = 11;
static const int MAX_ELEM = 50;

typedef struct elemento { /* Elemento do netlist */
    string nome;
    double valor;
    int a,b,c,d,x,y;
} elemento;

/* Rotina que conta os nos e atribui numeros a eles */
int numero(char *nome, int &nv, vector<string> &lista){
    int i=0, achou=0;

    while (!achou && i<=nv)
        if (!(achou=!lista[i].compare(nome))) i++;
    if (!achou) {
        if (nv==MAX_NOS) {
            cout << "O programa so aceita ate " << nv <<  " nos" << endl;
            exit(1);
        }
        nv++;
        lista[nv] = nome;
        return nv; /* novo no */
    }
    else {
        return i; /* no ja conhecido */
    }
}

int main(void)
{
    ifstream arquivo;
    string nomearquivo,
           txt;
    bool arquivovalido = false;
    vector<string> lista(MAX_NOME+2); /*Tem que caber jx antes do nome */
    lista[0] = "0";
    vector<elemento> netlist(MAX_ELEM);

    int ne=0, /* Elementos */
        nv=0, /* Variaveis */
        nn=0; /* Nos */

    /* Foram colocados limites nos formatos de leitura para alguma protecao
       contra excesso de caracteres nestas variaveis */
    char tipo,
         na[MAX_NOME],
         nb[MAX_NOME],
         nc[MAX_NOME],
         nd[MAX_NOME];

    double g,
           Yn[MAX_NOS+1][MAX_NOS+2];

    cout << "Modified Nodal Analysis Demo" << endl;
    cout << "Originally by Antonio Carlos M. de Queiroz (acmq@coe.ufrj.br)" << endl;
    cout << "Modified by Dhiana Deva, Felipe de Leo, Silvino Vieira" << endl;

    /* Leitura do netlist */
    do{
        cout << "Nome do arquivo com o netlist (ex: mna.net): ";
        cin >> nomearquivo;
        arquivo.open(nomearquivo.c_str(), ifstream::in);
        if(!arquivo.is_open()){
            cout << "Arquivo " << nomearquivo << " inexistente" << endl;
            continue;
        }
        arquivovalido = true;
    } while(!arquivovalido);

    cout << "Lendo netlist:" << endl;
    getline(arquivo, txt);
    cout << "Titulo: " << txt;
    while (getline(arquivo, txt)) {
        ne++; /* Nao usa o netlist[0] */
        if (ne>MAX_ELEM) {
            cout << "O programa so aceita ate " << MAX_ELEM << " elementos" << endl;
            exit(1);
        }
        txt[0]=toupper(txt[0]);
        tipo=txt[0];
        //TODO: verificar necessidade da string txt
        // ver se eh possivel usar stringstream no getline
        stringstream txtstream(txt);
        txtstream >> netlist[ne].nome;
        //TODO: talvez nao seja preciso usar p
        string p(txt, netlist[ne].nome.size(), string::npos);
        txtstream.str(p);
        /* O que e lido depende do tipo */
        if (tipo=='R' || tipo=='I' || tipo=='V') {
            txtstream >> na >> nb >> netlist[ne].valor;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << netlist[ne].valor << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
        }
        else if (tipo=='G' || tipo=='E' || tipo=='F' || tipo=='H') {
            txtstream >> na >> nb >> nc >> nd >> netlist[ne].valor;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << nc << " "
                 << nd << " "<< netlist[ne].valor << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
            netlist[ne].c = numero(nc, nv, lista);
            netlist[ne].d = numero(nd, nv, lista);
        }
        else if (tipo=='O') {
            txtstream >> na >> nb >> nc >> nd;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << nc << " " << nd << " " << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
            netlist[ne].c = numero(nc, nv, lista);
            netlist[ne].d = numero(nd, nv, lista);
        }
        else if (tipo=='*') { /* Comentario comeca com "*" */
            cout << "Comentario: " << txt;
            ne--;
        }
        else {
            cout << "Elemento desconhecido: " << txt << endl;
            cin.get();
            exit(1);
        }
    }
    arquivo.close();

    /* Acrescenta variaveis de corrente acima dos nos, anotando no netlist */
    nn=nv;
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='V' || tipo=='E' || tipo=='F' || tipo=='O') {
            nv++;
            if (nv>MAX_NOS) {
                cout << "As correntes extra excederam o numero de variaveis permitido (" << MAX_NOS << ")" << endl;
                exit(1);
            }
            lista[nv] = "j"; /* Tem espaco para mais dois caracteres */
            lista[nv].append( netlist[i].nome );
            netlist[i].x=nv;
        }
        else if (tipo=='H') {
            nv=nv+2;
            if (nv>MAX_NOS) {
                cout << "As correntes extra excederam o numero de variaveis permitido (" << MAX_NOS << ")" << endl;
                exit(1);
            }
            lista[nv-1] = "jx";
            lista[nv-1].append(netlist[i].nome);
            netlist[i].x=nv-1;
            lista[nv] = "jy";
            lista[nv].append( netlist[i].nome );
            netlist[i].y=nv;
        }
    }
    cin.get();
    /* Lista tudo */
    cout << "Variaveis internas: " << endl;
    for (int i=0; i<=nv; i++)
        cout << i << " -> " << lista[i] << endl;
    cin.get();
    cout << "Netlist interno final" << endl;
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='R' || tipo=='I' || tipo=='V') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " " << netlist[i].valor << endl;
        }
        else if (tipo=='G' || tipo=='E' || tipo=='F' || tipo=='H') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " "
                 << netlist[i].c << " " << netlist[i].d   << " " << netlist[i].valor << endl;
        }
        else if (tipo=='O') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " "
                 << netlist[i].c << " " << netlist[i].d   << endl;
        }
        if (tipo=='V' || tipo=='E' || tipo=='F' || tipo=='O')
            cout << "Corrente jx: " << netlist[i].x << endl;
        else if (tipo=='H')
            cout << "Correntes jx e jy: " << netlist[i].x << ", " << netlist[i].y << endl;
    }
    cin.get();
    /* Monta o sistema nodal modificado */
    cout << "O circuito tem " << nn << " nos, " << nv << " variaveis e " << ne << " elementos" << endl;
    cin.get();
    /* Zera sistema */
    for (int i=0; i<=nv; i++) {
        for (int j=0; j<=nv+1; j++)
            Yn[i][j]=0;
    }
    /* Monta estampas */
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='R') {
            g=1/netlist[i].valor;
            Yn[netlist[i].a][netlist[i].a]+=g;
            Yn[netlist[i].b][netlist[i].b]+=g;
            Yn[netlist[i].a][netlist[i].b]-=g;
            Yn[netlist[i].b][netlist[i].a]-=g;
        }
        else if (tipo=='G') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].c]+=g;
            Yn[netlist[i].b][netlist[i].d]+=g;
            Yn[netlist[i].a][netlist[i].d]-=g;
            Yn[netlist[i].b][netlist[i].c]-=g;
        }
        else if (tipo=='I') {
            g=netlist[i].valor;
            Yn[netlist[i].a][nv+1]-=g;
            Yn[netlist[i].b][nv+1]+=g;
        }
        else if (tipo=='V') {
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].a]-=1;
            Yn[netlist[i].x][netlist[i].b]+=1;
            Yn[netlist[i].x][nv+1]-=netlist[i].valor;
        }
        else if (tipo=='E') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].a]-=1;
            Yn[netlist[i].x][netlist[i].b]+=1;
            Yn[netlist[i].x][netlist[i].c]+=g;
            Yn[netlist[i].x][netlist[i].d]-=g;
        }
        else if (tipo=='F') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].x]+=g;
            Yn[netlist[i].b][netlist[i].x]-=g;
            Yn[netlist[i].c][netlist[i].x]+=1;
            Yn[netlist[i].d][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].c]-=1;
            Yn[netlist[i].x][netlist[i].d]+=1;
        }
        else if (tipo=='H') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].y]+=1;
            Yn[netlist[i].b][netlist[i].y]-=1;
            Yn[netlist[i].c][netlist[i].x]+=1;
            Yn[netlist[i].d][netlist[i].x]-=1;
            Yn[netlist[i].y][netlist[i].a]-=1;
            Yn[netlist[i].y][netlist[i].b]+=1;
            Yn[netlist[i].x][netlist[i].c]-=1;
            Yn[netlist[i].x][netlist[i].d]+=1;
            Yn[netlist[i].y][netlist[i].x]+=g;
        }
        else if (tipo=='O') {
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].c]+=1;
            Yn[netlist[i].x][netlist[i].d]-=1;
        }
#ifdef DEBUG
        /* Opcional: Mostra o sistema apos a montagem da estampa */
        cout << "Sistema apos a estampa de " << netlist[i].nome << endl;
        for (int k=1; k<=nv; k++) {
            for (int j=1; j<=nv+1; j++)
                if (Yn[k][j]!=0){
                    cout << setprecision( 1 ) << fixed << setw( 3 ) << showpos;
                    cout << Yn[k][j] << " ";
                }
                else cout << " ... ";
            cout << endl;
        }
        cin.get();
#endif
    }
    /* Resolve o sistema */
    if (solve(nv, Yn)) {
        cin.get();
        exit(0);
    }
#ifdef DEBUG
    /* Opcional: Mostra o sistema resolvido */
    cout << "Sistema resolvido:" << endl;
    for (int i=1; i<=nv; i++) {
        for (int j=1; j<=nv+1; j++)
            if (Yn[i][j]!=0){
                cout << setprecision( 1 ) << fixed << setw( 3 ) << showpos;
                cout << Yn[i][j] << " ";
            }
            else cout << " ... ";
        cout << endl;
    }
    cin.get();
#endif
    /* Mostra solucao */
    cout << "Solucao:" << endl;
    txt = "Tensao";
    for (int i=1; i<=nv; i++) {
        if (i==nn+1)
            txt = "Corrente";
        cout << txt << " " << lista[i] << ": " << Yn[i][nv+1] << endl;
    }
    cin.get();
}

<commit_msg>Qualifies numero as inline (and nome as const)<commit_after>/*
Demonstration of Modified Nodal Analysis
Originally by Antonio Carlos M. de Queiroz (acmq@coe.ufrj.br)
Modified by Dhiana Deva, Felipe de Leo, Silvino Vieira
*/

/*
Elementos aceitos e linhas do netlist:

Resistor:  R<nome> <no+> <no-> <resistencia>
VCCS:            G<nome> <io+> <io-> <vi+> <vi-> <transcondutancia>
VCVC:            E<nome> <vo+> <vo-> <vi+> <vi-> <ganho de tensao>
CCCS:            F<nome> <io+> <io-> <ii+> <ii-> <ganho de corrente>
CCVS:            H<nome> <vo+> <vo-> <ii+> <ii-> <transresistencia>
Fonte I:     I<nome> <io+> <io-> <corrente>
Fonte V:     V<nome> <vo+> <vo-> <tensao>
Amp. op.:  O<nome> <vo1> <vo2> <vi1> <vi2>

As fontes F e H tem o ramo de entrada em curto
O amplificador operacional ideal tem a saida suspensa
Os nos podem ser nomes
*/

#include "matrix/solve.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdlib>
#include <cmath>

using namespace std;

#define DEBUG

static const int MAX_LINHA = 80;
static const int MAX_NOME = 11;
static const int MAX_ELEM = 50;

typedef struct elemento { /* Elemento do netlist */
    string nome;
    double valor;
    int a,b,c,d,x,y;
} elemento;

/* Rotina que conta os nos e atribui numeros a eles */
inline int numero(const char *nome, int &nv, vector<string> &lista){
    int i=0, achou=0;

    while (!achou && i<=nv)
        if (!(achou=!lista[i].compare(nome))) i++;
    if (!achou) {
        if (nv==MAX_NOS) {
            cout << "O programa so aceita ate " << nv <<  " nos" << endl;
            exit(1);
        }
        nv++;
        lista[nv] = nome;
        return nv; /* novo no */
    }
    else {
        return i; /* no ja conhecido */
    }
}

int main(void)
{
    ifstream arquivo;
    string nomearquivo,
           txt;
    bool arquivovalido = false;
    vector<string> lista(MAX_NOME+2); /*Tem que caber jx antes do nome */
    lista[0] = "0";
    vector<elemento> netlist(MAX_ELEM);

    int ne=0, /* Elementos */
        nv=0, /* Variaveis */
        nn=0; /* Nos */

    /* Foram colocados limites nos formatos de leitura para alguma protecao
       contra excesso de caracteres nestas variaveis */
    char tipo,
         na[MAX_NOME],
         nb[MAX_NOME],
         nc[MAX_NOME],
         nd[MAX_NOME];

    double g,
           Yn[MAX_NOS+1][MAX_NOS+2];

    cout << "Modified Nodal Analysis Demo" << endl;
    cout << "Originally by Antonio Carlos M. de Queiroz (acmq@coe.ufrj.br)" << endl;
    cout << "Modified by Dhiana Deva, Felipe de Leo, Silvino Vieira" << endl;

    /* Leitura do netlist */
    do{
        cout << "Nome do arquivo com o netlist (ex: mna.net): ";
        cin >> nomearquivo;
        arquivo.open(nomearquivo.c_str(), ifstream::in);
        if(!arquivo.is_open()){
            cout << "Arquivo " << nomearquivo << " inexistente" << endl;
            continue;
        }
        arquivovalido = true;
    } while(!arquivovalido);

    cout << "Lendo netlist:" << endl;
    getline(arquivo, txt);
    cout << "Titulo: " << txt;
    while (getline(arquivo, txt)) {
        ne++; /* Nao usa o netlist[0] */
        if (ne>MAX_ELEM) {
            cout << "O programa so aceita ate " << MAX_ELEM << " elementos" << endl;
            exit(1);
        }
        txt[0]=toupper(txt[0]);
        tipo=txt[0];
        //TODO: verificar necessidade da string txt
        // ver se eh possivel usar stringstream no getline
        stringstream txtstream(txt);
        txtstream >> netlist[ne].nome;
        //TODO: talvez nao seja preciso usar p
        string p(txt, netlist[ne].nome.size(), string::npos);
        txtstream.str(p);
        /* O que e lido depende do tipo */
        if (tipo=='R' || tipo=='I' || tipo=='V') {
            txtstream >> na >> nb >> netlist[ne].valor;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << netlist[ne].valor << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
        }
        else if (tipo=='G' || tipo=='E' || tipo=='F' || tipo=='H') {
            txtstream >> na >> nb >> nc >> nd >> netlist[ne].valor;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << nc << " "
                 << nd << " "<< netlist[ne].valor << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
            netlist[ne].c = numero(nc, nv, lista);
            netlist[ne].d = numero(nd, nv, lista);
        }
        else if (tipo=='O') {
            txtstream >> na >> nb >> nc >> nd;
            cout << netlist[ne].nome << " " << na << " " << nb << " " << nc << " " << nd << " " << endl;
            netlist[ne].a = numero(na, nv, lista);
            netlist[ne].b = numero(nb, nv, lista);
            netlist[ne].c = numero(nc, nv, lista);
            netlist[ne].d = numero(nd, nv, lista);
        }
        else if (tipo=='*') { /* Comentario comeca com "*" */
            cout << "Comentario: " << txt;
            ne--;
        }
        else {
            cout << "Elemento desconhecido: " << txt << endl;
            cin.get();
            exit(1);
        }
    }
    arquivo.close();

    /* Acrescenta variaveis de corrente acima dos nos, anotando no netlist */
    nn=nv;
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='V' || tipo=='E' || tipo=='F' || tipo=='O') {
            nv++;
            if (nv>MAX_NOS) {
                cout << "As correntes extra excederam o numero de variaveis permitido (" << MAX_NOS << ")" << endl;
                exit(1);
            }
            lista[nv] = "j"; /* Tem espaco para mais dois caracteres */
            lista[nv].append( netlist[i].nome );
            netlist[i].x=nv;
        }
        else if (tipo=='H') {
            nv=nv+2;
            if (nv>MAX_NOS) {
                cout << "As correntes extra excederam o numero de variaveis permitido (" << MAX_NOS << ")" << endl;
                exit(1);
            }
            lista[nv-1] = "jx";
            lista[nv-1].append(netlist[i].nome);
            netlist[i].x=nv-1;
            lista[nv] = "jy";
            lista[nv].append( netlist[i].nome );
            netlist[i].y=nv;
        }
    }
    cin.get();
    /* Lista tudo */
    cout << "Variaveis internas: " << endl;
    for (int i=0; i<=nv; i++)
        cout << i << " -> " << lista[i] << endl;
    cin.get();
    cout << "Netlist interno final" << endl;
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='R' || tipo=='I' || tipo=='V') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " " << netlist[i].valor << endl;
        }
        else if (tipo=='G' || tipo=='E' || tipo=='F' || tipo=='H') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " "
                 << netlist[i].c << " " << netlist[i].d   << " " << netlist[i].valor << endl;
        }
        else if (tipo=='O') {
            cout << netlist[i].nome << " " << netlist[i].a << " " << netlist[i].b << " "
                 << netlist[i].c << " " << netlist[i].d   << endl;
        }
        if (tipo=='V' || tipo=='E' || tipo=='F' || tipo=='O')
            cout << "Corrente jx: " << netlist[i].x << endl;
        else if (tipo=='H')
            cout << "Correntes jx e jy: " << netlist[i].x << ", " << netlist[i].y << endl;
    }
    cin.get();
    /* Monta o sistema nodal modificado */
    cout << "O circuito tem " << nn << " nos, " << nv << " variaveis e " << ne << " elementos" << endl;
    cin.get();
    /* Zera sistema */
    for (int i=0; i<=nv; i++) {
        for (int j=0; j<=nv+1; j++)
            Yn[i][j]=0;
    }
    /* Monta estampas */
    for (int i=1; i<=ne; i++) {
        tipo=netlist[i].nome[0];
        if (tipo=='R') {
            g=1/netlist[i].valor;
            Yn[netlist[i].a][netlist[i].a]+=g;
            Yn[netlist[i].b][netlist[i].b]+=g;
            Yn[netlist[i].a][netlist[i].b]-=g;
            Yn[netlist[i].b][netlist[i].a]-=g;
        }
        else if (tipo=='G') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].c]+=g;
            Yn[netlist[i].b][netlist[i].d]+=g;
            Yn[netlist[i].a][netlist[i].d]-=g;
            Yn[netlist[i].b][netlist[i].c]-=g;
        }
        else if (tipo=='I') {
            g=netlist[i].valor;
            Yn[netlist[i].a][nv+1]-=g;
            Yn[netlist[i].b][nv+1]+=g;
        }
        else if (tipo=='V') {
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].a]-=1;
            Yn[netlist[i].x][netlist[i].b]+=1;
            Yn[netlist[i].x][nv+1]-=netlist[i].valor;
        }
        else if (tipo=='E') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].a]-=1;
            Yn[netlist[i].x][netlist[i].b]+=1;
            Yn[netlist[i].x][netlist[i].c]+=g;
            Yn[netlist[i].x][netlist[i].d]-=g;
        }
        else if (tipo=='F') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].x]+=g;
            Yn[netlist[i].b][netlist[i].x]-=g;
            Yn[netlist[i].c][netlist[i].x]+=1;
            Yn[netlist[i].d][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].c]-=1;
            Yn[netlist[i].x][netlist[i].d]+=1;
        }
        else if (tipo=='H') {
            g=netlist[i].valor;
            Yn[netlist[i].a][netlist[i].y]+=1;
            Yn[netlist[i].b][netlist[i].y]-=1;
            Yn[netlist[i].c][netlist[i].x]+=1;
            Yn[netlist[i].d][netlist[i].x]-=1;
            Yn[netlist[i].y][netlist[i].a]-=1;
            Yn[netlist[i].y][netlist[i].b]+=1;
            Yn[netlist[i].x][netlist[i].c]-=1;
            Yn[netlist[i].x][netlist[i].d]+=1;
            Yn[netlist[i].y][netlist[i].x]+=g;
        }
        else if (tipo=='O') {
            Yn[netlist[i].a][netlist[i].x]+=1;
            Yn[netlist[i].b][netlist[i].x]-=1;
            Yn[netlist[i].x][netlist[i].c]+=1;
            Yn[netlist[i].x][netlist[i].d]-=1;
        }
#ifdef DEBUG
        /* Opcional: Mostra o sistema apos a montagem da estampa */
        cout << "Sistema apos a estampa de " << netlist[i].nome << endl;
        for (int k=1; k<=nv; k++) {
            for (int j=1; j<=nv+1; j++)
                if (Yn[k][j]!=0){
                    cout << setprecision( 1 ) << fixed << setw( 3 ) << showpos;
                    cout << Yn[k][j] << " ";
                }
                else cout << " ... ";
            cout << endl;
        }
        cin.get();
#endif
    }
    /* Resolve o sistema */
    if (solve(nv, Yn)) {
        cin.get();
        exit(0);
    }
#ifdef DEBUG
    /* Opcional: Mostra o sistema resolvido */
    cout << "Sistema resolvido:" << endl;
    for (int i=1; i<=nv; i++) {
        for (int j=1; j<=nv+1; j++)
            if (Yn[i][j]!=0){
                cout << setprecision( 1 ) << fixed << setw( 3 ) << showpos;
                cout << Yn[i][j] << " ";
            }
            else cout << " ... ";
        cout << endl;
    }
    cin.get();
#endif
    /* Mostra solucao */
    cout << "Solucao:" << endl;
    txt = "Tensao";
    for (int i=1; i<=nv; i++) {
        if (i==nn+1)
            txt = "Corrente";
        cout << txt << " " << lista[i] << ": " << Yn[i][nv+1] << endl;
    }
    cin.get();
}

<|endoftext|>


<commit_before>#include "Flocking.h"
#include <cmath>

/**************************************************************************************************************/

/*Constructs the flocking object*/
JAM_Flocking::JAM_Flocking(int numberOfBoids, JAM_Texture* texture, int xBoundary, int yBoundary, float maxVel, int screenHeight)
{
	/*initialize random seed*/
	srand((unsigned int)time(NULL));

	/*initialise the size of the screen height*/
	this->screenHeight = screenHeight;

	/*initialise a the number of Boid objects*/
	for (int i = 0; i < numberOfBoids; i++)
	{
		/*creates a Boid at a random position on the screen*/
		boids.push_back(new JAM_Particle(texture, JAM_Utilities::scaleNumber(4.0f, screenHeight), JAM_Vec2(0.0f, 0.0f), maxVel,
			JAM_Vec2((float)(rand() % xBoundary), (float)(rand() % yBoundary))));
	}

	/*initialise the boundaries*/
	this->xBoundary = xBoundary;
	this->yBoundary = yBoundary;

	/*initialise all of the rules to be on*/
	applyRule1 = applyRule2 = applyRule3 = 1;

	/*initialise the max velocity*/
	this->maxVel = maxVel;
}

/**************************************************************************************************************/

/*Destructs the flocking object*/
JAM_Flocking::~JAM_Flocking()
{
	/*delete pointers*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		delete boids[i];
	}
}

/**************************************************************************************************************/

/*updates the flocking*/
void JAM_Flocking::update(float dt)
{
	/*initialise the resultant velocities*/
	JAM_Vec2 v1 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v2 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v3 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v4 = JAM_Vec2( 0.0f, 0.0f );

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*test rule 1 and apply activity*/
		v1 = (rule1(i) * (float)applyRule1);
		/*test rule 2 and apply activity*/
		v2 = (rule2(i) * (float)applyRule2);
		/*test rule 3 and apply activity*/
		v3 = (rule3(i) * (float)applyRule3);

		/*apply boundaries*/
		v4 = roughBoundaries(i);

		/*update the Boid velocity*/
		boids[i]->setDirection(boids[i]->getDirection() + v1 + v2 + v3 + v4);
		/*limit the velocity of the Boid*/
		limitVelocity(i);
		/*update the Boid position*/
		boids[i]->setPosition(boids[i]->getPosition() + boids[i]->getDirection());
	}
}

/**************************************************************************************************************/

/*draws the game*/
void JAM_Flocking::draw(SDL_Renderer* renderer)
{
	/*display the Boid objects*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*display the Boid*/
		boids[i]->draw(renderer);
	}
}

/**************************************************************************************************************/

/*applies Boid rule 1*/
JAM_Vec2 JAM_Flocking::rule1(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);
	/*initialise the center of mass*/
	JAM_Vec2 cOfM = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*update the center of mass*/
			cOfM = boids[i]->getPosition() + cOfM;
		}
	}

	/*divide the center of mass by the number of Boid objects tested*/
	cOfM = cOfM / (float)(boids.size() - 2);

	/*set the new velocity to the amount to move towards the Boid (1% of the distance in this case)*/
	vel = (cOfM - boids[boidIndex]->getPosition()) / 100;

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rule 2*/
JAM_Vec2 JAM_Flocking::rule2(int boidIndex)
{
	/*the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*if the Boid is closer than 10 pixels to another Boid on the x axis (using absolute values)*/
			if (std::abs(boids[boidIndex]->getPosition().x - boids[i]->getPosition().x) < 10)
			{
				vel.x = vel.x - (boids[i]->getPosition().x - boids[boidIndex]->getPosition().x);
			}

			/*if the Boid is closer than 10 pixels to another Boid on the y axis (using absolute values)*/
			if (std::abs(boids[boidIndex]->getPosition().y - boids[i]->getPosition().y) < 10)
			{
				vel.y = vel.y - (boids[i]->getPosition().y - boids[boidIndex]->getPosition().y);
			}
		}
	}

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rule 3*/
JAM_Vec2 JAM_Flocking::rule3(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*add all of the Boid velocities together*/
			vel = vel + boids[i]->getDirection();
		}
	}

	/*get the average velocity*/
	vel = vel / (float)(boids.size() - 2);

	/*set it to about an eighth of the Boid velocity*/
	vel = (vel - boids[boidIndex]->getDirection()) / 8;

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rough boundaries*/
JAM_Vec2 JAM_Flocking::roughBoundaries(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*check if the Boid is off the right of the screen*/
	if (boids[boidIndex]->getPosition().x > xBoundary)
	{
		/*set a negative x velocity*/
		vel.x = -10.0f;
	}
	/*check if the Boid is off the right of the screen*/
	else if (boids[boidIndex]->getPosition().x < 0)
	{
		/*set a positive x velocity*/
		vel.x = 10.0f;
	}

	/*check if the Boid is off the bottom of the screen*/
	if (boids[boidIndex]->getPosition().y > yBoundary)
	{
		/*set a negative y velocity*/
		vel.y = -10.0f;
	}
	/*check if the Boid is off the top of the screen*/
	else if (boids[boidIndex]->getPosition().y < 0)
	{
		/*set a positive y velocity*/
		vel.y = 10.0f;
	}

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*limit the velocity of the Boid*/
void JAM_Flocking::limitVelocity(int boidIndex)
{
	/*test if the absolute of the x velocity is greater than the max velocity*/
	if (std::abs(boids[boidIndex]->getDirection().x) > maxVel)
	{
		/*work out if negative or positive*/
		float sign = boids[boidIndex]->getDirection().x / std::abs(boids[boidIndex]->getDirection().x);
		/*set the x velocity to the max velocity*/
		boids[boidIndex]->setDirection(JAM_Vec2(maxVel * sign, boids[boidIndex]->getDirection().y));
	}

	/*test if the absolute of the y velocity is greater than the max velocity*/
	if (std::abs(boids[boidIndex]->getDirection().y) > maxVel)
	{
		/*work out if negative or positive*/
		float sign = boids[boidIndex]->getDirection().y / std::abs(boids[boidIndex]->getDirection().y);
		/*set the y velocity to the max velocity*/
		boids[boidIndex]->setDirection(JAM_Vec2(boids[boidIndex]->getDirection().x, maxVel * sign));
	}
}

/**************************************************************************************************************/

/*Set applyRule1.*/
void JAM_Flocking::setRule1(int applyRule1)
{
	/*set the rule*/
	this->applyRule1 = applyRule1;
}

/**************************************************************************************************************/

/*Set applyRule2.*/
void JAM_Flocking::setRule2(int applyRule2)
{
	/*set the rule*/
	this->applyRule2 = applyRule2;
}

/**************************************************************************************************************/

/*Set applyRule3.*/
void JAM_Flocking::setRule3(int applyRule3)
{
	/*set the rule*/
	this->applyRule3 = applyRule3;
}<commit_msg>Updated Flocking.cpp<commit_after>#include "Flocking.h"
#include <cmath>

/**************************************************************************************************************/

/*Constructs the flocking object*/
JAM_Flocking::JAM_Flocking(int numberOfBoids, JAM_Texture* texture, int xBoundary, int yBoundary, float maxVel, int screenHeight)
{
	/*initialize random seed*/
	srand((unsigned int)time(NULL));

	/*initialise the size of the screen height*/
	this->screenHeight = screenHeight;

	/*initialise a the number of Boid objects*/
	for (int i = 0; i < numberOfBoids; i++)
	{
		/*creates a Boid at a random position on the screen*/
		boids.push_back(new JAM_Particle(texture, JAM_Utilities::scaleNumber(4.0f, screenHeight), JAM_Vec2(0.0f, 0.0f), maxVel,
			JAM_Vec2((float)(rand() % xBoundary), (float)(rand() % yBoundary))));
	}

	/*initialise the boundaries*/
	this->xBoundary = xBoundary;
	this->yBoundary = yBoundary;

	/*initialise all of the rules to be on*/
	applyRule1 = applyRule2 = applyRule3 = 1;

	/*initialise the max velocity*/
	this->maxVel = maxVel;
}

/**************************************************************************************************************/

/*Destructs the flocking object*/
JAM_Flocking::~JAM_Flocking()
{
	/*delete pointers*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		delete boids[i];
	}
}

/**************************************************************************************************************/

/*updates the flocking*/
void JAM_Flocking::update(float dt)
{
	/*initialise the resultant velocities*/
	JAM_Vec2 v1 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v2 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v3 = JAM_Vec2( 0.0f, 0.0f );
	JAM_Vec2 v4 = JAM_Vec2( 0.0f, 0.0f );

	/*The speed increase of the boids*/
	float speed = 25.0f;

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*test rule 1 and apply activity*/
		v1 = (rule1(i) * (float)applyRule1);
		/*test rule 2 and apply activity*/
		v2 = (rule2(i) * (float)applyRule2);
		/*test rule 3 and apply activity*/
		v3 = (rule3(i) * (float)applyRule3);

		/*apply boundaries*/
		v4 = roughBoundaries(i);

		/*update the Boid velocity*/
		boids[i]->setDirection(boids[i]->getDirection() + v1 + v2 + v3 + v4);
		/*limit the velocity of the Boid*/
		limitVelocity(i);
		/*update the Boid position*/
		boids[i]->setPosition(boids[i]->getPosition() + (boids[i]->getDirection() * dt) * speed);
	}
}

/**************************************************************************************************************/

/*draws the game*/
void JAM_Flocking::draw(SDL_Renderer* renderer)
{
	/*display the Boid objects*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*display the Boid*/
		boids[i]->draw(renderer);
	}
}

/**************************************************************************************************************/

/*applies Boid rule 1 (cohesion)*/
JAM_Vec2 JAM_Flocking::rule1(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);
	/*initialise the center of mass*/
	JAM_Vec2 cOfM = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*update the center of mass*/
			cOfM = boids[i]->getPosition() + cOfM;
		}
	}

	/*divide the center of mass by the number of Boid objects tested*/
	cOfM = cOfM / (float)(boids.size() - 1);

	/*set the new velocity to the amount to move towards the Boid (1% of the distance in this case)*/
	vel = (cOfM - boids[boidIndex]->getPosition()) / 100;

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rule 2 (speration)*/
JAM_Vec2 JAM_Flocking::rule2(int boidIndex)
{
	/*the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*if the Boid is closer than 10 pixels to another Boid on the x axis (using absolute values)*/
			if (std::abs(boids[boidIndex]->getPosition().x - boids[i]->getPosition().x) < 10)
			{
				vel.x = vel.x - (boids[i]->getPosition().x - boids[boidIndex]->getPosition().x);
			}

			/*if the Boid is closer than 10 pixels to another Boid on the y axis (using absolute values)*/
			if (std::abs(boids[boidIndex]->getPosition().y - boids[i]->getPosition().y) < 10)
			{
				vel.y = vel.y - (boids[i]->getPosition().y - boids[boidIndex]->getPosition().y);
			}
		}
	}

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rule 3 (alignment)*/
JAM_Vec2 JAM_Flocking::rule3(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*test each Boid*/
	for (unsigned int i = 0; i < boids.size(); i++)
	{
		/*if the Boid to be tested is not the inputed Boid*/
		if (i != (unsigned int)boidIndex)
		{
			/*add all of the Boid velocities together*/
			vel = vel + boids[i]->getDirection();
		}
	}

	/*get the average velocity*/
	vel = vel / (float)(boids.size() - 1);

	/*set it to about an eighth of the Boid velocity*/
	vel = (vel - boids[boidIndex]->getDirection()) / 8;

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*applies Boid rough boundaries*/
JAM_Vec2 JAM_Flocking::roughBoundaries(int boidIndex)
{
	/*initialise the new velocity*/
	JAM_Vec2 vel = JAM_Vec2(0.0f, 0.0f);

	/*check if the Boid is off the right of the screen*/
	if (boids[boidIndex]->getPosition().x > xBoundary)
	{
		/*set a negative x velocity*/
		vel.x = -10.0f;
	}
	/*check if the Boid is off the right of the screen*/
	else if (boids[boidIndex]->getPosition().x < 0)
	{
		/*set a positive x velocity*/
		vel.x = 10.0f;
	}

	/*check if the Boid is off the bottom of the screen*/
	if (boids[boidIndex]->getPosition().y > yBoundary)
	{
		/*set a negative y velocity*/
		vel.y = -10.0f;
	}
	/*check if the Boid is off the top of the screen*/
	else if (boids[boidIndex]->getPosition().y < 0)
	{
		/*set a positive y velocity*/
		vel.y = 10.0f;
	}

	/*return the new velocity*/
	return vel;
}

/**************************************************************************************************************/

/*limit the velocity of the Boid*/
void JAM_Flocking::limitVelocity(int boidIndex)
{
	/*test if the absolute of the x velocity is greater than the max velocity*/
	if (std::abs(boids[boidIndex]->getDirection().x) > maxVel)
	{
		/*work out if negative or positive*/
		float sign = boids[boidIndex]->getDirection().x / std::abs(boids[boidIndex]->getDirection().x);
		/*set the x velocity to the max velocity*/
		boids[boidIndex]->setDirection(JAM_Vec2(maxVel * sign, boids[boidIndex]->getDirection().y));
	}

	/*test if the absolute of the y velocity is greater than the max velocity*/
	if (std::abs(boids[boidIndex]->getDirection().y) > maxVel)
	{
		/*work out if negative or positive*/
		float sign = boids[boidIndex]->getDirection().y / std::abs(boids[boidIndex]->getDirection().y);
		/*set the y velocity to the max velocity*/
		boids[boidIndex]->setDirection(JAM_Vec2(boids[boidIndex]->getDirection().x, maxVel * sign));
	}
}

/**************************************************************************************************************/

/*Set applyRule1.*/
void JAM_Flocking::setRule1(int applyRule1)
{
	/*set the rule*/
	this->applyRule1 = applyRule1;
}

/**************************************************************************************************************/

/*Set applyRule2.*/
void JAM_Flocking::setRule2(int applyRule2)
{
	/*set the rule*/
	this->applyRule2 = applyRule2;
}

/**************************************************************************************************************/

/*Set applyRule3.*/
void JAM_Flocking::setRule3(int applyRule3)
{
	/*set the rule*/
	this->applyRule3 = applyRule3;
}<|endoftext|>


<commit_before>#include "LIBSPU.H"
#include "LIBETC.H"
#include <stdio.h>
#include "EMULATOR.H"
#include "LIBAPI.H"

#include <string.h>

#define SPU_CENTERNOTE (49152)

short _spu_voice_centerNote[24] =
{
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE
};

SpuCommonAttr dword_424;//Might be wrong struct, need to check
int _spu_isCalled = 0;
int _spu_FiDMA = 0;///@TODO decl as extern find initial value
int _spu_EVdma = 0;
int _spu_rev_flag = 0;
int _spu_rev_reserve_wa = 0;
int _spu_rev_offsetaddr = 0;
int _spu_rev_startaddr = 0;
int _spu_AllocBlockNum = 0;
int _spu_AllocLastNum = 0;
int _spu_memList = 0;
int _spu_trans_mode = 0;
int _spu_transMode = 0;
int _spu_keystat = 0;
int _spu_RQmask = 0;
int _spu_RQvoice = 0;
int _spu_env = 0;

unsigned long SpuWrite(unsigned char * addr, unsigned long size)
{
	//eprintf("SPU WRITE size=%d\n", size);
	//memcpy(spu_buf, addr, size);
	//spu_b_size = size;
	UNIMPLEMENTED();
	return 0;
}

long SpuSetTransferMode(long mode)
{
	long mode_fix = mode == 0 ? 0 : 1;

	//trans_mode = mode;
	//transMode = mode_fix;

	return mode_fix;
}

unsigned long SpuSetTransferStartAddr(unsigned long addr)
{
	UNIMPLEMENTED();
	return 0;
}

long SpuIsTransferCompleted(long flag)
{
	UNIMPLEMENTED();
	return 0;
}

void _SpuDataCallback(int a0)
{
	UNIMPLEMENTED();
}

void SpuStart()//(F)
{
	long event = 0;

	if (_spu_isCalled == 0)
	{
		_spu_isCalled = 1;
		EnterCriticalSection();
		_SpuDataCallback(_spu_FiDMA);
		event = OpenEvent(HwSPU, EvSpCOMP, EvMdNOINTR, NULL);
		_spu_EVdma = event;
		EnableEvent(event);
		ExitCriticalSection();
	}
	//loc_348
}

void _spu_init(int a0)
{
	UNIMPLEMENTED();
}

void _SpuInit(int a0)
{
	ResetCallback();
	_spu_init(a0);

	//s0 = a0
	if (a0 == 0)
	{
		for (int i = 0; i < sizeof(_spu_voice_centerNote) / sizeof(short); i++)
		{
			_spu_voice_centerNote[i] = SPU_CENTERNOTE;
		}
	}
	//loc_240
	SpuStart();

	_spu_rev_flag = 0;
	_spu_rev_reserve_wa = 0;
	dword_424.mask = 0;
	dword_424.mvol.left = 0;
	dword_424.mvol.right = 0;
	dword_424.mvolmode.left = 0;
	dword_424.mvolmode.right = 0;
	dword_424.mvolx.left = 0;
	dword_424.mvolx.right = 0;
	_spu_rev_offsetaddr = _spu_rev_startaddr;
	//_spu_FsetRXX(209, _spu_rev_startaddr, 0);
	_spu_AllocBlockNum = 0;
	_spu_AllocLastNum = 0;
	_spu_memList = 0;
	_spu_trans_mode = 0;
	_spu_transMode = 0;
	_spu_keystat = 0;
	_spu_RQmask = 0;
	_spu_RQvoice = 0;
	_spu_env = 0;
}

void SpuInit(void)
{
	_SpuInit(0);
}

long SpuSetReverb(long on_off)
{
	UNIMPLEMENTED();
	return 0;
}

unsigned long SpuSetReverbVoice(long on_off, unsigned long voice_bit)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetCommonAttr(SpuCommonAttr * attr)
{
	UNIMPLEMENTED();
}

long SpuInitMalloc(long num, char * top)
{
	if (num > 0)
	{
		///memList = top;
		//AllocLastNum = 0;
		//AllocBlockNum = num;
		//*((int*)memList) = mem_mode_plus = 0x4000 | 0x1010;
		//*((int*)memList + 1) = 0x4000;
	}

	return num;
}

long SpuMalloc(long size)
{
	return 0/*(long)(uintptr_t)malloc(size)*/;
}

long SpuMallocWithStartAddr(unsigned long addr, long size)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuFree(unsigned long addr)
{
	/*free((void*)(uintptr_t)addr)*/;
}

void SpuSetCommonMasterVolume(short mvol_left, short mvol_right)// (F)
{
	//MasterVolume.VolumeLeft.Raw = mvol_left;
	//MasterVolume.VolumeRight.Raw = mvol_right;
}

long SpuSetReverbModeType(long mode)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetReverbModeDepth(short depth_left, short depth_right)
{
	UNIMPLEMENTED();
}
<commit_msg>[Emu]: Implement _spu_FsetRXX.<commit_after>#include "LIBSPU.H"
#include "LIBETC.H"
#include <stdio.h>
#include "EMULATOR.H"
#include "LIBAPI.H"

#include <string.h>

#define SPU_CENTERNOTE (49152)

short _spu_voice_centerNote[24] =
{
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE
};

SpuCommonAttr dword_424;//Might be wrong struct, need to check
int _spu_isCalled = 0;
int _spu_FiDMA = 0;///@TODO decl as extern find initial value
int _spu_EVdma = 0;
int _spu_rev_flag = 0;
int _spu_rev_reserve_wa = 0;
int _spu_rev_offsetaddr = 0;
int _spu_rev_startaddr = 0;
int _spu_AllocBlockNum = 0;
int _spu_AllocLastNum = 0;
int _spu_memList = 0;
int _spu_trans_mode = 0;
int _spu_transMode = 0;
int _spu_keystat = 0;
int _spu_RQmask = 0;
int _spu_RQvoice = 0;
int _spu_env = 0;
short* _spu_RXX = (short*)0x1F801C00;
int _spu_mem_mode_plus = 3;

unsigned long SpuWrite(unsigned char * addr, unsigned long size)
{
	//eprintf("SPU WRITE size=%d\n", size);
	//memcpy(spu_buf, addr, size);
	//spu_b_size = size;
	UNIMPLEMENTED();
	return 0;
}

long SpuSetTransferMode(long mode)
{
	long mode_fix = mode == 0 ? 0 : 1;

	//trans_mode = mode;
	//transMode = mode_fix;

	return mode_fix;
}

unsigned long SpuSetTransferStartAddr(unsigned long addr)
{
	UNIMPLEMENTED();
	return 0;
}

long SpuIsTransferCompleted(long flag)
{
	UNIMPLEMENTED();
	return 0;
}

void _SpuDataCallback(int a0)
{
	UNIMPLEMENTED();
}

void SpuStart()//(F)
{
	long event = 0;

	if (_spu_isCalled == 0)
	{
		_spu_isCalled = 1;
		EnterCriticalSection();
		_SpuDataCallback(_spu_FiDMA);
		event = OpenEvent(HwSPU, EvSpCOMP, EvMdNOINTR, NULL);
		_spu_EVdma = event;
		EnableEvent(event);
		ExitCriticalSection();
	}
	//loc_348
}

void _spu_init(int a0)
{
	UNIMPLEMENTED();
}

void _spu_FsetRXX(int a0, int a1, int a2)//(F)
{
	if (a2 == 0)
	{
		_spu_RXX[a0] = a1;
	}
	else
	{
		_spu_RXX[a0] = a1 >> _spu_mem_mode_plus;
	}
}

void _SpuInit(int a0)
{
	ResetCallback();
	_spu_init(a0);

	//s0 = a0
	if (a0 == 0)
	{
		for (int i = 0; i < sizeof(_spu_voice_centerNote) / sizeof(short); i++)
		{
			_spu_voice_centerNote[i] = SPU_CENTERNOTE;
		}
	}
	//loc_240
	SpuStart();

	_spu_rev_flag = 0;
	_spu_rev_reserve_wa = 0;
	dword_424.mask = 0;
	dword_424.mvol.left = 0;
	dword_424.mvol.right = 0;
	dword_424.mvolmode.left = 0;
	dword_424.mvolmode.right = 0;
	dword_424.mvolx.left = 0;
	dword_424.mvolx.right = 0;
	_spu_rev_offsetaddr = _spu_rev_startaddr;
	_spu_FsetRXX(209, _spu_rev_startaddr, 0);
	_spu_AllocBlockNum = 0;
	_spu_AllocLastNum = 0;
	_spu_memList = 0;
	_spu_trans_mode = 0;
	_spu_transMode = 0;
	_spu_keystat = 0;
	_spu_RQmask = 0;
	_spu_RQvoice = 0;
	_spu_env = 0;
}

void SpuInit(void)
{
	_SpuInit(0);
}

long SpuSetReverb(long on_off)
{
	UNIMPLEMENTED();
	return 0;
}

unsigned long SpuSetReverbVoice(long on_off, unsigned long voice_bit)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetCommonAttr(SpuCommonAttr * attr)
{
	UNIMPLEMENTED();
}

long SpuInitMalloc(long num, char * top)
{
	if (num > 0)
	{
		///memList = top;
		//AllocLastNum = 0;
		//AllocBlockNum = num;
		//*((int*)memList) = mem_mode_plus = 0x4000 | 0x1010;
		//*((int*)memList + 1) = 0x4000;
	}

	return num;
}

long SpuMalloc(long size)
{
	return 0/*(long)(uintptr_t)malloc(size)*/;
}

long SpuMallocWithStartAddr(unsigned long addr, long size)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuFree(unsigned long addr)
{
	/*free((void*)(uintptr_t)addr)*/;
}

void SpuSetCommonMasterVolume(short mvol_left, short mvol_right)// (F)
{
	//MasterVolume.VolumeLeft.Raw = mvol_left;
	//MasterVolume.VolumeRight.Raw = mvol_right;
}

long SpuSetReverbModeType(long mode)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetReverbModeDepth(short depth_left, short depth_right)
{
	UNIMPLEMENTED();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file sched/job.hxx
 ** \brief Inline implementation of Job.
 */

#ifndef SCHED_JOB_HXX
# define SCHED_JOB_HXX

# include <libport/bind.hh>
# include <libport/cassert>
# include <libport/debug.hh>

# include <sched/scheduler.hh>
# include <sched/coroutine.hh>

GD_ADD_CATEGORY(sched);

namespace sched
{

  /*------------.
  | job_state.  |
  `------------*/

  inline const char*
  name(job_state state)
  {
#define CASE(State) case State: return #State;
    switch (state)
    {
      CASE(to_start)
      CASE(running)
      CASE(sleeping)
      CASE(waiting)
      CASE(joining)
      CASE(zombie)
    }
#undef CASE
    return "<unknown state>";
  }

  inline
  std::ostream&
  operator<<(std::ostream& o, job_state s)
  {
    return o << name(s);
  }

  /*------.
  | Job.  |
  `------*/

  inline void
  Job::init_common(const libport::Symbol& name)
  {
    state_ = to_start;
    frozen_since_ = 0;
    time_shift_ = 0;
    name_ = name;
    coro_ = coroutine_new();
    non_interruptible_ = false;
    side_effect_free_ = false;
    check_stack_space_ = true;
    alive_jobs_++;
  }

  inline
  Job::Job(Scheduler& scheduler, const libport::Symbol& name)
    : RefCounted()
    , scheduler_(scheduler)
  {
    init_common(name);
  }

  inline
  Job::Job(const Job& model, const libport::Symbol& name)
    : RefCounted()
    , scheduler_(model.scheduler_)
  {
    init_common(name);
    time_shift_ = model.time_shift_;
  }

  inline
  Job::~Job()
  {
    passert(children_, children_.empty());
    coroutine_free(coro_);
    alive_jobs_--;
  }

  inline Scheduler&
  Job::scheduler_get() const
  {
    return scheduler_;
  }

  inline bool
  Job::terminated() const
  {
    return state_ == zombie;
  }

  inline void
  Job::yield()
  {
    // The only case where we yield while being non-interruptible
    // is when we get frozen. This is used to suspend a task
    // and resume it in non-interruptible contexts.
    if (non_interruptible_ && !frozen())
      return;

    state_ = running;
    scheduler_.resume_scheduler(this);
  }

  inline void
  Job::yield_until(libport::utime_t deadline)
  {
    if (non_interruptible_)
      scheduling_error("attempt to sleep in non-interruptible code");

    state_ = sleeping;
    deadline_ = deadline;
    scheduler_.resume_scheduler(this);
  }

  inline Coro*
  Job::coro_get() const
  {
    aver(coro_);
    return coro_;
  }

  inline void
  Job::start_job()
  {
    aver(state_ == to_start);
    scheduler_.add_job(this);
  }

  inline void
  Job::side_effect_free_set(bool s)
  {
    side_effect_free_ = s;
  }

  inline bool
  Job::side_effect_free_get() const
  {
    return side_effect_free_;
  }

  inline const libport::Symbol&
  Job::name_get() const
  {
    return name_;
  }

  inline bool
  Job::non_interruptible_get() const
  {
    return non_interruptible_;
  }

  inline void
  Job::non_interruptible_set(bool ni)
  {
    non_interruptible_ = ni;
  }

  inline void
  Job::check_stack_space()
  {
    if (check_stack_space_
	&& coroutine_stack_space_almost_gone(coro_))
    {
      libport::Finally finally(libport::scoped_set(check_stack_space_, false));
      GD_CATEGORY(sched);
      GD_ERROR("Stack space exhausted");
      scheduling_error("stack space exhausted");
    }
  }

  inline job_state
  Job::state_get() const
  {
    return state_;
  }

  inline void
  Job::state_set(job_state state)
  {
    state_ = state;
  }

  inline libport::utime_t
  Job::deadline_get() const
  {
    return deadline_;
  }

  inline void
  Job::notice_frozen(libport::utime_t current_time)
  {
    if (!frozen_since_)
      frozen_since_ = current_time;
  }

  inline void
  Job::notice_not_frozen(libport::utime_t current_time)
  {
    if (frozen_since_)
    {
      libport::utime_t time_spent_frozen = current_time - frozen_since_;
      time_shift_ += time_spent_frozen;
      if (state_ == sleeping)
	deadline_ += time_spent_frozen;
    }
    frozen_since_ = 0;
  }

  inline libport::utime_t
  Job::frozen_since_get() const
  {
    return frozen_since_;
  }

  inline libport::utime_t
  Job::time_shift_get() const
  {
    return time_shift_;
  }

  inline void
  Job::time_shift_set(libport::utime_t ts)
  {
    time_shift_ = ts;
  }

  inline bool
  Job::has_pending_exception() const
  {
    return pending_exception_.get();
  }

  inline bool
  Job::child_job() const
  {
    return parent_;
  }

  inline
  bool
  Job::ancester_of(const rJob& that) const
  {
    for (const Job* j = that.get(); j; j = j->parent_.get())
      if (j == this)
        return true;
    return false;
  }

  inline std::ostream&
  operator<< (std::ostream& o, const Job& j)
  {
    return j.dump(o);
  }

  /*-----------------.
  | ChildException.  |
  `-----------------*/

  inline
  ChildException::ChildException(exception_ptr exc)
    : child_exception_(exc)
  {
  }

  inline
  ChildException::ChildException(const ChildException& exc)
    : SchedulerException(exc)
    , child_exception_(exc.child_exception_)
  {
  }

  inline exception_ptr
  ChildException::clone() const
  {
    return exception_ptr(new ChildException(child_exception_));
  }

  inline void
  ChildException::rethrow_() const
  {
    throw *this;
  }

  inline void
  ChildException::rethrow_child_exception() const
  {
    child_exception_->rethrow();
  }

  /*------------.
  | Collector.  |
  `------------*/

  ATTRIBUTE_ALWAYS_INLINE
  Job::Collector::Collector(rJob parent, size_t)
    : super_type()
    , parent_(parent)
  {
  }

} // namespace sched

#endif // !SCHED_JOB_HXX
<commit_msg>Use FINALLY.<commit_after>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file sched/job.hxx
 ** \brief Inline implementation of Job.
 */

#ifndef SCHED_JOB_HXX
# define SCHED_JOB_HXX

# include <libport/bind.hh>
# include <libport/cassert>
# include <libport/debug.hh>

# include <sched/scheduler.hh>
# include <sched/coroutine.hh>

GD_ADD_CATEGORY(sched);

namespace sched
{

  /*------------.
  | job_state.  |
  `------------*/

  inline const char*
  name(job_state state)
  {
#define CASE(State) case State: return #State;
    switch (state)
    {
      CASE(to_start)
      CASE(running)
      CASE(sleeping)
      CASE(waiting)
      CASE(joining)
      CASE(zombie)
    }
#undef CASE
    return "<unknown state>";
  }

  inline
  std::ostream&
  operator<<(std::ostream& o, job_state s)
  {
    return o << name(s);
  }

  /*------.
  | Job.  |
  `------*/

  inline void
  Job::init_common(const libport::Symbol& name)
  {
    state_ = to_start;
    frozen_since_ = 0;
    time_shift_ = 0;
    name_ = name;
    coro_ = coroutine_new();
    non_interruptible_ = false;
    side_effect_free_ = false;
    check_stack_space_ = true;
    alive_jobs_++;
  }

  inline
  Job::Job(Scheduler& scheduler, const libport::Symbol& name)
    : RefCounted()
    , scheduler_(scheduler)
  {
    init_common(name);
  }

  inline
  Job::Job(const Job& model, const libport::Symbol& name)
    : RefCounted()
    , scheduler_(model.scheduler_)
  {
    init_common(name);
    time_shift_ = model.time_shift_;
  }

  inline
  Job::~Job()
  {
    passert(children_, children_.empty());
    coroutine_free(coro_);
    alive_jobs_--;
  }

  inline Scheduler&
  Job::scheduler_get() const
  {
    return scheduler_;
  }

  inline bool
  Job::terminated() const
  {
    return state_ == zombie;
  }

  inline void
  Job::yield()
  {
    // The only case where we yield while being non-interruptible
    // is when we get frozen. This is used to suspend a task
    // and resume it in non-interruptible contexts.
    if (non_interruptible_ && !frozen())
      return;

    state_ = running;
    scheduler_.resume_scheduler(this);
  }

  inline void
  Job::yield_until(libport::utime_t deadline)
  {
    if (non_interruptible_)
      scheduling_error("attempt to sleep in non-interruptible code");

    state_ = sleeping;
    deadline_ = deadline;
    scheduler_.resume_scheduler(this);
  }

  inline Coro*
  Job::coro_get() const
  {
    aver(coro_);
    return coro_;
  }

  inline void
  Job::start_job()
  {
    aver(state_ == to_start);
    scheduler_.add_job(this);
  }

  inline void
  Job::side_effect_free_set(bool s)
  {
    side_effect_free_ = s;
  }

  inline bool
  Job::side_effect_free_get() const
  {
    return side_effect_free_;
  }

  inline const libport::Symbol&
  Job::name_get() const
  {
    return name_;
  }

  inline bool
  Job::non_interruptible_get() const
  {
    return non_interruptible_;
  }

  inline void
  Job::non_interruptible_set(bool ni)
  {
    non_interruptible_ = ni;
  }

  inline void
  Job::check_stack_space()
  {
    if (check_stack_space_
	&& coroutine_stack_space_almost_gone(coro_))
    {
      FINALLY(((bool, check_stack_space_)),
              libport::scoped_set(check_stack_space_, false));
      GD_CATEGORY(sched);
      GD_ERROR("Stack space exhausted");
      scheduling_error("stack space exhausted");
    }
  }

  inline job_state
  Job::state_get() const
  {
    return state_;
  }

  inline void
  Job::state_set(job_state state)
  {
    state_ = state;
  }

  inline libport::utime_t
  Job::deadline_get() const
  {
    return deadline_;
  }

  inline void
  Job::notice_frozen(libport::utime_t current_time)
  {
    if (!frozen_since_)
      frozen_since_ = current_time;
  }

  inline void
  Job::notice_not_frozen(libport::utime_t current_time)
  {
    if (frozen_since_)
    {
      libport::utime_t time_spent_frozen = current_time - frozen_since_;
      time_shift_ += time_spent_frozen;
      if (state_ == sleeping)
	deadline_ += time_spent_frozen;
    }
    frozen_since_ = 0;
  }

  inline libport::utime_t
  Job::frozen_since_get() const
  {
    return frozen_since_;
  }

  inline libport::utime_t
  Job::time_shift_get() const
  {
    return time_shift_;
  }

  inline void
  Job::time_shift_set(libport::utime_t ts)
  {
    time_shift_ = ts;
  }

  inline bool
  Job::has_pending_exception() const
  {
    return pending_exception_.get();
  }

  inline bool
  Job::child_job() const
  {
    return parent_;
  }

  inline
  bool
  Job::ancester_of(const rJob& that) const
  {
    for (const Job* j = that.get(); j; j = j->parent_.get())
      if (j == this)
        return true;
    return false;
  }

  inline std::ostream&
  operator<< (std::ostream& o, const Job& j)
  {
    return j.dump(o);
  }

  /*-----------------.
  | ChildException.  |
  `-----------------*/

  inline
  ChildException::ChildException(exception_ptr exc)
    : child_exception_(exc)
  {
  }

  inline
  ChildException::ChildException(const ChildException& exc)
    : SchedulerException(exc)
    , child_exception_(exc.child_exception_)
  {
  }

  inline exception_ptr
  ChildException::clone() const
  {
    return exception_ptr(new ChildException(child_exception_));
  }

  inline void
  ChildException::rethrow_() const
  {
    throw *this;
  }

  inline void
  ChildException::rethrow_child_exception() const
  {
    child_exception_->rethrow();
  }

  /*------------.
  | Collector.  |
  `------------*/

  ATTRIBUTE_ALWAYS_INLINE
  Job::Collector::Collector(rJob parent, size_t)
    : super_type()
    , parent_(parent)
  {
  }

} // namespace sched

#endif // !SCHED_JOB_HXX
<|endoftext|>


<commit_before>#include <functional>
#include <boost/optional.hpp>

#include "key_aliases.hh"
#include "file_contents.hh"
#include "mode.hh"
#include "show_message.hh"

std::map < char, std::function < void (contents&, boost::optional<int>) > >
    global_normal_map,
    global_insert_map;

mode::mode(const std::string& name, bool (*handle)(char))
    : name(name)
    , handle(handle) {
    static int uid = 0;
    unique_id = uid++;
}

bool mode::operator()(char ch) const {
    return handle(ch);
}

const std::string& mode::get_name() const {
    return this->name;
}

bool mode::operator==(const mode& other) const {
    return unique_id == other.unique_id;
}
bool mode::operator!=(const mode& other) const {
    return unique_id != other.unique_id;
}

static bool fundamental_handle(char ch) {
    if(ch == _resize) return true;

    auto it = global_normal_map.find(ch);
    if(it == global_normal_map.end()) return false;

    clear_message();
    it->second(get_contents(),boost::none);
    return true;
}

mode mode::fundamental("Fundamental",fundamental_handle);
<commit_msg>Remove redundant ``this->``<commit_after>#include <functional>
#include <boost/optional.hpp>

#include "key_aliases.hh"
#include "file_contents.hh"
#include "mode.hh"
#include "show_message.hh"

std::map < char, std::function < void (contents&, boost::optional<int>) > >
    global_normal_map,
    global_insert_map;

mode::mode(const std::string& name, bool (*handle)(char))
    : name(name)
    , handle(handle) {
    static int uid = 0;
    unique_id = uid++;
}

bool mode::operator()(char ch) const {
    return handle(ch);
}

const std::string& mode::get_name() const {
    return name;
}

bool mode::operator==(const mode& other) const {
    return unique_id == other.unique_id;
}
bool mode::operator!=(const mode& other) const {
    return unique_id != other.unique_id;
}

static bool fundamental_handle(char ch) {
    if(ch == _resize) return true;

    auto it = global_normal_map.find(ch);
    if(it == global_normal_map.end()) return false;

    clear_message();
    it->second(get_contents(),boost::none);
    return true;
}

mode mode::fundamental("Fundamental",fundamental_handle);
<|endoftext|>


<commit_before>/* Copyright (c) 2016 Cornell University
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "MemServerIndication.h"
#include "MainIndication.h"
#include "MainRequest.h"
#include "GeneratedTypes.h"
#include "lutils.h"
#include "lpcap.h"
#include <pcap.h>
#include <pthread.h>

#define DATA_WIDTH 128
#define MAXBYTES2CAPTURE 2048
#define BUFFSIZE 4096
#define LINK_SPEED 10

static MainRequestProxy *device = 0;
char* pktbuf=NULL;
char* p=NULL;
int size = 0;
static bool tosend = false;

bool hwpktgen = false;
bool metagen = false;

static sem_t sem_read_version;

extern void app_init(MainRequestProxy* device);

void device_writePacketData(uint64_t* data, uint8_t* mask, int sop, int eop) {
    if (hwpktgen) {
      device->writePktGenData(data, mask, sop, eop);
    } else if (metagen) {
      device->writeMetaGenData(data, mask, sop, eop);
    } else {
      device->writePacketData(data, mask, sop, eop);
    }
}

class MainIndication : public MainIndicationWrapper
{
public:
    virtual void read_version_rsp(uint32_t a) {
        fprintf(stderr, "version %x\n", a);
        sem_post(&sem_read_version);
    }
    virtual void read_pktcap_perf_info_resp(PktCapRec a) {
        fprintf(stderr, "perf: pktcap data_bytes=%ld idle_cycle=%ld total_cycle=%ld\n", a.data_bytes, a.idle_cycles, a.total_cycles);
    }
    virtual void readPacketData(const uint64_t data, const uint8_t mask, const uint8_t sop, const uint8_t eop) {
        //fprintf(stderr, "Rdata %016lx, mask %02x, sop %x eop %x\n", data, mask, sop, eop);
        if (sop == 1) {
            pktbuf = (char *) malloc(4096);
            p = pktbuf;
        }
        memcpy(p, &data, 8);
        int bits = (mask * 01001001001ULL & 042104210421ULL) % 017;
        p += bits;
        size += bits;
        if (eop == 1) {
            tosend = true;
        }
    }
    MainIndication(unsigned int id): MainIndicationWrapper(id) {}
};

class MemServerIndication : public MemServerIndicationWrapper
{
public:
    virtual void error(uint32_t code, uint32_t sglId, uint64_t offset, uint64_t extra) {
        fprintf(stderr, "memServer Indication.error=%d\n", code);
    }
    virtual void addrResponse ( const uint64_t physAddr ) {
        fprintf(stderr, "phyaddr=%lx\n", physAddr);
    }
    virtual void reportStateDbg ( const DmaDbgRec rec ) {
        fprintf(stderr, "rec\n");
    }
    virtual void reportMemoryTraffic ( const uint64_t words ) {
        fprintf(stderr, "words %lx\n", words);
    }
    MemServerIndication(unsigned int id) : MemServerIndicationWrapper(id) {}
};

void usage (const char *program_name) {
    printf("%s: p4fpga tester\n"
     "usage: %s [OPTIONS] \n",
     program_name, program_name);
    printf("\nOther options:\n"
    " -p, --parser=FILE                pcap trace to run\n"
    " -I, --intf=interface             listen on interface\n"
    " -r, --rate=x                     packet generation rate\n"
    );
}

struct arg_info {
    double rate;
    uint64_t tracelen;
    uint64_t instance; // pktgen instances
    bool metagen;
};

static void
parse_options(int argc, char *argv[], char **pcap_file, char **intf, char **outf, struct arg_info* info) {
    int c, option_index;

    static struct option long_options [] = {
        {"help",                no_argument, 0, 'h'},
        {"pcap",                required_argument, 0, 'p'},
        {"intf",                required_argument, 0, 'I'},
        {"outf",                required_argument, 0, 'O'},
        {"pktgen-rate",         required_argument, 0, 'r'},
        {"pktgen-count",        required_argument, 0, 'n'},
        {"pktgen-instance",     required_argument, 0, 'g'},
        {"metagen",             no_argument, 0, 'M'},
        {0, 0, 0, 0}
    };

    static std::string short_options
        (long_options_to_short_options(long_options));

    for (;;) {
        c = getopt_long(argc, argv, short_options.c_str(), long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {
            case 'h':
                usage(get_exe_name(argv[0]));
                break;
            case 'p':
                *pcap_file = optarg;
                break;
            case 'I':
                fprintf(stderr, "%s", optarg);
                *intf = optarg;
                break;
            case 'O':
                fprintf(stderr, "%s", optarg);
                *outf = optarg;
                break;
            case 'r':
                info->rate = strtod(optarg, NULL);
                break;
            case 'n':
                info->tracelen = strtol(optarg, NULL, 0);
                break;
            case 'M':
                info->metagen = true;
                break;
            case 'g':
                info->instance = strtol(optarg, NULL, 0);
            default:
                break;
        }
    }
}

/* processPacket(): Callback function called by pcap_loop() everytime a packet */
/* arrives to the network card. This function prints the captured raw data in  */
/* hexadecimal.                                                                */
void processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const u_char * packet){
    int *counter = (int *)arg;
    printf("Packet Count: %d\n", ++(*counter));
    printf("Received Packet Size: %d\n", pkthdr->len);
    mem_copy(packet, pkthdr->len);
    return;
}

void *captureThread(void * pcapt) {
    pcap_t * pt;
    int count=0;
    pt = (pcap_t *)pcapt;
    pcap_loop(pt, -1, processPacket, (u_char*)&count);
    /* should not be reached */
    pcap_close(pt);
    return NULL;
}

void *sendThread(void *pcapt) {
    pcap_t *pt;
    pt = (pcap_t *)pcapt;
    while (1) {
        if (tosend) {
            fprintf(stderr, "inject packet %d\n", size);
            pcap_inject(pt, pktbuf, size);
            tosend = false;
            size = 0;
        }
        usleep(100);
    }
    return NULL;
}

void run_demo(char *intf, char *outf) {
  pthread_t t_cap, t_snd;
  pcap_t *handle = NULL, *handle2=NULL;
  char errbuf[PCAP_ERRBUF_SIZE];
  memset(errbuf,0,PCAP_ERRBUF_SIZE);

  printf("Opening device %s\n", intf);
  /* Open device in promiscuous mode */
  if ((handle = pcap_open_live(intf, MAXBYTES2CAPTURE, 0,  512, errbuf)) == NULL){
    fprintf(stderr, "ERROR: %s\n", errbuf);
    exit(1);
  }
  pthread_create(&t_cap, NULL, captureThread, (void*)handle);

  if (outf) {
    printf("Opening device %s\n", outf);
    if ((handle2 = pcap_open_live(outf, MAXBYTES2CAPTURE, 0, 512, errbuf)) == NULL) {
      fprintf(stderr, "ERROR: %s\n", errbuf);
      exit(1);
    }
    pthread_create(&t_snd, NULL, sendThread, (void*)handle2);
  }

  pthread_join(t_cap, NULL);
  pthread_join(t_snd, NULL);
  /* Loop forever & call processPacket() for every received packet */
  //if (pcap_loop(pt, -1, processPacket, (u_char *)&count) == -1){
  //   fprintf(stderr, "ERROR: %s\n", pcap_geterr(pt) );
  //   exit(1);
  //}
}

int main(int argc, char **argv)
{
    char *pcap_file=NULL;
    struct arg_info arguments = {0.0, 0, 0};
    char *intf=NULL, *outf=NULL;

    struct pcap_trace_info pcap_info = {0, 0};
    MainIndication echoindication(IfcNames_MainIndicationH2S);
    device = new MainRequestProxy(IfcNames_MainRequestS2H);

    parse_options(argc, argv, &pcap_file, &intf, &outf, &arguments);
    device->set_verbosity(6);

    // application specific call
    // e.g. insert table entries here.
    app_init(device);

    device->read_version();
//    sem_wait(&sem_read_version);
//    fprintf(stderr, "receved version rsp\n");
//
//    sleep(3);

    // if specified intf on command line
    if (intf && outf) {
      run_demo(intf, outf);
    }

    // load pcap to pktgen
    hwpktgen = (arguments.rate && arguments.tracelen) ? true : false;

    // load pcap to metagen
    metagen = (arguments.metagen) ? true : false;

    if (pcap_file) {
      fprintf(stderr, "Attempts to read pcap file %s\n", pcap_file);
      load_pcap_file(pcap_file, &pcap_info);
    }

    if (hwpktgen) {
      fprintf(stderr, "%lx %llx\n", pcap_info.packet_count, pcap_info.byte_count);
      int idle = compute_idle(&pcap_info, arguments.rate, LINK_SPEED);
      fprintf(stderr, "IDLE=%d\n", idle);
      device->pktcap_start(arguments.tracelen);
      device->pktgen_start(arguments.tracelen, idle, arguments.instance);
    }

    if (metagen) {
      fprintf(stderr, "start metagen %ld\n", arguments.tracelen);
      device->metagen_start(arguments.tracelen, 1);
    }

    sleep(300);

    device->read_pktcap_perf_info();
    return 0;
}
<commit_msg>refactor main.cpp<commit_after>/* Copyright (c) 2016 Cornell University
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "MemServerIndication.h"
#include "MainIndication.h"
#include "MainRequest.h"
#include "GeneratedTypes.h"
#include "lutils.h"
#include "lpcap.h"
#include <pcap.h>
#include <pthread.h>

#define DATA_WIDTH 128
#define MAXBYTES2CAPTURE 2048
#define BUFFSIZE 4096
#define LINK_SPEED 10

static MainRequestProxy *device = 0;
char* pktbuf=NULL;
char* p=NULL;
int size = 0;
static bool tosend = false;

bool hwpktgen = false;
bool metagen = false;

static sem_t sem_read_version;

extern void app_init(MainRequestProxy* device);

void device_writePacketData(uint64_t* data, uint8_t* mask, int sop, int eop) {
    if (hwpktgen) {
      device->writePktGenData(data, mask, sop, eop);
    } else if (metagen) {
      device->writeMetaGenData(data, mask, sop, eop);
    } else {
      device->writePacketData(data, mask, sop, eop);
    }
}

class MainIndication : public MainIndicationWrapper
{
public:
    virtual void read_version_rsp(uint32_t a) {
        fprintf(stderr, "version %x\n", a);
        sem_post(&sem_read_version);
    }
    virtual void read_pktcap_perf_info_resp(PktCapRec a) {
        fprintf(stderr, "perf: pktcap data_bytes=%ld idle_cycle=%ld total_cycle=%ld\n", a.data_bytes, a.idle_cycles, a.total_cycles);
    }
    virtual void readPacketData(const uint64_t data, const uint8_t mask, const uint8_t sop, const uint8_t eop) {
        //fprintf(stderr, "Rdata %016lx, mask %02x, sop %x eop %x\n", data, mask, sop, eop);
        if (sop == 1) {
            pktbuf = (char *) malloc(4096);
            p = pktbuf;
        }
        memcpy(p, &data, 8);
        int bits = (mask * 01001001001ULL & 042104210421ULL) % 017;
        p += bits;
        size += bits;
        if (eop == 1) {
            tosend = true;
        }
    }
    MainIndication(unsigned int id): MainIndicationWrapper(id) {}
};

class MemServerIndication : public MemServerIndicationWrapper
{
public:
    virtual void error(uint32_t code, uint32_t sglId, uint64_t offset, uint64_t extra) {
        fprintf(stderr, "memServer Indication.error=%d\n", code);
    }
    virtual void addrResponse ( const uint64_t physAddr ) {
        fprintf(stderr, "phyaddr=%lx\n", physAddr);
    }
    virtual void reportStateDbg ( const DmaDbgRec rec ) {
        fprintf(stderr, "rec\n");
    }
    virtual void reportMemoryTraffic ( const uint64_t words ) {
        fprintf(stderr, "words %lx\n", words);
    }
    MemServerIndication(unsigned int id) : MemServerIndicationWrapper(id) {}
};

/* processPacket(): Callback function called by pcap_loop() everytime a packet */
/* arrives to the network card. This function prints the captured raw data in  */
/* hexadecimal.                                                                */
void processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const u_char * packet){
    int *counter = (int *)arg;
    printf("Packet Count: %d\n", ++(*counter));
    printf("Received Packet Size: %d\n", pkthdr->len);
    mem_copy(packet, pkthdr->len);
    return;
}

void *captureThread(void * pcapt) {
    pcap_t * pt;
    int count=0;
    pt = (pcap_t *)pcapt;
    pcap_loop(pt, -1, processPacket, (u_char*)&count);
    /* should not be reached */
    pcap_close(pt);
    return NULL;
}

void *sendThread(void *pcapt) {
    pcap_t *pt;
    pt = (pcap_t *)pcapt;
    while (1) {
        if (tosend) {
            fprintf(stderr, "inject packet %d\n", size);
            pcap_inject(pt, pktbuf, size);
            tosend = false;
            size = 0;
        }
        usleep(100);
    }
    return NULL;
}

void run_demo(char *intf, char *outf) {
  pthread_t t_cap, t_snd;
  pcap_t *handle = NULL, *handle2=NULL;
  char errbuf[PCAP_ERRBUF_SIZE];
  memset(errbuf,0,PCAP_ERRBUF_SIZE);

  printf("Opening device %s\n", intf);
  /* Open device in promiscuous mode */
  if ((handle = pcap_open_live(intf, MAXBYTES2CAPTURE, 0,  512, errbuf)) == NULL){
    fprintf(stderr, "ERROR: %s\n", errbuf);
    exit(1);
  }
  pthread_create(&t_cap, NULL, captureThread, (void*)handle);

  if (outf) {
    printf("Opening device %s\n", outf);
    if ((handle2 = pcap_open_live(outf, MAXBYTES2CAPTURE, 0, 512, errbuf)) == NULL) {
      fprintf(stderr, "ERROR: %s\n", errbuf);
      exit(1);
    }
    pthread_create(&t_snd, NULL, sendThread, (void*)handle2);
  }

  pthread_join(t_cap, NULL);
  pthread_join(t_snd, NULL);
  /* Loop forever & call processPacket() for every received packet */
  //if (pcap_loop(pt, -1, processPacket, (u_char *)&count) == -1){
  //   fprintf(stderr, "ERROR: %s\n", pcap_geterr(pt) );
  //   exit(1);
  //}
}

void usage (const char *program_name) {
    printf("%s: p4fpga tester\n"
     "usage: %s [OPTIONS] \n",
     program_name, program_name);
    printf("\nOther options:\n"
    " -p, --parser=FILE                pcap trace to run\n"
    " -I, --intf=interface             listen on interface\n"
    " -r, --rate=x                     packet generation rate\n"
    " -n, --pktgen-count=n             packet generation count\n"
    " -i, --pktgen-intf=n              packet generation interface\n"
    " -v, --verbose=n                  set verbosity level\n"
    );
}

int main(int argc, char **argv)
{
    char *pcap_file=NULL;
    char *intf=NULL, *outf=NULL;

    double rate = 0.0;
    long tracelen = 0;
    long instance = 0; // pktgen instances
    bool metagen = false;
    long verbose = 0;

    struct pcap_trace_info pcap_info = {0, 0};
    MainIndication echoindication(IfcNames_MainIndicationH2S);
    device = new MainRequestProxy(IfcNames_MainRequestS2H);

    int c, option_index;

    static struct option long_options [] = {
        {"help",                no_argument, 0, 'h'},
        {"pcap",                required_argument, 0, 'p'},
//        {"intf",                required_argument, 0, 'I'},
//        {"outf",                required_argument, 0, 'O'},
        {"pktgen-rate",         required_argument, 0, 'r'},
        {"pktgen-count",        required_argument, 0, 'n'},
        {"pktgen-instance",     required_argument, 0, 'i'},
        {"metagen",             no_argument, 0, 'M'},
        {"verbose",             required_argument, 0, 'v'},
        {0, 0, 0, 0}
    };

    static std::string short_options
        (long_options_to_short_options(long_options));

    for (;;) {
        c = getopt_long(argc, argv, short_options.c_str(), long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {
            case 'h':
                usage(get_exe_name(argv[0]));
                break;
            case 'p':
                pcap_file = optarg;
                break;
//            case 'I':
//                fprintf(stderr, "%s", optarg);
//                intf = optarg;
//                break;
//            case 'O':
//                fprintf(stderr, "%s", optarg);
//                outf = optarg;
//                break;
            case 'r':
                rate = strtod(optarg, NULL);
                break;
            case 'n':
                tracelen = strtol(optarg, NULL, 0);
                break;
            case 'M':
                metagen = true;
                break;
            case 'i':
                instance = strtol(optarg, NULL, 0);
                break;
            case 'v':
                verbose = strtol(optarg, NULL, 0);
                break;
            default:
                break;
        }
    }

    device->set_verbosity(verbose);

    // application specific call
    // e.g. insert table entries here.
    app_init(device);

    device->read_version();

    sleep(3);

    // if specified intf on command line
    if (intf && outf) {
      run_demo(intf, outf);
    }

    // load pcap to pktgen
    hwpktgen = (rate && tracelen) ? true : false;

    // load pcap to metagen
    metagen = (metagen) ? true : false;

    if (pcap_file) {
      fprintf(stderr, "Attempts to read pcap file %s\n", pcap_file);
      load_pcap_file(pcap_file, &pcap_info);
    }

    if (hwpktgen) {
      fprintf(stderr, "%lx %llx\n", pcap_info.packet_count, pcap_info.byte_count);
      int idle = compute_idle(&pcap_info, rate, LINK_SPEED);
      fprintf(stderr, "IDLE=%d\n", idle);
      device->pktcap_start(tracelen);
      device->pktgen_start(tracelen, idle, instance);
    }

    if (metagen) {
      fprintf(stderr, "start metagen %ld\n", tracelen);
      device->metagen_start(tracelen, 1);
    }

    sleep(30);

    device->read_pktcap_perf_info();
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Bernhard Firner and Rutgers University
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * or visit http://www.gnu.org/licenses/gpl-2.0.html
 */

/**
 * @file message_receiver.hpp
 * Defines the MessageReceiver class that simplifies receiving messages in the
 * owl/grail platform format.
 *
 * @author Bernhard Firner
 */

#include "message_receiver.hpp"

#include <stdexcept>
#include <vector>
#include <cstring>
#include <unistd.h>
#include "simple_sockets.hpp"

#include "netbuffer.hpp"

MessageReceiver::MessageReceiver(ClientSocket& s) : sock(s), raw_messages(10000) {
  previous_unfinished = std::vector<unsigned char>(0);
}

bool MessageReceiver::messageAvailable(bool& interrupted) {
  //Try to process data from the previously unfinished buffer, but
  //if there is not enough data available receive from the network.
  //There must be at least 4 bytes to try to process a packet and
  //the size of a piece is stored in its first four bytes.
  uint32_t piece_length = 0;
  if (previous_unfinished.size() >= 4) {
    piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  }
  //See if we need more data to complete the current packet
  //True if we do not have enough data to determine a packet size
  //or we do not have enough data for a complete packet.
  if (not interrupted and
         (previous_unfinished.size() < 4 or
          previous_unfinished.size() < piece_length)) {

    //Receive a message from the network to get more data.
    ssize_t length = sock.receive(raw_messages);
    if ( -1 == length ) {
      //Check for a nonblocking socket
      if (EAGAIN == errno or
          EWOULDBLOCK == errno) {
        //No message available
        return false;
      }
      else {
        //Check the error value to give a more explicit error message.
        std::string err_str(strerror(errno));
        throw std::runtime_error("Error receiving message or the connection was closed: "+err_str);
      }
    }
    else if (0 == length) {
      //0 length indicates end of file (a closed connection)
      throw std::runtime_error("Connection was closed.");
    }
    //Append the message data into the previous_unfinished buffer.
    previous_unfinished.insert(previous_unfinished.end(),
        raw_messages.begin(), raw_messages.begin()+length);
  }

  //Return true if there is enough data to form a packet.
  piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  return piece_length <= previous_unfinished.size();
}

std::vector<unsigned char> MessageReceiver::getNextMessage(bool& interrupted) {
  //Try to process data from the previously unfinished buffer, but
  //if there is not enough data available receive from the network.
  //There must be at least 4 bytes to try to process a packet and
  //the size of a piece is stored in its first four bytes.
  uint32_t piece_length = 0;
  if (previous_unfinished.size() >= 4) {
    piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
    //std::cerr<<"Getting piece with length "<<piece_length<<'\n';
  }
  //Get the next packet - keep going while the size can't be read or the
  //size was read but the buffer does not have the whole packet
  while (not interrupted and
         (previous_unfinished.size() < 4 or
          previous_unfinished.size() < piece_length)) {

    //Receive a message from the network to get more data.
    ssize_t length = sock.receive(raw_messages);
    if ( -1 == length ) {
      //Check for a nonblocking socket
      if (EAGAIN == errno or
          EWOULDBLOCK == errno) {
        //Sleep for one millisecond and try again
        usleep(1000);
        continue;
      }
      else {
        //Check the error value to give a more explicit error message.
        std::string err_str(strerror(errno));
        throw std::runtime_error("Error receiving message or the connection was closed: "+err_str);
      }
    }
    else if (0 == length) {
      //0 length indicates end of file (a closed connection)
      throw std::runtime_error("Connection was closed.");
    }
    //Append the message data into the previous_unfinished buffer.
    previous_unfinished.insert(previous_unfinished.end(),
        raw_messages.begin(), raw_messages.begin()+length);

    //Read in the piece length and continue receiving packets until at least
    //that much data has been received. The length bytes themselves take 4 bytes
    if (previous_unfinished.size() >= 4) {
      piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
      //std::cerr<<"Continuing next piece with length "<<piece_length<<'\n';
    }
  }
  //If the receive function is interrupted just leave.
  if (interrupted) {
    return std::vector<unsigned char>(0);
  }

  piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  std::vector<unsigned char> new_packet(previous_unfinished.begin(),
      previous_unfinished.begin()+piece_length);
  //Save the unused portion of the buffer. Otherwise there is no more data left over
  //so zero the buffer.
  if ( piece_length < previous_unfinished.size() ) {
    previous_unfinished = std::vector<unsigned char>(previous_unfinished.begin() + piece_length, previous_unfinished.end());
    //std::cerr<<"Saving data for next call:\n";
    //std::for_each(previous_unfinished.begin(), previous_unfinished.end(), [&](unsigned char c) {
        //std::cerr<<c;
        //});
    //std::cerr<<'\n';
  }
  else {
    previous_unfinished.clear();
  }
  return new_packet;
}

<commit_msg>Use a blocking poll in the message receiver to reduce CPU usage.<commit_after>/*
 * Copyright (c) 2012 Bernhard Firner and Rutgers University
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 * or visit http://www.gnu.org/licenses/gpl-2.0.html
 */

/**
 * @file message_receiver.hpp
 * Defines the MessageReceiver class that simplifies receiving messages in the
 * owl/grail platform format.
 *
 * @author Bernhard Firner
 */

#include "message_receiver.hpp"

#include <stdexcept>
#include <vector>
#include <cstring>
#include <unistd.h>
#include "simple_sockets.hpp"
#include <poll.h>
#include <sys/poll.h>

#include "netbuffer.hpp"

MessageReceiver::MessageReceiver(ClientSocket& s) : sock(s), raw_messages(10000) {
  previous_unfinished = std::vector<unsigned char>(0);
}

bool MessageReceiver::messageAvailable(bool& interrupted) {
  //Try to process data from the previously unfinished buffer, but
  //if there is not enough data available receive from the network.
  //There must be at least 4 bytes to try to process a packet and
  //the size of a piece is stored in its first four bytes.
  uint32_t piece_length = 0;
  if (previous_unfinished.size() >= 4) {
    piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  }
  //See if we need more data to complete the current packet
  //True if we do not have enough data to determine a packet size
  //or we do not have enough data for a complete packet.
  if (not interrupted and
         (previous_unfinished.size() < 4 or
          previous_unfinished.size() < piece_length)) {
    //Wait 10ms for data on the socket.
    if (not sock.inputReady(10)) {
      return false;
    }

    //Receive a message from the network to get more data.
    ssize_t length = sock.receive(raw_messages);
    if ( -1 == length ) {
      //Check for a nonblocking socket
      if (EAGAIN == errno or
          EWOULDBLOCK == errno) {
        //No message available
        return false;
      }
      else {
        //Check the error value to give a more explicit error message.
        std::string err_str(strerror(errno));
        throw std::runtime_error("Error receiving message or the connection was closed: "+err_str);
      }
    }
    else if (0 == length) {
      //0 length indicates end of file (a closed connection)
      throw std::runtime_error("Connection was closed.");
    }
    //Append the message data into the previous_unfinished buffer.
    previous_unfinished.insert(previous_unfinished.end(),
        raw_messages.begin(), raw_messages.begin()+length);
  }

  //Return true if there is enough data to form a packet.
  piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  return piece_length <= previous_unfinished.size();
}

std::vector<unsigned char> MessageReceiver::getNextMessage(bool& interrupted) {
  //Try to process data from the previously unfinished buffer, but
  //if there is not enough data available receive from the network.
  //There must be at least 4 bytes to try to process a packet and
  //the size of a piece is stored in its first four bytes.
  uint32_t piece_length = 0;
  if (previous_unfinished.size() >= 4) {
    piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
    //std::cerr<<"Getting piece with length "<<piece_length<<'\n';
  }
  //Get the next packet - keep going while the size can't be read or the
  //size was read but the buffer does not have the whole packet
  while (not interrupted and
         (previous_unfinished.size() < 4 or
          previous_unfinished.size() < piece_length)) {

    //Receive a message from the network to get more data.
    ssize_t length = sock.receive(raw_messages);
    if ( -1 == length ) {
      //Check for a nonblocking socket
      if (EAGAIN == errno or
          EWOULDBLOCK == errno) {
        //Sleep for one millisecond and try again
        usleep(1000);
        continue;
      }
      else {
        //Check the error value to give a more explicit error message.
        std::string err_str(strerror(errno));
        throw std::runtime_error("Error receiving message or the connection was closed: "+err_str);
      }
    }
    else if (0 == length) {
      //0 length indicates end of file (a closed connection)
      throw std::runtime_error("Connection was closed.");
    }
    //Append the message data into the previous_unfinished buffer.
    previous_unfinished.insert(previous_unfinished.end(),
        raw_messages.begin(), raw_messages.begin()+length);

    //Read in the piece length and continue receiving packets until at least
    //that much data has been received. The length bytes themselves take 4 bytes
    if (previous_unfinished.size() >= 4) {
      piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
      //std::cerr<<"Continuing next piece with length "<<piece_length<<'\n';
    }
  }
  //If the receive function is interrupted just leave.
  if (interrupted) {
    return std::vector<unsigned char>(0);
  }

  piece_length = readPrimitive<uint32_t>(previous_unfinished, 0) + 4;
  std::vector<unsigned char> new_packet(previous_unfinished.begin(),
      previous_unfinished.begin()+piece_length);
  //Save the unused portion of the buffer. Otherwise there is no more data left over
  //so zero the buffer.
  if ( piece_length < previous_unfinished.size() ) {
    previous_unfinished = std::vector<unsigned char>(previous_unfinished.begin() + piece_length, previous_unfinished.end());
    //std::cerr<<"Saving data for next call:\n";
    //std::for_each(previous_unfinished.begin(), previous_unfinished.end(), [&](unsigned char c) {
        //std::cerr<<c;
        //});
    //std::cerr<<'\n';
  }
  else {
    previous_unfinished.clear();
  }
  return new_packet;
}

<|endoftext|>