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

📄 jma.cpp

📁 linux下的任天堂模拟器代码。供大家参考。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <sstream>#include "jma.h"using namespace std;#include "portable.h"#include "7z.h"#include "crc32.h"namespace JMA{  const char jma_magic[] = { 'J', 'M', 'A', 0, 'N' };  const unsigned int jma_header_length = 5;  const unsigned char jma_version = 1;  const unsigned int jma_version_length = 1;  const unsigned int jma_total_header_length = jma_header_length + jma_version_length + UINT_SIZE;  //Convert DOS/zip/JMA integer time to to time_t  time_t uint_to_time(unsigned short date, unsigned short time)  {    tm formatted_time;    formatted_time.tm_mday = date & 0x1F;    formatted_time.tm_mon  = ((date >> 5) & 0xF) - 1;    formatted_time.tm_year = ((date >> 9) & 0x7f) + 80;    formatted_time.tm_sec  = (time & 0x1F) * 2;    formatted_time.tm_min  = (time >> 5) & 0x3F;    formatted_time.tm_hour = (time >> 11) & 0x1F;    return(mktime(&formatted_time));  }  //Retreive the file block, what else?  void jma_open::retrieve_file_block() throw(jma_errors)  {    unsigned char uint_buffer[UINT_SIZE];    unsigned char ushort_buffer[USHORT_SIZE];    //File block size is the last UINT in the file    stream.seekg(-UINT_SIZE,ios::end);    stream.read((char *)uint_buffer, UINT_SIZE);    size_t file_block_size = charp_to_uint(uint_buffer);    //Currently at the end of the file, so that's the file size    size_t jma_file_size = stream.tellg();    //The file block can't be larger than the JMA file without it's header.    //This if can probably be improved    if (file_block_size >= jma_file_size-jma_total_header_length)    {      throw(JMA_BAD_FILE);    }    //Seek to before file block so we can read the file block    stream.seekg(-((int)file_block_size+UINT_SIZE),ios::end);    //This is needed if the file block is compressed    stringstream decompressed_file_block;    //Pointer to where to read file block from (file or decompressed buffer)    istream *file_block_stream;    //Setup file info buffer and byte to read with    jma_file_info file_info;    char byte;    stream.get(byte);    if (!byte) //If file block is compressed    {      //Compressed size isn't counting the byte we just read or the UINT for compressed size      size_t compressed_size = file_block_size - (1+UINT_SIZE);      //Read decompressed size / true file block size      stream.read((char *)uint_buffer, UINT_SIZE);      file_block_size = charp_to_uint(uint_buffer);      //Setup access methods for decompression      ISequentialInStream_Istream compressed_data(stream);      ISequentialOutStream_Ostream decompressed_data(decompressed_file_block);      //Decompress the data      if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, file_block_size))      {        throw(JMA_DECOMPRESS_FAILED);      }      //Go to beginning, setup pointer to buffer      decompressed_file_block.seekg(0, ios::beg);      file_block_stream = &decompressed_file_block;    }    else    {      stream.putback(byte); //Putback byte, byte is part of filename, not compressed indicator      file_block_stream = &stream;    }    //Minimum file name length is 2 bytes, a char and a null    //Minimum comment length is 1 byte, a null    //There are currently 2 UINTs and 2 USHORTs per file    while (file_block_size >= 2+1+UINT_SIZE*2+USHORT_SIZE*2) //This does allow for a gap, but that's okay    {      //First stored in the file block is the file name null terminated      file_info.name = "";      file_block_stream->get(byte);      while (byte)      {        file_info.name += byte;        file_block_stream->get(byte);      }      //There must be a file name or the file is bad      if (!file_info.name.length())      {        throw(JMA_BAD_FILE);      }      //Same trick as above for the comment      file_info.comment = "";      file_block_stream->get(byte);      while (byte)      {        file_info.comment += byte;        file_block_stream->get(byte);      }      //Next is a UINT representing the file's size      file_block_stream->read((char *)uint_buffer, UINT_SIZE);      file_info.size = charp_to_uint(uint_buffer);      //Followed by CRC32      file_block_stream->read((char *)uint_buffer, UINT_SIZE);      file_info.crc32 = charp_to_uint(uint_buffer);      //Special USHORT representation of file's date      file_block_stream->read((char *)ushort_buffer, USHORT_SIZE);      file_info.date = charp_to_ushort(ushort_buffer);      //Special USHORT representation of file's time      file_block_stream->read((char *)ushort_buffer, USHORT_SIZE);      file_info.time = charp_to_ushort(ushort_buffer);      file_info.buffer = 0; //Pointing to null till we decompress files      files.push_back(file_info); //Put file info into our structure      //Subtract size of the file info we just read      file_block_size -= file_info.name.length()+file_info.comment.length()+2+UINT_SIZE*2+USHORT_SIZE*2;    }  }  //Constructor for opening JMA files for reading  jma_open::jma_open(const char *compressed_file_name) throw (jma_errors)  {    decompressed_buffer = 0;    compressed_buffer = 0;    stream.open(compressed_file_name, ios::in | ios::binary);    if (!stream.is_open())    {      throw(JMA_NO_OPEN);    }    //Header is "JMA\0N"    unsigned char header[jma_header_length];    stream.read((char *)header, jma_header_length);    if (memcmp(jma_magic, header, jma_header_length))    {      throw(JMA_BAD_FILE);    }    //Not the cleanest code but logical    stream.read((char *)header, 5);    if (*header <= jma_version)    {      chunk_size = charp_to_uint(header+1); //Chunk size is a UINT that follows version #      retrieve_file_block();    }    else    {      throw(JMA_UNSUPPORTED_VERSION);    }  }  //Destructor only has to close the stream if neccesary  jma_open::~jma_open()  {    if (stream.is_open())    {      stream.close();    }  }  //Return a vector containing useful info about the files in the JMA  vector<jma_public_file_info> jma_open::get_files_info()  {    vector<jma_public_file_info> file_info_vector;    jma_public_file_info file_info;    for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++)    {      file_info.name = i->name;      file_info.comment = i->comment;      file_info.size = i->size;      file_info.datetime = uint_to_time(i->date, i->time);      file_info.crc32 = i->crc32;      file_info_vector.push_back(file_info);    }    return(file_info_vector);  }  //Skip forward a given number of chunks  void jma_open::chunk_seek(unsigned int chunk_num) throw(jma_errors)  {    //Check the stream is open    if (!stream.is_open())    {      throw(JMA_NO_OPEN);    }    //Clear possible errors so the seek will work    stream.clear();    //Move forward over header    stream.seekg(jma_total_header_length, ios::beg);    unsigned char int4_buffer[UINT_SIZE];    while (chunk_num--)    {      //Read in size of chunk      stream.read((char *)int4_buffer, UINT_SIZE);      //Skip chunk plus it's CRC32      stream.seekg(charp_to_uint(int4_buffer)+UINT_SIZE, ios::cur);    }  }  //Return a vector of pointers to each file in the JMA, the buffer to hold all the files  //must be initilized outside.  vector<unsigned char *> jma_open::get_all_files(unsigned char *buffer) throw(jma_errors)  {    //If there's no stream we can't read from it, so exit    if (!stream.is_open())    {      throw(JMA_NO_OPEN);    }    //Seek to the first chunk    chunk_seek(0);    //Set the buffer that decompressed data goes to    decompressed_buffer = buffer;    //If the JMA is not solid    if (chunk_size)    {

⌨️ 快捷键说明

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