uint32_t crc32_calculate(const uint8_t *data, size_t length) { size_t i; uint32_t checksum = ~0; for (i = 0; i < length; i++) checksum = crc32_adjust(checksum, data[i]); return ~checksum; }
void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) { mode = cartridge_mode; region = Region::NTSC; ram_size = 0; spc7110_data_rom_offset = 0x100000; st_A_ram_size = 0; st_B_ram_size = 0; supergameboy_version = SuperGameBoyVersion::Version1; supergameboy_ram_size = 0; supergameboy_rtc_size = 0; has_bsx_slot = false; has_superfx = false; has_sa1 = false; has_necdsp = false; has_srtc = false; has_sdd1 = false; has_spc7110 = false; has_spc7110rtc = false; has_cx4 = false; has_obc1 = false; has_st0018 = false; has_msu1 = false; has_serial = false; parse_xml(xml_list); //print(xml_list[0], "\n\n"); if(ram_size > 0) { memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size); } if(has_srtc || has_spc7110rtc) { memory::cartrtc.map(allocate<uint8_t>(20, 0xff), 20); } if(mode == Mode::Bsx) { memory::bsxram.map (allocate<uint8_t>( 32 * 1024, 0xff), 32 * 1024); memory::bsxpram.map(allocate<uint8_t>(512 * 1024, 0xff), 512 * 1024); } if(mode == Mode::SufamiTurbo) { if(st_A_ram_size) memory::stAram.map(allocate<uint8_t>(st_A_ram_size, 0xff), st_A_ram_size); if(st_B_ram_size) memory::stBram.map(allocate<uint8_t>(st_B_ram_size, 0xff), st_B_ram_size); } if(mode == Mode::SuperGameBoy) { if(memory::gbrom.data()) { if(supergameboy_ram_size) memory::gbram.map(allocate<uint8_t>(supergameboy_ram_size, 0xff), supergameboy_ram_size); if(supergameboy_rtc_size) memory::gbrtc.map(allocate<uint8_t>(supergameboy_rtc_size, 0x00), supergameboy_rtc_size); } } memory::cartrom.write_protect(true); memory::cartram.write_protect(false); memory::cartrtc.write_protect(false); memory::bsxflash.write_protect(true); memory::bsxram.write_protect(false); memory::bsxpram.write_protect(false); memory::stArom.write_protect(true); memory::stAram.write_protect(false); memory::stBrom.write_protect(true); memory::stBram.write_protect(false); memory::gbrom.write_protect(true); memory::gbram.write_protect(false); memory::gbrtc.write_protect(false); unsigned checksum = ~0; foreach(n, memory::cartrom ) checksum = crc32_adjust(checksum, n); if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0) foreach(n, memory::bsxflash) checksum = crc32_adjust(checksum, n); if(memory::stArom.size() != 0 && memory::stArom.size() != ~0) foreach(n, memory::stArom ) checksum = crc32_adjust(checksum, n); if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0) foreach(n, memory::stBrom ) checksum = crc32_adjust(checksum, n); if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0) foreach(n, memory::gbrom ) checksum = crc32_adjust(checksum, n); crc32 = ~checksum; sha256_ctx sha; uint8_t shahash[32]; sha256_init(&sha); sha256_chunk(&sha, memory::cartrom.data(), memory::cartrom.size()); sha256_final(&sha); sha256_hash(&sha, shahash); string hash; foreach(n, shahash) hash << hex<2>(n); sha256 = hash; bus.load_cart(); system.serialize_init(); loaded = true; }
void Cartridge::load(Mode cartridge_mode) { mode = cartridge_mode; read_header(memory::cartrom.data(), memory::cartrom.size()); if(ram_size > 0) { memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size); } if(has_srtc || has_spc7110rtc) { memory::cartrtc.map(allocate<uint8_t>(20, 0xff), 20); } if(mode == ModeBsx) { memory::bsxram.map (allocate<uint8_t>( 32 * 1024, 0xff), 32 * 1024); memory::bsxpram.map(allocate<uint8_t>(512 * 1024, 0xff), 512 * 1024); } if(mode == ModeSufamiTurbo) { if(memory::stArom.data()) memory::stAram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024); if(memory::stBrom.data()) memory::stBram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024); } if(mode == ModeSuperGameBoy) { if(memory::gbrom.data()) { unsigned ram_size = gameboy_ram_size(); unsigned rtc_size = gameboy_rtc_size(); if(ram_size) memory::gbram.map(allocate<uint8_t>(ram_size, 0xff), ram_size); if(rtc_size) memory::gbrtc.map(allocate<uint8_t>(rtc_size, 0x00), rtc_size); } } memory::cartrom.write_protect(true); memory::cartram.write_protect(false); memory::cartrtc.write_protect(false); memory::bsxflash.write_protect(true); memory::bsxram.write_protect(false); memory::bsxpram.write_protect(false); memory::stArom.write_protect(true); memory::stAram.write_protect(false); memory::stBrom.write_protect(true); memory::stBram.write_protect(false); memory::gbrom.write_protect(true); memory::gbram.write_protect(false); memory::gbrtc.write_protect(false); unsigned checksum = ~0; for(unsigned n = 0; n < memory::cartrom.size(); n++) checksum = crc32_adjust(checksum, memory::cartrom[n]); if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0) for(unsigned n = 0; n < memory::bsxflash.size(); n++) checksum = crc32_adjust(checksum, memory::bsxflash[n]); if(memory::stArom.size() != 0 && memory::stArom.size() != ~0) for(unsigned n = 0; n < memory::stArom.size(); n++) checksum = crc32_adjust(checksum, memory::stArom[n]); if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0) for(unsigned n = 0; n < memory::stBrom.size(); n++) checksum = crc32_adjust(checksum, memory::stBrom[n]); if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0) for(unsigned n = 0; n < memory::gbrom.size(); n++) checksum = crc32_adjust(checksum, memory::gbrom[n]); crc32 = ~checksum; #if 0 fprintf(stdout, "crc32 = %.8x\n", (unsigned)crc32); sha256_ctx sha; uint8_t shahash[32]; sha256_init(&sha); sha256_chunk(&sha, memory::cartrom.data(), memory::cartrom.size()); sha256_final(&sha); sha256_hash(&sha, shahash); fprintf(stdout, "sha256 = "); for(unsigned i = 0; i < 32; i++) fprintf(stdout, "%.2x", shahash[i]); fprintf(stdout, "\n"); #endif bus.load_cart(); system.serialize_init(); loaded = true; }
bool bpslinear::create(const string &filename, const string &metadata) { file modifyFile; if(modifyFile.open(filename, file::mode::write) == false) return false; uint32_t modifyChecksum = ~0; unsigned targetRelativeOffset = 0, outputOffset = 0; auto write = [&](uint8_t data) { modifyFile.write(data); modifyChecksum = crc32_adjust(modifyChecksum, data); }; auto encode = [&](uint64_t data) { while(true) { uint64_t x = data & 0x7f; data >>= 7; if(data == 0) { write(0x80 | x); break; } write(x); data--; } }; unsigned targetReadLength = 0; auto targetReadFlush = [&]() { if(targetReadLength) { encode(TargetRead | ((targetReadLength - 1) << 2)); unsigned offset = outputOffset - targetReadLength; while(targetReadLength) write(targetData[offset++]), targetReadLength--; } }; write('B'); write('P'); write('S'); write('1'); encode(sourceSize); encode(targetSize); unsigned markupSize = metadata.length(); encode(markupSize); for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); while(outputOffset < targetSize) { unsigned sourceLength = 0; for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) { if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break; sourceLength++; } unsigned rleLength = 0; for(unsigned n = 1; outputOffset + n < targetSize; n++) { if(targetData[outputOffset] != targetData[outputOffset + n]) break; rleLength++; } if(rleLength >= 4) { //write byte to repeat targetReadLength++; outputOffset++; targetReadFlush(); //copy starting from repetition byte encode(TargetCopy | ((rleLength - 1) << 2)); unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset; encode(relativeOffset << 1); outputOffset += rleLength; targetRelativeOffset = outputOffset - 1; } else if(sourceLength >= 4) { targetReadFlush(); encode(SourceRead | ((sourceLength - 1) << 2)); outputOffset += sourceLength; } else { targetReadLength += Granularity; outputOffset += Granularity; } } targetReadFlush(); uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize); for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); uint32_t targetChecksum = crc32_calculate(targetData, targetSize); for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); uint32_t outputChecksum = ~modifyChecksum; for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); modifyFile.close(); return true; }
bool bpsdelta::create(const string& filename, const string& metadata) { file modifyFile; if(modifyFile.open(filename, file::mode::write) == false) return false; uint32_t sourceChecksum = ~0, modifyChecksum = ~0; unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; auto write = [&](uint8_t data) { modifyFile.write(data); modifyChecksum = crc32_adjust(modifyChecksum, data); }; auto encode = [&](uint64_t data) { while(true) { uint64_t x = data & 0x7f; data >>= 7; if(data == 0) { write(0x80 | x); break; } write(x); data--; } }; write('B'); write('P'); write('S'); write('1'); encode(sourceSize); encode(targetSize); unsigned markupSize = metadata.length(); encode(markupSize); for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); Node* sourceTree[65536]; Node* targetTree[65536]; for(unsigned n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr; //source tree creation for(unsigned offset = 0; offset < sourceSize; offset++) { uint16_t symbol = sourceData[offset + 0]; sourceChecksum = crc32_adjust(sourceChecksum, symbol); if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8; Node *node = new Node; node->offset = offset; node->next = sourceTree[symbol]; sourceTree[symbol] = node; } unsigned targetReadLength = 0; auto targetReadFlush = [&]() { if(targetReadLength) { encode(TargetRead | ((targetReadLength - 1) << 2)); unsigned offset = outputOffset - targetReadLength; while(targetReadLength) write(targetData[offset++]), targetReadLength--; } }; while(outputOffset < targetSize) { unsigned maxLength = 0, maxOffset = 0, mode = TargetRead; uint16_t symbol = targetData[outputOffset + 0]; if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8; { //source read unsigned length = 0, offset = outputOffset; while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { length++; offset++; } if(length > maxLength) maxLength = length, mode = SourceRead; } { //source copy Node* node = sourceTree[symbol]; while(node) { unsigned length = 0, x = node->offset, y = outputOffset; while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++; if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy; node = node->next; } } { //target copy Node* node = targetTree[symbol]; while(node) { unsigned length = 0, x = node->offset, y = outputOffset; while(y < targetSize && targetData[x++] == targetData[y++]) length++; if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy; node = node->next; } //target tree append node = new Node; node->offset = outputOffset; node->next = targetTree[symbol]; targetTree[symbol] = node; } { //target read if(maxLength < 4) { maxLength = min((unsigned)Granularity, targetSize - outputOffset); mode = TargetRead; } } if(mode != TargetRead) targetReadFlush(); switch(mode) { case SourceRead: encode(SourceRead | ((maxLength - 1) << 2)); break; case TargetRead: //delay write to group sequential TargetRead commands into one targetReadLength += maxLength; break; case SourceCopy: case TargetCopy: encode(mode | ((maxLength - 1) << 2)); signed relativeOffset; if(mode == SourceCopy) { relativeOffset = maxOffset - sourceRelativeOffset; sourceRelativeOffset = maxOffset + maxLength; } else { relativeOffset = maxOffset - targetRelativeOffset; targetRelativeOffset = maxOffset + maxLength; } encode((relativeOffset < 0) | (abs(relativeOffset) << 1)); break; } outputOffset += maxLength; } targetReadFlush(); sourceChecksum = ~sourceChecksum; for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); uint32_t targetChecksum = crc32_calculate(targetData, targetSize); for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); uint32_t outputChecksum = ~modifyChecksum; for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); modifyFile.close(); return true; }
void write(uint8_t data) { fp.write(data); checksum = crc32_adjust(checksum, data); }