1 // Hyperbolic Rogue for Android
2 // Copyright (C) 2012-2018 Zeno Rogue
3
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 #define ISANDROID 1
19 #define GL_ES
20 #define CAP_ACHIEVE 1
21 #define CAP_SHADER 1
22 #define CAP_VERTEXBUFFER 0
23 #define CAP_TIMEOFDAY 1
24 #define NO_STD_HYPOT
25 #define NOMAIN
26
27 #define HNEW 1
28
29 #define MOBPAR_FORMAL JNIEnv *env, jobject thiz
30 #define MOBPAR_ACTUAL env, thiz
31
32 #include <android/log.h>
33 #include <stdio.h>
34
35 char android_log_buf[1000000];
36 int android_log_bufpos = 0;
37
38 FILE *slog;
39
40 #define SPECIAL_LOGGER
41
42 void special_log(char c);
43
44 #include <jni.h>
45 #include <string>
46
47 namespace hr {
48 std::string get_asset(const std::string &str);
49 void gdpush(int t);
50
51 void shareScore(MOBPAR_FORMAL);
52
53 const char *scorefile;
54
55 bool settingsChanged = false;
56
57 struct transmatrix getOrientation();
58 }
59
60 #include "../../../../../hyper.cpp"
61
special_log(char c)62 void special_log(char c) {
63 if(slog) fprintf(slog, "%c", c), fflush(slog); /*
64 if(c == 10 || android_log_bufpos == 999999) {
65 android_log_buf[android_log_bufpos] = 0;
66 __android_log_print(ANDROID_LOG_VERBOSE, "HRLOG", "%s", android_log_buf);
67 android_log_bufpos = 0;
68 }
69 else {
70 android_log_buf[android_log_bufpos++] = c;
71 } */
72 }
73
74
75 namespace hr {
76
77 // #define delref env->DeleteLocalRef(_thiz)
78
79 int semaphore = 0;
80 bool crash = false;
81
82 #define LOCK(s, x) \
83 semaphore++; const char *xs = x; if(semaphore > 1) { crash = true; \
84 __android_log_print(ANDROID_LOG_WARN, "HyperRogue", "concurrency crash in %s\n", x); semaphore--; fflush(stdout); return s; }
85 #define UNLOCK semaphore--; if(crash) { crash = false; __android_log_print(ANDROID_LOG_WARN, "HyperRogue", "concurrency crashed with %s\n", xs); fflush(stdout); }
86
87
88 extern "C" jintArray
Java_com_roguetemple_hyperroid_HyperRogue_loadMap(MOBPAR_FORMAL)89 Java_com_roguetemple_hyperroid_HyperRogue_loadMap
90 ( MOBPAR_FORMAL)
91 {
92 // if(debfile) fprintf(debfile, "loadmap started.\n"), fflush(debfile);
93 LOCK(NULL, "loadMap")
94
95 jintArray result;
96 result = env->NewIntArray(isize(graphdata));
97 if(result == NULL) return NULL;
98
99 env->SetIntArrayRegion(result, 0, isize(graphdata), &*graphdata.begin());
100 // delref;
101 // env->DeleteLocalRef(result);
102 // if(debfile) fprintf(debfile, "loadmap finished.\n"), fflush(debfile);
103
104 UNLOCK
105 return result;
106 }
107
108 extern "C" bool
Java_com_roguetemple_hyperroid_HyperRogue_captureBack(MOBPAR_FORMAL)109 Java_com_roguetemple_hyperroid_HyperRogue_captureBack
110 ( MOBPAR_FORMAL) {
111 if(cmode & sm::NORMAL) return false;
112 popScreenAll();
113 return true;
114 }
115
116 void uploadAll(MOBPAR_FORMAL);
117
118 extern "C" bool
Java_com_roguetemple_hyperroid_HyperRogue_keepinmemory(MOBPAR_FORMAL)119 Java_com_roguetemple_hyperroid_HyperRogue_keepinmemory
120 ( MOBPAR_FORMAL) {
121 if(!casual) saveStats(true);
122 uploadAll(MOBPAR_ACTUAL);
123 if(!canmove) return false;
124 if(items[itOrbSafety]) return false;
125 return gold() >= 10 || tkills() >= 50;
126 }
127
128 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getland(MOBPAR_FORMAL)129 Java_com_roguetemple_hyperroid_HyperRogue_getland
130 ( MOBPAR_FORMAL)
131 {
132 return getCurrentLandForMusic();
133 }
134
135 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getLanguage(MOBPAR_FORMAL)136 Java_com_roguetemple_hyperroid_HyperRogue_getLanguage
137 ( MOBPAR_FORMAL)
138 {
139 return vid.language;
140 }
141
142 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getMusicVolume(MOBPAR_FORMAL)143 Java_com_roguetemple_hyperroid_HyperRogue_getMusicVolume
144 ( MOBPAR_FORMAL)
145 {
146 return musicvolume;
147 }
148
149 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getEffVolume(MOBPAR_FORMAL)150 Java_com_roguetemple_hyperroid_HyperRogue_getEffVolume
151 ( MOBPAR_FORMAL)
152 {
153 return effvolume;
154 }
155
156 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getImmersive(MOBPAR_FORMAL)157 Java_com_roguetemple_hyperroid_HyperRogue_getImmersive(MOBPAR_FORMAL)
158 {
159 return vid.full;
160 }
161
162 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getGL(MOBPAR_FORMAL)163 Java_com_roguetemple_hyperroid_HyperRogue_getGL(MOBPAR_FORMAL)
164 {
165 return vid.usingGL;
166 }
167
168 extern "C" void
Java_com_roguetemple_hyperroid_HyperRogue_glhrinit(MOBPAR_FORMAL)169 Java_com_roguetemple_hyperroid_HyperRogue_glhrinit(MOBPAR_FORMAL)
170 {
171 __android_log_print(ANDROID_LOG_WARN, "HyperRogue", "glhr::init %d\n", 0);
172 #if HNEW
173 // matched_programs get clobbered on activity destruction -- force their re-creation
174 if (!matched_programs.empty()) matched_programs.clear();
175 glhr::init();
176 #endif
177 __android_log_print(ANDROID_LOG_WARN, "HyperRogue", "glhr::init done %d\n", 0);
178 }
179
180 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getaPosition(MOBPAR_FORMAL)181 Java_com_roguetemple_hyperroid_HyperRogue_getaPosition(MOBPAR_FORMAL)
182 {
183 return aPosition;
184 }
185
186 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getaTexture(MOBPAR_FORMAL)187 Java_com_roguetemple_hyperroid_HyperRogue_getaTexture(MOBPAR_FORMAL)
188 {
189 return aTexture;
190 }
191
192 extern "C" int
Java_com_roguetemple_hyperroid_HyperRogue_getuColor(MOBPAR_FORMAL)193 Java_com_roguetemple_hyperroid_HyperRogue_getuColor(MOBPAR_FORMAL)
194 {
195 return glhr::current_glprogram->uColor;
196 }
197
198 string sscorefile, sconffile, scachefile;
199
200 #include <sys/stat.h>
201
202 extern "C" void
Java_com_roguetemple_hyperroid_HyperRogue_setFilesDir(MOBPAR_FORMAL,jstring dir)203 Java_com_roguetemple_hyperroid_HyperRogue_setFilesDir(MOBPAR_FORMAL, jstring dir)
204 {
205 const char *nativeString = env->GetStringUTFChars(dir, 0);
206 sscorefile = nativeString; sscorefile += "/hyperrogue.log";
207 sconffile = nativeString; sconffile += "/hyperrogue.ini";
208 scachefile = nativeString; scachefile += "/scorecache.txt";
209 levelfile = nativeString; levelfile += "/hyperrogue.lev";
210 picfile = nativeString; picfile += "/hyperrogue.pic";
211 scorefile = sscorefile.c_str();
212 conffile = sconffile.c_str();
213 chmod(scorefile, 0777);
214 chmod(conffile, 0777);
215 chmod(nativeString, 0777);
216 chmod((string(nativeString)+"/..").c_str(), 0777);
217 env->ReleaseStringUTFChars(dir, nativeString);
218 }
219
220 bool gamerunning;
221
222 extern "C"
223 jint
Java_com_roguetemple_hyperroid_HyperRogue_initGame(MOBPAR_FORMAL)224 Java_com_roguetemple_hyperroid_HyperRogue_initGame(MOBPAR_FORMAL) {
225
226 // debfile = fopen("/sdcard/hyperdebug.txt", "wt");
227 // if(!debfile) debfile = fopen("/storage/simulated/0/hyperdebug.txt", "wt");
228
229 // if(debfile) fprintf(debfile, "initgame started.\n"), fflush(debfile);
230
231
232 __android_log_print(ANDROID_LOG_VERBOSE, "HyperRogue", "Initializing game, gamerunning = %d\n", gamerunning);
233 printf("test\n");
234 fflush(stdout);
235 if(gamerunning) return 1;
236 gamerunning = true;
237 initAll();
238 if(showstartmenu) pushScreen(showStartMenu);
239 uploadAll(MOBPAR_ACTUAL);
240 __android_log_print(ANDROID_LOG_VERBOSE, "HyperRogue", "Game initialized, gamerunning = %d\n", gamerunning);
241 return 0;
242 }
243
244 JNIEnv *tw_env; jobject tw_thiz;
245
get_asset(const string & str)246 string get_asset(const string &str) {
247 jclass cls = tw_env->GetObjectClass(tw_thiz);
248 jmethodID mid = tw_env->GetMethodID(cls, "getAsset", "(Ljava/lang/String;)[B");
249 jobject jstr = tw_env->NewStringUTF(str.c_str());
250 jbyteArray arr = (jbyteArray) tw_env->CallObjectMethod(tw_thiz, mid, jstr);
251 tw_env->DeleteLocalRef(jstr);
252 tw_env->DeleteLocalRef(cls);
253 jsize len = tw_env->GetArrayLength(arr);
254 jbyte* data = tw_env->GetByteArrayElements(arr, NULL);
255 string s((char*) & (data[0]), len);
256 tw_env->DeleteLocalRef(arr);
257 return s;
258 }
259
textwidth(int siz,const string & str)260 int textwidth(int siz, const string &str) {
261 jclass cls = tw_env->GetObjectClass(tw_thiz);
262 jmethodID mid = tw_env->GetMethodID(cls, "getTextWidth", "(Ljava/lang/String;I)I");
263 jobject jstr = tw_env->NewStringUTF(str.c_str());
264 int res = tw_env->CallIntMethod(tw_thiz, mid, jstr, siz);
265 tw_env->DeleteLocalRef(jstr);
266 tw_env->DeleteLocalRef(cls);
267 return res;
268 }
269
270 bool achievementsConnected = false;
271 string doViewLeaderboard;
272 bool doViewAchievements;
273 bool doOpenURL;
274
currentlyConnecting()275 bool currentlyConnecting() { return false; }
currentlyConnected()276 bool currentlyConnected() { return false; }
277
viewLeaderboard(string what)278 void viewLeaderboard(string what) { doViewLeaderboard = what; }
viewAchievements()279 void viewAchievements() { doViewAchievements = true; }
280
281 vector<pair<int, int> > scoresToUpload;
282 vector<const char *> achievementsToUpload;
283 vector<pair<string, int> > soundsToPlay;
284
openURL()285 void openURL() {
286 doOpenURL = true;
287 }
288
289 int last_upload[NUMLEADER];
290
shareScore(MOBPAR_FORMAL)291 void shareScore(MOBPAR_FORMAL) {
292 string s = buildScoreDescription();
293 jclass cls = env->GetObjectClass(thiz);
294 jmethodID mid = env->GetMethodID(cls, "shareScore", "(Ljava/lang/String;)V");
295 jobject str = env->NewStringUTF(s.c_str());
296 env->CallVoidMethod(thiz, mid, str);
297 env->DeleteLocalRef(str);
298 env->DeleteLocalRef(cls);
299 }
300
Java_com_roguetemple_hyperroid_HyperRogue_draw(MOBPAR_FORMAL)301 extern "C" void Java_com_roguetemple_hyperroid_HyperRogue_draw(MOBPAR_FORMAL) {
302 // if(debfile) fprintf(debfile, "draw started.\n"), fflush(debfile);
303
304 LOCK(, "draw")
305 /* static int infoticks;
306 if(getticks() - infoticks > 10000 && !timerghost) {
307 addMessage("ticks: " + its(getticks()));
308 infoticks = getticks();
309 } */
310 tw_thiz = thiz; tw_env = env;
311
312 #if HNEW
313 glhr::be_textured();
314 glhr::be_nontextured();
315
316 #if CAP_SHADER
317 glEnableVertexAttribArray(aPosition);
318 #else
319 glEnableClientState(GL_VERTEX_ARRAY);
320 #endif
321 #endif
322
323 mobile_draw(MOBPAR_ACTUAL);
324 uploadAll(MOBPAR_ACTUAL);
325
326 #if HNEW
327 // text is drawn with 'textured'
328 dynamicval<eModel> p(pmodel, mdManual);
329 current_display->next_shader_flags = GF_TEXTURE;
330 current_display->set_all(0, 0);
331 glhr::set_depthtest(false);
332 current_display->set_viewport(0);
333 current_display->set_mask(0);
334 glhr::new_projection();
335 glhr::projection_multiply(glhr::translate(-1,-1,0));
336 glhr::projection_multiply(glhr::ortho(vid.xres/2, vid.yres/2, 1));
337 glhr::set_modelview(glhr::id);
338 glhr::color2(0xC08040F0);
339 #endif
340
341 UNLOCK
342 }
343
Java_com_roguetemple_hyperroid_HyperRogue_drawScreenshot(MOBPAR_FORMAL)344 extern "C" void Java_com_roguetemple_hyperroid_HyperRogue_drawScreenshot(MOBPAR_FORMAL) {
345 dynamicval<bool> d(vid.usingGL, false);
346 Java_com_roguetemple_hyperroid_HyperRogue_draw(MOBPAR_ACTUAL);
347 }
348
Java_com_roguetemple_hyperroid_HyperRogue_handleKey(MOBPAR_FORMAL,jint keycode)349 extern "C" void Java_com_roguetemple_hyperroid_HyperRogue_handleKey(MOBPAR_FORMAL, jint keycode) {
350 flashMessages(); mousing = false;
351 handlekey(keycode, keycode);
352 }
353
Java_com_roguetemple_hyperroid_HyperRogue_update(MOBPAR_FORMAL,jint xres,jint yres,jint _ticks,jint _mousex,jint _mousey,jboolean _clicked)354 extern "C" void Java_com_roguetemple_hyperroid_HyperRogue_update
355 ( MOBPAR_FORMAL,
356 jint xres, jint yres, jint _ticks,
357 jint _mousex, jint _mousey, jboolean _clicked) {
358
359 LOCK(, "update")
360
361 // if(debfile) fprintf(debfile, "update started.\n"), fflush(debfile);
362
363 if(xres != vid.xres || yres != vid.yres)
364 vid.killreduction = 0;
365
366 vid.xres = xres;
367 vid.yres = yres;
368 vid.fsize = (min(vid.xres, vid.yres) * vid.fontscale + 50) / 3200;
369
370 mousex = _mousex;
371 mousey = _mousey;
372 clicked = _clicked;
373 uploadAll(MOBPAR_ACTUAL);
374 UNLOCK
375 // delref;
376 // if(debfile) fprintf(debfile, "update stopped.\n"), fflush(debfile);
377 }
378
resetmusic()379 void resetmusic() {}
380
playSound(cell * c,const string & fname,int vol)381 void playSound(cell *c, const string& fname, int vol) {
382 LATE( hr::playSound(c, fname, vol); )
383 soundsToPlay.push_back(make_pair(fname, vol));
384 }
385
386 transmatrix orientation = Id;
387 bool orientation_requested;
388
getOrientation()389 transmatrix getOrientation() {
390 orientation_requested = true;
391 return orientation;
392 }
393
uploadAll(JNIEnv * env,jobject thiz)394 void uploadAll(JNIEnv *env, jobject thiz) {
395
396 jclass cls = env->GetObjectClass(thiz);
397
398 if(orientation_requested) {
399 jmethodID mid = env->GetMethodID(cls, "getOrientation", "(II)D");
400 for(int i=0; i<3; i++)
401 for(int j=0; j<3; j++)
402 orientation[i][j] = env->CallDoubleMethod(thiz, mid, i, j);
403 for(int i=0; i<3; i++)
404 orientation[i][3] = orientation[3][i] = 0;
405 orientation[3][3] = 1;
406 orientation_requested = false;
407 }
408
409 for(int i=0; i<isize(soundsToPlay); i++) {
410 jmethodID mid = env->GetMethodID(cls, "playSound", "(Ljava/lang/String;I)V");
411 jobject str = env->NewStringUTF(soundsToPlay[i].first.c_str());
412 env->CallVoidMethod(thiz, mid, str, soundsToPlay[i].second);
413 env->DeleteLocalRef(str);
414 }
415 soundsToPlay.clear();
416
417 if(settingsChanged) {
418 jmethodID mid = env->GetMethodID(cls, "applyUserSettings", "()V");
419 env->CallVoidMethod(thiz, mid);
420 settingsChanged = false;
421 }
422
423 if(doOpenURL) {
424 jmethodID mid = env->GetMethodID(cls, "openWebsite", "()V");
425 env->CallVoidMethod(thiz, mid);
426 doOpenURL = false;
427 }
428
429 env->DeleteLocalRef(cls);
430 }
431
achievement_init()432 void achievement_init() {}
achievement_close()433 void achievement_close() {}
achievement_gain(const char * s,char flags)434 void achievement_gain(const char* s, char flags) {}
435
436 }
437
438