/*
    tools.c
    Nützliche Routinen, die oft benötigt werden.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
//#include "mcurses.h"
//#include "tools.h"
//#include "driver.h"
//#include "xprintf.h"
//#include "main.h"

#if 0
////////////////////////////////////////////
// Statuszeile unten ausgeben
void statusline(char* zeile)
{
    char xpos,ypos;
    
    getyx(ypos,xpos);           // Alte Pos speichern
    move(23,0);                 // Statuszeile
    deleteln();
    attrset(A_UNDERLINE);
    addstr("Z80 > ");
    addstr(zeile);
    attrset(A_NORMAL);
    move(ypos,xpos);
}
#endif

#if 0
////////////////////////////////////////////
// 1 Zeichen Hex -> Int konvertieren
// Eingabe: "C" = 0x43
// Ausgabe: 0x0C
static uint8_t xtoc (uint8_t ch)
{
    uint8_t val;
    uint8_t c = toupper(ch);

    // Grossbuchstaben
    if (c >= 'A' && c <= 'F')
        val = (c - 'A') + 10;
    else
        val = (c - '0');

    return val;
}
#endif

static uint8_t gethex_digit(void) 
{
	uint8_t c;

	c = toupper(getchar());
	c -= '0';
	if (c > 9)
		c -= ('A' - '0' - 10);
	return c;
}

static uint8_t gethex(uint8_t *csum)
{
	uint8_t val = (gethex_digit() << 4) + gethex_digit();
	
	*csum += val;
	return val;
}

__at (0) unsigned char mem[0x10000];         // Kompletter Speicher

// Global, da viel kürzerer Code!
struct ihx_data {
       uint8_t len;
       uint16_t datalength;
       uint16_t recordsets;
       uint16_t adress;
       uint8_t record;
       uint8_t csum;
};
 

char ihx_decode(struct ihx_data *ihx)
{
    #define DATA_RECORD     0x00
    #define END_RECORD      0x01

   uint8_t ch,i,k,data;
   uint8_t cnt,cnt2;
   
   // Nullen.... 
   k = 0;
   cnt = 0;
   cnt2 = 0;
   ihx->datalength = 0;
   ihx->recordsets = 0;
   
   do {
        // warte auf Startzeichen
        do ch = getchar();
        while (ch != ':');
        if (++cnt2 > 2) {
            cnt2 = 0;
#if 0
            if (++cnt < 54)
                addstr(".");
            else  {
                addstr("\r");
                cnt = 0;
            }
#endif
        }        

        ihx->csum = 0;

        // Hole Anzahl Zeichen des Satzes
        ihx->len = gethex(&ihx->csum);

        // Hole Zieladresse des Satzes
        // Setze Adresse zusammen
        ihx->adress = (gethex(&ihx->csum) << 8) + gethex(&ihx->csum);
        
        // Hole Record Type
        ihx->record = gethex(&ihx->csum);
        ihx->recordsets++;

        // Record 0 = Daten
        if (ihx->record == DATA_RECORD)  {
            // Hole Datenbytes ab
            for (i=0;i<ihx->len;i++)
            {
                data = gethex(&ihx->csum);
                mem[ihx->adress+i] = data;
//                SetLedByte(data);
            }
            ihx->datalength += ihx->len;

            // Prüfsumme holen
            gethex(&ihx->csum);

            // Prüfsumme überprüfen
            if (ihx->csum != 0)
                return (0);

//            SetDigit(k++);
        }

    } while (ihx->record != END_RECORD);

    //xprintf("\rDatabytes        : %u",ihx->datalength);
    //xprintf("\rRecord Sets      : %u",ihx->recordsets);
    // Dateiende abwarten
    do
        ch = getchar();
    while (ch!=0x0a);

    return (1);

}

/////////////////////////////////////////////
// Zufallszahlengenerator

#ifdef USE_SIMPLE_RANDOM

static uint16_t seed=10000;

void sprng(uint16_t start)
{
    seed = start;
}

uint16_t prng(uint16_t max)
{
    uint16_t result;

    seed ^= seed<<7;
    seed ^= seed>>9;
    seed ^= seed<<5;
    seed ^= seed>>3;
    result = seed % max;

    return (result);
}

#endif

// Mersenne - Twister Algorithmus

#ifdef USE_MERSENNE_TWISTER

uint32_t TT800(uint16_t range) {
#define N  25
#define M   7
   static const uint32_t A[2] = { 0, 0x8ebfd028 };
   static uint32_t y[N];
   static int index = N+1;
   uint32_t  e;

   if (index >= N) {
     int k;
     if (index > N) {
        unsigned r = 9, s = 3402;
        for (k=0; k<N; ++k) {
          r = 509845221 * r + 3;
          s *= s + 1;
          y[k] = s + (r >> 10);
        }
     }
     for (k=0; k<N-M; ++k)
        y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
     for (; k<N; ++k)
        y[k] = y[k+(M-N)] ^ (y[k] >> 1) ^ A[y[k] & 1];
     index = 0;
   }

   e = y[index++];

   e ^= (e <<  7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return (e % range);
#undef N
#undef M
}

#endif


