#include #ifndef LOCUTUS_TYPES_HPP_ #define LOCUTUS_TYPES_HPP_ #include #include #include #include #include #include #include #include #include #include #include "metadata/metadata.h" static const int LOCUTUS_PERM_READ = 0; static const int LOCUTUS_PERM_WRITE = 1; static const int LOCUTUS_PERM_NARROW = 2; // allow writes to 8 LSBs only static const int LOCUTUS_PERM_BANKSW = 3; // Bankswitch / Pageflip enable typedef std::bitset< 4 > t_perm; typedef std::pair< uint32_t, uint32_t > t_addr_span; typedef std::list< t_addr_span > t_addr_list; typedef std::vector< uint8_t > t_byte_vec; typedef std::vector< uint16_t > t_word_vec; typedef std::vector< std::string > t_string_vec; typedef std::vector< game_date_t > t_game_date_vec; typedef std::pair< std::string, std::string > t_var; typedef std::vector< t_var > t_var_vec; static const int PAGE_NONE = 0xFF; // ------------------------------------------------------------------------ // // T_BIN_HUNK // // ------------------------------------------------------------------------ // struct t_bin_hunk { uint32_t s_addr, e_addr; // Locutus addresses uint8_t page; // ECS page (0xFF if none) bool mapped; // True == map to INTV space at s_addr t_word_vec data; // actual ROM data t_perm perm; // permissions t_bin_hunk( const uint32_t s_addr_, const uint32_t e_addr_, const uint8_t page_, const bool mapped_, const t_word_vec data_, const t_perm perm_ = 0 ) : s_addr( s_addr_ ), e_addr( e_addr_ ), page( page_ ), mapped( mapped_ ), data( data_ ), perm( perm_ ) { } t_bin_hunk( const uint32_t s_addr_, const uint32_t e_addr_, const uint8_t page_, const bool mapped_, const uint16_t* data_, const t_perm perm_ = 0 ) : s_addr( s_addr_ ), e_addr( e_addr_ ), page( page_ ), mapped( mapped_ ), data( ), perm( perm_ ) { data.resize( e_addr_ - s_addr_ + 1, 0 ); if ( data_ ) std::memcpy( static_cast(&data[0]), static_cast(&data_[0]), sizeof( uint16_t ) * data.size() ); } inline bool operator < ( const t_bin_hunk& rhs ) const { return page < rhs.page ? true : page == rhs.page && s_addr < rhs.s_addr ? true : false; } static bool page_then_addr( const t_bin_hunk& lhs, const t_bin_hunk& rhs ) { return lhs.page < rhs.page ? true : lhs.page == rhs.page && lhs.s_addr < rhs.s_addr ? true : false; } static bool addr_then_page( const t_bin_hunk& lhs, const t_bin_hunk& rhs ) { return lhs.s_addr < rhs.s_addr ? true : lhs.s_addr == rhs.s_addr &&lhs.page < rhs.page ? true : false; } inline bool can_merge_with( const t_bin_hunk& rhs ) const { return e_addr == rhs.s_addr - 1 && page == rhs.page && mapped == rhs.mapped; } inline void merge_with( const t_bin_hunk& rhs ) { assert( can_merge_with( rhs ) ); e_addr = rhs.e_addr; data.insert( data.end(), rhs.data.begin(), rhs.data.end() ); } // After split, e_addr = split_addr - 1, and we return a new hunk starting // at split_addr ending at the old e_addr. That is: // this => [ s_addr, split_addr ) // new => [ split_addr, e_addr ] t_bin_hunk split_at( const uint32_t split_addr ) { assert( split_addr > s_addr && split_addr <= e_addr ); t_bin_hunk new_hunk( split_addr, e_addr, page, mapped, &data[split_addr - s_addr] ); e_addr = split_addr - 1; data.resize( e_addr - s_addr + 1 ); return new_hunk; } }; typedef std::vector< t_bin_hunk > t_hunk_vec; // ------------------------------------------------------------------------ // // T_MEMATTR_SPAN // // ------------------------------------------------------------------------ // static const uint8_t MEMATTR_BAD = 0; static const uint8_t MEMATTR_ROM = 1; static const uint8_t MEMATTR_WOM = 2; static const uint8_t MEMATTR_RAM = 3; struct t_memattr_span { uint16_t s_addr, e_addr; uint8_t type, width; t_memattr_span( const uint16_t s_addr_, const uint16_t e_addr_, const uint8_t type_, const uint8_t width_ ) : s_addr( s_addr_ ), e_addr( e_addr_ ), type( type_ ), width( width_ ) { } inline bool operator < ( const t_memattr_span& rhs ) const { return s_addr < rhs.s_addr ? true : false; } inline bool can_merge_with( const t_memattr_span& rhs ) const { return e_addr == rhs.s_addr - 1 && type == rhs.type && width == rhs.width; } inline void merge_with( const t_memattr_span& rhs ) { assert( can_merge_with( rhs ) ); e_addr = rhs.e_addr; } }; typedef std::vector< t_memattr_span > t_memattr_vec; // ------------------------------------------------------------------------ // // T_BANKSW_SPAN // // ------------------------------------------------------------------------ // struct t_banksw_span { uint16_t s_addr, e_addr; t_banksw_span( const uint16_t s_addr_, const uint16_t e_addr_ ) : s_addr( s_addr_ ), e_addr( e_addr_ ) { } inline bool operator < ( const t_banksw_span& rhs ) const { return s_addr < rhs.s_addr ? true : false; } inline bool can_merge_with( const t_banksw_span& rhs ) const { return e_addr == rhs.s_addr - 1; } inline void merge_with( const t_banksw_span& rhs ) { assert( can_merge_with( rhs ) ); e_addr = rhs.e_addr; } }; typedef std::vector< t_banksw_span > t_banksw_vec; // ------------------------------------------------------------------------ // // T_METADATA // // ------------------------------------------------------------------------ // struct t_metadata { private: void pack_string( uint8_t tag, t_byte_vec& v, const std::string& s ) const; template void unpack_string( std::string& str, T& si, uint8_t len ); template void unpack_string( t_string_vec& vec, T& si, uint8_t len ); public: std::string name; std::string short_name; t_string_vec authors; t_string_vec game_artists; t_string_vec composers; t_string_vec sfx_artists; t_string_vec voice_actors; t_string_vec doc_writers; t_string_vec conceptualizers; t_string_vec box_artists; t_string_vec more_infos; t_string_vec publishers; t_game_date_vec release_dates; t_string_vec licenses; t_string_vec descriptions; t_string_vec misc; compat_level_t ecs_compat; compat_level_t voice_compat; compat_level_t intv2_compat; compat_level_t kc_compat; compat_level_t tv_compat; bool lto_mapper; jlp_accel_t jlp_accel; int jlp_flash; bool is_defaults; game_metadata_t* to_game_metadata() const; void from_game_metadata( const game_metadata_t* ); bool empty( ) const; void clear( ); t_byte_vec serialize( ) const; void deserialize( const t_byte_vec& serial ); }; #endif