Advertisement
Guest User

CITAlloc visualiser module

a guest
Sep 11th, 2024
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 29.38 KB | None | 0 0
  1. #include "rl.h"
  2.  
  3. volatile int exit_flag=0;
  4. char *watch_module_id = NULL;
  5. char watch_wahe_name[51];
  6.  
  7. #define BYTES_PER_UNIT (32.*1024.)
  8. #define CITA_MAX_INFO_SIZE 128
  9.  
  10. typedef struct
  11. {
  12.     int focus_index;
  13.     xy_t pos0, pos1;
  14.     double zoomscale_base, zoomscale_top;
  15.     double time0, time1, time2, time3;
  16.     double result_id_v;
  17.     int zoom_transition_on, filter_count;
  18. } filter_focus_t;
  19.  
  20. typedef struct
  21. {
  22.     int64_t addr, size;
  23.     char info[CITA_MAX_INFO_SIZE+1], *label;
  24.  
  25.     xy_t pos;
  26.     rect_t area;
  27.     col_t colour;
  28.     double row;
  29.     int filtered, filter_pos;
  30. } mem_range_t;
  31.  
  32. typedef struct
  33. {
  34.     char *name;
  35.     int64_t addr;
  36. } mem_type_start_t;
  37.  
  38. typedef enum { no_img, pal8, bw_bit, rgbx8 } vis_mode_t;
  39. const char *vis_mode_name[] = { "None", "Palettised bytes", "Black & white bits", "sRGBX 8-bit" };
  40. vis_mode_t vis_mode = no_img;
  41.  
  42. mem_range_t *mem_range = NULL;
  43. size_t mem_range_count = 0, mem_range_as = 0;
  44. mem_type_start_t *mts = NULL;
  45. size_t mts_count = 0, mts_as = 0, mts_index = 0;
  46. double max_row, starting_row = 0.;
  47. size_t pixel_address = (size_t) -1;
  48. int first_range_in_current_file;
  49. int vert = 1, img_update = 0, image_stride = 0, image_offset = 0;
  50. size_t filtered_size = 0;
  51.  
  52. xy_t flip_xy(xy_t a)
  53. {
  54.     if (vert)
  55.         return (xy(a.y, a.x));
  56.     return a;
  57. }
  58.  
  59. xyi_t flip_xyi(xyi_t a)
  60. {
  61.     if (vert)
  62.         return (xyi(a.y, a.x));
  63.     return a;
  64. }
  65.  
  66. size_t pix_to_addr(xyi_t pos, xyi_t im_dim)
  67. {
  68.     pos = flip_xyi(pos);
  69.     int32_t dim_y = flip_xyi(im_dim).y;
  70.     pos.y -= image_offset;
  71.  
  72.     if (vis_mode == bw_bit)
  73.     {
  74.         pos.y >>= 3;
  75.         dim_y >>= 3;
  76.     }
  77.  
  78.     if (vis_mode == rgbx8)
  79.     {
  80.         pos.y *= 4;
  81.         dim_y *= 4;
  82.     }
  83.  
  84.     return pos.x * dim_y + pos.y;
  85. }
  86.  
  87. sqrgb_t *make_byte_palette()
  88. {
  89.     sqrgb_t *pal = calloc(256, sizeof(sqrgb_t));
  90.  
  91.     for (int i=0; i < 256; i++)
  92.     {
  93.         double t = (255. - (double) i) * 0.2;
  94.         double m = sqrt((double) i / 255.);
  95.  
  96.         double red = (1.-fabs(sin_tr(0.16 * t))) * m;
  97.         double grn = (1.-fabs(sin_tr(0.02 * t))) * (double) i/255.;
  98.         double blu = (1.-fabs(sin_tr(0.15 * t))) * m;
  99.  
  100.         pal[i].r = sqrt(red) * 1023. + 0.5;
  101.         pal[i].g = sqrt(grn) * 4092. + 0.5;
  102.         pal[i].b = sqrt(blu) * 1023. + 0.5;
  103.     }
  104.  
  105.     return pal;
  106. }
  107.  
  108. void prepare_focus_transition(filter_focus_t *focus, int way)
  109. {
  110.     // Update result ID
  111.     focus->result_id_v = circ_index(nearbyint(focus->result_id_v) + way, focus->filter_count);
  112.  
  113.     // Find message index of new focus message
  114.     for (int ir=0; ir < mem_range_count; ir++)
  115.         if (mem_range[ir].filter_pos == focus->result_id_v)
  116.         {
  117.             focus->focus_index = ir;
  118.             break;
  119.         }
  120.  
  121.     if (focus->focus_index < 0)     // not sure why
  122.         focus->focus_index = 0;
  123.  
  124.     focus->pos0 = xyq_to_xy(zc.offset_uq);
  125.     focus->pos1 = rect_p01(mem_range[focus->focus_index].area);
  126.  
  127.     focus->zoomscale_base = zc.zoomscale;
  128.     focus->zoomscale_top = MINN(focus->zoomscale_base, 14. / hypot_xy(focus->pos0, focus->pos1));
  129.  
  130.     focus->time0 = get_time_hr();
  131.     focus->time1 = focus->time0 + 0.13 * (focus->zoomscale_base != focus->zoomscale_top);
  132.     focus->time2 = focus->time1 + 0.5 * MAXN(0., hypot_xy(focus->pos0, focus->pos1) * focus->zoomscale_top - 7.) / (14.-7.);
  133.     focus->time3 = focus->time2 + 0.13 * (focus->zoomscale_base != focus->zoomscale_top);
  134.     focus->zoom_transition_on = 1;
  135. }
  136.  
  137. void perform_focus_transition(filter_focus_t *focus)
  138. {
  139.     double now, t;
  140.  
  141.     if (focus->zoom_transition_on == 0)
  142.         return;
  143.  
  144.     now = get_time_hr();
  145.  
  146.     if (now <= focus->time1)    // zoom out at pos0
  147.     {
  148.         zc.offset_uq = xy_to_xyq(focus->pos0);
  149.         t = (now - focus->time0) / (focus->time1 - focus->time0);
  150.         //t = floor(t * 2.) / 2.;
  151.         zc.zoomscale = exp(mix(log(focus->zoomscale_base), log(focus->zoomscale_top), t));
  152.     }
  153.     else if (now <= focus->time2)   // travel from pos0 to pos1 zoomed out
  154.     {
  155.         t = (now - focus->time1) / (focus->time2 - focus->time1);
  156.         //t = floor(t * 3.) / 3.;
  157.         zc.offset_uq = xy_to_xyq(mix_xy(focus->pos0, focus->pos1, set_xy(t)));
  158.         zc.zoomscale = focus->zoomscale_top;
  159.     }
  160.     else if (now <= focus->time3)   // zoom in at pos1
  161.     {
  162.         zc.offset_uq = xy_to_xyq(focus->pos1);
  163.         t = (now - focus->time2) / (focus->time3 - focus->time2);
  164.         //t = floor(t * 2.) / 2.;
  165.         zc.zoomscale = exp(mix(log(focus->zoomscale_top), log(focus->zoomscale_base), t));
  166.     }
  167.     else                // end the transition
  168.     {
  169.         zc.offset_uq = xy_to_xyq(focus->pos1);
  170.         zc.zoomscale = focus->zoomscale_base;
  171.         focus->zoom_transition_on = 0;
  172.     }
  173.  
  174.     calc_screen_limits(&zc);
  175. }
  176.  
  177. void knob_print_addr_hex(char *str, knob_t *knob_data, double value)
  178. {
  179.     sprintf(str, "0x%zx", (size_t)nearbyint(value));
  180. }
  181.  
  182. double knob_parse_addr_hex(const char *str, knob_t *knob_data)
  183. {
  184.     int64_t vi = 0;
  185.  
  186.     sscanf(str, "%" SCNi64, &vi);
  187.  
  188.     return (double)vi;
  189. }
  190.  
  191. void cita_vis_options_window(int *memory_update, int *update_cont, xy_t *visual_item_rect, int *knob_ret, char **filter_string, filter_focus_t *focus, double *image_stride_v, double *image_offset_v)
  192. {
  193.     // GUI layout
  194.     static gui_layout_t layout={0};
  195.     const char *layout_src[] = {
  196.         "elem 0", "type none", "label Options", "pos    0   0", "dim    3   12;1;6", "off   0   1", "",
  197.         "elem 20", "type knob", "label A square is", "knob 0.015625 64 8192 log %.2g", "knob_unit kB", "link_pos_id 60.cb", "pos    -0;1    -0;3", "dim 1", "off    1", "",
  198.         "elem 21", "type knob", "label Image stride", "knob 1 256 16384 logoff %.0f", "knob_arg 40", "knob_unit pixels", "link_pos_id 20", "pos 0;2 0", "dim    1", "off    0   1", "",
  199.         "elem 22", "type knob", "label Pixel offset", "knob 0 0 80 linear %.0f", "link_pos_id 21.rb", "pos  0   -0;1;6", "dim   0;8", "off  1", "",
  200.         "elem 30", "type textedit", "link_pos_id 70.cb", "pos   0   -0;6;6", "dim   2   0;7", "off  0;6 1", "",
  201.         "elem 31", "type label", "label Filter:", "link_pos_id 30.lt", "pos 0;1 0;0;6", "dim    1;10    0;4", "off  0", "",
  202.         "elem 40", "type button", "label \342\207\246", "link_pos_id 30.lb", "pos   0   -0;2", "dim 0;7", "off  0   1", "",
  203.         "elem 41", "type button", "label Go", "link_pos_id 40.r_", "pos 0;1;6   0", "dim    0;7", "off  0   1", "",
  204.         "elem 42", "type button", "label \342\207\250", "link_pos_id 41.r_", "pos   0;1;6   0", "dim    0;7", "off  0   1", "",
  205.         "elem 45", "type knob", "label Result #", "knob 0 0 667 linear %.0f", "link_pos_id 41.cb", "pos 0   -0;1;6", "dim   1;2;6", "off    0;6 1", "",
  206.         "elem 46", "type label", "link_pos_id 45.cb", "pos  0   -0;2;6", "dim   2   0;4;6", "off    0;6 1", "",
  207.         "elem 50", "type button", "label Update", "pos  0;6 -1", "dim   2   0;9", "off  0   1", "",
  208.         "elem 51", "type checkbox", "label Update continuously", "link_pos_id 50.cb", "pos  0   -0;2", "dim 2   0;6", "off  0;6 1", "",
  209.         "elem 60", "type selmenu", "link_pos_id 51.cb", "pos    0   -0;6;6", "dim   2   0;6", "off  0;6 1", "",
  210.         "elem 61", "type label", "label Visualisation mode", "link_pos_id 60.lt", "pos  0;1 0;0;6", "dim    1;10    0;3", "off  0", "",
  211.         "elem 70", "type knob", "label View address", "knob 0 0 4.29497e+09 logoff", "knob_arg 1e+06", "link_pos_id 60.cb", "pos    0   -2", "dim   2", "off    0;6 1", "",
  212.         "elem 80", "type checkbox", "label Vertical layout", "link_pos_id 46.cb", "pos  0   -0;2;6", "dim   2   0;4", "off  0;6 1", "",
  213.     };
  214.  
  215.     gui_layout_init_pos_scale(&layout, XY0, 1., XY0, 0);
  216.     make_gui_layout(&layout, layout_src, sizeof(layout_src)/sizeof(char *), "CIT Alloc visualiser options");
  217.  
  218.     // GUI window
  219.     static flwindow_t window={0};
  220.     flwindow_init_defaults(&window);
  221.     flwindow_init_pinned(&window);
  222.     window.bg_opacity = 0.94;
  223.     window.shadow_strength = 0.5*window.bg_opacity;
  224.     draw_dialog_window_fromlayout(&window, cur_wind_on, &cur_parent_area, &layout, 0);
  225.  
  226.     // GUI controls
  227.     *memory_update = ctrl_button_fromlayout(&layout, 50);
  228.     ctrl_checkbox_fromlayout(update_cont, &layout, 51);
  229.    
  230.  
  231.     // Address knob
  232.     double addr_offset = 0.;
  233.     if (mts)
  234.         addr_offset = mts[mts_index].addr;
  235.  
  236.     static double addr_v=NAN;
  237.     static int addr_ret = 0;
  238.     xy_t new_pos0 = XYNAN;
  239.     static xy_t new_pos1 = {NAN, NAN};
  240.     knob_t *knob_data = get_knob_data_fromlayout(&layout, 70);
  241.     knob_data->display_print_func = knob_print_addr_hex;
  242.     knob_data->editor_print_func = knob_print_addr_hex;
  243.     knob_data->parse_func = knob_parse_addr_hex;
  244.     knob_data->max = 65536.*65536.-1.;
  245.     if (knob_data->knob_state.down == 0 && knob_data->edit_open == 0 && addr_ret == 0)
  246.     {
  247.         if (pixel_address != (size_t) -1)
  248.         {
  249.             addr_v = pixel_address;
  250.             pixel_address = (size_t) -1;
  251.         }
  252.         else
  253.             addr_v = flip_xy(zc.offset_u).x * (vert?-1.:1.) * BYTES_PER_UNIT + addr_offset;
  254.     }
  255.     if (addr_ret == 1)
  256.         if (vert)
  257.             new_pos0 = xy(zc.offset_u.x, -(addr_v-addr_offset)/BYTES_PER_UNIT);
  258.         else
  259.             new_pos0 = xy((addr_v-addr_offset)/BYTES_PER_UNIT, zc.offset_u.y);
  260.     addr_ret = ctrl_knob_fromlayout(&addr_v, &layout, 70);
  261.  
  262.     // Visualisation knobs
  263.     visual_item_rect->x = 1.;
  264.     *knob_ret |= ctrl_knob_fromlayout(&visual_item_rect->y, &layout, 20);   // range box thickness
  265.     ctrl_knob_fromlayout(image_stride_v, &layout, 21);          // image stride in pixels
  266.     set_knob_circularity_fromlayout(1, &layout, 22);
  267.     get_knob_data_fromlayout(&layout, 22)->max = nearbyint(*image_stride_v);
  268.     ctrl_knob_fromlayout(image_offset_v, &layout, 22);          // image pixel offset
  269.  
  270.     // Filter field
  271.     draw_label_fromlayout(&layout, 31, ALIG_LEFT | MONODIGITS);
  272.     ctrl_textedit_fromlayout(&layout, 30);
  273.     *filter_string = get_textedit_string_fromlayout(&layout, 30);
  274.  
  275.     // Message focus controls
  276.     if (ctrl_button_fromlayout(&layout, 40))
  277.         prepare_focus_transition(focus, -1);
  278.     if (ctrl_button_fromlayout(&layout, 41))
  279.         prepare_focus_transition(focus, 0);
  280.     if (ctrl_button_fromlayout(&layout, 42))
  281.         prepare_focus_transition(focus, 1);
  282.  
  283.     get_knob_data_fromlayout(&layout, 45)->max = MAXN(1., focus->filter_count-1);
  284.     ctrl_knob_fromlayout(&focus->result_id_v, &layout, 45);
  285.  
  286.     // Vertical layout
  287.     if (ctrl_checkbox_fromlayout(&vert, &layout, 80))
  288.     {
  289.         new_pos1 = neg_xy(zc.offset_u);
  290.         swap_double(&new_pos1.x, &new_pos1.y);
  291.         img_update = 1;
  292.     }
  293.  
  294.     // Update offset menu index
  295.     if (mts && mts_index != get_selmenu_selid_fromlayout(&layout, 60))
  296.         gui_layout_selmenu_set_entry_id(mts_index, &layout, 60);
  297.  
  298.     // Offset menu
  299.     int menu_count = sizeof(vis_mode_name)/sizeof(char*);
  300.  
  301.     gui_layout_selmenu_set_count(menu_count, &layout, 60);
  302.     gui_layout_selmenu_set_entry_id(vis_mode, &layout, 60);
  303.     if (ctrl_selmenu_fromlayout(&layout, 60))
  304.     {
  305.         vis_mode = get_selmenu_selid_fromlayout(&layout, 60);
  306.         img_update = 1;
  307.     }
  308.  
  309.     for (int i=0; i < menu_count; i++)
  310.         draw_selmenu_entry_fromlayout(i, vis_mode_name[i], &layout, 60);
  311.  
  312.     draw_label_fromlayout(&layout, 61, ALIG_LEFT | MONODIGITS);
  313.  
  314.     // Combined size of highlighted ranges
  315.     if (filtered_size < 5000)
  316.         gui_printf_to_label(&layout, 46, 0, "%d B", filtered_size);
  317.     else if (filtered_size < 90 << 10)
  318.         gui_printf_to_label(&layout, 46, 0, "%.2f kB", filtered_size/1024.);
  319.     else if (filtered_size < 900 << 10)
  320.         gui_printf_to_label(&layout, 46, 0, "%.1f kB", filtered_size/1024.);
  321.     else
  322.         gui_printf_to_label(&layout, 46, 0, "%.2f MB", filtered_size/1048576.);
  323.     draw_label_fromlayout(&layout, 46, ALIG_CENTRE | MONODIGITS);
  324.  
  325.     change_zoom(new_pos1, NAN);
  326.     new_pos1 = new_pos0;
  327. }
  328.  
  329. int mem_range_add(int64_t addr, int64_t size, const char *info, int info_size)
  330. {
  331.     mem_range_t range = {0};
  332.  
  333.     if (size <= 0)
  334.         return -1;
  335.  
  336.     range.addr = addr;
  337.     range.size = size;
  338.     memcpy(range.info, info, info_size);
  339.     range.info[info_size] = '\0';
  340.  
  341.     buffer_t buf = {0};
  342.     bufprintf(&buf, "%s\n", range.info);
  343.     if (range.size > 90 << 20)
  344.         bufprintf(&buf, "%.0f MB, ", range.size/1048576.);
  345.     else if (range.size > 9 << 20)
  346.         bufprintf(&buf, "%.1f MB, ", range.size/1048576.);
  347.     else if (range.size > 1000 << 10)
  348.         bufprintf(&buf, "%.2f MB, ", range.size/1048576.);
  349.     else if (range.size > 9000)
  350.         bufprintf(&buf, "%.0f kB, ", range.size/1024.);
  351.     bufprintf(&buf, "%zd / %#zx B at %#zx", range.size, range.size, range.addr);
  352.     range.label = buf.buf;
  353.  
  354.     // Add range to table
  355.     if (mem_range_count == 0 || (range.addr != mem_range[mem_range_count - 1].addr || range.size != mem_range[mem_range_count - 1].size))
  356.         alloc_enough(&mem_range, mem_range_count += 1, &mem_range_as, sizeof(mem_range_t), 1.2);
  357.     // Replace the previous range if they have the same range
  358.     else
  359.         free_null(&mem_range[mem_range_count - 1].label);
  360.  
  361.     mem_range[mem_range_count - 1] = range;
  362.  
  363.     // Calculate obj file colour
  364.     mem_range[mem_range_count - 1].colour = add_col(make_grey(0.2), get_colour_seq((double) get_string_hash(range.info)*0.007+1.5, xyz(0.36, 0.187, 0.13), set_xyz(0.2)));
  365.  
  366.     // Calculate the row to avoid overlapping with other ranges
  367.     mem_range[mem_range_count - 1].row = starting_row;
  368.     for (int ir = first_range_in_current_file; ir < mem_range_count-1; ir++)
  369.         //if (mem_range[ir].addr <= range.addr+range.size-1 && mem_range[ir].addr+mem_range[ir].size-1 >= range.addr)
  370.         if (MAXN(mem_range[ir].addr, range.addr) < MINN(mem_range[ir].addr+mem_range[ir].size, range.addr+range.size))
  371.             mem_range[mem_range_count - 1].row = MAXN(mem_range[mem_range_count - 1].row, mem_range[ir].row + 1.);
  372.     max_row = MAXN(max_row, mem_range[mem_range_count - 1].row);
  373.  
  374.     return mem_range_count - 1;
  375. }
  376.  
  377. size_t get_module_stack_pointer()
  378. {
  379.     size_t ptr=0;
  380.     char cmd[300];
  381.     sprintf(cmd, "From module ID %s\nGet stack pointer of module ID %s", module_id, watch_module_id);
  382.     char *response = wahe_run_command(cmd);
  383.     if (response)
  384.         sscanf(response, "%" SCNi64, &ptr);
  385.     free(response);
  386.     return ptr;
  387. }
  388.  
  389. typedef struct
  390. {
  391.     int index, addr, time, link, info;
  392. } cita_layout_t;
  393.  
  394. int64_t get_int_at_addr(uint8_t *addr, int size_of_int, int int_signed)
  395. {
  396.     switch (size_of_int)
  397.     {
  398.         case 1: if (int_signed) return (int64_t) *(int8_t  *) addr; else return (int64_t) *(uint8_t  *) addr;
  399.         case 2: if (int_signed) return (int64_t) *(int16_t *) addr; else return (int64_t) *(uint16_t *) addr;
  400.         case 4: if (int_signed) return (int64_t) *(int32_t *) addr; else return (int64_t) *(uint32_t *) addr;
  401.         case 8: return *(int64_t *) addr;
  402.  
  403.         case 3:
  404.             int32_t low = (int32_t) *(uint16_t *) addr;
  405.             int32_t v = addr[2];
  406.             v = (v << 16) | low;
  407.             if (int_signed && v >> 23)
  408.                 v |= 0xFF000000;
  409.             return v;
  410.     }
  411.  
  412.     return 0;
  413. }
  414.  
  415. void cita_visualiser()
  416. {
  417.     int i;
  418.     static int init=1, options_detach=0;
  419.     static xy_t visual_item_rect = {NAN, NAN};
  420.     static double box_aspect_ratio_v = NAN, image_stride_v = NAN, image_offset_v = NAN;
  421.     static int visual_item_length_ret = 0, os_openfile_diag = 0, memory_update = 1, update_cont = 1, full_memory = 1;
  422.     static char *filter_string = NULL, *filter_string_prev;
  423.     static buffer_t table0={0}, table1={0}, memory={0};
  424.     static size_t heap_base=0, memory_size=0;
  425.     int refilter = 0;
  426.     static sqrgb_t *palette;
  427.     static raster_t data_image={0};
  428.     int cita_elem_size=0;
  429.     cita_layout_t cita_size={0}, cita_pos={0};
  430.  
  431.     static int refresh_data_layout = 0;
  432.     static filter_focus_t focus = {0};
  433.  
  434.     // Getting a file path from the command line
  435.     if (init)
  436.     {
  437.         focus.filter_count = -1;
  438.         focus.focus_index = -1;
  439.         filter_string_prev = make_string_copy("");
  440.  
  441.         palette = make_byte_palette();
  442.         data_image.table_index = -1;
  443.  
  444.         init = 0;
  445.     }
  446.  
  447.     // Check what might trigger updating
  448.     if (update_cont)
  449.         memory_update = 1;
  450.     if (isfinite(image_stride_v) && image_stride_v > 0. && image_stride != (int) nearbyint(image_stride_v))
  451.     {
  452.         image_stride = (int) nearbyint(image_stride_v);
  453.         img_update = 1;
  454.     }
  455.     if (isfinite(image_offset_v) && image_offset != (int) nearbyint(image_offset_v))
  456.     {
  457.         image_offset = (int) nearbyint(image_offset_v);
  458.         img_update = 1;
  459.     }
  460.  
  461.     // Refresh heap copy
  462.     if (watch_module_id && (memory_update || img_update))
  463.     {
  464.         char *response, cmd[200];
  465.  
  466.         if (memory_update)
  467.         {
  468.             heap_base = 0;
  469.             memory_size = 0;
  470.  
  471.             // Get heap base
  472.             sprintf(cmd, "From module ID %s\nGet heap base of module ID %s", module_id, watch_module_id);
  473.             response = wahe_run_command(cmd);
  474.             if (response)
  475.                 sscanf(response, "%" SCNi64, &heap_base);
  476.             free(response);
  477.  
  478.             // Get memory size
  479.             sprintf(cmd, "From module ID %s\nGet memory size of module ID %s", module_id, watch_module_id);
  480.             response = wahe_run_command(cmd);
  481.             if (response)
  482.                 sscanf(response, "%" SCNi64, &memory_size);
  483.             free(response);
  484.  
  485.             if (heap_base == 0 || memory_size == 0)
  486.                 goto watch_end;
  487.         }
  488.  
  489.         // Copy full memory
  490.         if (full_memory)
  491.         {
  492.             if (memory_update)
  493.             {
  494.                 memory.len = memory_size;
  495.                 buf_alloc_enough(&memory, memory_size);
  496.                 sprintf(cmd, "From module ID %s\nCopy %" PRIu64 " bytes at %" PRIu64 " (module %s) to %" PRIu64 " (module %s)", module_id, memory.len, (size_t)0, watch_module_id, (size_t) memory.buf, module_id);
  497.                 free(wahe_run_command(cmd));
  498.             }
  499.  
  500.             // Rasterise data
  501.             const int h = image_stride ? image_stride : 64;
  502.             if (vis_mode == no_img)
  503.                 free_raster(&data_image);
  504.             if (vis_mode == pal8)
  505.             {
  506.                 data_image.dim = flip_xyi(xyi((memory_size+h-1)/h, h));
  507.                 alloc_enough(&data_image.sq, mul_x_by_y_xyi(data_image.dim), &data_image.as, sizeof(sqrgb_t), 1.2);
  508.                 memset(data_image.sq, 0, mul_x_by_y_xyi(data_image.dim)*sizeof(sqrgb_t));
  509.                 for (int i=0; i < memory_size; i++)
  510.                 {
  511.                     int io = i + image_offset;
  512.                     if (io < mul_x_by_y_xyi(data_image.dim))
  513.                         if (vert)
  514.                             data_image.sq[io/h*data_image.dim.x + io%h] = palette[memory.buf[i]];
  515.                         else
  516.                             data_image.sq[io%h*data_image.dim.x + io/h] = palette[memory.buf[i]];
  517.                 }
  518.             }
  519.             if (vis_mode == bw_bit)
  520.             {
  521.                 data_image.dim = flip_xyi(xyi((memory_size*8+h-1)/h, h));
  522.                 alloc_enough(&data_image.sq, mul_x_by_y_xyi(data_image.dim), &data_image.as, sizeof(sqrgb_t), 1.2);
  523.                 memset(data_image.sq, 0, mul_x_by_y_xyi(data_image.dim)*sizeof(sqrgb_t));
  524.                 for (int i=0; i < memory_size*8; i++)
  525.                 {
  526.                     int io = i + image_offset;
  527.                     if (io < mul_x_by_y_xyi(data_image.dim))
  528.                     {
  529.                         int ic = get_bit(memory.buf[i>>3], i&7) * 0x81 | (rand_xsm32(i) & 3);
  530.                         if (vert)
  531.                             data_image.sq[io/h*data_image.dim.x + io%h] = palette[ic];
  532.                         else
  533.                             data_image.sq[io%h*data_image.dim.x + io/h] = palette[ic];
  534.                     }
  535.                 }
  536.             }
  537.             if (vis_mode == rgbx8)
  538.             {
  539.                 data_image.dim = flip_xyi(xyi((memory_size/4+h-1)/h, h));
  540.                 alloc_enough(&data_image.sq, mul_x_by_y_xyi(data_image.dim), &data_image.as, sizeof(sqrgb_t), 1.2);
  541.                 memset(data_image.sq, 0, mul_x_by_y_xyi(data_image.dim)*sizeof(sqrgb_t));
  542.                 lut_t ssqrgb_l = get_lut_ssqrgb();
  543.                 for (int i=0; i < memory_size/4; i++)
  544.                 {
  545.                     int io = i + image_offset;
  546.                     if (io < mul_x_by_y_xyi(data_image.dim))
  547.                     {
  548.                         sqrgb_t col;
  549.                         col.r = ssqrgb_l.lutint[memory.buf[i*4+0]] >> 2;
  550.                         col.g = ssqrgb_l.lutint[memory.buf[i*4+1]];
  551.                         col.b = ssqrgb_l.lutint[memory.buf[i*4+2]] >> 2;
  552.                         if (vert)
  553.                             data_image.sq[io/h*data_image.dim.x + io%h] = col;
  554.                         else
  555.                             data_image.sq[io%h*data_image.dim.x + io/h] = col;
  556.                     }
  557.                 }
  558.             }
  559.             cl_unref_raster(&data_image);
  560.         }
  561.  
  562.         // Copy table0
  563.         table0.len = MINN(memory_size - heap_base, 48);
  564.         if (full_memory)
  565.             table0.buf = &memory.buf[heap_base];
  566.         else if (memory_update)
  567.         {
  568.             buf_alloc_enough(&table0, table0.len);
  569.             sprintf(cmd, "From module ID %s\nCopy %" PRIu64 " bytes at %" PRIu64 " (module %s) to %" PRIu64 " (module %s)", module_id, table0.len, heap_base, watch_module_id, (size_t) table0.buf, module_id);
  570.             free(wahe_run_command(cmd));
  571.         }
  572.  
  573.         // Parse table0
  574.         if (memcmp(&table0.buf[0], "CITA", 4))
  575.         {
  576.             fprintf_rl(stderr, "No CIT Alloc detected at heap base %#zx in module %s (ID %s)\n", heap_base, watch_wahe_name, watch_module_id);
  577.             goto watch_end;
  578.         }
  579.  
  580.         // Check CITA version and load parameters
  581.         int version_pos = *(int32_t *)&table0.buf[4];
  582.         char *version = &table0.buf[version_pos];
  583.         const char *p = version;
  584.  
  585.         while (p[0])
  586.         {
  587.             if (strncmp("CITA", p, 4) == 0)
  588.                 if (strncmp(version, "CITA 1.0", 8))
  589.                 {
  590.                     fprintf_rl(stderr, "Module %s (ID %s) has an unknown CIT Alloc version: \"%s\"\n", watch_wahe_name, watch_module_id, version);
  591.                     goto watch_end;
  592.                 }
  593.             sscanf(p, "Address %d", &cita_size.addr);
  594.             sscanf(p, "Index %d", &cita_size.index);
  595.             sscanf(p, "Time %d", &cita_size.time);
  596.             sscanf(p, "Link %d", &cita_size.link);
  597.             sscanf(p, "Info %d", &cita_size.info);
  598.  
  599.             p = skip_line(p);
  600.         }
  601.  
  602.         cita_pos.index = 0;
  603.         cita_pos.addr  = cita_pos.index + 2 * cita_size.index;
  604.         cita_pos.time  = cita_pos.addr  + 3 * cita_size.addr;
  605.         cita_pos.link  = cita_pos.time  + 2 * cita_size.time;
  606.         cita_pos.info  = cita_pos.link  + 1 * cita_size.link;
  607.         cita_elem_size = cita_pos.info  + 1 * cita_size.info;
  608.        
  609.         if (isnan(image_stride_v))
  610.             image_stride_v = cita_elem_size;
  611.  
  612.         size_t elem_addr = *(int32_t *)&table0.buf[16];
  613.         size_t elem_count = *(int32_t *)&table0.buf[20];
  614.  
  615.         // Copy table1
  616.         table1.len = elem_count * cita_elem_size;
  617.         if (full_memory)
  618.             table1.buf = &memory.buf[elem_addr];
  619.         else if (memory_update)
  620.         {
  621.             buf_alloc_enough(&table1, table1.len);
  622.             sprintf(cmd, "From module ID %s\nCopy %" PRIu64 " bytes at %" PRIu64 " (module %s) to %" PRIu64 " (module %s)", module_id, table1.len, elem_addr, watch_module_id, (size_t) table1.buf, module_id);
  623.             free(wahe_run_command(cmd));
  624.         }
  625.  
  626.         // Set MTS
  627.         alloc_enough(&mts, mts_count = 1, &mts_as, sizeof(mem_type_start_t), 1.);
  628.         mts[0].name = sprintf_alloc("Module %s (ID %s)", watch_wahe_name, watch_module_id);
  629.         mts[0].addr = heap_base;
  630.  
  631.         // Free previous structure
  632.         for (int ir = 0; ir < mem_range_count; ir++)
  633.             free_null(&mem_range[ir].label);
  634.         free_null(&mem_range);
  635.         mem_range_as = mem_range_count = 0;
  636.  
  637.         // Add top range
  638.         mem_range_add(0, memory_size, "RAM", 3);
  639.  
  640.         // Add range
  641.         int32_t next_index;
  642.         size_t ir = 0, count = 0;
  643.         do
  644.         {
  645.             if ((ir+1)*cita_elem_size <= table1.len && ir >= 0)
  646.             {
  647.                 // Read the next element's index
  648.                 next_index = get_int_at_addr(&table1.buf[ir*cita_elem_size + cita_pos.index + cita_size.index], cita_size.index, 1);
  649.                 if (next_index > elem_count || next_index < 0)
  650.                 {
  651.                     next_index = 0;
  652.  
  653.                     // Find the next index by going through the table
  654.                     for (int32_t i=0; i < elem_count; i++)
  655.                         if (get_int_at_addr(&table1.buf[i*cita_elem_size + cita_pos.index], cita_size.index, 1) == ir)  // if that element points back to this element
  656.                         {
  657.                             next_index = i;
  658.                             break;
  659.                         }
  660.                 }
  661.  
  662.                 size_t range_addr = get_int_at_addr(&table1.buf[ir*cita_elem_size + cita_pos.addr], cita_size.addr, 0);
  663.                 size_t range_end = get_int_at_addr(&table1.buf[ir*cita_elem_size + cita_pos.addr + cita_size.addr], cita_size.addr, 0);
  664.                 char *info = &table1.buf[ir*cita_elem_size + cita_pos.info];
  665.                 mem_range_add(range_addr, range_end-range_addr, info, cita_size.info);
  666.                 ir = next_index;
  667.             }
  668.             else
  669.             {
  670.                 char cmd[200];
  671.                 sprintf(cmd, "From module ID %s\nPrint ir out of range: %zd, elem_count = %zd\n", module_id, ir, elem_count);
  672.                 next_index = 0;
  673.             }
  674.             count++;
  675.         }
  676.         while (next_index && count < elem_count);
  677.  
  678.         refresh_data_layout = 1;
  679.         refilter = 1;
  680.  
  681.         // Update flags
  682.         memory_update = 0;
  683.         img_update = 0;
  684.     }
  685. watch_end:
  686.  
  687.     if (visual_item_length_ret)
  688.     {
  689.         visual_item_length_ret = 0;
  690.         refresh_data_layout = 1;
  691.     }
  692.  
  693.     // Apply filter
  694.     if (filter_string && (strcmp(filter_string, filter_string_prev) || refilter))
  695.     {
  696.         refilter = 0;
  697.         free(filter_string_prev);
  698.         filter_string_prev = make_string_copy(filter_string);
  699.  
  700.         focus.filter_count = 0;
  701.         filtered_size = 0;
  702.  
  703.         for (int ir = 0; ir < mem_range_count; ir++)
  704.             if (strstr_i(mem_range[ir].label, filter_string))
  705.             {
  706.                 mem_range[ir].filtered = 0;
  707.                 mem_range[ir].filter_pos = focus.filter_count;
  708.                 focus.filter_count++;
  709.                 if (mem_range[ir].row > 0)
  710.                     filtered_size += mem_range[ir].size;
  711.             }
  712.             else
  713.             {
  714.                 mem_range[ir].filtered = 1;
  715.                 mem_range[ir].filter_pos = -1;
  716.             }
  717.     }
  718.  
  719.     // Calculate visual layout of messages
  720.     xy_t byte_scale = xy(visual_item_rect.x / BYTES_PER_UNIT, (visual_item_rect.y*1024.) / BYTES_PER_UNIT);
  721.     if (refresh_data_layout && isfinite_xy(visual_item_rect))
  722.     {
  723.         refresh_data_layout = 0;
  724.  
  725.         for (int ir=0; ir < mem_range_count; ir++)
  726.         {
  727.             // Set position
  728.             mem_range[ir].pos = flip_xy(xy(byte_scale.x * (double) (mem_range[ir].addr + (ir ? image_offset : 0) - mts[mts_index].addr), -byte_scale.y * (1.06 * (mem_range[ir].row-1) - 1.)));
  729.             if (vert)
  730.             {
  731.                 mem_range[ir].pos.y = -mem_range[ir].pos.y;
  732.                 mem_range[ir].pos.x = -mem_range[ir].pos.x;
  733.             }
  734.  
  735.             mem_range[ir].area = make_rect_off(mem_range[ir].pos, flip_xy(xy((double) mem_range[ir].size * byte_scale.x, byte_scale.y)), xy(0., 1.));
  736.         }
  737.     }
  738.  
  739.     // Focus transition
  740.     perform_focus_transition(&focus);
  741.  
  742.     // Draw range data
  743.     col_t filtered_colour = make_colour(0.3, 0.015, 0., 1.);
  744.     for (int ir = 0; ir < mem_range_count; ir++)
  745.     {
  746.         if (check_box_on_screen(mem_range[ir].area))
  747.         {
  748.             col_t colour = mem_range[ir].colour;
  749.             if (mem_range[ir].filtered)
  750.                 colour = filtered_colour;
  751.  
  752.             // Draw box and label
  753.             draw_rangebox_fade_to_solid(mem_range[ir].area, "", colour);
  754.             if (rect_min_side(sc_rect(mem_range[ir].area)) > 4.)
  755.                 draw_string_bestfit_asis(font, mem_range[ir].label, sc_rect(mem_range[ir].area), 1./12., 1e30, colour, 1., drawing_thickness, vert ? ALIG_LEFT : ALIG_LEFT | MONODIGITS, NULL);
  756.  
  757.         }
  758.     }
  759.  
  760.     // Draw data pixels
  761.     if (data_image.sq && mem_range)
  762.     {
  763.         rect_t area = make_rect_off(add_xy(mem_range[0].pos, flip_xy(xy(0., -byte_scale.y*2.06 * (vert?-1:1.)))), flip_xy(xy((double) mem_range[0].size * byte_scale.x, byte_scale.y*1e6)), xy(0., 1.));
  764.         area = fit_rect_in_area(xyi_to_xy(data_image.dim), area, flip_xy(xy(0.5, vert?0.:1.)));
  765.  
  766.         xy_t r_scale, r_offset, r_scale_inv, r_offset_inv;
  767.         rect_range_and_dim_to_scale_offset(area, data_image.dim, &r_scale, &r_offset, 0);
  768.         rect_range_and_dim_to_scale_offset_inv(area, data_image.dim, &r_scale_inv, &r_offset_inv, 0);
  769.  
  770.         // Calculate hovered pixel address
  771.         ctrl_button_state_t butt_state={0};
  772.         ctrl_button_invis(area, &butt_state);
  773.         if (butt_state.over)
  774.         {
  775.             xyi_t pix_pos = xy_to_xyi(nearbyint_xy(mad_xy(mouse.u, r_scale_inv, r_offset_inv)));
  776.             pixel_address = pix_to_addr(pix_pos, data_image.dim);
  777.         }
  778.  
  779.         // Draw data image
  780.         blit_in_rect(&data_image, sc_rect(area), 1, AA_NEAREST_INTERP);
  781.  
  782.         // Get module's current stack pointer
  783.         size_t stack_ptr = get_module_stack_pointer();
  784.  
  785.         // Draw data labels
  786.         col_t label_col_pos = make_colour(0.5, 0.5, 0.5, 1.);
  787.         col_t label_col_neg = make_colour(-0.5, -0.5, -0.5, 1.);
  788.         col_t stack_top_col = make_colour(0.1, 0.1, 0.4, 1.);
  789.         if (zc.zoomscale * r_scale.x > 3./12.)
  790.         {
  791.             xyi_t ip, label_range = xyi(74., 38.);
  792.             xyi_t pix_pos = xy_to_xyi(nearbyint_xy(mad_xy(zc.offset_u, r_scale_inv, r_offset_inv)));
  793.             for (ip.y = MAXN(0, pix_pos.y-label_range.y); ip.y < MINN(data_image.dim.y, pix_pos.y+label_range.y); ip.y++)
  794.                 for (ip.x = MAXN(0, pix_pos.x-label_range.x); ip.x < MINN(data_image.dim.x, pix_pos.x+label_range.x); ip.x++)
  795.                 {
  796.                     size_t addr = pix_to_addr(ip, data_image.dim);
  797.  
  798.                     if (vis_mode == pal8 && addr < memory_size)
  799.                     {
  800.                         // Pixel area
  801.                         uint8_t byte = memory.buf[addr];
  802.                         if (byte)
  803.                         {
  804.                             // Print label
  805.                             double scale = isprint(byte) ? 11./12. : 8./12.;
  806.                             char label[32];
  807.                             if (isprint(byte))
  808.                                 sprintf(label, "%c", byte);
  809.                             else
  810.                                 sprintf(label, "%d %#02x", byte, byte);
  811.  
  812.                             // Draw label
  813.                             xy_t pos = mad_xy(xyi_to_xy(ip), r_scale, r_offset);
  814.                             rect_t area = make_rect_centred(pos, set_xy(r_scale.x * scale));
  815.                             draw_label(label, area, byte < 235 ? label_col_pos : label_col_neg, ALIG_CENTRE | MONODIGITS);
  816.                         }
  817.  
  818.                         // Draw stack pointer hint
  819.                         if (addr < stack_ptr)
  820.                         {
  821.                             xy_t pos = mad_xy(xyi_to_xy(ip), r_scale, r_offset);
  822.                             rect_t area = make_rect_centred(pos, set_xy(r_scale.x));
  823.                             draw_rect_full(sc_rect(area), drawing_thickness, stack_top_col, blend_add, 1.);
  824.                         }
  825.                     }
  826.                 }
  827.         }
  828.     }
  829.  
  830.     // GUI window
  831.     window_register(1, cita_vis_options_window, NULL, make_rect_off(xy(-zc.limit_u.x, zc.limit_u.y), xy(6., 12.), xy(0., 1.)), &options_detach, 8, &memory_update, &update_cont, &visual_item_rect, &visual_item_length_ret, &filter_string, &focus, &image_stride_v, &image_offset_v);
  832. }
  833.  
  834. int main_loop(void *data)
  835. {
  836.     sdl_main_param_t param={0};
  837.     param.window_name = "CIT Alloc Visualiser";
  838.     param.func = cita_visualiser;
  839.     param.use_drawq = 1;
  840.     param.maximise_window = 1;
  841.     param.gui_toolbar = 1;
  842.     param.show_cursor = 1;
  843.     param.exit_flag = &exit_flag;
  844.     rl_sdl_standard_main_loop(param);
  845.     return 0;
  846. }
  847.  
  848. static rl_thread_t thread_handle=NULL;
  849.  
  850. EXPORT("module_message_input")
  851. char *module_message_input(char *message)
  852. {
  853.     static char *ret_msg = NULL;
  854.     int n;
  855.  
  856.     if (message == NULL)
  857.         return NULL;
  858.  
  859.     free(ret_msg);
  860.     ret_msg = NULL;
  861.  
  862.     // Parse each line
  863.     for (const char *line = message; line; line = find_next_line(line))
  864.     {
  865.         // Receive module index
  866.         if (sscanf(line, "Module ID %60s", module_id) == 1)
  867.             // Create thread
  868.             rl_thread_create(&thread_handle, main_loop, NULL);
  869.  
  870.         // Receive wahe_run_command() pointer
  871.         #ifndef __wasm__
  872.         sscanf(line, "wahe_run_command() = %zx", (size_t *) &wahe_run_command);
  873.         #endif
  874.  
  875.         // Init
  876.         n = 0;
  877.         sscanf(line, "Init%n", &n);
  878.         if (n)
  879.         {}
  880.  
  881.         // Deinit
  882.         n = 0;
  883.         sscanf(line, "Deinit%n", &n);
  884.         if (n)
  885.         {
  886.             exit_flag = 1;
  887.             rl_thread_join_and_null(&thread_handle);
  888.         }
  889.  
  890.         // Documentation
  891.         n = 0;
  892.         sscanf(line, "Documentation%n", &n);
  893.         if (n)
  894.         {
  895.             return  "module_message_input() takes:\n\n"
  896.                 "   Watch module <WAHE instance name>\n"
  897.                 "       Example: Watch module Time_mod\n\n"
  898.                 ;
  899.         }
  900.  
  901.         // Watch module, this tells us the WAHE setup name of the instance whose CIT Alloc heap to watch
  902.         if (sscanf(line, "Watch module %50s", watch_wahe_name) == 1)
  903.         {
  904.             char cmd[68];
  905.             sprintf(cmd, "Get ID of module %s", watch_wahe_name);
  906.             free(watch_module_id);
  907.             watch_module_id = wahe_run_command(cmd);
  908.         }
  909.     }
  910.  
  911.     return NULL;
  912. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement