diff options
Diffstat (limited to 'core.c')
| -rw-r--r-- | core.c | 226 |
1 files changed, 0 insertions, 226 deletions
@@ -1,226 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <stdbool.h> -#include <unistd.h> -#include <assert.h> -#include <signal.h> -#include <SDL.h> - -#include "procfs.h" -#include "memview.h" - -static int screen_width = 640; -static int screen_height = 480; - -static double scale = 5; -static double pos_x = 1024; -static double pos_y = 0; - -static int mouse_x = 0; -static int mouse_y = 0; - -SDL_Window *window = NULL; -SDL_Renderer *renderer = NULL; - -pid_t pid; -int mem_fd; -struct viewer *viewer; - -static void add_scale(double amount) { - pos_x += mouse_x / scale; - pos_y += mouse_y / scale; - scale += amount; - if (scale > 50) scale = 50; - else if (scale < 0.5) scale = 0.5; - pos_x -= mouse_x / scale; - pos_y -= mouse_y / scale; -} - -static void world_pos(double *x, double *y) { - *x = *x / scale + floor(pos_x); - *y = *y / scale + floor(pos_y); -} - -static void goto_addr(uintptr_t addr) { - int x, y; - to_pos(addr, &x, &y); - pos_x = x; pos_y = y; - pos_x -= (double) screen_width / 2 * scale; - pos_y -= (double) screen_height / 2 * scale; -} - -static size_t current_map = 0; - -static void next_map() { - struct procfs_map *maps; - int n = procfs_maps(pid, &maps); - if (n < 1) return; - for (int i = 0; i < n; i++) { - current_map = (current_map + 1) % n; - if (maps[current_map].prot & PROT_READ) - break; - } - goto_addr(maps[current_map].base); - free(maps); -} - -static void prev_map() { - struct procfs_map *maps; - int n = procfs_maps(pid, &maps); - if (n < 1) return; - for (int i = 0; i < n; i++) { - current_map = current_map > 1 ? current_map - 1 : n - 1; - if (maps[current_map].prot & PROT_READ) - break; - } - goto_addr(maps[current_map].base); - free(maps); -} - -static void report_error() { - fprintf(stderr, "SDL Error: %s\n", SDL_GetError()); - exit(-1); -} - -static void init_sdl(const char *title) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) report_error(); - window = SDL_CreateWindow(title, - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - screen_width, screen_height, - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); - if (window == NULL) report_error(); - renderer = SDL_CreateRenderer(window, -1, 0); - if (renderer == NULL) report_error(); -} - -static void deinit_sdl() { - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); -} - -static bool held(SDL_Keycode k) { - const uint8_t *state = SDL_GetKeyboardState(NULL); - return state[SDL_GetScancodeFromKey(k)]; -} - -static void handle_events() { - bool refresh = false; - SDL_Event e; - while (SDL_PollEvent(&e)) { - switch (e.type) { - case SDL_QUIT: - exit(0); break; - case SDL_WINDOWEVENT: - switch (e.window.event) { - case SDL_WINDOWEVENT_RESIZED: - screen_width = e.window.data1; - screen_height = e.window.data2; - SDL_SetWindowSize(window, screen_width, screen_height); - refresh = true; - break; - case SDL_WINDOWEVENT_EXPOSED: - refresh = true; - break; - default: - break; - } - break; - case SDL_MOUSEMOTION:; - uint32_t state = e.motion.state; - if (state & SDL_BUTTON_MMASK || - (state & SDL_BUTTON_RMASK && held(SDLK_LSHIFT))) { - pos_x -= (double) e.motion.xrel / scale; - pos_y -= (double) e.motion.yrel / scale; - refresh = true; - } else if (state & (SDL_BUTTON_LMASK | SDL_BUTTON_RMASK)) { - double x1 = e.motion.x - e.motion.xrel; - double y1 = e.motion.y - e.motion.yrel; - double x2 = e.motion.x; double y2 = e.motion.y; - world_pos(&x1, &y1); world_pos(&x2, &y2); - pencil(viewer, - x1, y1, x2, y2, !(state & SDL_BUTTON_RMASK)); - refresh = true; - } - mouse_x = e.motion.x; - mouse_y = e.motion.y; - break; - case SDL_MOUSEBUTTONDOWN:; - double x = e.button.x; double y = e.button.y; - world_pos(&x, &y); - if (e.button.button == SDL_BUTTON_LEFT) - pencil(viewer, x, y, x, y, true); - else if (e.button.button == SDL_BUTTON_RIGHT) - pencil(viewer, x, y, x, y, false); - break; - case SDL_MOUSEWHEEL: - if (e.wheel.y == 0) break; - add_scale((double) e.wheel.y / 2); - refresh = true; - break; - case SDL_KEYDOWN: - switch (e.key.keysym.sym) { - case SDLK_RIGHT: - next_map(); - refresh = true; - break; - case SDLK_LEFT: - prev_map(); - refresh = true; - break; - case SDLK_SPACE:; - static bool stopped = false; - kill(pid, stopped ? SIGSTOP : SIGCONT); - stopped = !stopped; - break; - default: - break; - } - default: - break; - } - } - if (render_pages(viewer, pos_x, pos_y, - screen_width, screen_height, scale, refresh)) - SDL_RenderPresent(renderer); -} - -void cleanup() { - destroy_viewer(viewer); - deinit_sdl(); -} - -int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "todo: show usage\n"); - return -1; - } - pid = atoi(argv[1]); - if (pid == 0) { - fprintf(stderr, "todo: show usage\n"); - return -1; - } - mem_fd = procfs_open(pid); - if (mem_fd == -1) perror("error attaching to process"); - - char title[1024]; - snprintf(title, 1024, "%s [%d]", argv[0], pid); - init_sdl(title); - viewer = create_viewer(mem_fd, renderer); - if (!viewer) abort(); - atexit(cleanup); - - prev_map(); - - int last_time = 0; - int current_time = 0; - while (1) { - handle_events(); - last_time = current_time; - current_time = SDL_GetTicks(); - int elapsed = current_time - last_time; - if (elapsed < 1000 / 30) - SDL_Delay(1000 / 30 - elapsed); - } -} |
