mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 17:10:36 +00:00
new memory handling
This commit is contained in:
parent
fc47ec3338
commit
06301d73fc
@ -942,8 +942,11 @@ void configureOther() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
dialog::addBoolItem_action(XLAT("skip the start menu"), vid.skipstart, 'm');
|
dialog::addBoolItem_action(XLAT("skip the start menu"), vid.skipstart, 'm');
|
||||||
|
|
||||||
|
dialog::addItem(XLAT("memory configuration"), 'y');
|
||||||
|
dialog::add_action_push(show_memory_menu);
|
||||||
|
|
||||||
dialog::addBoolItem_action(XLAT("forget faraway cells"), memory_saving_mode, 'y');
|
// dialog::addBoolItem_action(XLAT("forget faraway cells"), memory_saving_mode, 'y');
|
||||||
|
|
||||||
#if CAP_AUDIO
|
#if CAP_AUDIO
|
||||||
if(CAP_AUDIO) {
|
if(CAP_AUDIO) {
|
||||||
@ -1289,6 +1292,7 @@ void show3D() {
|
|||||||
dialog::addSelItem(XLAT("Eye level"), fts(vid.eye), 'E');
|
dialog::addSelItem(XLAT("Eye level"), fts(vid.eye), 'E');
|
||||||
|
|
||||||
dialog::addSelItem(XLAT("Ground level below the plane"), fts(vid.depth), 'g');
|
dialog::addSelItem(XLAT("Ground level below the plane"), fts(vid.depth), 'g');
|
||||||
|
|
||||||
|
|
||||||
if(GDIM == 2)
|
if(GDIM == 2)
|
||||||
dialog::addSelItem(XLAT("Projection at the ground level"), fts(vid.alpha), 'p');
|
dialog::addSelItem(XLAT("Projection at the ground level"), fts(vid.alpha), 'p');
|
||||||
@ -2039,6 +2043,9 @@ int read_config_args() {
|
|||||||
else if(argis("-msm")) {
|
else if(argis("-msm")) {
|
||||||
PHASEFROM(2); memory_saving_mode = true;
|
PHASEFROM(2); memory_saving_mode = true;
|
||||||
}
|
}
|
||||||
|
else if(argis("-mrsv")) {
|
||||||
|
PHASEFROM(2); shift(); reserve_limit = argi(); apply_memory_reserve();
|
||||||
|
}
|
||||||
else if(argis("-yca")) {
|
else if(argis("-yca")) {
|
||||||
PHASEFROM(2);
|
PHASEFROM(2);
|
||||||
shift_arg_formula(vid.yshift);
|
shift_arg_formula(vid.yshift);
|
||||||
|
@ -108,6 +108,8 @@ void movepckeydir(int d) {
|
|||||||
DEBB(DF_GRAPH, ("movepckeydir\n"));
|
DEBB(DF_GRAPH, ("movepckeydir\n"));
|
||||||
// EUCLIDEAN
|
// EUCLIDEAN
|
||||||
|
|
||||||
|
if(protect_memory()) return;
|
||||||
|
|
||||||
movedir md = vectodir(move_destination_vec(d));
|
movedir md = vectodir(move_destination_vec(d));
|
||||||
|
|
||||||
if(!canmove) movepcto(md), remission(); else movepcto(md);
|
if(!canmove) movepcto(md), remission(); else movepcto(md);
|
||||||
@ -152,6 +154,9 @@ void calcMousedest() {
|
|||||||
|
|
||||||
void mousemovement() {
|
void mousemovement() {
|
||||||
if(DIM == 3) return;
|
if(DIM == 3) return;
|
||||||
|
|
||||||
|
if(protect_memory()) return;
|
||||||
|
|
||||||
calcMousedest();
|
calcMousedest();
|
||||||
if(!canmove) movepcto(mousedest), remission(); else movepcto(mousedest);
|
if(!canmove) movepcto(mousedest), remission(); else movepcto(mousedest);
|
||||||
lmouseover = NULL;
|
lmouseover = NULL;
|
||||||
@ -468,6 +473,8 @@ void handleKeyNormal(int sym, int uni) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(sym == SDLK_F1) gotoHelp(help);
|
if(sym == SDLK_F1) gotoHelp(help);
|
||||||
|
|
||||||
|
if(sym == PSEUDOKEY_MEMORY) pushScreen(show_memory_menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_mouseh = false;
|
bool need_mouseh = false;
|
||||||
@ -619,6 +626,7 @@ void mainloopiter() {
|
|||||||
#if CAP_SDLAUDIO
|
#if CAP_SDLAUDIO
|
||||||
if(audio) handlemusic();
|
if(audio) handlemusic();
|
||||||
#endif
|
#endif
|
||||||
|
apply_memory_reserve();
|
||||||
SDL_Event ev;
|
SDL_Event ev;
|
||||||
DEBB(DF_GRAPH, ("polling for events\n"));
|
DEBB(DF_GRAPH, ("polling for events\n"));
|
||||||
|
|
||||||
|
@ -4826,7 +4826,7 @@ void draw_ceiling(cell *c, const transmatrix& V, int fd, color_t& fcol, color_t&
|
|||||||
color_t wcol2 = gradient(0, wcol, 0, .8, 1);
|
color_t wcol2 = gradient(0, wcol, 0, .8, 1);
|
||||||
placeSidewall(c, i, SIDE_SKY, V, darkena(wcol2, fd, 0xFF));
|
placeSidewall(c, i, SIDE_SKY, V, darkena(wcol2, fd, 0xFF));
|
||||||
}
|
}
|
||||||
sky->sky.emplace_back(c, V, 0);
|
if(!euclid) sky->sky.emplace_back(c, V, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
hud.cpp
8
hud.cpp
@ -651,7 +651,13 @@ void drawStats() {
|
|||||||
}
|
}
|
||||||
string vers = VER;
|
string vers = VER;
|
||||||
if(!nofps) vers += XLAT(" fps: ") + its(calcfps());
|
if(!nofps) vers += XLAT(" fps: ") + its(calcfps());
|
||||||
if(displayButtonS(4, vid.yres - 4 - vid.fsize/2, vers, 0x202020, 0, vid.fsize/2)) {
|
|
||||||
|
if(reserve_limit && reserve_count < reserve_limit) {
|
||||||
|
vers += " " + its(reserve_count) + "/" + its(reserve_limit) + " MB";
|
||||||
|
if(displayButtonS(4, vid.yres - 4 - vid.fsize/2, vers, 0xFF2020, 0, vid.fsize/2))
|
||||||
|
getcstat = PSEUDOKEY_MEMORY, instat = true;
|
||||||
|
}
|
||||||
|
else if(displayButtonS(4, vid.yres - 4 - vid.fsize/2, vers, 0x202020, 0, vid.fsize/2)) {
|
||||||
mouseovers = XLAT("frames per second"),
|
mouseovers = XLAT("frames per second"),
|
||||||
getcstat = SDLK_F1,
|
getcstat = SDLK_F1,
|
||||||
instat = true,
|
instat = true,
|
||||||
|
7
hyper.h
7
hyper.h
@ -5526,4 +5526,11 @@ namespace dual {
|
|||||||
void raise_error();
|
void raise_error();
|
||||||
bool invalid_matrix(const transmatrix T);
|
bool invalid_matrix(const transmatrix T);
|
||||||
|
|
||||||
|
extern bool show_memory_warning;
|
||||||
|
extern bool ignored_memory_warning;
|
||||||
|
extern int reserve_count, reserve_limit;
|
||||||
|
void apply_memory_reserve();
|
||||||
|
void show_memory_menu();
|
||||||
|
static const int PSEUDOKEY_MEMORY = 16397;
|
||||||
|
|
||||||
}
|
}
|
113
savemem.cpp
113
savemem.cpp
@ -5,6 +5,9 @@ namespace hr {
|
|||||||
|
|
||||||
bool memory_saving_mode = true;
|
bool memory_saving_mode = true;
|
||||||
|
|
||||||
|
bool show_memory_warning = true;
|
||||||
|
bool ignored_memory_warning;
|
||||||
|
|
||||||
static const int LIM = 150;
|
static const int LIM = 150;
|
||||||
|
|
||||||
heptagon *last_cleared;
|
heptagon *last_cleared;
|
||||||
@ -170,4 +173,114 @@ void set_if_removed(cell*& c, cell *val) {
|
|||||||
if(is_cell_removed(c)) c = val;
|
if(is_cell_removed(c)) c = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef array<char, 1048576> reserve_block;
|
||||||
|
|
||||||
|
int reserve_count = 0;
|
||||||
|
int reserve_limit = 128;
|
||||||
|
|
||||||
|
const int max_reserve = 4096;
|
||||||
|
array<reserve_block*, max_reserve> reserve;
|
||||||
|
|
||||||
|
std::new_handler default_handler;
|
||||||
|
|
||||||
|
purehookset hooks_clear_cache;
|
||||||
|
|
||||||
|
void reserve_handler() {
|
||||||
|
if(reserve_count) {
|
||||||
|
reserve_count--;
|
||||||
|
delete reserve[reserve_count];
|
||||||
|
}
|
||||||
|
if(reserve_count < 32) callhooks(hooks_clear_cache);
|
||||||
|
if(!reserve_count) std::set_new_handler(default_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_memory_reserve() {
|
||||||
|
if(reserve_count > 0) std::set_new_handler(default_handler);
|
||||||
|
if(reserve_limit > max_reserve) reserve_limit = max_reserve;
|
||||||
|
if(reserve_limit < 0) reserve_limit = 0;
|
||||||
|
while(reserve_count > reserve_limit) { reserve_count--; delete reserve[reserve_count]; }
|
||||||
|
try {
|
||||||
|
while(reserve_count < reserve_limit) {
|
||||||
|
reserve[reserve_count] = new reserve_block;
|
||||||
|
/* only if successful */
|
||||||
|
reserve_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(std::bad_alloc&) {}
|
||||||
|
default_handler = std::get_new_handler();
|
||||||
|
if(reserve_count > 0) std::set_new_handler(reserve_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_for_lib() {
|
||||||
|
if(reserve_count) { reserve_count--; delete reserve[reserve_count]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_memory_menu() {
|
||||||
|
gamescreen(0);
|
||||||
|
dialog::init(XLAT("memory"));
|
||||||
|
|
||||||
|
dialog::addHelp(XLAT(
|
||||||
|
"HyperRogue takes place in a world that is larger than anything Euclidean. "
|
||||||
|
"Unfortunately, in some cases running it on an Euclidean computer might be "
|
||||||
|
"a problem -- the computer could simply run out of memory. Some lands (such as the Ocean or the Brown Islands) "
|
||||||
|
"may use up memory very fast!\n\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
if(sizeof(void*) <= 4)
|
||||||
|
dialog::addHelp(XLAT(
|
||||||
|
"You are playing a 32-bit HyperRogue executable, which can only use 4GB of memory.\n\n"));
|
||||||
|
|
||||||
|
dialog::addHelp(XLAT(
|
||||||
|
"Although you are extremely unlikely to return to a place you have already been to, "
|
||||||
|
"the game never forgets these areas, unless you start a new game, use an Orb of "
|
||||||
|
"Safety (found in Land of Eternal Motion and the Prairie), or activate the memory "
|
||||||
|
"saving mode, which tries to intelligently predict which cells you will never find "
|
||||||
|
"again and can be safely forgotten.\n\n")
|
||||||
|
);
|
||||||
|
|
||||||
|
if(cheater) dialog::addSelItem(XLAT("cells in memory"), its(cellcount) + "+" + its(heptacount), 0);
|
||||||
|
|
||||||
|
dialog::addBoolItem(XLAT("memory saving mode"), memory_saving_mode, 'f');
|
||||||
|
dialog::add_action([] { memory_saving_mode = !memory_saving_mode; if(memory_saving_mode) save_memory(), apply_memory_reserve(); });
|
||||||
|
|
||||||
|
dialog::addBoolItem_action(XLAT("show memory warnings"), show_memory_warning, 'w');
|
||||||
|
|
||||||
|
if(reserve_limit > 0 && reserve_count < reserve_limit) {
|
||||||
|
dialog::addItem(XLAT("just let me find Orb of Safety or finish the game"), 'l');
|
||||||
|
dialog::add_action([] { ignored_memory_warning = true; popScreen(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog::addSelItem("memory reserve", its(reserve_count) + "/" + its(reserve_limit) + " MB", 'r');
|
||||||
|
dialog::add_action([] {
|
||||||
|
dialog::editNumber(reserve_limit, 0, max_reserve, 16, 128, XLAT("memory reserve"),
|
||||||
|
XLAT("When to show a memory warning.")
|
||||||
|
);
|
||||||
|
dialog::bound_low(0);
|
||||||
|
dialog::bound_up(max_reserve);
|
||||||
|
dialog::reaction = apply_memory_reserve;
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog::addItem("clear caches", 'c');
|
||||||
|
dialog::add_action([] { callhooks(hooks_clear_cache); });
|
||||||
|
|
||||||
|
dialog::addBack();
|
||||||
|
dialog::display();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool protect_memory() {
|
||||||
|
if(reserve_limit && reserve_count < reserve_limit && !ignored_memory_warning) {
|
||||||
|
pushScreen(show_memory_menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(reserve_limit && reserve_count < 8) {
|
||||||
|
pushScreen(show_memory_menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool memory_issues() {
|
||||||
|
return reserve_limit && reserve_count < 16;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
43
sound.cpp
43
sound.cpp
@ -80,10 +80,17 @@ void handlemusic() {
|
|||||||
if(callhandlers(false, hooks_music, id)) return;
|
if(callhandlers(false, hooks_music, id)) return;
|
||||||
if(outoffocus) id = eLand(0);
|
if(outoffocus) id = eLand(0);
|
||||||
if(musfname[id] == "LAST") id = cid;
|
if(musfname[id] == "LAST") id = cid;
|
||||||
if(!loaded[id]) {
|
if(!loaded[id] && !memory_issues()) {
|
||||||
loaded[id] = true;
|
loaded[id] = true;
|
||||||
// printf("loading (%d)> %s\n", id, musfname[id].c_str());
|
// printf("loading (%d)> %s\n", id, musfname[id].c_str());
|
||||||
|
// reuse music
|
||||||
if(musfname[id] != "") {
|
if(musfname[id] != "") {
|
||||||
|
for(int i=0; i<landtypes; i++)
|
||||||
|
if(music[i] && musfname[i] == musfname[id])
|
||||||
|
music[id] = music[i];
|
||||||
|
}
|
||||||
|
if(!music[id]) {
|
||||||
|
memory_for_lib();
|
||||||
music[id] = Mix_LoadMUS(musfname[id].c_str());
|
music[id] = Mix_LoadMUS(musfname[id].c_str());
|
||||||
if(!music[id]) {
|
if(!music[id]) {
|
||||||
printf("Mix_LoadMUS: %s\n", Mix_GetError());
|
printf("Mix_LoadMUS: %s\n", Mix_GetError());
|
||||||
@ -205,6 +212,8 @@ void playSound(cell *c, const string& fname, int vol) {
|
|||||||
// printf("Play sound: %s\n", fname.c_str());
|
// printf("Play sound: %s\n", fname.c_str());
|
||||||
if(!chunks.count(fname)) {
|
if(!chunks.count(fname)) {
|
||||||
string s = wheresounds+fname+".ogg";
|
string s = wheresounds+fname+".ogg";
|
||||||
|
if(memory_issues()) return;
|
||||||
|
memory_for_lib();
|
||||||
chunks[fname] = Mix_LoadWAV(s.c_str());
|
chunks[fname] = Mix_LoadWAV(s.c_str());
|
||||||
// printf("Loading, as %p\n", chunks[fname]);
|
// printf("Loading, as %p\n", chunks[fname]);
|
||||||
}
|
}
|
||||||
@ -215,6 +224,34 @@ void playSound(cell *c, const string& fname, int vol) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reuse_music_memory() {
|
||||||
|
for(int i=0; i<landtypes; i++)
|
||||||
|
if(music[i] && music[i] != music[cid]) {
|
||||||
|
Mix_Music *which = music[i];
|
||||||
|
println(hlog, "freeing music for ", dnameof(eLand(i)));
|
||||||
|
Mix_FreeMusic(which);
|
||||||
|
for(int j=0; j<landtypes; j++) if(music[j] == which) {
|
||||||
|
println(hlog, "... which equals ", dnameof(eLand(j)));
|
||||||
|
music[j] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set<Mix_Chunk*> currently_played;
|
||||||
|
for(int ch=0; ch<16; ch++) currently_played.insert(Mix_GetChunk(ch));
|
||||||
|
set<string> to_free;
|
||||||
|
for(auto& p: chunks)
|
||||||
|
if(p.second) {
|
||||||
|
if(currently_played.count(p.second)) {
|
||||||
|
println(hlog, p.first, ": currently played");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Mix_FreeChunk(p.second);
|
||||||
|
to_free.insert(p.first);
|
||||||
|
println(hlog, p.first, ": freed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto& s: to_free) chunks.erase(s);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
void resetmusic() {}
|
void resetmusic() {}
|
||||||
#endif
|
#endif
|
||||||
@ -231,7 +268,7 @@ int read_sound_args() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ah_sound = addHook(hooks_args, 0, read_sound_args);
|
auto ah_sound = addHook(hooks_args, 0, read_sound_args) + addHook(hooks_clear_cache, 0, reuse_music_memory);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1313,6 +1313,7 @@ void start_game() {
|
|||||||
restart:
|
restart:
|
||||||
game_active = true;
|
game_active = true;
|
||||||
gamegen_failure = false;
|
gamegen_failure = false;
|
||||||
|
ignored_memory_warning = false;
|
||||||
check_cgi();
|
check_cgi();
|
||||||
cgi.require_basics();
|
cgi.require_basics();
|
||||||
initcells();
|
initcells();
|
||||||
|
Loading…
Reference in New Issue
Block a user