/**
 * Replacement Debug Interface

 * Copyright (C) 2022, 2023 Yeoldetoast

 * This file is part of YeoldeDink

 * Yeoldedink is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.

 * Yeoldedink is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "SDL.h"
#include "SDL2_gfxPrimitives.h"
#if defined __linux__
#include <SDL2/SDL_mixer_ext.h>
#else
#include "SDL_mixer.h"
#endif

#include "debug_imgui.h"
#include "game_state.h"
#include "game_engine.h"
#include "live_sprites_manager.h"
#include "input.h"
#include "log.h"
#include "dinkc.h"
#include "dinkc_console.h"
#include "freedink.h"
#include "gfx.h"
#include "gfx_sprites.h"
#include "update_frame.h"
#include "live_screen.h"
#include "ImageLoader.h"
#include "status.h"
#include "sfx.h"
#include "bgm.h"
#include "DMod.h"
#include "savegame.h"
#include "paths.h"
#include "app.h"

#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "implot.h"

//For the log window
ImGuiTextBuffer Buf;
ImGuiTextFilter Filter;
ImVector <int> LineOffsets;
bool AutoScroll = true;
//For transparent overlay
static int corner = 0;
char debugbuf[128];
static int ts = 1;
char sfbuf[128];
//For various other window settings
bool render_tiles = true;
bool drawhard;
bool globinfo;
int modorder;
int sfxvol;
int musvol;

//for the var/sprite editors
int varedit = 1;
int spriedit = 2;
int sprigrid = 0;
int mspried = 1;
bool spoutline;
bool autoredraw;
bool sprilivechk;
bool hboxprev, ddotprev;
editor_sprite spritebuf;
editor_screen screenbuf;

//For dink.ini viewer
bool freeslots;

//Toggleable settings
bool debug_meminfo;
bool debug_pinksquares;
bool debug_drawsprites = true;
bool debug_drawgame = true;
bool debug_gamewindow;
bool debug_paused;
bool debug_conpause;
bool debug_scripboot;
bool debug_interp = true;
bool debug_infhp;
bool debug_magcharge;
bool debug_invspri;
bool debug_noclip;
bool debug_vision;
bool debug_screenlock;
bool debug_badpic = true;
bool debug_conwrite;

//Toggles for smaller windows
bool ultcheat;
bool graphicsopt;
bool dswitch;
bool logwindow;
bool keeb;
bool scripfo;
bool sprinfo;
bool varinfo;
bool sfxinfo;
bool metrics;
bool mapsquares;
bool maptiles;
bool sysinfo;
bool mapsprites;
bool dinkini;
bool helpbox;
bool aboutbox;

SDL_Texture* texture1 = NULL;

void gameload(int slot) {
	kill_all_scripts_for_real();
	load_game(slot);
	*pupdate_status = 1;
	draw_status_all();
}

void livesprtomap(int srcspr) {
	//Saves a live sprite to an editor sprite. Not all values are transferred of course
	cur_ed_screen.sprite[spr[srcspr].sp_index].brain = spr[srcspr].brain;
	cur_ed_screen.sprite[spr[srcspr].sp_index].x = spr[srcspr].x;
	cur_ed_screen.sprite[spr[srcspr].sp_index].y = spr[srcspr].y;
	cur_ed_screen.sprite[spr[srcspr].sp_index].size = spr[srcspr].size;
	cur_ed_screen.sprite[spr[srcspr].sp_index].seq = spr[srcspr].pseq;
	cur_ed_screen.sprite[spr[srcspr].sp_index].frame = spr[srcspr].pframe;
	cur_ed_screen.sprite[spr[srcspr].sp_index].touch_damage = spr[srcspr].touch_damage;
}	

//Stolen from the editor. Writes to dink.ini
static void add_text() {
	char death[150];
	char filename[10];
	//I should have just used getpic()
	sprintf(death, "SET_SPRITE_INFO %d %d %d %d %d %d %d %d\n",
		spr[spriedit].pseq, spr[spriedit].pframe,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].xoffset,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].yoffset,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.left,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.top,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.right,
		k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.bottom);

	strcpy(filename, "dink.ini");

	FILE* fp = paths_dmodfile_fopen(filename, "ab");
	if (fp != NULL) {
		fwrite(death, strlen(death), 1, fp);
		fclose(fp);
	} else {
		perror("add_text");
	}
}

void dbg_imgui(void) {
    //Only show stuff if debug is on and the game has loaded to title screen
	if (debug_mode && mode) {
//Show the mouse
ImGuiIO& io = ImGui::GetIO();
io.MouseDrawCursor = true;
//Main Menu bar
ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("File"))
{
    if (ImGui::MenuItem("Leave debug mode"))
    log_debug_off();
	if (ImGui::MenuItem("Pause", NULL, &debug_paused)) {
		stop_entire_game = 1;
		PauseMidi();
	} else if (!debug_paused)
		ResumeMidi();
	if (ImGui::MenuItem("Restart"))
		game_restart();
	if (ImGui::MenuItem("Quit")) {
	    SDL_Event ev;
	    ev.type = SDL_QUIT;
	    SDL_PushEvent(&ev);
	}

	ImGui::EndMenu();
}

if (ImGui::BeginMenu("Debug")) {
	ImGui::MenuItem("Info overlay", NULL, &dswitch);
	ImGui::MenuItem("Game popout window", NULL, &debug_gamewindow);
	ImGui::MenuItem("Ultimate Cheat", NULL, &ultcheat);
	ImGui::Separator();
	ImGui::MenuItem("Debug Log", NULL, &logwindow);
	if (ImGui::MenuItem("DinkC Console", "Alt+C"))
		dinkc_console_show();
	ImGui::Separator();
	ImGui::MenuItem("Pause while console activated", NULL, &debug_conpause);
	ImGui::MenuItem("Render game in main window", NULL, &debug_drawgame);
	ImGui::MenuItem("Show pink squares on hit()", NULL, &debug_pinksquares);
	ImGui::MenuItem("Show Hard.dat overlay", "Alt+H", &drawhard);
	ImGui::MenuItem("Render tiles and background", NULL, &render_tiles);
	if (ImGui::MenuItem("Draw invisible sprites", NULL, &debug_invspri)) {
		game_place_sprites_background();
		draw_screen_game_background();
	}
	ImGui::MenuItem("Ignore sprite visions ", NULL, &debug_vision);
	ImGui::MenuItem("Write to debug.txt", NULL, &debug_conwrite);
	ImGui::EndMenu();
}

if (ImGui::BeginMenu("Display")) {		
	ImGui::MenuItem("Texture filtering", NULL, &debug_interp);
	ImGui::Separator();
	if (ImGui::MenuItem("Set window to 640x480")) {
		SDL_SetWindowFullscreen(g_display->window, 0);
		SDL_SetWindowSize(g_display->window, 640, 480);
		SDL_SetWindowPosition(g_display->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
	}
	if (ImGui::MenuItem("Set window to 1280x960")) {
	SDL_SetWindowFullscreen(g_display->window, 0);
	SDL_SetWindowSize(g_display->window, 1280, 960);
	SDL_SetWindowPosition(g_display->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
	}
	if (ImGui::MenuItem("Set window to 1920x1440")) {
		SDL_SetWindowFullscreen(g_display->window, 0);
		SDL_SetWindowSize(g_display->window, 1920, 1440);
		SDL_SetWindowPosition(g_display->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
	}
	ImGui::Separator();
	if (ImGui::MenuItem("Toggle full screen display")) {
		g_display->toggleFullScreen();
	}
	if (ImGui::MenuItem("Make window borderless")) {
		SDL_SetWindowBordered(g_display->window, SDL_FALSE);
	}

	ImGui::EndMenu();
}

if (ImGui::BeginMenu("System"))
{
    //ImGui::MenuItem("Debug Mode Options", NULL, &dswitch);
	//ImGui::MenuItem("Graphics Options", NULL, &graphicsopt); 
    ImGui::MenuItem("Gamepad and Joystick", NULL, &keeb);
    ImGui::MenuItem("Audio", NULL, &sfxinfo);
	ImGui::MenuItem("System Information", NULL, &sysinfo);

	ImGui::EndMenu();
}

//TODO: incorporate this in one of the other menus
//if (ImGui::BeginMenu("Log Level"))
//{
//	if (ImGui::MenuItem("Errors only"))
//		log_debug_on(0);
//	if (ImGui::MenuItem("Standard"))
//		log_debug_on(1);
//	if (ImGui::MenuItem("Verbose"))
//		log_debug_on(2);
//
//	ImGui::EndMenu();
//}

if (ImGui::BeginMenu("Engine Data"))
{
	//ImGui::MenuItem("Tile Screen Preview", NULL, &maptiles);
	ImGui::MenuItem("Sprites", NULL, &sprinfo);
	ImGui::MenuItem("Variables", NULL, &varinfo);
	ImGui::MenuItem("Scripts", NULL, &scripfo);
	ImGui::Separator();
	ImGui::MenuItem("Map Index", NULL, &mapsquares);
	ImGui::MenuItem("Dink.ini", NULL, &dinkini);
	ImGui::EndMenu();
}

if (ImGui::BeginMenu("Speed"))
{
	if (ImGui::MenuItem("Normal Speed"))
		game_set_normal_speed();
	if (ImGui::MenuItem("High speed"))
		game_set_high_speed();
	if (ImGui::MenuItem("Slow speed"))
		game_set_slow_speed();

	ImGui::EndMenu();
}


	//Only show if game has started. Does weird stuff otherwise and I can't be bothered to fix it
if (ImGui::BeginMenu("Quick Save/Load"))
{
	if (mode < 2)
	ImGui::BeginDisabled();
	if (ImGui::MenuItem("QuickSave #1"))
		save_game(1337);
	if (ImGui::MenuItem("QuickSave #2"))
		save_game(1338);
	if (ImGui::MenuItem("QuickSave #3"))
		save_game(1339);
	ImGui::Separator();
	if (ImGui::MenuItem("Load #1")) {
		gameload(1337);
		*pupdate_status = 1;
	}
	if (ImGui::MenuItem("Load #2")) {
		gameload(1338);
	}
	if (ImGui::MenuItem("Load #3")) {
		gameload(1339);
	}
	if (mode < 2)
	ImGui::EndDisabled();

	ImGui::EndMenu();
}

if (ImGui::BeginMenu("Help")) {
	ImGui::MenuItem("Contents", NULL, &helpbox);
	ImGui::MenuItem("About", NULL, &aboutbox);
	ImGui::EndMenu();
}

if (console_active == 1) {
	if (ImGui::BeginMenu("Warning! Console Active!")) {
		if (ImGui::MenuItem("Deactivate Console", "Alt+C"))
			dinkc_console_hide();
		ImGui::EndMenu();
	}
	
}


ImGui::EndMainMenuBar();
//ImGui::ShowDemoWindow();
//ImPlot::ShowDemoWindow();
//Transparent overlay info window, stolen from the demo
if (dswitch) {
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
if (corner != -1)
    {
        const float PAD = 10.0f;
        const ImGuiViewport* viewport = ImGui::GetMainViewport();
        ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
        ImVec2 work_size = viewport->WorkSize;
        ImVec2 window_pos, window_pos_pivot;
        window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
        window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
        window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f;
        window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f;
        ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
        window_flags |= ImGuiWindowFlags_NoMove;
    }
	ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
    if (ImGui::Begin("Example: Simple overlay", NULL, window_flags))
    {
        ImGui::Text("Debug mode enabled. Press Alt+D to disable, Alt+C for console");
        ImGui::Separator();
		//Change the colour according to framerate
		ImVec4 col = ImVec4(1.0f, 1.0f, 0.0f, 1.0f);
		float fram = ImGui::GetIO().Framerate;
		if (fram >= 50)
			col = ImVec4(0.1f, 1.0f, 0.0f, 1.0f);
		if (fram < 30)
			col = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
		ImGui::TextColored(col, "Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
		ImGui::Text("Sprites: %d Moveman X%d X%d: Speed: %d Y%d Y%d, Screen: %d (%d)",
					last_sprite_created, spr[1].lpx[0],
					spr[1].lpy[0], spr[1].moveman, spr[1].lpx[1], spr[1].lpy[1], *pplayer_map, g_dmod.map.loc[*pplayer_map]);
        //if (ImGui::IsMousePosValid()) {
		//	float x, y;
		//	SDL_RenderWindowToLogical(SDL_GetRenderer(g_display->window), io.MousePos.x, io.MousePos.y, &x, &y);
        //   ImGui::Text("Mouse Position: (%.1f,%.1f) (%d, %d)", io.MousePos.x, io.MousePos.y, x, y);
		//}
        //else
         //   ImGui::Text("Mouse Position: <invalid>");
        ImGui::Text("%s", log_getLastLog());
		ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue;
		if (console_active) {
			if (debug_conpause)
				debug_paused = 1;
		if (ImGui::InputText("DinkC Console", debugbuf, IM_ARRAYSIZE(debugbuf), input_text_flags))
			{
			ImGui::SetItemDefaultFocus();
			dinkc_execute_one_liner(debugbuf);
			strcpy(debugbuf, "");
			}
		}
        if (ImGui::BeginPopupContextWindow())
        {
            if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
            if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
            if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
            if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
            if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
            if (ImGui::MenuItem("Close")) dswitch = false;
            ImGui::EndPopup();
        }
    }
    ImGui::End();
}
//Keyboard state and gamepad
if (keeb) {
ImGui::Begin("Gamepad and Joystick", &keeb);
if (ImGui::Button("Reinitialise input")) {
	joystick = 1;
	input_init();
}
int x;
for (x = 0; x < 256; x++)
	if (input_getcharstate(x))
	ImGui::Text("Key %i", x);
	if (jinfo) {
			SDL_GameController* ginfo = SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(jinfo));
			ImGui::Text("Detected Name: %s", SDL_JoystickName(jinfo));
			ImGui::Text("Button map loaded: %s", SDL_GameControllerMapping(ginfo));
			if (SDL_JoystickHasRumble(jinfo) && ImGui::Button("Test rumble")) {
				SDL_GameControllerRumble(ginfo, 0xFFFF, 0xFFFF, 500);
				SDL_GameControllerRumbleTriggers(ginfo, 0xFFFF, 0xFFFF, 900);
				}
			ImGui::SameLine();
			if (ImGui::Button("Reload button map")) {
				int mapping = SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
			}
			}
	else {
		ImGui::Text("Joystick/Gamepad not available");
	}
ImGui::End();
}

//Log Window
if (logwindow) {
ImGui::Begin("Log", &logwindow);
ImGui::Text("Log Level:");
ImGui::SameLine();
if (ImGui::Button("Errors Only"))
log_debug_on(0);
ImGui::SameLine();
if (ImGui::Button("All Debug and Application Info"))
log_debug_on(1);
ImGui::SameLine();
if (ImGui::Button("Verbose"))
log_debug_on(2);
ImGui::Separator();
ImGui::Text("Log:");
ImGui::SameLine();
ImGui::Checkbox("Meminfo", &debug_meminfo);
ImGui::SameLine();
ImGui::Checkbox("Boot", &debug_scripboot);
ImGui::SameLine();
ImGui::Checkbox("'Bad pic' warnings", &debug_badpic);
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue;
	if (console_active) {
	if (ImGui::InputText("DinkC Console", debugbuf, IM_ARRAYSIZE(debugbuf), input_text_flags))
	{
		dinkc_execute_one_liner(debugbuf);
		strcpy(debugbuf, "");
	}
	}
ImGui::Separator();
ImGui::Checkbox("Auto-scroll", &AutoScroll);
ImGui::SameLine();
if (ImGui::Button("Clear"))
memset(&Buf, 0, sizeof(debugbuf));
ImGui::SameLine();
if (ImGui::Button("Copy last message to clipboard")) {
ImGui::LogToClipboard();
ImGui::LogText(log_getLastLog());
ImGui::LogFinish();
ImGui::Separator();
}
ImGui::Separator();
//Child window with text in it
ImGui::BeginChild("scrolling");
const char* buf = Buf.begin();
const char* buf_end = Buf.end();
ImGui::TextUnformatted(buf, buf_end);
if (AutoScroll)
ImGui::SetScrollHereY(1.0f);

ImGui::EndChild();
ImGui::End();
}

//Ultimate Cheat
if (ultcheat) {
ImGui::Begin("Ultimater Cheat", &ultcheat);

if (ImGui::Button("Refill health")) {
    *plife = *plifemax;
	draw_status_all();
}
ImGui::SameLine();
if (ImGui::Button("Redraw status bar"))
    draw_status_all();
ImGui::SameLine();
if (ImGui::Button("Unlock screen"))
	screenlock = 0;
ImGui::SameLine();
if (ImGui::Button("Load/Draw screen")) {
	game_load_screen(g_dmod.map.loc[*pplayer_map]);
	draw_screen_game();
}
if (ImGui::Button("Kill enemies (no exp)")) {
	for (int i = 2; i < MAX_SPRITES_AT_ONCE; i++) {
		if (spr[i].hitpoints > 0)
		spr[i].damage = spr[i].hitpoints;
	}
}
ImGui::SameLine();
if (ImGui::Button("Unfreeze Sprite 1")) {
	spr[1].freeze = 0;
}

ImGui::Checkbox("Infinite health", &debug_infhp);
ImGui::SameLine();
ImGui::Checkbox("Infinite magic", &debug_magcharge);
ImGui::SameLine();
ImGui::Checkbox("Noclip", &debug_noclip);
//ImGui::SameLine();
//ImGui::Checkbox("Screenlock inactive", &debug_screenlock);
ImGui::Separator();
ImGui::SliderInt("Gold", pgold, 0, 99000);
ImGui::SliderInt("Attack", pstrength, 0, 999);
ImGui::SliderInt("Defense", pdefense, 0, 999);
ImGui::SliderInt("Magic", pmagic, 0, 999);
ImGui::SliderInt("Life", plife, 0, *plifemax);
ImGui::SliderInt("Lifemax", plifemax, 1, 500);
ImGui::SliderInt("Level", plevel, 1, 32);
ImGui::SliderInt("Map Screen", pplayer_map, 1, 768);
ImGui::SliderInt("Walk Speed (lower is faster)", &dinkspeed, 0, 5);
ImGui::SliderInt("Screen X", &spr[1].x, 0, 620);
ImGui::SliderInt("Screen Y", &spr[1].y, -1, 400);

ImGui::End();
}

if (graphicsopt) {
//Rendering options - obsoleted
ImGui::Begin("Graphics", &graphicsopt);
ImGui::Text("Video driver: %s", SDL_GetCurrentVideoDriver());
ImGui::Separator();
ImGui::Checkbox("Draw all Collision Data", &drawhard);
//ImGui::Checkbox("Draw Sprites", &debug_drawsprites);
ImGui::Checkbox("Redraw background", &render_tiles);
if (ImGui::Button("Fade Down"))
dinkc_execute_one_liner("fade_down()");
if (ImGui::Button("Fade up instantly"))
up_cycle();
ImGui::End();
}

if (scripfo) {
ImGui::Begin("Scrip Info", &scripfo, ImGuiWindowFlags_AlwaysAutoResize);
//For making scrip to show just one time
int m = 0;
//C has no reflection apparently
if (ImGui::BeginTable("table2", 13, ImGuiTableFlags_Borders)) {
	ImGui::TableSetupColumn("Name");
	ImGui::TableSetupColumn("Line");
	ImGui::TableSetupColumn("Column");
	ImGui::TableSetupColumn("Sprite");
	ImGui::TableSetupColumn("arg1");
	ImGui::TableSetupColumn("arg2");
	ImGui::TableSetupColumn("arg3");
	ImGui::TableSetupColumn("arg4");
	ImGui::TableSetupColumn("arg5");
	ImGui::TableSetupColumn("arg6");
	ImGui::TableSetupColumn("arg7");
	ImGui::TableSetupColumn("arg8");
	ImGui::TableSetupColumn("arg9");
	ImGui::TableHeadersRow();
for (int i = 0; i < MAX_SCRIPTS; i++)
	if (rinfo[i] != NULL)
    {	
		ImGui::TableNextColumn();
        ImGui::Text("%s", rinfo[i]->name);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->cur_line);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->cur_col);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->sprite);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg1);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg2);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg3);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg4);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg5);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg6);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg7);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg8);
		ImGui::TableNextColumn();
		ImGui::Text("%d", rinfo[i]->arg9);
		m++;
    }
	ImGui::EndTable();
}
ImGui::Separator();
ImGui::Text("Scrips to show:");
ImGui::SameLine();
float progress = (float)m / (float)MAX_SCRIPTS;
char buf[32];
sprintf(buf, "%d/%d", m, MAX_SCRIPTS);
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), buf);

ImGui::End();
}
//Sprite Information
if (sprinfo) {
    ImGui::Begin("Sprites", &sprinfo, ImGuiWindowFlags_AlwaysAutoResize);
	if (ImGui::BeginTabBar("spritab")) {
		if (ImGui::BeginTabItem("List")) {
			//ImGui::Checkbox("Filter editor sprites", &sprilivechk);
    	if (ImGui::BeginTable("table1", 17, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable)) {
			ImGui::TableSetupColumn("No.");
			ImGui::TableSetupColumn("x");
			ImGui::TableSetupColumn("y");
			ImGui::TableSetupColumn("pSeq");
			ImGui::TableSetupColumn("pFrame");
			ImGui::TableSetupColumn("Timing");
			ImGui::TableSetupColumn("Script");
			ImGui::TableSetupColumn("Brain/parms");
			ImGui::TableSetupColumn("HP");
			ImGui::TableSetupColumn("Dir");
			ImGui::TableSetupColumn("Cue");
			ImGui::TableSetupColumn("Freeze");
			ImGui::TableSetupColumn("Size");
			ImGui::TableSetupColumn("Text");
			ImGui::TableSetupColumn("Editor No.");
			ImGui::TableSetupColumn("Hard");
			ImGui::TableSetupColumn("Nodraw");
			ImGui::TableHeadersRow();
			for (int x = 1; x < MAX_SPRITES_AT_ONCE; ++x) {
				if (spr[x].active) {
					ImGui::TableNextColumn();
					ImGui::Text("%d", x);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].x);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].y);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].pseq);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].pframe);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].timing);
					ImGui::TableNextColumn();
					if (spr[x].script > 0)
					//ImGui::Text("%s", rinfo[spr[x].script]->name);
					ImGui::Text("%i", spr[x].script);
					else
					ImGui::Text("None");
					ImGui::TableNextColumn();
					ImGui::Text("%d/%d/%d", spr[x].brain, spr[x].brain_parm, spr[x].brain_parm2);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].hitpoints);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].dir);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].que);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].freeze);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].size);
					ImGui::TableNextColumn();
					ImGui::Text("%s", spr[x].text);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].sp_index);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].hard);
					ImGui::TableNextColumn();
					ImGui::Text("%d", spr[x].nodraw);
				}	
    	}
		ImGui::EndTable();
		}
		ImGui::EndTabItem();
		}
	//Sprite editor tab
	if (ImGui::BeginTabItem("Live Sprite Editor")) {
		ImGui::Text("Activate the console to type directly into the boxes");
		ImGui::Text("Selected Sprite: %d", spriedit);
		ImGui::SameLine();
		ImGui::PushButtonRepeat(true);
		if (ImGui::ArrowButton("##left", ImGuiDir_Left) && spriedit != 1) { spriedit--; }
		ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
		if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { spriedit++; }
		ImGui::PopButtonRepeat();
		ImGui::SameLine();
		ImGui::Checkbox("Highlight", &spoutline);
		ImGui::Separator();
		//Sprite properties
		if (ImGui::Button("Deactivate sprite")) {
			spr[spriedit].active = 0;
		}
		if (spr[spriedit].sp_index > 0) {
			ImGui::SameLine();
			if (ImGui::Button("Edit corresponding map sprite"))
			mspried = spr[spriedit].sp_index;
			if (ImGui::Button("Copy and save live sprite data to map sprite")) {
				livesprtomap(spriedit);
				save_screen(g_dmod.map.map_dat.c_str(), g_dmod.map.loc[*pplayer_map]);
			}
		}
		ImGui::SliderInt("X", &spr[spriedit].x, 0, 600);
		ImGui::SliderInt("Y", &spr[spriedit].y, 0, 400);
		ImGui::RadioButton("Frozen", &spr[spriedit].freeze, 1);
		ImGui::SameLine();
		ImGui::RadioButton("Thawed", &spr[spriedit].freeze, 0);
		ImGui::RadioButton("Not nohit", &spr[spriedit].nohit, 0);
		ImGui::SameLine();
		ImGui::RadioButton("Nohit active", &spr[spriedit].nohit, 1);
		ImGui::RadioButton("Drawn", &spr[spriedit].nodraw, 0);
		ImGui::SameLine();
		ImGui::RadioButton("Nodraw", &spr[spriedit].nodraw, 1);
		ImGui::RadioButton("Hard on", &spr[spriedit].hard, 0);
		ImGui::SameLine();
		ImGui::RadioButton("Hard off", &spr[spriedit].hard, 1);
		ImGui::SliderInt("pSequence", &spr[spriedit].pseq, 1, 1000);
		ImGui::SliderInt("pFrame", &spr[spriedit].pframe, 1, 69);
		ImGui::SliderInt("Direction", &spr[spriedit].dir, 1, 8);
		ImGui::SliderInt("Size", &spr[spriedit].size, 1, 200);
		ImGui::SameLine();
		if (ImGui::SmallButton("Reset"))
			spr[spriedit].size = 100;
		ImGui::InputInt("Timing", &spr[spriedit].timing);
		ImGui::InputInt("Frame Delay", &spr[spriedit].frame_delay);
		//Change to drop down box eventually
		//ImGui::InputInt("Brain", &spr[spriedit].brain, 1, 2);
		ImGui::SliderInt("Depth Cue", &spr[spriedit].que, -1000, 1000);
		ImGui::InputText("Text", spr[spriedit].text, sizeof(spr[spriedit].text));
		//ImGui::SliderInt("Hitpoints", &spr[spriedit].hitpoints, 0, 100);
		ImGui::Separator();
		if (ImGui::TreeNode("More sequences")) {
			ImGui::InputInt("Sequence", &spr[spriedit].seq);
			ImGui::InputInt("Frame", &spr[spriedit].frame);
			ImGui::InputInt("Blood Sequence", &spr[spriedit].bloodseq);
			ImGui::InputInt("Blood number", &spr[spriedit].bloodnum);
			ImGui::InputInt("Base Walk", &spr[spriedit].base_walk);
			ImGui::InputInt("Base Idle", &spr[spriedit].base_idle);
			ImGui::InputInt("Base Hit", &spr[spriedit].base_hit);
			ImGui::InputInt("Base Attack", &spr[spriedit].base_attack);
			ImGui::InputInt("Base Die", &spr[spriedit].base_die);
			ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::TreeNode("Enemy parameters")) {
			ImGui::InputInt("Hitpoints", &spr[spriedit].hitpoints);
			ImGui::InputInt("Touch damage", &spr[spriedit].touch_damage);
			ImGui::InputInt("Defence", &spr[spriedit].defense);
			ImGui::InputInt("Strength", &spr[spriedit].strength);
			ImGui::InputInt("Experience points", &spr[spriedit].exp);

			ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::TreeNode("Brain and parms")) {
			ImGui::InputInt("Brain", &spr[spriedit].brain);
			ImGui::InputInt("Parm 1", &spr[spriedit].brain_parm);
			ImGui::InputInt("Parm 2", &spr[spriedit].brain_parm2);

			ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::TreeNode("Trimming")) {
			ImGui::InputInt("Trim top", &spr[spriedit].alt.top);
			ImGui::InputInt("Trim left", &spr[spriedit].alt.left);
			ImGui::InputInt("Trim/show right", &spr[spriedit].alt.right);
			//ImGui::Text("Set this as high as it will go");
			ImGui::InputInt("Trim/show bottom", &spr[spriedit].alt.bottom);

			ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::TreeNode("Dink.ini properties")) {
			ImGui::Checkbox("Hardbox preview", &hboxprev);
			ImGui::SameLine();
			ImGui::Checkbox("Dot preview", &ddotprev);
			ImGui::SeparatorText("Hardbox");
			ImGui::TextWrapped("Be aware that this may have been edited by an init() line at some point.");
			ImGui::InputInt("Left", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.left);
			ImGui::InputInt("Top", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.top);
			ImGui::InputInt("Right", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.right);
			ImGui::InputInt("Bottom", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.bottom);
			ImGui::SeparatorText("Depth dot offset");
			ImGui::InputInt("X", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].xoffset);
			ImGui::InputInt("Y", &k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].yoffset);
			ImGui::Separator();
			if (ImGui::Button("Copy depth dot and hardbox values to clipboard")) {
				ImGui::LogToClipboard();
				ImGui::LogText("%d %d %d %d %d %d", k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].xoffset, k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].yoffset,
				k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.left, k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.top, k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.right, k[seq[spr[spriedit].pseq].frame[spr[spriedit].pframe]].hardbox.bottom);
				ImGui::LogFinish();
			}
			if (ImGui::Button("Append SET_SPRITE_INFO line to Dink.ini")) {
				add_text();
		}
		ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::Button("Copy create_sprite() command to clipboard")) {
			ImGui::LogToClipboard();
			ImGui::LogText("create_sprite(%d, %d, %d, %d, %d)", spr[spriedit].x, spr[spriedit].y, spr[spriedit].brain, spr[spriedit].pseq, spr[spriedit].pframe);
			ImGui::LogFinish();
		}
		ImGui::EndTabItem();
	} // Start of screen sprite editor
	if (ImGui::BeginTabItem("Map.dat Sprite Editor")) {
		if (mode == 1)
		ImGui::BeginDisabled();
		int maxframe = 0;
		//ImGui::Text("Careful now.");
		//Index selector
		ImGui::Text("Selected editor sprite: %d", mspried);
		ImGui::SameLine();
		ImGui::PushButtonRepeat(true);
		if (ImGui::ArrowButton("##back", ImGuiDir_Left)) {if (mspried > 1) mspried--;}
		ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
		if (ImGui::ArrowButton("##forward", ImGuiDir_Right)) { mspried++; } 
		ImGui::PopButtonRepeat();
		ImGui::SameLine();
		if (ImGui::Button("1")) 
			mspried = 1;
		if (ImGui::IsItemHovered())
			ImGui::SetTooltip("Return to the first sprite index");
		//Various buttons
		if (ImGui::Button("Redraw screen")) {
			draw_screen_game();
		}
		ImGui::SameLine();
		ImGui::Checkbox("Automatic redraw", &autoredraw);
		ImGui::Separator();

		if (cur_ed_screen.sprite[mspried].active == 0) {
		if (ImGui::Button("Activate Sprite")) {
			cur_ed_screen.sprite[mspried].active = 1;
		}
		}
		else {
		if (ImGui::Button("Remove Sprite"))
			cur_ed_screen.sprite[mspried].active = 0;
		
		ImGui::SameLine();
		if (ImGui::Button("Make duplicate")) {
			//Find an empty slot
			for (int i = 1; i < MAX_SPRITES_EDITOR; i++) {
				if (cur_ed_screen.sprite[i].active == 0) {
					memcpy(&cur_ed_screen.sprite[i], &cur_ed_screen.sprite[mspried], sizeof(editor_sprite));
					mspried = i;
					break;
				}
			}
		}
		}
		ImGui::Separator();
		//Get top frame
		ImGui::SliderInt("X position", &cur_ed_screen.sprite[mspried].x, 0, 620);
		ImGui::SliderInt("Y position", &cur_ed_screen.sprite[mspried].y, 0, 400);
		ImGui::RadioButton("Type 0: background", &cur_ed_screen.sprite[mspried].type, 0);
		ImGui::SameLine();
		ImGui::RadioButton("1: normal", &cur_ed_screen.sprite[mspried].type, 1);
		ImGui::SameLine();
		ImGui::RadioButton("2: invisible", &cur_ed_screen.sprite[mspried].type, 2);
		ImGui::RadioButton("Hard off", &cur_ed_screen.sprite[mspried].hard, 1);
		ImGui::SameLine();
		ImGui::RadioButton("Hard on", &cur_ed_screen.sprite[mspried].hard, 0);
		ImGui::RadioButton("Nohit off", &cur_ed_screen.sprite[mspried].nohit, 0);
		ImGui::SameLine();
		ImGui::RadioButton("Nohit on", &cur_ed_screen.sprite[mspried].nohit, 1);
		ImGui::SliderInt("Vision", &cur_ed_screen.sprite[mspried].vision, 0, 9);
		ImGui::InputInt("Sequence", &cur_ed_screen.sprite[mspried].seq,1);
		ImGui::SliderInt("Frame", &cur_ed_screen.sprite[mspried].frame, 1, 50);
		ImGui::SliderInt("Size", &cur_ed_screen.sprite[mspried].size, 1, 200);
		ImGui::SameLine();
		if (ImGui::SmallButton("Reset"))
			cur_ed_screen.sprite[mspried].size = 100;
		ImGui::InputInt("Brain", &cur_ed_screen.sprite[mspried].brain);
		ImGui::SliderInt("Depth Cue", &cur_ed_screen.sprite[mspried].que, -100, 100);
		ImGui::InputText("Script", cur_ed_screen.sprite[mspried].script, sizeof(cur_ed_screen.sprite[mspried].script));
		ImGui::Separator();
		ImGui::InputInt("Speed", &cur_ed_screen.sprite[mspried].speed);
		ImGui::InputInt("Timing", &cur_ed_screen.sprite[mspried].timing);
		ImGui::Separator();
		if (ImGui::TreeNode("Warp properties")) {
			ImGui::RadioButton("Warp Off", &cur_ed_screen.sprite[mspried].is_warp, 0);
			ImGui::SameLine();
			ImGui::RadioButton("Warp On", &cur_ed_screen.sprite[mspried].is_warp, 1);
			ImGui::InputInt("Map screen", &cur_ed_screen.sprite[mspried].warp_map);
			ImGui::SliderInt("X position", &cur_ed_screen.sprite[mspried].warp_x, 0, 620);
			ImGui::SliderInt("Y position", &cur_ed_screen.sprite[mspried].warp_y, 0, 400);
			ImGui::InputInt("Warp sequence", &cur_ed_screen.sprite[mspried].parm_seq);
			ImGui::InputInt("Sound", &cur_ed_screen.sprite[mspried].sound);
			ImGui::TreePop();
		}
		if (ImGui::TreeNode("Enemy properties")) {
			ImGui::InputInt("Hitpoints", &cur_ed_screen.sprite[mspried].hitpoints);
			ImGui::InputInt("Strength", &cur_ed_screen.sprite[mspried].strength);
			ImGui::InputInt("Defence", &cur_ed_screen.sprite[mspried].defense);
			ImGui::InputInt("Experience points", &cur_ed_screen.sprite[mspried].exp);
			ImGui::InputInt("Touch damage", &cur_ed_screen.sprite[mspried].touch_damage);
			ImGui::InputInt("Gold", &cur_ed_screen.sprite[mspried].gold);
			ImGui::TreePop();
		}
		if (ImGui::TreeNode("Base sequences")) {
			ImGui::InputInt("Base walk", &cur_ed_screen.sprite[mspried].base_walk);
			ImGui::InputInt("Base attack", &cur_ed_screen.sprite[mspried].base_attack);
			ImGui::InputInt("Base idle", &cur_ed_screen.sprite[mspried].base_idle);
			ImGui::InputInt("Base die", &cur_ed_screen.sprite[mspried].base_die);
			ImGui::InputInt("Base hit (unused)", &cur_ed_screen.sprite[mspried].base_hit);
			ImGui::TreePop();
		}
		if (ImGui::TreeNode("Trimming")) {
			ImGui::InputInt("Trim top", &cur_ed_screen.sprite[mspried].alt.top);
			ImGui::InputInt("Trim left", &cur_ed_screen.sprite[mspried].alt.left);
			ImGui::InputInt("Trim/show right", &cur_ed_screen.sprite[mspried].alt.right);
			ImGui::InputInt("Trim/show bottom", &cur_ed_screen.sprite[mspried].alt.bottom);
			ImGui::TreePop();
		}
		ImGui::Separator();
		if (ImGui::Button("Save changes to MAP.DAT")) {
			save_screen(g_dmod.map.map_dat.c_str(), g_dmod.map.loc[*pplayer_map]);
		}


		if (mode == 1)
		ImGui::EndDisabled();

		if (autoredraw) {
			draw_screen_game();
		}
		ImGui::EndTabItem();
	}
	ImGui::EndTabBar();  
	}
	ImGui::End();
}


if (varinfo) {
    ImGui::Begin("Variables", &varinfo, ImGuiWindowFlags_AlwaysAutoResize);
	//editor and option(s)
	ImGui::Checkbox("Hide globals", &globinfo);
	ImGui::Separator();
	ImGui::Text("Variable number: %d", varedit);
	ImGui::SameLine();
	ImGui::PushButtonRepeat(true);
	if (ImGui::ArrowButton("##left", ImGuiDir_Left) && varedit != 1) { varedit--; }
	ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
	if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { varedit++; }
	ImGui::PopButtonRepeat();
	ImGui::InputInt("Value", &play.var[varedit].var);
	ImGui::Separator();
	//Table begins
	if (ImGui::BeginTable("table5", 5, ImGuiTableFlags_Borders)) {
	ImGui::TableSetupColumn("Number");
	ImGui::TableSetupColumn("Name");
	ImGui::TableSetupColumn("Value");
	ImGui::TableSetupColumn("Active");
	ImGui::TableSetupColumn("Scope");
	ImGui::TableHeadersRow();
    for (int i = 1; i < MAX_VARS; i++) {
		if (!strncmp(play.var[i].name, "&", 1)) {
			if (play.var[i].scope == 0 && globinfo) { }
			else {
		ImGui::TableNextColumn();
		ImGui::Text("%d", i);
		ImGui::TableNextColumn();
        ImGui::Text(play.var[i].name);
		ImGui::TableNextColumn();
		ImGui::Text("%d", play.var[i].var);
		//ImGui::DragInt("##value", *play.var[i].var);
		ImGui::TableNextColumn();
		ImGui::Text("%d", play.var[i].active);
		ImGui::TableNextColumn();
		ImGui::Text("%d", play.var[i].scope);
		if (i == varedit)
		ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImGui::GetColorU32(ImVec4(0.7f, 0.3f, 0.3f, 0.65f)));
		ImGui::TableNextRow();
			}
		}
	
    }
	ImGui::EndTable();
	}
    ImGui::End();
}

if (sfxinfo) {
    ImGui::Begin("Audio Settings", &sfxinfo, ImGuiWindowFlags_AlwaysAutoResize);
	sfxvol = Mix_MasterVolume(-1);
	musvol = Mix_VolumeMusic(-1);
	if (Mix_GetSoundFonts() != NULL) {
		ImGui::Text("SoundFont in use: %s", Mix_GetSoundFonts());
	}
	else {
	ImGui::InputText("Full path to SoundFont", sfbuf, IM_ARRAYSIZE(sfbuf)); 
	ImGui::SameLine();
	if (ImGui::Button("Set"))
	{
	Mix_SetSoundFonts(sfbuf);
	}
	}
	//ImGui::Separator();
	//ImGui::SliderInt("Mod/XM order", &modorder, 0, 99);
	//ImGui::SameLine();
	//if (ImGui::Button("Set")) {
	//Mix_ModMusicJumpToOrder(modorder);
	//}
	ImGui::SeparatorText("Volume");
	if (ImGui::SliderInt("SFX", &sfxvol, 0, MIX_MAX_VOLUME))
	Mix_MasterVolume(sfxvol);
	if (ImGui::SliderInt("Music", &musvol, 0, MIX_MAX_VOLUME))
	Mix_VolumeMusic(musvol);
	ImGui::SeparatorText("BGM and SFX control");
	if (something_playing()) {
		if (ImGui::Button("Halt BGM"))
		bgm_quit();
		ImGui::SameLine();
	}
	if (ImGui::Button("Pause BGM"))
		PauseMidi();
	ImGui::SameLine();
	if (ImGui::Button("Resume BGM"))
		ResumeMidi();
	ImGui::SameLine();
	if (ImGui::Button("Rewind BGM"))
		Mix_RewindMusic();
	ImGui::SameLine();
	if (ImGui::Button("Halt SFX"))
		Mix_HaltChannel(-1);
	ImGui::SeparatorText("Audio Decoders");
	if (Mix_GetNumMusicDecoders() == 0) {
		ImGui::Text("No music decoders enabled. Sound is probably switched off.");
	}
	for (int i=0; i < Mix_GetNumMusicDecoders(); i++)
		ImGui::Text("%s", Mix_GetMusicDecoder(i));

	#ifdef __linux__
	ImGui::SeparatorText("MixerX Settings");
	ImGui::Text("Select MIDI Backend:");
	if (ImGui::Button("ADLMIDI"))
		Mix_SetMidiPlayer(MIDI_ADLMIDI);
	ImGui::SameLine();
	if (ImGui::Button("OPNMIDI"))
		Mix_SetMidiPlayer(MIDI_OPNMIDI);
	ImGui::SameLine();
	if (ImGui::Button("FluidSynth"))
		Mix_SetMidiPlayer(MIDI_Fluidsynth);
	if (ImGui::Button("Timidity++")) {
		Mix_SetMidiPlayer(MIDI_Timidity);
	}
	#endif
	ImGui::End();
}

if (sysinfo) {
	ImGui::Begin("System Information", &sysinfo, ImGuiWindowFlags_AlwaysAutoResize);
	ImGui::Text("SDL Revision: %s", SDL_GetRevision());
	ImGui::Text("Platform: %s", SDL_GetPlatform());
	ImGui::Text("Video driver: %s", SDL_GetCurrentVideoDriver());
	ImGui::Text("Audio driver: %s", SDL_GetCurrentAudioDriver());
	//ImGui::Text("Mixer ver: %d", Mix_Linked_Version());
	ImGui::Text("System RAM: %iMiB", SDL_GetSystemRAM());
	if (truecolor)
	ImGui::Text("Truecolour 24-bit mode enabled");
	if (!truecolor)
	ImGui::Text("256 colour-paletted 8-bit graphics mode in use");
	if (ImGui::SmallButton("Okay"))
	sysinfo = false;
	ImGui::End();
}

if (metrics) {
	ImGui::Begin("Metrics Graphs", &metrics, ImGuiWindowFlags_AlwaysAutoResize);
	ImGui::Text("Todo");
	ImGui::End();
}

if (mapsquares) {
	ImGui::Begin("Map Screens", &mapsquares, ImGuiWindowFlags_AlwaysAutoResize);
	if (ImGui::BeginTable("table3", 32, ImGuiTableFlags_Borders))
{
    for (int item = 1; item < 769; item++)
    {
        ImGui::TableNextColumn();
		if (item == *pplayer_map)
		ImGui::TextColored(ImVec4(0,1,0,1), "%i", g_dmod.map.loc[item]);
		else
        ImGui::Text("%i", g_dmod.map.loc[item]);
		if (ImGui::IsItemHovered())
                ImGui::SetTooltip("Screen: %i, Indoor: %i, Music: %i", item, g_dmod.map.indoor[item], g_dmod.map.music[item]);
		if (ImGui::BeginPopupContextWindow()) {
			if (ImGui::MenuItem("Custom", NULL)) dswitch = -1;
			ImGui::EndPopup();
		}
    }
    ImGui::EndTable();
}
ImGui::End();
}

if (maptiles) {
	ImGui::Begin("Tilescreens", &maptiles);
	if (ImGui::SliderInt("Screen", &ts, 1, 41)) {
	texture1 = NULL;
	texture1 = SDL_CreateTextureFromSurface(SDL_GetRenderer(g_display->window), g_dmod.bgTilesets.slots[ts]->screenshot());
	}
	ImGui::Image(texture1, ImVec2((int)g_dmod.bgTilesets.slots[ts]->w, g_dmod.bgTilesets.slots[ts]->h));
	ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
	ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); 
	ImDrawList* draw_list = ImGui::GetWindowDrawList();
	ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
	//for (int i = 1; i < 96; i++) {
	//	
	//	ImGui::Text("%i", cur_ed_screen.t[i].square_full_idx0);
	//}
	ImGui::End();
}

if (mapsprites) {
	ImGui::Begin("Sprites", &mapsprites);
		int seq_no = 75;
		SDL_Texture *texture = SDL_CreateTextureFromSurface(SDL_GetRenderer(g_display->window), GFX_k[seq[seq_no].frame[1]].k->screenshot());
		ImGui::Image(texture, ImVec2((int)GFX_k[seq[seq_no].frame[1]].k->w, GFX_k[seq[seq_no].frame[1]].k->h));
	ImGui::End();
}

if (dinkini) {
	ImGui::Begin("Dink.ini", &dinkini);
	ImGui::Checkbox("Show unused sequence slots", &freeslots);
	ImGui::Separator();
	if (ImGui::BeginTable("table9", 3, ImGuiTableFlags_Borders)) {
		ImGui::TableSetupColumn("Number", ImGuiTableColumnFlags_WidthFixed, 35.1f);
		ImGui::TableSetupColumn("ini line or init() command");
		ImGui::TableSetupColumn("Frames", ImGuiTableColumnFlags_WidthFixed, 35.1f);
		ImGui::TableHeadersRow();
		for (int i = 1; i < MAX_SEQUENCES; i++) {
			if ((!seq[i].is_active && freeslots) || seq[i].is_active) {
				ImGui::TableNextColumn();
				ImGui::Text("%i", i);
				ImGui::TableNextColumn();
				if (seq[i].ini != NULL)
				ImGui::Text("%s", seq[i].ini);
				else
				ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Empty");
				ImGui::TableNextColumn();
				ImGui::Text("%hi", seq[i].len);
			}
			
		}
		ImGui::EndTable();
	}
	ImGui::End();
}

if (helpbox) {
	ImGui::Begin("A Brief Description of YeOldeDink", &helpbox);
	ImGui::TextWrapped("Welcome to YeOldeDink, a fork of GNU Freedink with many bugfixes and enhancements based upon Ghostknight's fork and using Ocornut's Dear ImGui for the interface. As a general reminder, most input boxes can be typed into by activating the console, and slider/drag widgets can have their increment speed modified by holding either shift or alt while interacting with it.\n\n");
	ImGui::Spacing();
	ImGui::SeparatorText("File menu");
	ImGui::BulletText("Leave debug mode: This closes the ImGui interface and is equivalent to pressing Alt+D\n");
	ImGui::BulletText("Pause: This interrupts the execution of the engine until you choose to unpause\n");
	ImGui::BulletText("Restart: This will take you back to the title screen or similar\n");
	ImGui::BulletText("Quit: This will terminate the process and return you to your OS environment\n\n");
	ImGui::Spacing();
	ImGui::SeparatorText("Debug menu");
	ImGui::TextWrapped("- Info overlay: A transparent window that shows your FPS, along with the last debug log entry. The window may be moved to any corner of the screen or to a custom location by right-clicking. The DinkC console will appear here when activated.\n");
	ImGui::TextWrapped("- Game popout window: Dink within Dink. Useful if you want to go full-screen while using the debug log at the same time etc\n");
	ImGui::TextWrapped("- Ultimat(er) Cheat: Homage to the much-beloved script by Gary Hertel and Ted Shutes.\n");
	ImGui::TextWrapped("- Debug Log: See engine messages in real-time. Log level selects which messages are displayed, and some of the more useless log triggers have been switched off by default. The DinkC console will also appear in this window when enabled.\n");
	ImGui::TextWrapped("- DinkC Console: manually toggles the console. Equivalent to pressing Alt+C. It will also bypass keyboard input control for typing into text boxes etc\n");
	ImGui::TextWrapped("- Pause while console activated: The execution of the engine will be interrupted, and your DinkC command results apparent after deactivating the console while enabled\n");
	ImGui::TextWrapped("- Render game in main window: Toggles the display to the background. Designed for use with the popout window.\n");
	ImGui::TextWrapped("- Show pink squares: Shows a pink hardbox overlay on touchable sprites, as well as bounding boxes for all sprites upon punching things.\n");
	ImGui::TextWrapped("- Show hard.dat squares: Display tile and sprite collision without having to open DinkEdit.");
	ImGui::TextWrapped("- Render tiles and background: Turns off the re-rendering of the background upon a screen change. Probably best to leave it on.\n");
	ImGui::TextWrapped("- Draw invisible sprites: Draws sprites that are either set to type 2, or are specified nodraw.\n");
	ImGui::TextWrapped("- Ignore sprite visions: Display all sprites on a screen regardless of which vision they're assigned.\n");
	ImGui::TextWrapped("- Write to debug.txt: Chooses if messages are appended to debug.txt\n\n");
	ImGui::Spacing();
	ImGui::SeparatorText("Display menu");
	ImGui::BulletText("Texture filtering: Choose whether to filter the screen texture or use nearest-neighbour sampling");
	ImGui::BulletText("Set window to...: Changes the resolution in windowed mode.\n");
	ImGui::BulletText("Toggle full-screen display: Equivalent to pressing Alt+Enter.\n");
	ImGui::BulletText("Make window borderless: Removes the menu bar and outline provided by the operating system.");
	ImGui::Spacing();
	ImGui::SeparatorText("System menu");
	ImGui::TextWrapped("- Gamepad and Joystick: See whether or not your controller is detected, and attempt to connect it if it isn't.\n");
	ImGui::TextWrapped("- Audio: Set a SoundFont for MIDI playback here with FluidSynth, and change the volume due to FluidSynth being extremely loud. You can also see which audio file decoders are being used. On GNU/Linux you will also be able to adjust a few additional MIDI settings.\n");
	ImGui::TextWrapped("- System information: Shows your linked SDL2 version along with the video/audio backend in use. Also reminds you of how much RAM you have, and your operating system in case you forgot.\n\n");
	ImGui::Spacing();
	ImGui::SeparatorText("Engine data menu");
	ImGui::TextWrapped("- Sprites: On the first tab, shows you active sprites on the current screen along with some parameters. The second tab will allow you to edit these parameters in real-time, and the third tab edits the sprite properties in MAP.DAT itself");
	ImGui::TextWrapped("- Variables: View and edit your local and global variables. Filter out globals with the checkbox.\n");
	ImGui::TextWrapped("- Scripts: Lists which scripts are running at the moment, along with which part of the file is being read.\n");
	ImGui::TextWrapped("- Map Index: An overview of which screens are in use, which screen you're on, and the map.dat index number of the screen. Mouse over to see the dink.dat screen number and the corresponding parameters");
	ImGui::TextWrapped("- Dink.ini: See which sequences are in use, and which are empty. Note that the list may not be entirely accurate due to SET_FRAME_FRAME commands etc.\n\n");
	ImGui::Spacing();
	ImGui::SeparatorText("Speed");
	ImGui::BulletText("Normal speed: Equivalent to releasing the Tab key outside of debug mode after having held it down.\n");
	ImGui::BulletText("High speed: This will run the engine at twice the usual speed until chosen otherwise.");
	ImGui::BulletText("Slow speed: This runs the engine at half the normal speed. Unavailable outside of debug mode.");
	ImGui::Spacing();
	ImGui::SeparatorText("Quick save/load");
	ImGui::BulletText("QuickSave #Whatever: Saves the game into very high-numbered slots");
	ImGui::BulletText("Load: Reads a save file from a corresponding slot. Not available in mouse mode.\n");
	ImGui::Spacing();
	ImGui::SeparatorText("Other stuff");
	ImGui::BulletText("PNG support for both sprites and tiles in 24-bit mode");
	ImGui::BulletText("MP3 support for 1.08 Aural+ enjoyers, as well as FLAC and Opus");
	ImGui::BulletText("Pressing Tab in mouse mode will centre the cursor on the screen");
	ImGui::BulletText("DinkC: get_client_fork() returns 3");
	ImGui::BulletText("DinkC: play_mod_order(int) will set the pattern for tracker music");
	ImGui::End();
}

if (aboutbox) {
	ImGui::Begin("About", &aboutbox);
	ImGui::InvisibleButton("sneed", ImVec2(1.0f, 1.0f));
	ImGui::SameLine();
	ImGui::Text("YeOldeDink 0.6 © 2022-2023 YeOldeToast");
	ImGui::InvisibleButton("feed", ImVec2(1.0f, 1.0f));
	ImGui::SameLine();
	ImGui::Text("Based upon GNU Freedink by Beuc with improvements by Ghostknight");
	ImGui::InvisibleButton("chuck", ImVec2(1.0f, 1.0f));
	ImGui::SameLine();
	ImGui::Text("Many thanks to drone1400 for suggestions, TealCool for beta testing, \n\tredink1 for keeping the Dink forums alive, and RTSoft for making Dink.");
	ImGui::Spacing();
	ImGui::Text("\tUses Dear ImGui by Omar Cornut, and Tinyfiledialogs by Guillaume Vareille");
	if (ImGui::SmallButton("Okay"))
	aboutbox = false;
	ImGui::End();
}

//To make it pause when console is shown and relevant setting is on
if (console_active == 0 && debug_conpause) {
	debug_paused = 0;
}  

//ImGui::Begin("JSON thing");
//if (ImGui::Button("Get JSON")) {
//
//}
//ImGui::End();

//Stolen from freedinkedit, toggled in display options, requested by drone1400. Runs really slow in GL mode
if (drawhard) {
    int x1, y1;
	for (x1 = 0; x1 < 600; x1++)
		for (y1 = 0; y1 < 400; y1++) {
			if (screen_hitmap[x1][y1] == 1) {
				{
					SDL_Rect GFX_box_crap;
					GFX_box_crap.x = x1 + playl;
					GFX_box_crap.y = y1;
					GFX_box_crap.w = 1;
					GFX_box_crap.h = 1;
					IOGFX_backbuffer->fillRect(&GFX_box_crap, GFX_ref_pal[1].r,
											GFX_ref_pal[1].g,
											GFX_ref_pal[1].b);
				}
			}

			if (screen_hitmap[x1][y1] == 2) {
				{
					SDL_Rect GFX_box_crap;
					GFX_box_crap.x = x1 + playl;
					GFX_box_crap.y = y1;
					GFX_box_crap.w = 1;
					GFX_box_crap.h = 1;
					IOGFX_backbuffer->fillRect(
							&GFX_box_crap, GFX_ref_pal[128].r,
							GFX_ref_pal[128].g, GFX_ref_pal[128].b);
				}
			}

			if (screen_hitmap[x1][y1] == 3) {
				{
					SDL_Rect GFX_box_crap;
					GFX_box_crap.x = x1 + playl;
					GFX_box_crap.y = y1;
					GFX_box_crap.w = 1;
					GFX_box_crap.h = 1;
					IOGFX_backbuffer->fillRect(&GFX_box_crap, GFX_ref_pal[45].r,
											GFX_ref_pal[45].g,
											GFX_ref_pal[45].b);
				}
			}

			if (screen_hitmap[x1][y1] > 100) {

				if (cur_ed_screen.sprite[(screen_hitmap[x1][y1]) - 100]
							.is_warp == 1) {
					{
						SDL_Rect GFX_box_crap;
						GFX_box_crap.x = x1 + playl;
						GFX_box_crap.y = y1;
						GFX_box_crap.w = 1;
						GFX_box_crap.h = 1;
						IOGFX_backbuffer->fillRect(
								&GFX_box_crap, GFX_ref_pal[20].r,
								GFX_ref_pal[20].g, GFX_ref_pal[20].b);
					}
				} else {
					{
						SDL_Rect GFX_box_crap;
						GFX_box_crap.x = x1 + playl;
						GFX_box_crap.y = y1;
						GFX_box_crap.w = 1;
						GFX_box_crap.h = 1;
						IOGFX_backbuffer->fillRect(
								&GFX_box_crap, GFX_ref_pal[23].r,
								GFX_ref_pal[23].g, GFX_ref_pal[23].b);
					}
				}
			}
		}

}
//Draws a box around the sprite bounds so you can see which one you're editing. Toggled in the live sprite editor.
if (spr[spriedit].active == 1 && sprinfo) {
if (spoutline) {
	rect box;
	rect_copy(&box, &k[getpic(spriedit)].box);
	SDL_Rect r = {box.left + spr[spriedit].x - k[getpic(spriedit)].xoffset, box.top + spr[spriedit].y - k[getpic(spriedit)].yoffset, box.right - box.left,
									box.bottom - box.top};
						IOGFX_backbuffer->fillRect(&r, 255, 100, 0);
}
//hardbox preview for the sprite editor
if (hboxprev) {
	rect hbox;
	rect_copy(&hbox, &k[getpic(spriedit)].hardbox);
	SDL_Rect h = {hbox.left + spr[spriedit].x, hbox.top + spr[spriedit].y, hbox.right - hbox.left,
									hbox.bottom - hbox.top};
	IOGFX_backbuffer->fillRect(&h, 0, 100, 255);
}
//Depth dot
if (ddotprev) {
	rect ddot;
	ddot.left = spr[spriedit].x - 2;
	ddot.right = ddot.left + 3;
	ddot.top = spr[spriedit].y - 2;
	ddot.bottom = ddot.top + 3;
	SDL_Rect i = {ddot.left, ddot.top, 2, 2};
	IOGFX_backbuffer->fillRect(&i, 255,10,0);
}
}
//turns on overlay thingy
if (console_active && !dswitch && !logwindow)
dswitch = 1;

}
}