Browse Source

various improvements in GUI, mainly on fx-9860G

* True convention for F-keys:
  -> Corner = change tab
  -> Round (button) = perform action
  -> White = other display changes with no consequence

* mem: Move quickly with Shift
* mem: Jump to destination with F1
* gint/cpumem: More interesting values
* abuse mini font, scrollbars instead of triangles, quick moves
* fix a fair amoutn of warnings
dev
Lephenixnoir 2 months ago
parent
commit
02571b8957
Signed by: Lephenixnoir GPG Key ID: 1BBA026E13FC0495
31 changed files with 448 additions and 235 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +9
    -0
      assets-fx/fonts/fxconv-metadata.txt
  3. BIN
      assets-fx/fonts/mini.png
  4. BIN
      assets-fx/img/opt_dump.png
  5. BIN
      assets-fx/img/opt_gint_bopti.png
  6. BIN
      assets-fx/img/opt_gint_gray.png
  7. BIN
      assets-fx/img/opt_gint_ram.png
  8. BIN
      assets-fx/img/opt_gint_rtc.png
  9. BIN
      assets-fx/img/opt_gint_spuram.png
  10. BIN
      assets-fx/img/opt_gint_timer_callbacks.png
  11. BIN
      assets-fx/img/opt_gint_timers.png
  12. BIN
      assets-fx/img/opt_gint_tlb.png
  13. BIN
      assets-fx/img/opt_main.png
  14. BIN
      assets-fx/img/opt_mem.png
  15. BIN
      assets-fx/img/opt_switch.png
  16. BIN
      assets-fx/img/tlb_cells.png
  17. +5
    -4
      include/gintctl/menu.h
  18. +15
    -3
      include/gintctl/util.h
  19. +0
    -1
      src/gint/bopti.c
  20. +86
    -48
      src/gint/cpumem.c
  21. +30
    -19
      src/gint/ram.c
  22. +10
    -7
      src/gint/spuram.c
  23. +6
    -12
      src/gint/switch.c
  24. +9
    -5
      src/gint/timer.c
  25. +87
    -92
      src/gint/tlb.c
  26. +5
    -2
      src/gintctl.c
  27. +1
    -0
      src/libs/openlibm.c
  28. +29
    -20
      src/libs/printf.c
  29. +116
    -18
      src/mem/mem.c
  30. +16
    -4
      src/menu.c
  31. +23
    -0
      src/util.c

+ 1
- 0
CMakeLists.txt View File

@ -49,6 +49,7 @@ set(SOURCES
)
set(ASSETS_fx
assets-fx/fonts/hexa.png
assets-fx/fonts/mini.png
assets-fx/fonts/uf5x7
assets-fx/img/bopti_1col.png
assets-fx/img/bopti_2col.png


+ 9
- 0
assets-fx/fonts/fxconv-metadata.txt View File

@ -5,6 +5,15 @@ hexa.png:
grid.size: 3x5
grid.padding: 1
mini.png:
type: font
name: font_mini
charset: ascii
proportional: true
height: 5
grid.size: 5x6
grid.padding: 1
uf5x7:
type: font
name: font_uf5x7


BIN
assets-fx/fonts/mini.png View File

Before After
Width: 112  |  Height: 64  |  Size: 16 KiB

BIN
assets-fx/img/opt_dump.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.5 KiB Width: 128  |  Height: 8  |  Size: 2.5 KiB

BIN
assets-fx/img/opt_gint_bopti.png View File

Before After
Width: 128  |  Height: 35  |  Size: 4.9 KiB Width: 128  |  Height: 35  |  Size: 4.9 KiB

BIN
assets-fx/img/opt_gint_gray.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.5 KiB Width: 128  |  Height: 8  |  Size: 2.7 KiB

BIN
assets-fx/img/opt_gint_ram.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.3 KiB Width: 128  |  Height: 8  |  Size: 2.4 KiB

BIN
assets-fx/img/opt_gint_rtc.png View File

Before After
Width: 128  |  Height: 62  |  Size: 13 KiB Width: 128  |  Height: 62  |  Size: 13 KiB

BIN
assets-fx/img/opt_gint_spuram.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.1 KiB Width: 128  |  Height: 8  |  Size: 2.2 KiB

BIN
assets-fx/img/opt_gint_timer_callbacks.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.2 KiB Width: 128  |  Height: 8  |  Size: 2.2 KiB

BIN
assets-fx/img/opt_gint_timers.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.5 KiB Width: 128  |  Height: 8  |  Size: 2.6 KiB

BIN
assets-fx/img/opt_gint_tlb.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.9 KiB Width: 128  |  Height: 8  |  Size: 3.0 KiB

BIN
assets-fx/img/opt_main.png View File

Before After
Width: 128  |  Height: 8  |  Size: 3.4 KiB Width: 128  |  Height: 8  |  Size: 3.4 KiB

BIN
assets-fx/img/opt_mem.png View File

Before After
Width: 128  |  Height: 17  |  Size: 3.8 KiB Width: 128  |  Height: 17  |  Size: 3.8 KiB

BIN
assets-fx/img/opt_switch.png View File

Before After
Width: 128  |  Height: 8  |  Size: 2.6 KiB Width: 128  |  Height: 8  |  Size: 2.2 KiB

BIN
assets-fx/img/tlb_cells.png View File

Before After
Width: 35  |  Height: 5  |  Size: 3.4 KiB Width: 41  |  Height: 6  |  Size: 3.4 KiB

+ 5
- 4
include/gintctl/menu.h View File

@ -44,10 +44,11 @@ struct menu {
void menu_init(struct menu *menu, int top, int bottom);
/* menu_move(): Move the cursor in a menu
@menu Initialized list menu
@key Either KEY_UP, indicating up, or KEY_DOWN indicating down
@wrap Allow wrap-around */
void menu_move(struct menu *menu, int key, int wrap);
@menu Initialized list menu
@key Either KEY_UP, indicating up, or KEY_DOWN indicating down
@quick Whether to quick-move to start or end
@wrap Allow wrap-around */
void menu_move(struct menu *menu, int key, int quick, int wrap);
/* menu_show(): Render a list menu */
void menu_show(struct menu const *menu);


+ 15
- 3
include/gintctl/util.h View File

@ -50,11 +50,23 @@ int row_x(int x);
int row_y(int y);
//---
// General (x,y) printing
// General rendering
//---
/* print(): Formatted printing shorthand */
void print(int x, int y, char const *format, ...);
/* scrollbar_px(): Pixel-based scrollbar
@view_top First pixel covered by scrollbar area
@view_bottom Pixel below last pixel covered by scrollbar area
@range_min Minimum value in the virtual range we're scrolling through
@range_max Maximum value in the virtual range
@range_pos Position within the virtual range
@range_view How much of the range is visible on-screen */
void scrollbar_px(int view_top, int view_bottom, int range_min, int range_max,
int range_pos, int range_view);
#define print_prefix(x, y, prefix, fmt, ...) { \
dtext_opt(x-_(3,5), y, C_BLACK,C_NONE,DTEXT_RIGHT,DTEXT_TOP, prefix); \
dprint(x+_(3,5), y, C_BLACK, fmt __VA_OPT__(,) __VA_ARGS__); \
}
//---
// F-key rendering


+ 0
- 1
src/gint/bopti.c View File

@ -9,7 +9,6 @@
/* gintctl_gint_bopti(): Test image rendering */
void gintctl_gint_bopti(void)
{
extern bopti_image_t img_swift;
extern bopti_image_t img_swords;
extern bopti_image_t img_potion_17x22, img_potion_18x22;
extern bopti_image_t img_applejack_31x27, img_applejack_36x25;


+ 86
- 48
src/gint/cpumem.c View File

@ -2,18 +2,23 @@
#include <gint/keyboard.h>
#include <gint/display.h>
#include <gint/mmu.h>
#include <gint/std/stdio.h>
#include <gintctl/gint.h>
#include <gintctl/util.h>
#define put(...) row_print(++(*row), 1, __VA_ARGS__)
/* TODO: Include <gint/cpu.h> */
extern uint32_t cpu_getVBR(void);
/* Some symbols from the linker script */
extern uint32_t
brom, srom, /* Limits of ROM mappings */
sdata, rdata, /* User's data section */
sbss, rbss; /* User's BSS section */
#ifdef FX9860G
extern uint32_t sgmapped; /* Permanently mapped functions */
#endif
#define load_barrier(x) { \
if(!((x) & HW_LOADED)) { \
put(" (not loaded)"); \
return; \
} \
}
/* MPU type and processor version */
void show_mpucpu(void)
@ -35,8 +40,8 @@ void show_mpucpu(void)
};
char const *calc_names[] = {
"Unknown",
"SH3 fx-9860G*",
"SH4 fx-9860G*",
"fx-9860G-like",
"fx-9860G-like",
"Graph 35+E II",
"Prizm fx-CG 20",
"fx-CG 50/Graph 90+E",
@ -46,69 +51,101 @@ void show_mpucpu(void)
int mpu = gint[HWMPU];
int calc = gint[HWCALC];
char const *str_calc = _("Model", "Calculator model");
if(calc < 0 || calc > 6)
row_print(1, 1, "%s: <CALCID %d>", str_calc, calc);
else
row_print(1, 1, "%s: %s", str_calc, calc_names[calc]);
/* Generate a default calc name if invalid values are found */
char calc_default[16];
sprintf(calc_default, "<CALCID %d>", calc);
char const *str_calc = calc_default;
if(calc >= 0 && calc < 7) str_calc = calc_names[calc];
if(mpu < 0 || mpu > 4)
row_print(_(2,3), 1, "MPU: <MPUID %d>", mpu);
else
row_print(_(2,3), 1, "MPU: %s", mpu_names[mpu]);
/* Generate a default MPU name if invalid values are found */
char mpu_default[16];
sprintf(mpu_default, "<MPUID %d>", mpu);
char const *str_mpu = mpu_default;
if(mpu >= 0 && mpu < 5) str_mpu = mpu_names[mpu];
volatile uint32_t *CPUOPM = (void *)0xff2f0000;
uint32_t SR;
__asm__("stc sr, %0" : "=r"(SR));
uint32_t SR, r15;
__asm__("stc sr, %0" : "=r"(SR));
__asm__("mov r15, %0" : "=r"(r15));
#ifdef FX9860G
if(isSH3())
{
row_print(4, 1, " SR %08x", SR);
return;
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
dprint(1, 10, C_BLACK, "Model: %s", str_calc);
dprint(1, 16, C_BLACK, "MPU: %s", str_mpu);
print_prefix(29, 24, "SR", "%08X", SR);
dline(29, 24, 29, 46, C_BLACK);
if(isSH3()) {
print_prefix(29, 30, "PVR", "");
print_prefix(29, 36, "PRR", "");
print_prefix(29, 42, "CPUOPM", "");
}
else {
print_prefix(29, 30, "PVR", "%08X", gint[HWCPUVR]);
print_prefix(29, 36, "PRR", "%08X", gint[HWCPUPR]);
print_prefix(29, 42, "CPUOPM", "%08X", *CPUOPM);
}
row_print(4, 1, " SR %08x", SR);
row_print(5, 1, " PVR %08x", gint[HWCPUVR]);
row_print(6, 1, " PRR %08x", gint[HWCPUPR]);
row_print(7, 1, " CPUOPM %08x", *CPUOPM);
print_prefix(85, 24, "VBR", "%08X", cpu_getVBR());
print_prefix(85, 30, "R15", "%08X", r15);
dline(85, 24, 85, 34, C_BLACK);
dfont(old_font);
#endif
#ifdef FXCG50
row_print(1, 1, "Calculator model: %s", str_calc);
row_print(3, 1, "MPU: %s", str_mpu);
row_print(4, 1, " Status Register: %08x", SR);
row_print(5, 1, " Processor Version Register: %08x", gint[HWCPUVR]);
row_print(6, 1, " Product Register: %08x", gint[HWCPUPR]);
row_print(7, 1, " CPU Operation Mode: %08x", *CPUOPM);
row_print(8, 1, " Current VBR: %08x", cpu_getVBR());
row_print(9, 1, " Current stack pointer: %08x", r15);
#endif
}
/* Memory */
static void show_memory(void)
{
uint32_t base_rom = 0x80000000;
uint32_t base_ram = 0x88000000;
uint32_t base_uram = (uint32_t)mmu_uram();
int rom = gint[HWROM];
int ram = gint[HWRAM];
int uram = mmu_uram_size();
#ifdef FX9860G
row_title("Basic memory layout");
row_print(3, 2, "%08x %4dk ROM", base_rom, rom >> 10);
row_print(4, 2, "%08x %4dk RAM", base_ram, ram >> 10);
row_print(5, 2, "%08x %4dk URAM", base_uram, uram >> 10);
row_print(6, 2, "Mapped %4dk", gint[HWURAM] >> 10);
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
print_prefix(28, 10, "brom", "%08X", &brom);
print_prefix(28, 16, "rdata", "%08X", &rdata);
print_prefix(28, 22, "rbss", "%08X", &rbss);
print_prefix(28, 28, "rreloc", "%08X", mmu_uram());
print_prefix(98, 10, "srom", "%06d", &srom);
print_prefix(98, 16, "sdata", "%06d", &sdata);
print_prefix(98, 22, "sbss", "%06d", &sbss);
print_prefix(98, 28, "sreloc", "%06d", &sgmapped);
dprint(1, 38, C_BLACK, "ROM: %dk, RAM: %dk",
gint[HWROM] >> 10, gint[HWRAM] >> 10);
dprint(1, 45, C_BLACK, "User RAM: %08X (%dk, P0 %dk)",
mmu_uram(), mmu_uram_size() >> 10, gint[HWURAM] >> 10);
dfont(old_font);
#endif
#ifdef FXCG50
uint32_t base_ram = 0x88000000;
if(gint[HWCALC] == HWCALC_FXCG50) base_ram = 0x8c000000;
row_print(1, 1, "ROM: %dM", rom >> 20);
row_print(2, 2, "%08X ... %08X", 0x80000000, 0x80000000+rom-1);
row_print(3, 1, "RAM: %dM", ram >> 20);
row_print(4, 2, "%08X ... %08X", base_ram, base_ram+ram-1);
row_print(5, 1, "Userspace RAM: %dk blocked", uram >> 10);
row_print(6, 2, "%08X ... %08X", base_uram, base_uram+uram-1);
row_print(7, 1, "Total mapped RAM: %dk", gint[HWURAM] >> 10);
row_print(1, 1, "RAM: %dM, RAM: %dM (starts at %08X)",
gint[HWROM] >> 20, gint[HWRAM] >> 20, base_ram);
row_print(2, 1, "Userspace RAM: %08X (%dk continuous block)",
mmu_uram(), mmu_uram_size() >> 10);
row_print(3, 1, "Total RAM mapped in P0: %dk",
gint[HWURAM] >> 10);
print_prefix(80, row_y(5), "brom", "%08X", &brom);
print_prefix(80, row_y(6), "rdata", "%08X", &rdata);
print_prefix(80, row_y(7), "rbss", "%08X", &rbss);
print_prefix(240, row_y(5), "srom", "%06d", &srom);
print_prefix(240, row_y(6), "sdata", "%06d", &sdata);
print_prefix(240, row_y(7), "sbss", "%06d", &sbss);
#endif
}
@ -164,6 +201,7 @@ void gintctl_gint_cpumem(void)
if(tab == 1) show_memory();
#ifdef FX9860G
row_title("CPU and memory");
extern bopti_image_t img_opt_gint_cpumem;
dimage(0, 56, &img_opt_gint_cpumem);
#endif


+ 30
- 19
src/gint/ram.c View File

@ -127,31 +127,31 @@ static void show_region(int row, struct region *r)
/* Out-of-bounds rows */
if(row < 1 || row > 9 || (row == 1 && r)) return;
extern font_t font_hexa;
font_t const *old_font = dfont(&font_hexa);
int y = (row - 1) * 6;
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
int y = (row - 1) * 6 + 2 * (row > 1);
if(!r)
{
dprint( 1, y, C_BLACK, "Area");
dprint(24, y, C_BLACK, "Address");
dprint(60, y, C_BLACK, "Size");
dprint(80, y, C_BLACK, "Reason");
dprint(26, y, C_BLACK, "Address");
dprint(62, y, C_BLACK, "Size");
dprint(82, y, C_BLACK, "At end");
dfont(old_font);
return;
}
char const *reasons[] = { "", "Read-only", "Loops", "" };
char const *reasons[] = { "Not tested", "Read-only", "Loops", "" };
dprint( 1, y, C_BLACK, "%s", r->name);
dprint(24, y, C_BLACK, "%08X", r->mem);
dprint(26, y, C_BLACK, "%08X", r->mem);
if(r->reason != 0)
{
dprint(60, y, C_BLACK, "%dk", r->size >> 10);
dprint(80, y, C_BLACK, "%s", reasons[r->reason]);
}
dprint(62, y, C_BLACK, "%dk", r->size >> 10);
else
dprint(62, y, C_BLACK, "-");
dprint(82, y, C_BLACK, "%s", reasons[r->reason]);
dfont(old_font);
}
#endif
@ -172,7 +172,7 @@ static void show_region(int y, struct region *r)
row_print(y, 9, "Address");
row_print(y, 18, "AS");
row_print(y, 22, "Size");
row_print(y, 35, "Reason");
row_print(y, 35, "At end");
return;
}
@ -207,6 +207,7 @@ void gintctl_gint_ram(void)
/* List scroll no fx-9860G */
GUNUSED int scroll = spu_zero();
key_event_t ev;
int key = 0;
while(key != KEY_EXIT)
{
@ -214,13 +215,13 @@ void gintctl_gint_ram(void)
#ifdef FX9860G
show_region(1, NULL);
dhline(6, C_BLACK);
for(int i = 0; i < region_count; i++)
{
show_region(i+2-scroll, &r[i]);
}
if(scroll > 0) triangle_up(7);
if(scroll < region_count - 8) triangle_down(49);
scrollbar_px(/* view */ 8, 54, /* range */ 0, region_count,
/* visible */ scroll, 8);
extern bopti_image_t img_opt_gint_ram;
dimage(0, 56, &img_opt_gint_ram);
@ -242,7 +243,8 @@ void gintctl_gint_ram(void)
dupdate();
key = getkey().key;
ev = getkey();
key = ev.key;
if(key == KEY_F1)
{
explore_region(&r[0]);
@ -271,8 +273,17 @@ void gintctl_gint_ram(void)
}
#ifdef FX9860G
if(key == KEY_UP && scroll > 0) scroll--;
if(key == KEY_DOWN && scroll < region_count - 8) scroll++;
int scroll_max = region_count - 8;
if(key == KEY_UP)
{
if(ev.shift || keydown(KEY_SHIFT)) scroll=0;
else if(scroll > 0) scroll--;
}
if(key == KEY_DOWN)
{
if(ev.shift || keydown(KEY_SHIFT)) scroll=scroll_max;
else if(scroll < scroll_max) scroll++;
}
#endif
}
}

+ 10
- 7
src/gint/spuram.c View File

@ -41,7 +41,7 @@ static void restore(volatile uint32_t *area, uint32_t *save, int pages)
}
#ifdef FX9860G
static void render_header(int y, int bank_count)
static void render_header(int y, GUNUSED int bank_count)
{
y = 9 + 6*y;
dtext( 1, 9, C_BLACK, "Area");
@ -166,6 +166,8 @@ void gintctl_gint_spuram(void)
int cur_bank = 0;
int cur_page = 0;
int switch_key = _(KEY_F6, KEY_F1);
#ifdef FX9860G
int tab = 0;
#endif
@ -178,7 +180,7 @@ void gintctl_gint_spuram(void)
row_title("SPU memory banking");
extern font_t font_hexa;
font_t *old_font = dfont(&font_hexa);
font_t const *old_font = dfont(&font_hexa);
if(tab == 0)
{
@ -204,7 +206,8 @@ void gintctl_gint_spuram(void)
dfont(old_font);
extern bopti_image_t img_opt_gint_spuram;
dimage(0, 56, &img_opt_gint_spuram);
dsubimage(0, 56, &img_opt_gint_spuram, 0, 0,
(tab == 1 ? 128 : 107), 8, DIMAGE_NONE);
#endif
#ifdef FXCG50
@ -244,20 +247,20 @@ void gintctl_gint_spuram(void)
if(key == KEY_DOWN && cur_bank == 0)
cur_bank++;
if(key == KEY_F1 && cur_bank == 0 && _(tab == 1, 1))
if(key == switch_key && cur_bank == 0 && _(tab == 1, 1))
{
SPU.PBANKC0 ^= (1 << cur_page);
SPU.PBANKC1 ^= (1 << cur_page);
}
if(key == KEY_F1 && cur_bank == 1 && _(tab == 1, 1))
if(key == switch_key && cur_bank == 1 && _(tab == 1, 1))
{
SPU.XBANKC0 ^= (1 << cur_page);
SPU.XBANKC1 ^= (1 << cur_page);
}
#ifdef FX9860G
if(key == KEY_F2) tab = 0;
if(key == KEY_F3) tab = 1;
if(key == KEY_F1) tab = 0;
if(key == KEY_F2) tab = 1;
#endif
}


+ 6
- 12
src/gint/switch.c View File

@ -12,7 +12,6 @@
#include <gintctl/util.h>
static int switches = 0;
static int fast = 0;
static int menus = 0;
static void switch_function(void)
@ -230,8 +229,7 @@ void render(void)
extern bopti_image_t img_opt_switch;
row_print(1, 1, "Switch to OS");
row_print(3, 1, "Switches done: %d", switches);
row_print(4, 1, "Fast done: %d", fast);
row_print(5, 1, "Menus done: %d", menus);
row_print(4, 1, "Menus done: %d", menus);
dimage(0, 56, &img_opt_switch);
#endif
@ -239,11 +237,9 @@ void render(void)
#ifdef FXCG50
row_title("Hot switching between gint and OS");
row_print(2, 1, "Switches done: %d", switches);
row_print(3, 1, "Fast done: %d", fast);
row_print(4, 1, "Menus done: %d", menus);
row_print(3, 1, "Menus done: %d", menus);
fkey_button(1, "SWITCH");
fkey_button(2, "FAST");
fkey_button(3, "MENU");
fkey_button(2, "MENU");
fkey_action(6, "SYSTEM");
#endif
}
@ -260,10 +256,8 @@ void gintctl_gint_switch(void)
key = getkey().key;
if(key == KEY_F1) gint_switch(switch_function);
/* TODO: Fast gint switch in gintctl */
if(key == KEY_F2) {}
/* Wait for F3 to be released before calling next getkey() */
if(key == KEY_F3)
/* Wait for F2 to be released before calling next getkey() */
if(key == KEY_F2)
{
/* Render next frame in advance. When we return from
the main menu, our VRAM will be displayed but
@ -275,7 +269,7 @@ void gintctl_gint_switch(void)
dupdate();
gint_osmenu();
while(keydown(KEY_F3)) waitevent(NULL);
while(keydown(KEY_F2)) waitevent(NULL);
}
if(key == KEY_F6) system_contexts();
}


+ 9
- 5
src/gint/timer.c View File

@ -98,7 +98,6 @@ void gintctl_gint_timer(void)
program to ~90 FPS.) */
int key=0, tid=0;
GUNUSED int timeout=1;
volatile int flag = 0;
#ifdef FX9860G
int tab = 1;
@ -116,8 +115,11 @@ void gintctl_gint_timer(void)
extern bopti_image_t img_opt_gint_timers;
dimage(0, 56, &img_opt_gint_timers);
if(tid < 3) dprint(23, 56, C_BLACK, "TMU%d", tid);
else dprint(23, 56, C_BLACK, "ETMU%d", tid-3);
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
if(tid < 3) dprint(24, 57, C_BLACK, "\x01 TMU%d \x02", tid);
else dprint(24, 57, C_BLACK, "\x01 ETMU%d \x02", tid-3);
dfont(old_font);
#endif
#ifdef FXCG50
@ -155,7 +157,9 @@ void gintctl_gint_timer(void)
if(key == KEY_F6) tab = 3;
#endif
if(key == KEY_UP) tid = (tid+timer_count()-1) % timer_count();
if(key == KEY_DOWN) tid = (tid + 1) % timer_count();
if(key == KEY_LEFT)
tid = (tid + timer_count() - 1) % timer_count();
if(key == KEY_RIGHT)
tid = (tid + 1) % timer_count();
}
}

+ 87
- 92
src/gint/tlb.c View File

@ -37,8 +37,8 @@ static void draw_rom_cell(int x, int y, int status)
#ifdef FX9860G
#define PAGE_COUNT 0x80
#define SQUARE_WIDTH 4
#define SQUARE_HEIGHT 4
#define SQUARE_WIDTH 5
#define SQUARE_HEIGHT 5
#define LINE_SIZE 16
#define TLB_VIEW 8
@ -61,44 +61,6 @@ static int rom_cell_y(int page_number)
return (page_number / LINE_SIZE) * SQUARE_HEIGHT;
}
#ifdef FX9860G
void triangle_up(int y)
{
int x=118;
dpixel(x+2, y, C_BLACK);
dline(x+1, y+1, x+3, y+1, C_BLACK);
dline(x, y+2, x+4, y+2, C_BLACK);
}
void triangle_down(int y)
{
int x=118;
dline(x, y, x+4, y, C_BLACK);
dline(x+1, y+1, x+3, y+1, C_BLACK);
dpixel(x+2, y+2, C_BLACK);
}
#endif
#ifdef FXCG50
void triangle_up(int y)
{
int x=370;
dpixel(x+3, y, C_BLACK);
dline(x+2, y+1, x+4, y+1, C_BLACK);
dline(x+1, y+2, x+5, y+2, C_BLACK);
dline(x, y+3, x+6, y+3, C_BLACK);
dline(x, y+4, x+6, y+4, C_BLACK);
}
void triangle_down(int y)
{
int x=370;
dline(x, y, x+6, y, C_BLACK);
dline(x, y+1, x+6, y+1, C_BLACK);
dline(x+1, y+2, x+5, y+2, C_BLACK);
dline(x+2, y+3, x+4, y+3, C_BLACK);
dpixel(x+3, y+4, C_BLACK);
}
#endif
static void explore_pages(uint8_t *pages, uint32_t *next_miss)
{
extern uint32_t srom;
@ -177,44 +139,48 @@ void show_utlb(int row, int E)
char const *access_str[] = { "K:r", "K:rw", "U:r", "U:rw" };
uint16_t fg = valid ? C_BLACK : C_RGB(24,24,24);
#define fg_ fg, C_NONE
row_print_color(row, 2, fg_, "%d", E);
row_print_color(row, 5, fg_, "%08X", src);
row_print_color(row, 14, fg_, "%08X", dst);
row_print_color(row, 23, fg_, "%s", size_str[size]);
row_print_color(row, 28, fg_, "%s", access_str[data.PR]);
row_print_color(row, 34, fg_, "%s", (data.SH ? "SH" : "-"));
row_print_color(row, 37, fg_, "%s", (data.WT ? "WT" : "CB"));
row_print_color(row, 40, fg_, "%s", (data.C ? "C" : "-"));
row_print_color(row, 42, fg_, "%s", (addr.D || data.D ? "D" : "-"));
row_print_color(row, 44, fg_, "%s", (addr.V && data.V ? "V" : "-"));
#define fg_ fg, C_NONE, DTEXT_LEFT, DTEXT_TOP
int y = row_y(row) + 2 * (row > 1);
dprint_opt( 14, y, fg_, "%d", E);
dprint_opt( 38, y, fg_, "%08X", src);
dprint_opt(110, y, fg_, "%08X", dst);
dprint_opt(182, y, fg_, "%s", size_str[size]);
dprint_opt(222, y, fg_, "%s", access_str[data.PR]);
dprint_opt(270, y, fg_, "%s", (data.SH ? "SH" : "-"));
dprint_opt(294, y, fg_, "%s", (data.WT ? "WT" : "CB"));
dprint_opt(318, y, fg_, "%s", (data.C ? "C" : "-"));
dprint_opt(334, y, fg_, "%s", (addr.D || data.D ? "D" : "-"));
dprint_opt(350, y, fg_, "%s", (addr.V && data.V ? "V" : "-"));
}
#endif
#ifdef FX9860G
void show_utlb(int row, int E)
{
extern font_t font_hexa;
font_t const *old_font = dfont(&font_hexa);
int y = (row - 1) * 6;
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
int y = (row - 1) * 6 + 2 * (row > 1);
if(E == -1)
{
dprint( 1, y, C_BLACK, "ID");
dprint(12, y, C_BLACK, "Virtual");
dprint(47, y, C_BLACK, "Physical");
dprint(82, y, C_BLACK, "Len");
dprint(98, y, C_BLACK, "Mode");
dprint( 1, y, C_BLACK, "ID");
dprint( 12, y, C_BLACK, "Virtual");
dprint( 47, y, C_BLACK, "Physical");
dprint( 82, y, C_BLACK, "Len");
dprint( 97, y, C_BLACK, "Pr");
dprint(115, y, C_BLACK, "CD");
dfont(old_font);
return;
}
char const *size_str[] = { "1k", "4k", "64k", "1M" };
char const *access_str[] = { "K:r", "K:rw", "U:r", "U:rw" };
char const *access_str[] = { "Kr", "Krw", "Ur", "Urw" };
char const *cd_str[] = { "--", "-D", "C-", "CD" };
uint32_t src, dst;
int valid, size, pr;
int valid, size, pr, cd;
if(isSH3())
{
@ -232,6 +198,7 @@ void show_utlb(int row, int E)
dst = data.PPN << 10;
pr = data.PR;
cd = (data.C << 1) | data.D;
}
else
{
@ -244,16 +211,18 @@ void show_utlb(int row, int E)
valid = (addr.V != 0) && (data.V != 0);
size = (data.SZ1 << 1) | data.SZ2;
pr = data.PR;
cd = (data.C << 1) | data.D;
}
dprint( 1, y, C_BLACK, "%d", E);
if(valid)
{
dprint(12, y, C_BLACK, "%08X", src);
dprint(47, y, C_BLACK, "%08X", dst);
dprint(82, y, C_BLACK, "%s", size_str[size]);
dprint(98, y, C_BLACK, "%s", access_str[pr]);
dprint( 12, y, C_BLACK, "%08X", src);
dprint( 47, y, C_BLACK, "%08X", dst);
dprint( 82, y, C_BLACK, "%s", size_str[size]);
dprint( 97, y, C_BLACK, "%s", access_str[pr]);
dprint(115, y, C_BLACK, "%s", cd_str[cd]);
}
dfont(old_font);
@ -271,23 +240,29 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
#endif
row_title(_("TLB management", "TLB miss handler and TLB management"));
#ifdef FX9860G
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
#endif
if(tab == 0)
{
row_print(_(2,1), 1, _("srom=%x (%d pages)",
"Size of ROM sections: %08X (%d pages of 4k)"),
#ifdef FXCG50
row_print(1, 1, "Size of ROM sections: %08X (%d pages of 4k)",
rom_size, rom_pages);
#endif
for(uint p=0, y=_(19,36); p < PAGE_COUNT; p += 2*LINE_SIZE)
for(uint p=0, y=_(12,36); p < PAGE_COUNT; p += 2*LINE_SIZE)
{
dprint(_(4,18), y, C_BLACK, _("%06x","%08X"),
dprint(_(5,18), y, C_BLACK, "%08X",
0x00300000 + (p << 12));
y += 2*SQUARE_HEIGHT;
}
for(uint p = 0; p < PAGE_COUNT; p++)
{
draw_rom_cell(_(44,88) + rom_cell_x(p),
_(20,36) + rom_cell_y(p), pages[p]);
draw_rom_cell(_(39,88) + rom_cell_x(p),
_(11,36) + rom_cell_y(p), pages[p]);
}
#ifdef FXCG50
@ -308,18 +283,18 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
else if(tab == 1)
{
row_print(_(2,1), 1, "Legend:");
draw_rom_cell(_(8,18), _(17,36), 0);
draw_rom_cell(_(64,200), _(17,36), 1);
draw_rom_cell(_(8,18), _(25,50), 2);
draw_rom_cell(_(64,200), _(25,50), 3);
draw_rom_cell(_(8,18), _(15,36), 0);
draw_rom_cell(_(64,200), _(15,36), 1);
draw_rom_cell(_(8,18), _(22,50), 2);
draw_rom_cell(_(64,200), _(22,50), 3);
dprint(_(16,30), _(16,36), C_BLACK,
dprint(_(16,30), _(15,36), C_BLACK,
_("Unused", "Unused in add-in"));
dprint(_(72,212), _(16,36), C_BLACK,
dprint(_(72,212), _(15,36), C_BLACK,
_("Unmapped", "Currently unmapped"));
dprint(_(16,30), _(24,50), C_BLACK,
dprint(_(16,30), _(22,50), C_BLACK,
_("Data", "Data still mapped"));
dprint(_(72,212), _(24,50), C_BLACK,
dprint(_(72,212), _(22,50), C_BLACK,
_("Mapped", "Currently mapped"));
#ifdef FXCG50
@ -327,7 +302,7 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
dprint(30, 64, C_BLACK, "Next page to load");
row_print(6, 1,
"The MISS key will load an unmapped page to TLB by");
"The LOAD key will load an unmapped page to TLB by");
row_print(7, 1,
"performing a TLB miss, which calls %%003 on fx9860g");
row_print(8, 1,
@ -341,12 +316,16 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
#endif
#ifdef FX9860G
dprint(1, 30, C_BLACK, "Size of ROM text: %X (%d pages)",
rom_size, rom_pages);
if(next_miss != 0xffffffff)
row_print(5, 1, "Next load: %x", next_miss);
dprint(1, 36, C_BLACK, "Next load: %08x", next_miss);
else
row_print(5, 1, "No page left to load!");
row_print(6, 1, "MISS: TLB miss");
row_print(7, 1, "TIMER: From timer");
dprint(1, 36, C_BLACK, "No page left to load!");
dprint(1, 43, C_BLACK, "F5: Load a page by TLB miss");
dprint(1, 49, C_BLACK, "F6: Do it from a timer callback");
#endif
}
@ -356,11 +335,23 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
for(int i = 0; i < TLB_VIEW; i++)
show_utlb(i+2, tlb_scroll+i);
if(tlb_scroll > 0) triangle_up(_(7,38));
if(tlb_scroll < TLB_VIEW_MAX) triangle_down(_(49,192));
#ifdef FX9860G
dhline(6, C_BLACK);
#endif
#ifdef FXCG50
dline(12, 34, 363, 34, C_BLACK);
#endif
scrollbar_px(
/* view */ _(8,37), _(54,201),
/* range */ 0, TLB_VIEW_MAX + TLB_VIEW,
/* visible */ tlb_scroll, TLB_VIEW);
}
#ifdef FX9860G
dfont(old_font);
extern bopti_image_t img_opt_gint_tlb;
dimage(0, 56, &img_opt_gint_tlb);
#endif
@ -369,7 +360,7 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll)
fkey_menu(1, "ROM");
fkey_menu(2, "INFO");
fkey_menu(3, "TLB");
fkey_action(5, "MISS");
fkey_action(5, "LOAD");
fkey_action(6, "TIMER");
#endif
}
@ -408,13 +399,17 @@ void gintctl_gint_tlb(void)
if(tab == 2 && key == KEY_UP)
{
if(ev.shift) tlb_scroll = 0;
else if(tlb_scroll > 0) tlb_scroll--;
if(ev.shift || keydown(KEY_SHIFT))
tlb_scroll = 0;
else if(tlb_scroll > 0)
tlb_scroll--;
}
if(tab == 2 && key == KEY_DOWN)
{
if(ev.shift) tlb_scroll = TLB_VIEW_MAX;
else if (tlb_scroll < TLB_VIEW_MAX) tlb_scroll++;
if(ev.shift || keydown(KEY_SHIFT))
tlb_scroll = TLB_VIEW_MAX;
else if (tlb_scroll < TLB_VIEW_MAX)
tlb_scroll++;
}
if(key == KEY_F5 && next_miss != 0xffffffff)


+ 5
- 2
src/gintctl.c View File

@ -170,6 +170,7 @@ int main(GUNUSED int isappli, GUNUSED int optnum)
dfont(&font_uf5x7);
#endif
key_event_t ev;
int key = 0;
struct menu *menu = NULL;
@ -177,7 +178,9 @@ int main(GUNUSED int isappli, GUNUSED int optnum)
{
draw(menu);
dupdate();
key = getkey().key;
ev = getkey();
key = ev.key;
if(key == KEY_F1)
menu = NULL;
@ -195,7 +198,7 @@ int main(GUNUSED int isappli, GUNUSED int optnum)
if(!menu) continue;
if(key == KEY_UP || key == KEY_DOWN)
menu_move(menu, key, 0);
menu_move(menu, key, ev.shift || keydown(KEY_SHIFT),0);
if(key == KEY_EXE)
menu_exec(menu);
}


+ 1
- 0
src/libs/openlibm.c View File

@ -3,6 +3,7 @@
#include <gintctl/libs.h>
#include <gintctl/plot.h>
#include <gintctl/util.h>
#define __BSD_VISIBLE 1
#include <openlibm/openlibm.h>


+ 29
- 20
src/libs/printf.c View File

@ -12,7 +12,7 @@
#define NAN __builtin_nan("")
#define INFINITY __builtin_inf()
#define SCROLL_HEIGHT _(8,12)
#define SCROLL_HEIGHT _(9,12)
struct printf_test {
char const *format;
@ -198,27 +198,26 @@ static void draw(struct printf_test const *tests, char answers[][16],
dclear(C_WHITE);
#ifdef FX9860G
extern font_t font_hexa;
font_t const *old_font = dfont(&font_hexa);
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
dprint( 1, 0, C_BLACK, "ID");
dprint(13, 0, C_BLACK, "Format");
dprint(43, 0, C_BLACK, "Output");
dprint(91, 0, C_BLACK, "Valid");
dprint(99, 0, C_BLACK, "%d/%d", total_passed, total);
dhline(6, C_BLACK);
for(int i = 0; i < SCROLL_HEIGHT; i++)
{
struct printf_test const *t = &tests[offset+i];
int y = (i+1) * 6;
int y = (i+1) * 6 + 2;
dprint( 1, y, C_BLACK, "%d", offset+i+1);
dprint(13, y, C_BLACK, "%s", t->format);
dprint(43, y, C_BLACK, "%s", answers[offset+i][0]
? answers[offset+i] : "<empty>");
dprint(91, y, C_BLACK, "%s", passed[offset+i]?"Ok":"Err");
dprint(99, y, C_BLACK, "%s", passed[offset+i]?"Ok":"Err");
}
dfont(old_font);
row_print(8, 1, "Passed %d of %d.", total_passed, total);
#endif
#ifdef FXCG50
@ -228,25 +227,28 @@ static void draw(struct printf_test const *tests, char answers[][16],
row_print(1, 5, "Format");
row_print(1, 13, "Argument");
row_print(1, 29, "Answer");
dline(12, 34, 355, 34, C_BLACK);
for(int i = 0; i < SCROLL_HEIGHT; i++)
{
struct printf_test const *t = &tests[offset+i];
row_print(i+2, 2, "%d", offset+i+1);
row_print(i+2, 5, "%s", t->format);
row_print(i+2, 13, "%s", t->argument_as_string);
int y = row_y(i+2) + 2;
dprint( 14, y, C_BLACK, "%d", offset+i+1);
dprint( 38, y, C_BLACK, "%s", t->format);
dprint(102, y, C_BLACK, "%s", t->argument_as_string);
int fg = passed[offset+i] ? C_RGB(0,31,0) : C_RGB(31,0,0);
row_print_color(i+2, 29, fg, C_NONE, "%s", answers[offset+i][0]
? answers[offset+i] : "<empty>");
dprint_opt(230, y, fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, "%s",
answers[offset+i][0] ? answers[offset+i] : "<empty>");
}
row_print(14, 1, "Passed: %d/%d", total_passed, total);
#endif
if(offset > 0) triangle_up(_(7,38));
if(offset < total - SCROLL_HEIGHT) triangle_down(_(49,192));
scrollbar_px(
/* view */ _(8,37), _(60,201),
/* range */ 0, total,
/* visible */ offset, SCROLL_HEIGHT);
dupdate();
}
@ -267,9 +269,16 @@ void gintctl_libs_printf(void)
draw(tests, answers, passed, offset);
key = (ev = getkey()).key;
if(key == KEY_UP && offset > 0) offset--;
if(key == KEY_UP && ev.shift) offset = 0;
if(key == KEY_DOWN && offset < total - SCROLL_HEIGHT) offset++;
if(key == KEY_DOWN && ev.shift) offset = total - SCROLL_HEIGHT;
int scroll_max = total - SCROLL_HEIGHT;
if(key == KEY_UP)
{
if(ev.shift || keydown(KEY_SHIFT)) offset = 0;
else if(offset > 0) offset--;
}
if(key == KEY_DOWN)
{
if(ev.shift || keydown(KEY_SHIFT)) offset = scroll_max;
else if(offset < scroll_max) offset++;
}
}
}

+ 116
- 18
src/mem/mem.c View File

@ -53,7 +53,7 @@ int line(uint8_t *mem, char *header, char *bytes, char *ascii, int n)
/* Read single bytes when possible, but longwords when in SPU memory */
for(int k = 0; k < n; k++)
{
uint32_t addr = mem;
uint32_t addr = (uint32_t)mem;
int c = 0x11;
/* XRAM, YRAM, PRAM */
@ -78,10 +78,23 @@ int line(uint8_t *mem, char *header, char *bytes, char *ascii, int n)
return 0;
}
void draw_input(int x, int y, char *text, int cursor_pos)
{
int w, h;
int next = text[cursor_pos];
text[cursor_pos] = 0;
dsize(text, NULL, &w, &h);
text[cursor_pos] = next;
dtext(x, y, C_BLACK, text);
dline(x+w, y, x+w, y+h-1, C_BLACK);
}
/* gintctl_mem(): Memory browser */
void gintctl_mem(void)
{
uint32_t base = 0x88000000;
key_event_t ev;
int key = 0;
#ifdef FX9860G
@ -97,6 +110,16 @@ void gintctl_mem(void)
int size = 8;
int lines = _(9,14);
char input[9];
int input_pos = -1;
int input_len = -1;
int input_keys[16] = {
KEY_0, KEY_1, KEY_2, KEY_3,
KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_XOT, KEY_LOG,
KEY_LN, KEY_SIN, KEY_COS, KEY_TAN,
};
while(key != KEY_EXIT)
{
dclear(C_WHITE);
@ -129,36 +152,111 @@ void gintctl_mem(void)
}
#ifdef FX9860G
extern bopti_image_t img_opt_mem;
dsubimage(0, 56, &img_opt_mem, 0, 0, 128, 8, DIMAGE_NONE);
if(input_pos < 0)
{
extern bopti_image_t img_opt_mem;
dsubimage(0, 56, &img_opt_mem, 0, 0, 128, 8,
DIMAGE_NONE);
if(view_ascii) dsubimage(23, 56, &img_opt_mem, 23, 9,
21, 8, DIMAGE_NONE);
}
else
{
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
if(view_ascii) dsubimage(23, 56, &img_opt_mem, 23, 9, 21, 8,
DIMAGE_NONE);
dtext(1, 57, C_BLACK, "Go to:");
draw_input(24, 57, input, input_pos);
dfont(old_font);
}
#endif
#ifdef FXCG50
row_title("Memory browser");
fkey_button(1, "JUMP");
fkey_action(3, "ROM");
fkey_action(4, "RAM");
fkey_action(5, "ILRAM");
fkey_action(6, "ADDIN");
if(input_pos < 0)
{
fkey_button(1, "JUMP");
fkey_action(3, "ROM");
fkey_action(4, "RAM");
fkey_action(5, "ILRAM");
fkey_action(6, "ADDIN");
}
else
{
dtext(4, 210, C_BLACK, "Go to:");
draw_input(52, 210, input, input_pos);
}
#endif
dupdate();
key = getkey().key;
ev = getkey();
key = ev.key;
int move_speed = 1;
if(ev.shift || keydown(KEY_SHIFT)) move_speed = 8;
if(key == KEY_UP) base -= size * lines;
if(key == KEY_DOWN) base += size * lines;
if(key == KEY_UP) base -= move_speed * size * lines;
if(key == KEY_DOWN) base += move_speed * size * lines;
if(key == KEY_F1 && input_pos < 0)
{
input[0] = 0;
input_pos = 0;
input_len = 0;
}
if(key == KEY_EXIT && input_pos >= 0)
{
input_pos = -1;
input_len = -1;
/* Don't quit the memory viewer */
key = 0;
}
if(key == KEY_EXE && input_pos >= 0)
{
/* Parse string into hexa */
uint32_t target = 0;
for(int k = 0; k < input_len; k++)
{
target <<= 4;
if(input[k] <= '9') target += (input[k] - '0');
else target += (input[k] - 'A' + 10);
base = target & ~7;
}
input_pos = -1;
input_len = -1;
}
for(int i = 0; i < 16; i++)
if(key == input_keys[i] && input_pos >= 0 && input_len < 8)
{
/* Insert at input_pos, shift everything else right */
for(int k = 8; k >= input_pos; k--)
input[k + 1] = input[k];
input[input_pos++] = i + '0' + 7 * (i > 9);
input_len++;
}
if(key == KEY_DEL && input_pos > 0)
{
/* Shift everything after input_pos left one place */
for(int k = input_pos - 1; k < 8; k++)
input[k] = input[k + 1];
input_pos--;
input_len--;
}
if(key == KEY_LEFT && input_pos > 0) input_pos--;
if(key == KEY_RIGHT && input_pos < input_len) input_pos++;
#ifdef FX9860G
if(key == KEY_F2) view_ascii = !view_ascii;
if(key == KEY_F2 && input_pos < 0) view_ascii = !view_ascii;
#endif
if(key == KEY_F3) base = 0x80000000;
if(key == KEY_F4) base = 0x88000000;
if(key == KEY_F5) base = 0xe5200000;
if(key == KEY_F6) base = 0x00300000;
if(key == KEY_F3 && input_pos < 0) base = 0x80000000;
if(key == KEY_F4 && input_pos < 0) base = 0x88000000;
if(key == KEY_F5 && input_pos < 0) base = 0xe5200000;
if(key == KEY_F6 && input_pos < 0) base = 0x00300000;
}
#ifdef FX9860G


+ 16
- 4
src/menu.c View File

@ -25,12 +25,24 @@ void menu_init(struct menu *menu, int top, int bottom)
}
/* menu_move(): Move the cursor in a menu */
void menu_move(struct menu *menu, int key, int wrap)
void menu_move(struct menu *menu, int key, int quick, int wrap)
{
int visible = menu->bottom - menu->top;
int max_offset = max(menu->len - visible, 0);
if(key == KEY_UP && menu->pos > 0)
/* Quick moves */
if(key == KEY_UP && quick)
{
menu->pos = 0;
menu->offset = 0;
}
else if(key == KEY_DOWN && quick)
{
menu->pos = menu->len - 1;
menu->offset = max_offset;
}
/* Normal move up and wrapping move up */
else if(key == KEY_UP && menu->pos > 0)
{
menu->pos--;
menu->offset = min(menu->offset, menu->pos);
@ -40,8 +52,8 @@ void menu_move(struct menu *menu, int key, int wrap)
menu->pos = menu->len - 1;
menu->offset = max_offset;
}
if(key == KEY_DOWN && menu->pos + 1 < menu->len)
/* Normal move down and wrapping move down */
else if(key == KEY_DOWN && menu->pos + 1 < menu->len)
{
menu->pos++;
if(menu->pos > menu->offset + visible - 1


+ 23
- 0
src/util.c View File

@ -134,6 +134,29 @@ int row_y(int y)
return ROW_Y + ROW_H * (y - 1) + ROW_YPAD;
}
//---
// General rendering
//---
/* scrollbar_px(): Pixel-based scrollbar */
void scrollbar_px(int view_top, int view_bottom, int range_min, int range_max,
int range_pos, int range_view)
{
int view_x = _(127, 391);
int view_width = _(1, 2);
int view_height = view_bottom - view_top;
/* Bring virtual range to 0..range_max */
range_max -= range_min;
range_pos -= range_min;
int bar_pos = (range_pos * view_height + range_max/2) / range_max;
int bar_height = (range_view * view_height + range_max/2) / range_max;
drect(view_x, view_top + bar_pos, view_x + view_width - 1,
view_top + bar_pos + bar_height, C_BLACK);
}
//---
// Other drawing utilities
//---


Loading…
Cancel
Save