⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libsnss.c

📁 一个最快NFC的模拟器
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************/
/*
      libsnss.c

      (C) 2000 The SNSS Group
      See README.TXT file for license and terms of use.

      $Id: libsnss.c,v 1.1.1.1 2003/01/09 13:37:05 Rick Exp $
*/
/**************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libsnss.h"

/**************************************************************************/
/* This section deals with endian-specific code. */
/**************************************************************************/

static unsigned int
swap32 (unsigned int source)
{
#ifdef USE_LITTLE_ENDIAN
   char buffer[4];
   
   buffer[0] = ((char *) &source)[3];
   buffer[1] = ((char *) &source)[2];
   buffer[2] = ((char *) &source)[1];
   buffer[3] = ((char *) &source)[0];

   return *((unsigned int *) buffer);
#else /* !USE_LITTLE_ENDIAN */
   return source;
#endif /* !USE_LITTLE_ENDIAN */
}

static unsigned short
swap16 (unsigned short source)
{
#ifdef USE_LITTLE_ENDIAN
   char buffer[2];
   
   buffer[0] = ((char *) &source)[1];
   buffer[1] = ((char *) &source)[0];

   return *((unsigned short *) buffer);
#else /* !USE_LITTLE_ENDIAN */
   return source;
#endif /* !USE_LITTLE_ENDIAN */
}

/**************************************************************************/
/* support functions */
/**************************************************************************/

#define MIN(a,b) (((a) < (b)) ? (a) : (b))

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

static SNSS_RETURN_CODE
SNSS_ReadBlockHeader (SnssBlockHeader *header, SNSS_FILE *snssFile)
{
   char headerBytes[12];

   if (fread (headerBytes, 12, 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }

   strncpy (header->tag, &headerBytes[0], TAG_LENGTH);
   header->tag[4] = '\0';
   header->blockVersion = *((unsigned int *) &headerBytes[4]);
   header->blockVersion = swap32 (header->blockVersion);
   header->blockLength = *((unsigned int *) &headerBytes[8]);
   header->blockLength = swap32 (header->blockLength);

   return SNSS_OK;
}

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

static SNSS_RETURN_CODE
SNSS_WriteBlockHeader (SnssBlockHeader *header, SNSS_FILE *snssFile)
{
   char headerBytes[12];
   unsigned int tempInt;

   strncpy (&headerBytes[0], header->tag, TAG_LENGTH);

   tempInt = swap32 (header->blockVersion);
   headerBytes[4] = ((char *) &tempInt)[0];
   headerBytes[5] = ((char *) &tempInt)[1];
   headerBytes[6] = ((char *) &tempInt)[2];
   headerBytes[7] = ((char *) &tempInt)[3];

   tempInt = swap32 (header->blockLength);
   headerBytes[8] = ((char *) &tempInt)[0];
   headerBytes[9] = ((char *) &tempInt)[1];
   headerBytes[10] = ((char *) &tempInt)[2];
   headerBytes[11] = ((char *) &tempInt)[3];

   if (fwrite (headerBytes, 12, 1, snssFile->fp) != 1)
   {
      return SNSS_WRITE_FAILED;
   }

   return SNSS_OK;
}

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

const char *
SNSS_GetErrorString (SNSS_RETURN_CODE code)
{
   switch (code)
   {
   case SNSS_OK:
      return "no error";

   case SNSS_BAD_FILE_TAG:
      return "not an SNSS file";

   case SNSS_OPEN_FAILED:
      return "could not open SNSS file";

   case SNSS_CLOSE_FAILED:
      return "could not close SNSS file";

   case SNSS_READ_FAILED:
      return "could not read from SNSS file";

   case SNSS_WRITE_FAILED:
      return "could not write to SNSS file";

   case SNSS_OUT_OF_MEMORY:
      return "out of memory";

   case SNSS_UNSUPPORTED_BLOCK:
      return "unsupported block type";

   default:
      return "unknown error";
   }
}

/**************************************************************************/
/* functions for reading and writing SNSS file headers */
/**************************************************************************/

static SNSS_RETURN_CODE 
SNSS_ReadFileHeader (SNSS_FILE *snssFile)
{
   if (fread (snssFile->headerBlock.tag, 4, 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }
 
   if (0 != strncmp(snssFile->headerBlock.tag, "SNSS", 4))
   {
      return SNSS_BAD_FILE_TAG;
   }
   
   snssFile->headerBlock.tag[4] = '\0';

   if (fread (&snssFile->headerBlock.numberOfBlocks, sizeof (unsigned int), 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }
   snssFile->headerBlock.numberOfBlocks = swap32 (snssFile->headerBlock.numberOfBlocks);

   return SNSS_OK;
}

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

static SNSS_RETURN_CODE 
SNSS_WriteFileHeader (SNSS_FILE *snssFile)
{
   unsigned int tempInt;
   char writeBuffer[8];

   /* always place the SNSS tag in this field */
   strncpy (&writeBuffer[0], "SNSS", 4);
   tempInt = swap32 (snssFile->headerBlock.numberOfBlocks);
   writeBuffer[4] = ((char *) &tempInt)[0];
   writeBuffer[5] = ((char *) &tempInt)[1];
   writeBuffer[6] = ((char *) &tempInt)[2];
   writeBuffer[7] = ((char *) &tempInt)[3];

   if (fwrite (writeBuffer, 8, 1, snssFile->fp) != 1)
   {
      return SNSS_WRITE_FAILED;
   }

   return SNSS_OK;
}

/**************************************************************************/
/* general file manipulation functions */
/**************************************************************************/
SNSS_RETURN_CODE
SNSS_OpenFile (SNSS_FILE **snssFile, const char *filename, SNSS_OPEN_MODE mode)
{
   *snssFile = malloc(sizeof(SNSS_FILE));
   if (NULL == *snssFile)
   {
      return SNSS_OUT_OF_MEMORY;
   }

   (*snssFile)->mode = mode;

   if (SNSS_OPEN_READ == mode)
      (*snssFile)->fp = fopen (filename, "rb");
   else
   {
      (*snssFile)->fp = fopen (filename, "wb");
      (*snssFile)->headerBlock.numberOfBlocks = 0;
   }

   if (NULL == (*snssFile)->fp)
   {
      free(*snssFile);
      *snssFile = NULL;
      return SNSS_OPEN_FAILED;
   }

   if (SNSS_OPEN_READ == mode)
      return SNSS_ReadFileHeader(*snssFile);
   else
      return SNSS_WriteFileHeader(*snssFile);
}

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

SNSS_RETURN_CODE
SNSS_CloseFile (SNSS_FILE **snssFile)
{
   int prevLoc;
   SNSS_RETURN_CODE code;

   /* file was never open, so this should indicate success- kinda. */
   if (NULL == *snssFile)
   {
      return SNSS_OK;
   }

   if (SNSS_OPEN_WRITE == (*snssFile)->mode)
   {
      prevLoc = ftell((*snssFile)->fp);
      fseek((*snssFile)->fp, 0, SEEK_SET);

      /* write the header again to get block count correct */
      if (SNSS_OK != (code = SNSS_WriteFileHeader(*snssFile)))
         return SNSS_CLOSE_FAILED;

      fseek((*snssFile)->fp, prevLoc, SEEK_SET);
   }

   if (fclose ((*snssFile)->fp) != 0)
   {
      return SNSS_CLOSE_FAILED;
   }

   free(*snssFile);
   *snssFile = NULL;

   return SNSS_OK;
}

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

SNSS_RETURN_CODE 
SNSS_GetNextBlockType (SNSS_BLOCK_TYPE *blockType, SNSS_FILE *snssFile)
{
   char tagBuffer[TAG_LENGTH + 1];

   if (fread (tagBuffer, TAG_LENGTH, 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }
   tagBuffer[TAG_LENGTH] = '\0';

   /* reset the file pointer to the start of the block */
   if (fseek (snssFile->fp, -TAG_LENGTH, SEEK_CUR) != 0)
   {
      return SNSS_READ_FAILED;
   }

   /* figure out which type of block it is */
   if (strcmp (tagBuffer, "BASR") == 0)
   {
      *blockType = SNSS_BASR;
      return SNSS_OK;
   }
   else if (strcmp (tagBuffer, "VRAM") == 0)
   {
      *blockType = SNSS_VRAM;
      return SNSS_OK;
   }
   else if (strcmp (tagBuffer, "SRAM") == 0)
   {
      *blockType = SNSS_SRAM;
      return SNSS_OK;
   }
   else if (strcmp (tagBuffer, "MPRD") == 0)
   {
      *blockType = SNSS_MPRD;
      return SNSS_OK;
   }
   else if (strcmp (tagBuffer, "CNTR") == 0)
   {
      *blockType = SNSS_CNTR;
      return SNSS_OK;
   }
   else if (strcmp (tagBuffer, "SOUN") == 0)
   {
      *blockType = SNSS_SOUN;
      return SNSS_OK;
   }
   else
   {
      *blockType = SNSS_UNKNOWN_BLOCK;
      return SNSS_OK;
   }
}

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

SNSS_RETURN_CODE 
SNSS_SkipNextBlock (SNSS_FILE *snssFile)
{
   unsigned int blockLength;

   /* skip the block's tag and version */
   if (fseek (snssFile->fp, TAG_LENGTH + sizeof (unsigned int), SEEK_CUR) != 0)
   {
      return SNSS_READ_FAILED;
   }

   /* get the block data length */
   if (fread (&blockLength, sizeof (unsigned int), 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }
   blockLength = swap32 (blockLength);

   /* skip over the block data */
   if (fseek (snssFile->fp, blockLength, SEEK_CUR) != 0)
   {
      return SNSS_READ_FAILED;
   }

   return SNSS_OK;
}

/**************************************************************************/
/* functions for reading and writing base register blocks */
/**************************************************************************/

static SNSS_RETURN_CODE 
SNSS_ReadBaseBlock (SNSS_FILE *snssFile)
{
   char blockBytes[BASE_BLOCK_LENGTH];
   SnssBlockHeader header;

   if (SNSS_ReadBlockHeader (&header, snssFile) != SNSS_OK)
   {
      return SNSS_READ_FAILED;
   }

   if (fread (blockBytes, MIN (header.blockLength, BASE_BLOCK_LENGTH), 1, snssFile->fp) != 1)
   {
      return SNSS_READ_FAILED;
   }

   snssFile->baseBlock.regA = blockBytes[0x0];
   snssFile->baseBlock.regX = blockBytes[0x1];
   snssFile->baseBlock.regY = blockBytes[0x2];
   snssFile->baseBlock.regFlags = blockBytes[0x3];
   snssFile->baseBlock.regStack = blockBytes[0x4];
   snssFile->baseBlock.regPc = *((unsigned short *) &blockBytes[0x5]);
   snssFile->baseBlock.regPc = swap16 (snssFile->baseBlock.regPc);
   snssFile->baseBlock.reg2000 = blockBytes[0x7];
   snssFile->baseBlock.reg2001 = blockBytes[0x8];
   memcpy (&snssFile->baseBlock.cpuRam, &blockBytes[0x9], 0x800);
   memcpy (&snssFile->baseBlock.spriteRam, &blockBytes[0x809], 0x100);
   memcpy (&snssFile->baseBlock.ppuRam, &blockBytes[0x909], 0x1000);
   memcpy (&snssFile->baseBlock.palette, &blockBytes[0x1909], 0x20);
   memcpy (&snssFile->baseBlock.mirrorState, &blockBytes[0x1929], 0x4);
   snssFile->baseBlock.vramAddress = *((unsigned short *) &blockBytes[0x192D]);
   snssFile->baseBlock.vramAddress = swap16 (snssFile->baseBlock.vramAddress);
   snssFile->baseBlock.spriteRamAddress = blockBytes[0x192F];
   snssFile->baseBlock.tileXOffset = blockBytes[0x1930];

   return SNSS_OK;
}

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

static SNSS_RETURN_CODE 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -