1 #include <stdio.h>
2 #ifndef LOCUTUS_TYPES_HPP_
3 #define LOCUTUS_TYPES_HPP_
4 
5 #include <list>
6 #include <vector>
7 #include <map>
8 #include <utility>
9 #include <bitset>
10 #include <stdint.h>
11 #include <cstring>
12 #include <assert.h>
13 #include <iterator>
14 #include <algorithm>
15 #include "metadata/metadata.h"
16 
17 static const int LOCUTUS_PERM_READ   = 0;
18 static const int LOCUTUS_PERM_WRITE  = 1;
19 static const int LOCUTUS_PERM_NARROW = 2;   // allow writes to 8 LSBs only
20 static const int LOCUTUS_PERM_BANKSW = 3;   // Bankswitch / Pageflip enable
21 
22 typedef std::bitset< 4 >                        t_perm;
23 typedef std::pair< uint32_t, uint32_t >         t_addr_span;
24 typedef std::list< t_addr_span >                t_addr_list;
25 typedef std::vector< uint8_t >                  t_byte_vec;
26 typedef std::vector< uint16_t >                 t_word_vec;
27 typedef std::vector< std::string >              t_string_vec;
28 typedef std::vector< game_date_t >              t_game_date_vec;
29 typedef std::pair< std::string, std::string >   t_var;
30 typedef std::vector< t_var >                    t_var_vec;
31 
32 static const int PAGE_NONE = 0xFF;
33 
34 
35 // ------------------------------------------------------------------------ //
36 //  T_BIN_HUNK                                                              //
37 // ------------------------------------------------------------------------ //
38 struct t_bin_hunk
39 {
40     uint32_t    s_addr, e_addr;     // Locutus addresses
41     uint8_t     page;               // ECS page (0xFF if none)
42     bool        mapped;             // True == map to INTV space at s_addr
43     t_word_vec  data;               // actual ROM data
44     t_perm      perm;               // permissions
45 
t_bin_hunkt_bin_hunk46     t_bin_hunk( const uint32_t      s_addr_,
47                 const uint32_t      e_addr_,
48                 const uint8_t       page_,
49                 const bool          mapped_,
50                 const t_word_vec    data_,
51                 const t_perm        perm_ = 0 )
52     :
53         s_addr( s_addr_ ), e_addr( e_addr_ ), page( page_ ), mapped( mapped_ ),
54         data( data_ ), perm( perm_ )
55     { }
56 
t_bin_hunkt_bin_hunk57     t_bin_hunk( const uint32_t      s_addr_,
58                 const uint32_t      e_addr_,
59                 const uint8_t       page_,
60                 const bool          mapped_,
61                 const uint16_t*     data_,
62                 const t_perm        perm_ = 0 )
63     :
64         s_addr( s_addr_ ), e_addr( e_addr_ ), page( page_ ), mapped( mapped_ ),
65         data( ), perm( perm_ )
66     {
67         data.resize( e_addr_ - s_addr_ + 1, 0 );
68 
69         if ( data_ )
70             std::memcpy( static_cast<void*>(&data[0]),
71                          static_cast<const void *>(&data_[0]),
72                          sizeof( uint16_t ) * data.size() );
73     }
74 
75 
operator <t_bin_hunk76     inline bool operator < ( const t_bin_hunk& rhs ) const
77     {
78         return page <  rhs.page                         ? true
79             :  page == rhs.page && s_addr < rhs.s_addr  ? true
80             :                                             false;
81     }
82 
page_then_addrt_bin_hunk83     static bool page_then_addr( const t_bin_hunk& lhs, const t_bin_hunk& rhs )
84     {
85         return lhs.page <  rhs.page                             ? true
86             :  lhs.page == rhs.page && lhs.s_addr < rhs.s_addr  ? true
87             :                                                     false;
88     }
89 
addr_then_paget_bin_hunk90     static bool addr_then_page( const t_bin_hunk& lhs, const t_bin_hunk& rhs )
91     {
92         return lhs.s_addr < rhs.s_addr                        ? true
93             :  lhs.s_addr == rhs.s_addr &&lhs.page < rhs.page ? true
94             :                                                   false;
95     }
96 
can_merge_witht_bin_hunk97     inline bool can_merge_with( const t_bin_hunk& rhs ) const
98     {
99         return e_addr == rhs.s_addr - 1
100             && page   == rhs.page
101             && mapped == rhs.mapped;
102     }
103 
merge_witht_bin_hunk104     inline void merge_with( const t_bin_hunk& rhs )
105     {
106         assert( can_merge_with( rhs ) );
107 
108         e_addr = rhs.e_addr;
109         data.insert( data.end(), rhs.data.begin(), rhs.data.end() );
110     }
111 
112     // After split, e_addr = split_addr - 1, and we return a new hunk starting
113     // at split_addr ending at the old e_addr.  That is:
114     //  this => [ s_addr, split_addr )
115     //  new  => [ split_addr, e_addr ]
split_att_bin_hunk116     t_bin_hunk split_at( const uint32_t split_addr )
117     {
118         assert( split_addr > s_addr && split_addr <= e_addr );
119 
120         t_bin_hunk new_hunk( split_addr, e_addr, page, mapped,
121                              &data[split_addr - s_addr] );
122 
123         e_addr = split_addr - 1;
124         data.resize( e_addr - s_addr + 1 );
125 
126         return new_hunk;
127     }
128 };
129 
130 typedef std::vector< t_bin_hunk > t_hunk_vec;
131 
132 // ------------------------------------------------------------------------ //
133 //  T_MEMATTR_SPAN                                                          //
134 // ------------------------------------------------------------------------ //
135 static const uint8_t MEMATTR_BAD = 0;
136 static const uint8_t MEMATTR_ROM = 1;
137 static const uint8_t MEMATTR_WOM = 2;
138 static const uint8_t MEMATTR_RAM = 3;
139 
140 struct t_memattr_span
141 {
142     uint16_t        s_addr, e_addr;
143     uint8_t         type, width;
144 
t_memattr_spant_memattr_span145     t_memattr_span( const uint16_t s_addr_, const uint16_t e_addr_,
146                     const uint8_t type_,    const uint8_t width_ )
147     : s_addr( s_addr_ ), e_addr( e_addr_ ), type( type_ ), width( width_ )
148     { }
149 
operator <t_memattr_span150     inline bool operator < ( const t_memattr_span& rhs ) const
151     {
152         return s_addr < rhs.s_addr ? true : false;
153     }
154 
can_merge_witht_memattr_span155     inline bool can_merge_with( const t_memattr_span& rhs ) const
156     {
157         return e_addr == rhs.s_addr - 1
158             && type   == rhs.type
159             && width  == rhs.width;
160     }
161 
merge_witht_memattr_span162     inline void merge_with( const t_memattr_span& rhs )
163     {
164         assert( can_merge_with( rhs ) );
165 
166         e_addr = rhs.e_addr;
167     }
168 };
169 
170 typedef std::vector< t_memattr_span > t_memattr_vec;
171 
172 // ------------------------------------------------------------------------ //
173 //  T_BANKSW_SPAN                                                           //
174 // ------------------------------------------------------------------------ //
175 struct t_banksw_span
176 {
177     uint16_t s_addr, e_addr;
178 
t_banksw_spant_banksw_span179     t_banksw_span( const uint16_t s_addr_, const uint16_t e_addr_ )
180     : s_addr( s_addr_ ), e_addr( e_addr_ )
181     { }
182 
operator <t_banksw_span183     inline bool operator < ( const t_banksw_span& rhs ) const
184     {
185         return s_addr < rhs.s_addr ? true : false;
186     }
187 
can_merge_witht_banksw_span188     inline bool can_merge_with( const t_banksw_span& rhs ) const
189     {
190         return e_addr == rhs.s_addr - 1;
191     }
192 
merge_witht_banksw_span193     inline void merge_with( const t_banksw_span& rhs )
194     {
195         assert( can_merge_with( rhs ) );
196 
197         e_addr = rhs.e_addr;
198     }
199 };
200 
201 typedef std::vector< t_banksw_span  > t_banksw_vec;
202 
203 // ------------------------------------------------------------------------ //
204 //  T_METADATA                                                              //
205 // ------------------------------------------------------------------------ //
206 struct t_metadata
207 {
208 private:
209     void pack_string( uint8_t tag, t_byte_vec& v, const std::string& s ) const;
210 
211     template <typename T>
212     void unpack_string( std::string& str, T& si, uint8_t len );
213 
214     template <typename T>
215     void unpack_string( t_string_vec& vec, T& si, uint8_t len );
216 
217 public:
218 
219     std::string                 name;
220     std::string                 short_name;
221     t_string_vec                authors;
222     t_string_vec                game_artists;
223     t_string_vec                composers;
224     t_string_vec                sfx_artists;
225     t_string_vec                voice_actors;
226     t_string_vec                doc_writers;
227     t_string_vec                conceptualizers;
228     t_string_vec                box_artists;
229     t_string_vec                more_infos;
230     t_string_vec                publishers;
231     t_game_date_vec             release_dates;
232     t_string_vec                licenses;
233     t_string_vec                descriptions;
234     t_string_vec                misc;
235 
236     compat_level_t              ecs_compat;
237     compat_level_t              voice_compat;
238     compat_level_t              intv2_compat;
239     compat_level_t              kc_compat;
240     compat_level_t              tv_compat;
241     bool                        lto_mapper;
242     jlp_accel_t                 jlp_accel;
243     int                         jlp_flash;
244     bool                        is_defaults;
245 
246     game_metadata_t* to_game_metadata() const;
247     void from_game_metadata( const game_metadata_t* );
248 
249     bool empty( ) const;
250     void clear( );
251 
252     t_byte_vec serialize( ) const;
253     void deserialize( const t_byte_vec& serial );
254 };
255 
256 #endif
257