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