1 // ======================================================================== //
2 // Utilities: //
3 // //
4 // class t_rom_to_loc_impl //
5 // //
6 // ======================================================================== //
7
8 #include "config.h"
9 extern "C"
10 {
11 # include "icart/icartrom.h"
12 # include "misc/file_crc32.h"
13 # include "metadata/metadata.h"
14 # include "metadata/cfgvar_metadata.h"
15 # include <errno.h>
16 }
17
18 #include <cassert>
19 #include <cstdio>
20 #include <cstring>
21 #include <vector>
22 #include <list>
23 #include <map>
24 #include <algorithm>
25
26 using namespace std;
27
28 #include "locutus_types.hpp"
29 #include "locutus.hpp"
30 #include "rom_to_loc.hpp"
31
32 // ======================================================================== //
33 // CLASS T_ROM_TO_LOC_IMPL //
34 // ======================================================================== //
35 class t_rom_to_loc_impl
36 {
37 private:
38 icartrom_t* const icartrom;
39 t_locutus& locutus;
40 t_metadata& metadata;
41
42 int warnings;
43 int errors;
44
45 t_string_vec messages;
46
record_error(string error)47 void record_error( string error )
48 {
49 messages.push_back( string("ERROR: ") + error );
50 ++errors;
51 }
52
record_warning(string warning)53 void record_warning( string warning )
54 {
55 messages.push_back( string("WARNING: ") + warning );
56 ++warnings;
57 }
58
ic_get_bit(const uint32_t * bv,const int bit) const59 inline bool ic_get_bit( const uint32_t* bv, const int bit ) const
60 {
61 return ( bv[ bit >> 5 ] >> (bit & 0x1F) ) & 1;
62 }
63
ic_is_preload(const int para) const64 inline bool ic_is_preload( const int para ) const
65 {
66 return ic_get_bit( icartrom->preload, para );
67 }
68
ic_is_readable(const int para) const69 inline bool ic_is_readable( const int para ) const
70 {
71 return ic_get_bit( icartrom->readable, para );
72 }
73
ic_is_narrow(const int para) const74 inline bool ic_is_narrow( const int para ) const
75 {
76 return ic_get_bit( icartrom->narrow, para );
77 }
78
ic_is_writable(const int para) const79 inline bool ic_is_writable( const int para ) const
80 {
81 return ic_get_bit( icartrom->writable, para );
82 }
83
ic_is_banksw(const int para) const84 inline bool ic_is_banksw( const int para ) const
85 {
86 return ic_get_bit( icartrom->dobanksw, para );
87 }
88
89 bool process_romimg();
90 bool process_metadata();
91
92 public:
t_rom_to_loc_impl(icartrom_t * icartrom_,t_locutus & locutus_,uint32_t crc)93 t_rom_to_loc_impl
94 (
95 icartrom_t* icartrom_,
96 t_locutus& locutus_,
97 uint32_t crc
98 )
99 : icartrom( icartrom_ ),
100 locutus ( locutus_ ),
101 metadata( locutus_.get_metadata() ),
102 warnings( 0 ),
103 errors ( 0 )
104 {
105 locutus.set_uid( 0x4D4F522E00000000ull | crc );
106 }
107
~t_rom_to_loc_impl()108 ~t_rom_to_loc_impl()
109 {
110 }
111
process()112 bool process()
113 {
114 return process_romimg() && process_metadata();
115 }
116
is_ok() const117 bool is_ok() const { return !errors; }
get_errors() const118 int get_errors() const { return errors; }
get_warnings() const119 int get_warnings() const { return warnings; }
get_messages() const120 const t_string_vec& get_messages() const { return messages; }
121 };
122
123
124 // ------------------------------------------------------------------------ //
125 // T_ROM_TO_LOC_IMPL::PROCESS_ROMIMG() //
126 // ------------------------------------------------------------------------ //
process_romimg()127 bool t_rom_to_loc_impl::process_romimg()
128 {
129 for ( int para = 0; para < 256; para++ )
130 {
131 const bool is_preload = ic_is_preload ( para );
132 const bool is_readable = ic_is_readable( para );
133 const bool is_writable = ic_is_writable( para );
134 const bool is_narrow = ic_is_narrow ( para );
135 const bool is_banksw = ic_is_banksw ( para );
136 const int base_addr = para << 8;
137
138
139 t_perm perm;
140
141 perm[ LOCUTUS_PERM_READ ] = is_readable;
142 perm[ LOCUTUS_PERM_WRITE ] = is_writable;
143 perm[ LOCUTUS_PERM_NARROW ] = is_narrow;
144 perm[ LOCUTUS_PERM_BANKSW ] = is_banksw;
145
146 locutus.set_mem_perm( para, false, perm );
147 locutus.set_mem_perm( para, true, perm );
148
149 if ( is_readable || is_writable )
150 {
151 locutus.set_mem_map( para, false, para );
152 locutus.set_mem_map( para, true, para );
153 }
154
155 if ( is_preload )
156 {
157 for ( int ofs = 0; ofs < 256; ofs++ )
158 {
159 const int addr = base_addr + ofs;
160 locutus.write( addr, icartrom->image[ addr ] );
161 }
162 }
163 }
164
165 return errors == 0;
166 }
167
168 // ------------------------------------------------------------------------ //
169 // T_ROM_TO_LOC_IMPL::PROCESS_METADATA() //
170 // ------------------------------------------------------------------------ //
process_metadata()171 bool t_rom_to_loc_impl::process_metadata()
172 {
173 game_metadata_t* game_metadata =
174 (!icartrom || !icartrom->metadata)
175 ? default_game_metadata()
176 : icartrom->metadata;
177
178 metadata.from_game_metadata( game_metadata );
179
180 free_game_metadata( game_metadata );
181
182 // -------------------------------------------------------------------- //
183 // Update feature flags in Locutus to indicate what needs to be //
184 // enabled / disabled. //
185 // -------------------------------------------------------------------- //
186 locutus.set_compat_voice( metadata.voice_compat );
187 locutus.set_compat_ecs ( metadata.ecs_compat );
188 locutus.set_compat_intv2( metadata.intv2_compat );
189 locutus.set_compat_kc ( metadata.kc_compat );
190 locutus.set_compat_tv ( metadata.tv_compat );
191 locutus.set_jlp_features( metadata.jlp_accel, metadata.jlp_flash );
192 locutus.set_enable_lto_mapper( metadata.lto_mapper );
193 locutus.set_explicit_flags( !metadata.is_defaults );
194
195 return true;
196 }
197
198 // ------------------------------------------------------------------------ //
199 // Forwarding from T_ROM_TO_LOC to T_ROM_TO_LOC_IMPL //
200 // ------------------------------------------------------------------------ //
201
t_rom_to_loc(icartrom_t * icartrom,t_locutus & locutus,uint32_t crc)202 t_rom_to_loc::t_rom_to_loc
203 (
204 icartrom_t* icartrom,
205 t_locutus& locutus,
206 uint32_t crc
207 )
208 {
209 impl = new t_rom_to_loc_impl( icartrom, locutus, crc );
210 }
211
~t_rom_to_loc()212 t_rom_to_loc::~t_rom_to_loc()
213 {
214 delete impl;
215 }
216
is_ok() const217 bool t_rom_to_loc::is_ok() const { return impl->is_ok(); }
process()218 bool t_rom_to_loc::process() { return impl->process(); }
get_errors() const219 int t_rom_to_loc::get_errors() const { return impl->get_errors(); }
get_warnings() const220 int t_rom_to_loc::get_warnings() const { return impl->get_warnings(); }
221
get_messages() const222 const t_string_vec& t_rom_to_loc::get_messages() const
223 {
224 return impl->get_messages();
225 }
226
227
228