s98.cpp

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. filelength
  2. S98
  3. Open
  4. Dump
  5. NextData
  6. Loop

#include "s98.h"
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int filelength(int fd)
/* [<][>][^][v][top][bottom][index][help] */
{
  off_t save;
  int ret;
  save = lseek(fd, 0, SEEK_CUR);
  ret = lseek(fd, 0, SEEK_END);
  lseek(fd, save, SEEK_SET);
  return ret;
}

S98::~S98()
/* [<][>][^][v][top][bottom][index][help] */
{
  delete[] Data;
}

int S98::Open(string thefilename)
/* [<][>][^][v][top][bottom][index][help] */
{
  int fd;
  fd = ::open(thefilename.c_str(), O_RDONLY);
  
  if(fd < 0) return -1;
  filename = thefilename;
  size = filelength(fd);

  if(size <= sizeof(Header)) return -1;

  Data = new unsigned char[size - sizeof(Header)]; // XXX exception

  ::read(fd, reinterpret_cast<char*>(&Header), sizeof(Header));
  ::read(fd, Data, size - sizeof(Header));

  if(strncmp(Header.Magic, "S98", 3)) return -1;

  if(Header.Timer == 0) Header.Timer = 10;
  if(Header.NamePtr != 0) Header.NamePtr -= sizeof(Header);
  Header.DataPtr -= sizeof(Header);
  if(Header.LoopPtr != 0) Header.LoopPtr -= sizeof(Header);

  pointer = Header.DataPtr;

  ::close(fd);
  return 0;
}

void S98::Dump()
/* [<][>][^][v][top][bottom][index][help] */
{

  fprintf(stderr, "Filename: %s\n", filename.c_str());
  fprintf(stderr, "Length: %d\n", size);
  fprintf(stderr, "Format: %c\n", static_cast<int> (Header.Format[0]));
  fprintf(stderr, "Timer: %d\n" , Header.Timer);
  fprintf(stderr, "Compressed: %d\n", Header.Compress);
  fprintf(stderr, "Name: ");
  if(Header.NamePtr != 0) {
    fprintf(stderr, reinterpret_cast<char*>(&Data[Header.NamePtr]));
  } else {
    fprintf(stderr, "noname");
  }
  fprintf(stderr, "\n");
}

// 0 = ok, 1 = end, -1 = ng
int S98::NextData()
/* [<][>][^][v][top][bottom][index][help] */
{
  unsigned char* p;
  int n, s, i;
  p = &Data[pointer];
  if(pointer + sizeof(Header) >= size) return -1;

  switch(*p){
  case 0x00: // OPN(A) MASTER
    opnareg.DoProc(static_cast<unsigned int>(p[1]), 
                   static_cast<unsigned int>(p[2]));
    pointer += 3;
    break;
  case 0x01: // OPN(A) SLAVE
    opnareg.DoProc(0x100 | static_cast<unsigned int>(p[1]),
                   static_cast<unsigned int>(p[2]));
    pointer += 3;
    break;
  case 0xff: // WAIT SYNC(1)
    waitsync.DoProc(1 * Header.Timer);
    ++pointer;
    break;
  case 0xfe: // WAIT SYNC(n)
    n = s = 0; i = 0;
    do{
      ++i;
      n |= (p[i] & 0x7f) << s;
      s += 7;
    } while(p[i] & 0x80);
    n += 2;
    pointer += i + 1;
    waitsync.DoProc(Header.Timer * n);
    break;
  case 0xfd: // END/LOOP
    ++pointer;
    return 1;
  default:
    return -1;
    break;
  }
  return 0;
}

int S98::Loop()
/* [<][>][^][v][top][bottom][index][help] */
{
  if(Header.LoopPtr != 0){
    pointer = Header.LoopPtr;
    return 1;
  }
  return 0;
}


/* [<][>][^][v][top][bottom][index][help] */