diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 6927ba9b4f3..02c5986d6ad 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -3390,6 +3390,8 @@ files { MAME_DIR .. "src/mame/video/rdpblend.h", MAME_DIR .. "src/mame/video/rdptpipe.cpp", MAME_DIR .. "src/mame/video/rdptpipe.h", + MAME_DIR .. "src/mame/video/pin64.cpp", + MAME_DIR .. "src/mame/video/pin64.h", MAME_DIR .. "src/mame/drivers/hanaawas.cpp", MAME_DIR .. "src/mame/includes/hanaawas.h", MAME_DIR .. "src/mame/video/hanaawas.cpp", diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 9c30f686d08..db5099da55a 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -1172,6 +1172,8 @@ files { MAME_DIR .. "src/mame/video/rdpblend.h", MAME_DIR .. "src/mame/video/rdptpipe.cpp", MAME_DIR .. "src/mame/video/rdptpipe.h", + MAME_DIR .. "src/mame/video/pin64.cpp", + MAME_DIR .. "src/mame/video/pin64.h", MAME_DIR .. "src/mame/machine/megadriv.cpp", MAME_DIR .. "src/mame/drivers/naomi.cpp", MAME_DIR .. "src/mame/includes/naomi.h", diff --git a/src/mame/video/n64.h b/src/mame/video/n64.h index e1b0dd983ca..46b1fd243f8 100644 --- a/src/mame/video/n64.h +++ b/src/mame/video/n64.h @@ -6,6 +6,7 @@ #include "emu.h" #include "includes/n64.h" #include "video/poly.h" +#include "pin64.h" /*****************************************************************************/ @@ -367,6 +368,8 @@ private: int32_t m_norm_point_rom[64]; int32_t m_norm_slope_rom[64]; + pin64_t m_capture; + static uint32_t s_special_9bit_clamptable[512]; static const z_decompress_entry_t m_z_dec_table[8]; diff --git a/src/mame/video/pin64.cpp b/src/mame/video/pin64.cpp new file mode 100644 index 00000000000..4314820a434 --- /dev/null +++ b/src/mame/video/pin64.cpp @@ -0,0 +1,408 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz + +#include "pin64.h" + +#define CAP_NAME "pin64_%d.cap" + +// pin64_fileutil_t members + +void pin64_fileutil_t::write(FILE* file, uint32_t data) +{ + if (file == nullptr) + return; + + uint8_t temp(data >> 24); + fwrite(&temp, 1, 1, file); + + temp = (uint8_t)(data >> 16); + fwrite(&temp, 1, 1, file); + + temp = (uint8_t)(data >> 8); + fwrite(&temp, 1, 1, file); + + temp = (uint8_t)data; + fwrite(&temp, 1, 1, file); +} + +void pin64_fileutil_t::write(FILE* file, const uint8_t* data, uint32_t size) +{ + if (file == nullptr) + return; + + fwrite(data, 1, size, file); +} + +// pin64_block_t members + +void pin64_block_t::put8(uint8_t data) +{ + m_data.push_back(data); + m_offset++; +} + +void pin64_block_t::put16(uint16_t data) +{ + put8((uint8_t)(data >> 8)); + put8((uint8_t)data); +} + +void pin64_block_t::put32(uint32_t data) +{ + put16((uint16_t)(data >> 16)); + put16((uint16_t)data); +} + +uint8_t pin64_block_t::get8() +{ + if (m_offset >= m_data.size()) + fatalerror("PIN64: Call to get8() at end of block (requested offset %x, size %x)\n", m_offset, (uint32_t)m_data.size()); + + uint8_t ret = m_data[m_offset]; + m_offset++; + + return ret; +} + +uint16_t pin64_block_t::get16() +{ + uint16_t ret = 0; + ret |= get8() << 8; + ret |= get8(); + + return ret; +} + +uint32_t pin64_block_t::get32() +{ + uint32_t ret = 0; + ret |= get16() << 16; + ret |= get16(); + + return ret; +} + +uint8_t pin64_block_t::get8(uint32_t offset, bool update_current) +{ + update_offset(offset, update_current); + + uint8_t ret = get8(); + m_offset = m_old_offset; + return ret; +} + +uint16_t pin64_block_t::get16(uint32_t offset, bool update_current) +{ + update_offset(offset, update_current); + + uint16_t ret = get16(); + m_offset = m_old_offset; + return ret; +} + +uint32_t pin64_block_t::get32(uint32_t offset, bool update_current) +{ + update_offset(offset, update_current); + + uint32_t ret = get32(); + m_offset = m_old_offset; + return ret; +} + +uint32_t pin64_block_t::data_size() +{ + return m_data.size(); +} + +uint32_t pin64_block_t::size() +{ + return sizeof(uint32_t) * 2 + data_size(); +} + +void pin64_block_t::clear() +{ + reset(); + m_crc32 = 0; + m_data.clear(); +} + +void pin64_block_t::reset() +{ + m_old_offset = 0; + m_offset = 0; +} + +void pin64_block_t::finalize() +{ + if (m_data.size() > 0) + m_crc32 = util::crc32_creator::simple(&m_data[0], m_data.size()); + else + m_crc32 = ~0; + reset(); +} + +void pin64_block_t::write(FILE* file) +{ + pin64_fileutil_t::write(file, m_crc32); + pin64_fileutil_t::write(file, m_data.size()); + if (m_data.size() > 0) + pin64_fileutil_t::write(file, &m_data[0], m_data.size()); +} + +void pin64_block_t::update_offset(uint32_t offset, bool update_current) +{ + m_old_offset = (update_current ? offset : m_offset); + m_offset = offset; +} + +// pin64_frame_t members + +const uint8_t pin64_t::pin64_frame_t::FRAME_ID[8] = { 'P', 'I', 'N', '6', '4', 'F', 'R', 'M' }; + +pin64_t::pin64_frame_t::~pin64_frame_t() +{ + clear(); +} + +uint32_t pin64_t::pin64_frame_t::size() +{ + return header_size() + directory_size() + blocks_size() + m_commands.size(); +} + +uint32_t pin64_t::pin64_frame_t::header_size() +{ + return sizeof(uint8_t) * 8 // "PIN64FRM" + + sizeof(uint32_t) // total file size + + sizeof(uint32_t) // start of directory data + + sizeof(uint32_t) // start of block data + + sizeof(uint32_t); // start of command data +} + +uint32_t pin64_t::pin64_frame_t::directory_size() +{ + return m_blocks.size() * sizeof(uint32_t); +} + +uint32_t pin64_t::pin64_frame_t::blocks_size() +{ + uint32_t block_size = 0; + for (pin64_block_t* block : m_blocks) + block_size += block->size(); + + return block_size; +} + +pin64_block_t* pin64_t::pin64_frame_t::start_block() +{ + m_blocks.push_back(new pin64_block_t()); + return m_blocks[m_blocks.size() - 1]; +} + +void pin64_t::pin64_frame_t::write(FILE* file) { + const uint32_t size_total = size(); + const uint32_t size_header = header_size(); + const uint32_t size_dir = directory_size(); + const uint32_t size_blocks = blocks_size(); + + std::vector directory; + fill_directory(directory); + + pin64_fileutil_t::write(file, FRAME_ID, 8); + pin64_fileutil_t::write(file, size_total); + pin64_fileutil_t::write(file, size_header); + pin64_fileutil_t::write(file, size_header + size_dir); + pin64_fileutil_t::write(file, size_header + size_dir + size_blocks); + + for (uint32_t entry : directory) + pin64_fileutil_t::write(file, entry); + + for (pin64_block_t* block : m_blocks) + block->write(file); + + m_commands.write(file); +} + +void pin64_t::pin64_frame_t::fill_directory(std::vector& directory) { + uint32_t offset = header_size() + directory_size(); + for (pin64_block_t* block : m_blocks) { + directory.push_back(offset); + offset += block->size(); + } +} + +void pin64_t::pin64_frame_t::clear() { + for (pin64_block_t* block : m_blocks) + delete block; + + m_blocks.clear(); + m_commands.clear(); + + m_current_block = nullptr; +} + +pin64_block_t** pin64_t::pin64_frame_t::blocks() { + return (m_blocks.size() == 0) ? nullptr : &m_blocks[0]; +} + +// pin64_t members + +const uint8_t pin64_t::CAP_ID[8] = { 'P', 'I', 'N', '6', '4', 'C', 'A', 'P' }; + +pin64_t::~pin64_t() +{ + if (m_capture_file != nullptr) + finish(); + + clear(); +} + +void pin64_t::start(int frames) +{ + if (m_capture_index == ~0) + init_capture_index(); + + if (m_capture_file != nullptr) + fatalerror("PIN64: Call to start() while already capturing\n"); + + char name_buf[256]; + sprintf(name_buf, CAP_NAME, m_capture_index); + m_capture_index++; + + m_capture_file = fopen(name_buf, "wb"); + + m_capture_frames = frames; +} + +void pin64_t::finish() { + if (!m_capture_file) + return; + + write(m_capture_file); + fclose(m_capture_file); + m_capture_file = nullptr; + + clear(); +} + +pin64_t::pin64_frame_t* pin64_t::start_frame() +{ + if (!m_capture_file) + return nullptr; + + m_frames.push_back(new pin64_frame_t()); + return m_frames[m_frames.size() - 1]; +} + +void pin64_t::mark_frame(running_machine& machine) { + if (m_capture_file) { + if (m_frames.size() == m_capture_frames) { + finish(); + } else { + m_current_frame = start_frame(); + } + } + + if (machine.input().code_pressed_once(KEYCODE_N) && !m_capture_file) { + start(1); + } else if (machine.input().code_pressed_once(KEYCODE_M)) { + if (m_capture_file) { + finish(); + } else { + start(); + } + } +} + +uint32_t pin64_t::size() +{ + return header_size() + directory_size() + frames_size(); +} + +uint32_t pin64_t::header_size() +{ + return sizeof(uint8_t) * 8 // "PIN64CAP" + + sizeof(uint32_t) // total file size + + sizeof(uint32_t) // start of directory data + + sizeof(uint32_t); // start of frame data +} + +uint32_t pin64_t::directory_size() +{ + return m_frames.size() * sizeof(uint32_t); +} + +uint32_t pin64_t::frames_size() +{ + uint32_t frames_size = 0; + for (pin64_frame_t* frame : m_frames) + frames_size += frame->size(); + + return frames_size; +} + +void pin64_t::write(FILE* file) { + const uint32_t size_total = size(); + const uint32_t size_header = header_size(); + const uint32_t size_dir = directory_size(); + const uint32_t size_frames = frames_size(); + + std::vector directory; + fill_directory(directory); + + pin64_fileutil_t::write(file, CAP_ID, 8); + pin64_fileutil_t::write(file, size_total); + pin64_fileutil_t::write(file, size_header); + pin64_fileutil_t::write(file, size_header + size_dir); + pin64_fileutil_t::write(file, size_header + size_dir + size_frames); + + for (uint32_t entry : directory) + pin64_fileutil_t::write(file, entry); + + for (pin64_frame_t* frame : m_frames) + frame->write(file); +} + +void pin64_t::fill_directory(std::vector& directory) { + uint32_t offset = header_size() + directory_size(); + for (pin64_frame_t* frame : m_frames) { + directory.push_back(offset); + offset += frame->size(); + } +} + +void pin64_t::clear() { + if (m_capture_file != nullptr) { + fclose(m_capture_file); + m_capture_file = nullptr; + } + + for (pin64_frame_t* frame : m_frames) + delete frame; + + m_frames.clear(); + m_current_frame = nullptr; +} + +void pin64_t::init_capture_index() +{ + char name_buf[256]; + bool found = true; + + m_capture_index = 0; + + do + { + sprintf(name_buf, CAP_NAME, m_capture_index); + + FILE* temp = fopen(name_buf, "rb"); + if (temp == nullptr) + { + break; + } + else + { + fclose(temp); + m_capture_index++; + } + } while(found); +} diff --git a/src/mame/video/pin64.h b/src/mame/video/pin64.h new file mode 100644 index 00000000000..ffc2c52a44c --- /dev/null +++ b/src/mame/video/pin64.h @@ -0,0 +1,133 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +#pragma once + +#ifndef PIN64_H +#define PIN64_H + +#include +#include + +#include "emu.h" + +class pin64_fileutil_t +{ +public: + static void write(FILE* file, uint32_t data); + static void write(FILE* file, const uint8_t* data, uint32_t size); +}; + +class pin64_block_t +{ +public: + pin64_block_t() + : m_crc32{ 0 } + , m_offset(0) + , m_old_offset(0) + { } + + void put8(uint8_t data); + void put16(uint16_t data); + void put32(uint32_t data); + + void clear(); + void finalize(); + void reset(); + + void write(FILE* file); + + // getters + uint8_t get8(); + uint8_t get8(uint32_t offset, bool update_current = true); + uint16_t get16(); + uint16_t get16(uint32_t offset, bool update_current = true); + uint32_t get32(); + uint32_t get32(uint32_t offset, bool update_current = true); + + util::crc32_t crc32() const { return m_crc32; } + uint8_t* bytes() { return &m_data[0]; } + uint32_t data_size(); + uint32_t size(); + +private: + void update_offset(uint32_t offset, bool update_current = true); + + util::crc32_t m_crc32; + std::vector m_data; + + uint32_t m_offset; + uint32_t m_old_offset; +}; + +class pin64_t +{ +public: + pin64_t() + : m_capture_file(nullptr) + , m_capture_index(~0) + , m_capture_frames(0) + , m_current_frame(nullptr) + { } + ~pin64_t(); + + void start(int frames = 0); + void finish(); + void mark_frame(running_machine& machine); + + void clear(); + + bool capturing() const { return m_capture_file != nullptr; } + + uint32_t size(); + +private: + class pin64_frame_t { + public: + pin64_frame_t() { } + ~pin64_frame_t(); + + uint32_t size(); + + pin64_block_t* start_block(); + + void write(FILE* file); + void clear(); + + pin64_block_t& commands() { return m_commands; } + pin64_block_t** blocks(); + + private: + uint32_t header_size(); + uint32_t directory_size(); + uint32_t blocks_size(); + + void fill_directory(std::vector& directory); + + pin64_block_t* m_current_block; + std::vector m_blocks; + pin64_block_t m_commands; + + static const uint8_t FRAME_ID[8]; + }; + + void write(FILE* file); + pin64_t::pin64_frame_t* start_frame(); + + uint32_t header_size(); + uint32_t directory_size(); + uint32_t frames_size(); + + void fill_directory(std::vector& directory); + void init_capture_index(); + + FILE *m_capture_file; + int32_t m_capture_index; + int m_capture_frames; + + pin64_frame_t* m_current_frame; + std::vector m_frames; + + static const uint8_t CAP_ID[8]; +}; + +#endif // PIN64_H \ No newline at end of file