public static int Main(string[] args) { winx = Tools.GetArgument <int?>(args, "-screen-width") ?? 640; winy = Tools.GetArgument <int?>(args, "-screen-height") ?? 480; zoom = Tools.GetArgument <int?>(args, "-zoom") ?? 2; //init SDL SDL.SDL_Init(SDL.SDL_INIT_VIDEO); IntPtr window = SDL.SDL_CreateWindow("AITD memory viewer", SDL.SDL_WINDOWPOS_UNDEFINED, SDL.SDL_WINDOWPOS_UNDEFINED, winx, winy, SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE); IntPtr renderer = SDL.SDL_CreateRenderer(window, -1, SDL.SDL_RendererFlags.SDL_RENDERER_ACCELERATED | SDL.SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC); //IntPtr renderer = SDL.SDL_CreateRenderer(window, -1, SDL.SDL_RendererFlags.SDL_RENDERER_SOFTWARE); //SDL.SDL_SetHint(SDL.SDL_HINT_RENDER_SCALE_QUALITY, "linear"); IntPtr texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, RESX, RESY); uint[] palette = new uint[256]; byte[] palette256 = new byte[768]; SetRefreshState(true); bool quit = false, mcb = false, minimized = false; uint[] pixels = new uint[RESX * RESY * SCREENS]; uint[] mcbPixels = new uint[RESX * RESY * SCREENS]; byte[] pixelData = new byte[RESX * RESY * SCREENS]; byte[] oldPixelData = new byte[RESX * RESY * SCREENS]; long paletteAddress = -1; ProcessMemory process = null; uint lastCheck = 0, lastCheckPalette = 0; while (!quit) { SDL.SDL_Event sdlEvent; while (SDL.SDL_PollEvent(out sdlEvent) != 0 && !quit) { switch (sdlEvent.type) { case SDL.SDL_EventType.SDL_QUIT: quit = true; break; case SDL.SDL_EventType.SDL_MOUSEWHEEL: if ((SDL.SDL_GetModState() & SDL.SDL_Keymod.KMOD_CTRL) != 0) { if (sdlEvent.wheel.y > 0) { SetZoom(zoom + 1); } else if (sdlEvent.wheel.y < 0) { SetZoom(zoom - 1); } } break; case SDL.SDL_EventType.SDL_KEYDOWN: switch (sdlEvent.key.keysym.sym) { case SDL.SDL_Keycode.SDLK_SPACE: mcb = !mcb; SetRefreshState(true); break; } if ((sdlEvent.key.keysym.mod & SDL.SDL_Keymod.KMOD_CTRL) != 0) { switch (sdlEvent.key.keysym.sym) { case SDL.SDL_Keycode.SDLK_EQUALS: case SDL.SDL_Keycode.SDLK_KP_PLUS: SetZoom(zoom + 1); break; case SDL.SDL_Keycode.SDLK_MINUS: case SDL.SDL_Keycode.SDLK_KP_MINUS: SetZoom(zoom - 1); break; case SDL.SDL_Keycode.SDLK_0: case SDL.SDL_Keycode.SDLK_KP_0: SetZoom(2); break; } } break; case SDL.SDL_EventType.SDL_WINDOWEVENT: switch (sdlEvent.window.windowEvent) { case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED: winx = sdlEvent.window.data1; winy = sdlEvent.window.data2; SetRefreshState(true); break; case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED: minimized = true; break; case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESTORED: minimized = false; break; } break; } } if (process == null) { uint time = SDL.SDL_GetTicks(); if ((time - lastCheck) > 1000 || lastCheck == 0) { lastCheck = time; paletteAddress = -1; int processId = DosBox.SearchProcess(); if (processId != -1) { process = new ProcessMemory(processId); process.BaseAddress = process.SearchFor16MRegion(); if (process.BaseAddress == -1) { process.Close(); process = null; } } } } if (process != null) { if (paletteAddress == -1) { uint time = SDL.SDL_GetTicks(); if ((time - lastCheckPalette) > 1000 || lastCheckPalette == 0) { lastCheckPalette = time; //3 bytes + EGA 16 colors palette var pattern = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; paletteAddress = process.SearchForBytePattern(buffer => Tools.IndexOf(buffer, pattern, 1, 4)); } } } if (process != null) { //DOS conventional memory (640KB) //EMS memory (64000B) (skip 64KB (HMA) + 128KB (VCPI)) if (!(process.Read(pixelData, 0, 640 * 1024) > 0 && process.Read(pixelData, (1024 + 192) * 1024, 64000, 640 * 1024) > 0)) { process.Close(); process = null; } } if (process != null) { if (paletteAddress != -1) { if (process.Read(palette256, paletteAddress + 19 - process.BaseAddress, palette256.Length) <= 0) { process.Close(); process = null; } } } UpdatePalette(palette256, palette); Update(pixelData, oldPixelData, pixels, palette); UpdateMCB(pixelData, oldPixelData, mcbPixels); //render int tm = (winx + RESX * zoom - 1) / (RESX * zoom); int tn = (winy + RESY * zoom - 1) / (RESY * zoom); SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_NONE); Render(renderer, texture, tm, tn, pixels); if (mcb) { SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); Render(renderer, texture, tm, tn, mcbPixels); } SDL.SDL_RenderPresent(renderer); SetRefreshState(false); mustClearScreen = false; if (minimized) { SDL.SDL_Delay(1); } //swap buffers var tmp = pixelData; pixelData = oldPixelData; oldPixelData = tmp; } SDL.SDL_DestroyTexture(texture); SDL.SDL_DestroyRenderer(renderer); SDL.SDL_DestroyWindow(window); SDL.SDL_Quit(); return(0); }
static void CloseReader() { entryPoint = -1; process.Close(); process = null; }