1 // ======================================================================== //
2 // Adapt the Locutus class to the periph_t "class" in jzIntv //
3 // ======================================================================== //
4
5 #include "locutus.hpp"
6 #include "luigi.hpp"
7
8 #include "locutus_adapt.h"
9
10 #include <fstream>
11 #include <iostream>
12 #include <cstdio>
13 #include <string>
14
15 using namespace std;
16
17 class t_cpu_cache : public t_cpu_cache_if
18 {
19 private:
20 cp1600_t *const cp1600;
21
22 public:
t_cpu_cache(cp1600_t * cp1600_)23 t_cpu_cache( cp1600_t *cp1600_ ) : cp1600( cp1600_ ) { }
24
invalidate(uint16_t addr_lo,uint16_t addr_hi)25 virtual void invalidate( uint16_t addr_lo, uint16_t addr_hi )
26 {
27 if ( cp1600 )
28 cp1600_invalidate( cp1600, addr_lo, addr_hi );
29 }
30
31 ~t_cpu_cache();
32 };
33
34 // Anchor the vtable
~t_cpu_cache()35 t_cpu_cache::~t_cpu_cache() { }
36
37 struct t_locutus_priv
38 {
39 t_locutus locutus;
40 t_cpu_cache cpu_cache;
41
t_locutus_privt_locutus_priv42 t_locutus_priv( cp1600_t *cp1600 )
43 : cpu_cache( cp1600 )
44 { }
45 };
46
47
locutus_read(periph_t * const periph,periph_t *,uint32_t addr,uint32_t)48 LOCAL uint32_t locutus_read( periph_t *const periph, periph_t *,
49 uint32_t addr, uint32_t )
50 {
51 t_locutus_wrap *wrap = reinterpret_cast<t_locutus_wrap *>(periph);
52
53 try
54 {
55 return wrap->locutus_priv->locutus.intv_read( addr );
56 } catch ( string &s )
57 {
58 cerr << "EXCEPTION: " << s << endl;
59 exit(1);
60 }
61 }
62
locutus_write(periph_t * const periph,periph_t *,uint32_t addr,uint32_t data)63 LOCAL void locutus_write( periph_t *const periph, periph_t *,
64 uint32_t addr, uint32_t data )
65 {
66 t_locutus_wrap *wrap = reinterpret_cast<t_locutus_wrap *>(periph);
67
68 try
69 {
70 return wrap->locutus_priv->locutus.intv_write( addr, data );
71 } catch ( string &s )
72 {
73 cerr << "EXCEPTION: " << s << endl;
74 exit(1);
75 }
76 }
77
locutus_reset(periph_t * const periph)78 LOCAL void locutus_reset( periph_t *const periph )
79 {
80 t_locutus_wrap *wrap = reinterpret_cast<t_locutus_wrap *>(periph);
81
82 try
83 {
84 wrap->locutus_priv->locutus.intv_reset();
85 } catch ( string &s )
86 {
87 cerr << "EXCEPTION: " << s << endl;
88 exit(1);
89 }
90 }
91
locutus_dtor(periph_t * const periph)92 LOCAL void locutus_dtor( periph_t *const periph )
93 {
94 t_locutus_wrap *wrap = reinterpret_cast<t_locutus_wrap *>(periph);
95
96 delete wrap->locutus_priv;
97 wrap->locutus_priv = nullptr;
98 }
99
make_locutus(t_locutus_wrap * loc_wrap,const char * luigi_file,cp1600_t * cp1600,int silent,const char * savegame)100 extern "C" int make_locutus
101 (
102 t_locutus_wrap *loc_wrap, /* pointer to a Locutus wrapper */
103 const char *luigi_file, /* LUIGI file to load into Locutus */
104 cp1600_t *cp1600,
105 int silent,
106 const char *savegame
107 )
108 {
109 t_locutus_priv *priv = new t_locutus_priv( cp1600 );
110 loc_wrap->locutus_priv = priv;
111
112 ifstream ifs(luigi_file, ios::binary | ios::ate);
113
114 if ( !ifs.is_open() )
115 {
116 if (!silent)
117 cerr << "could not open " << luigi_file << endl;
118 return -1;
119 }
120
121 ifstream::pos_type pos = ifs.tellg();
122
123 t_byte_vec luigi_data(pos);
124
125 ifs.seekg(0, ios::beg);
126 ifs.read(reinterpret_cast<char *>(&luigi_data[0]), pos);
127
128 try
129 {
130 t_luigi::deserialize( priv->locutus, luigi_data );
131 } catch ( string &s )
132 {
133 if (!silent)
134 cerr << "EXCEPTION: " << s << endl;
135 return -1;
136 }
137
138 if ( (!silent || cp1600) && priv->locutus.was_scrambled() )
139 {
140 const uint8_t* druid = priv->locutus.get_scramble_druid();
141 char buf[50];
142 sprintf(buf,
143 "%.2X%.2X:%.2X%.2X:%.2X%.2X:%.2X%.2X:"
144 "%.2X%.2X:%.2X%.2X:%.2X%.2X:%.2X%.2X",
145 druid[15], druid[14], druid[13], druid[12],
146 druid[11], druid[10], druid[ 9], druid[ 8],
147 druid[ 7], druid[ 6], druid[ 5], druid[ 4],
148 druid[ 3], druid[ 2], druid[ 1], druid[ 0]);
149 cerr << "This LUIGI is scrambled for DRUID " << buf << "\n";
150 return -1;
151 }
152
153 priv->locutus.set_xregs( &cp1600->xr[0] );
154 priv->locutus.init_jlp_flash( savegame );
155 priv->locutus.intv_reset();
156
157 loc_wrap->periph.read = locutus_read;
158 loc_wrap->periph.write = locutus_write;
159 loc_wrap->periph.peek = locutus_read;
160 loc_wrap->periph.poke = locutus_write;
161 loc_wrap->periph.reset = locutus_reset;
162 loc_wrap->periph.dtor = locutus_dtor;
163
164 loc_wrap->periph.tick = nullptr;
165 loc_wrap->periph.min_tick = ~0U;
166 loc_wrap->periph.max_tick = ~0U;
167
168 loc_wrap->periph.addr_base = 0;
169 loc_wrap->periph.addr_mask = ~0U;
170 loc_wrap->periph.ser_init = nullptr; // no support for serializer()
171
172 return 0;
173 }
174
get_locutus_metadata(t_locutus_wrap * loc_wrap)175 extern "C" game_metadata_t* get_locutus_metadata
176 (
177 t_locutus_wrap *loc_wrap
178 )
179 {
180 t_locutus_priv* priv = loc_wrap->locutus_priv;
181 const t_metadata& metadata = priv->locutus.get_metadata();
182 return metadata.to_game_metadata();
183 }
184
get_locutus_compat_ecs(t_locutus_wrap * loc_wrap)185 extern "C" int get_locutus_compat_ecs ( t_locutus_wrap *loc_wrap )
186 {
187 return int( loc_wrap->locutus_priv->locutus.get_compat_ecs() );
188 }
189
get_locutus_compat_voice(t_locutus_wrap * loc_wrap)190 extern "C" int get_locutus_compat_voice( t_locutus_wrap *loc_wrap )
191 {
192 return int( loc_wrap->locutus_priv->locutus.get_compat_voice() );
193 }
194
get_locutus_compat_intv2(t_locutus_wrap * loc_wrap)195 extern "C" int get_locutus_compat_intv2( t_locutus_wrap *loc_wrap )
196 {
197 return int( loc_wrap->locutus_priv->locutus.get_compat_intv2() );
198 }
199
get_locutus_compat_kc(t_locutus_wrap * loc_wrap)200 extern "C" int get_locutus_compat_kc( t_locutus_wrap *loc_wrap )
201 {
202 return int( loc_wrap->locutus_priv->locutus.get_compat_kc() );
203 }
204
get_locutus_uid(t_locutus_wrap * loc_wrap)205 extern "C" uint64_t get_locutus_uid( t_locutus_wrap *loc_wrap )
206 {
207 return loc_wrap->locutus_priv->locutus.get_uid();
208 }
209
get_locutus_was_scrambled(t_locutus_wrap * loc_wrap)210 extern "C" int get_locutus_was_scrambled( t_locutus_wrap *loc_wrap )
211 {
212 return loc_wrap->locutus_priv->locutus.was_scrambled();
213 }
214
get_locutus_scramble_druid(t_locutus_wrap * loc_wrap)215 extern "C" const uint8_t* get_locutus_scramble_druid( t_locutus_wrap *loc_wrap )
216 {
217 return loc_wrap->locutus_priv->locutus.get_scramble_druid();
218 }
219