First/gui_display.c

352 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "config.h"
#include <ncurses.h>
#include "simdata.h"
#include <stdlib.h>
#include <string.h>
#include "gui.h"
#include "gui_display.h"
#ifdef USE_AALIB
#include <aalib.h>
#endif
int term_curs_x,term_curs_y;
///////////////////////////////////////////////
//// Braille code
///////////////////////////////////////////////
wchar_t braille_lookup[256]={
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
};
int print_braille_frame_buffer(WINDOW* win,uint8_t *buffer,int width,int height,int fullscreen){
for(int h=0;h<height/4;h++){
for(int w=0;w<width/2;w++){
uint8_t select=0;
if(buffer[w*2 +width*(h*4 )])
select|=0x01;
if(buffer[w*2 +width*(h*4+1)])
select|=0x02;
if(buffer[w*2 +width*(h*4+2)])
select|=0x04;
if(buffer[w*2 +width*(h*4+3)])
select|=0x40;
if(buffer[w*2+1 +width*(h*4 )])
select|=0x08;
if(buffer[w*2+1 +width*(h*4+1 )])
select|=0x10;
if(buffer[w*2+1 +width*(h*4+2 )])
select|=0x20;
if(buffer[w*2+1 +width*(h*4+3 )])
select|=0x80;
if(fullscreen)
mvwprintw(win,h,w,"%lc",braille_lookup[select]);
else
mvwprintw(win,h+1,w+1,"%lc",braille_lookup[select]);
}
}
return 0;
}
int braille_height,braille_width;
int init_braille(WINDOW __attribute__((unused)) *win,int fullscreen){
getmaxyx(win,braille_height,braille_width);
if(!fullscreen){
if(braille_height<2||braille_width<2)
return 1;
braille_height-=2;
braille_width-=2;
}
braille_height*=4;
braille_width*=2;
return 0;
}
int clean_braille(){
return 0;
}
///////////////////////////////////////////////
//// AALib code
///////////////////////////////////////////////
#ifdef USE_AALIB
struct aa_context *aactx;
int print_aalib_frame_buffer(WINDOW* win,uint8_t *fb,int fb_width,int fb_height,int fullscreen){
int height, width;
getmaxyx(win,height,width);
for(int y=0;y<fb_height;y++)
for(int x=0;x<fb_width;x++)
if(fb[x+y*fb_width])
aa_putpixel(aactx,x,y,255);
else
aa_putpixel(aactx,x,y,0);
aa_render(aactx,&aa_defrenderparams,0,0,fb_width,fb_height);
unsigned char *text=aa_text(aactx);
unsigned char *attr=aa_attrs(aactx);
for(int y=!fullscreen;y<height-(fullscreen?0:1);y++)
for(int x=!fullscreen;x<width-(fullscreen?0:1);x++){
char c=text[x+y*(width-(fullscreen?0:1))];
char a=attr[x+y*(width-(fullscreen?0:1))];
switch(a) {
case AA_NORMAL: break;
case AA_DIM: wattron(win,A_DIM); break;
case AA_BOLD: wattron(win,A_BOLD); break;
case AA_BOLDFONT: break;
case AA_REVERSE: wattron(win,A_REVERSE); break;
case AA_SPECIAL: break;
default: break;
}
mvwprintw(win,y,x,"%c",c);
switch(a) {
case AA_NORMAL: break;
case AA_DIM: wattroff(win,A_DIM); break;
case AA_BOLD: wattroff(win,A_BOLD); break;
case AA_BOLDFONT: break;
case AA_REVERSE: wattroff(win,A_REVERSE); break;
case AA_SPECIAL: break;
default: break;
}
}
return 0;
}
int init_aalib(WINDOW *win,int fullscreen){
int height, width;
getmaxyx(win,height,width);
if( (height<2||width<2) && fullscreen==0 )
return 1;
struct aa_hardware_params custom_params;
custom_params.font=NULL;
custom_params.supported=AA_NORMAL_MASK|AA_BOLD_MASK|AA_REVERSE_MASK;//AA_NORMAL_MASK, AA_DIM_MASK, AA_BOLD_MASK, AA_BOLDFONT_MASK, AA_REVERSE_MASK
custom_params.minwidth=0;
custom_params.minheight=0;
custom_params.maxwidth=0;
custom_params.maxheight=0;
custom_params.recwidth=0;
custom_params.recheight=0;
if(fullscreen){
custom_params.width=width;
custom_params.height=height;
}else{
custom_params.width=width-1;
custom_params.height=height-1;
}
aactx = aa_init(&mem_d, &custom_params, NULL);
if(!aactx)
return 1;
return 0;
}
#endif
int clean_aalib(){
aa_close(aactx);
return 0;
}
///////////////////////////////////////////////
//// Generic code
///////////////////////////////////////////////
int print_frame_buffer(WINDOW* win,uint8_t *fb,int fb_width,int fb_height,int fullscreen){
#ifdef USE_AALIB
if(selected_fb_driver==FB_AALIB)
return print_aalib_frame_buffer(win,fb,fb_width,fb_height,fullscreen);
else
#endif
return print_braille_frame_buffer(win,fb,fb_width,fb_height,fullscreen);
}
int init(WINDOW *win,int fullscreen){
#ifdef USE_AALIB
if(selected_fb_driver==FB_AALIB)
return init_aalib(win,fullscreen);
else
#endif
return init_braille(win,fullscreen);
}
float get_aspec_ratio(){
#ifdef USE_AALIB
if(selected_fb_driver==FB_AALIB)
return 2;
else
#endif
return 1.25;
}
void braille_frame_buffer_line(uint8_t *buffer,int buffer_width,int buffer_height,int x0, int y0, int x1, int y1){
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = (dx>dy ? dx : -dy)/2, e2;
uint32_t addr;
for(;;){
addr=x0+y0*buffer_width;
if(addr>0&&addr<(uint64_t)(buffer_width*buffer_height)&&x0<buffer_width&&x0>0)
buffer[addr]=1;
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
int update_terminal_output(WINDOW *win, struct simdata_t *simdata,uint8_t fullscreen){
int width,height;
werase(win);
getmaxyx(win,height,width);
term_curs_x=0;
term_curs_y=0;
int vector=0;
int vstate=0;
init(win,fullscreen);
int vfb_width, vfb_height;
#ifdef USE_AALIB
if(selected_fb_driver==FB_AALIB){
vfb_width=aa_imgwidth(aactx);
vfb_height=aa_imgheight(aactx);
}else
#endif
vfb_width=braille_width,vfb_height=braille_height;
uint8_t* vector_working_frame_buffer=malloc(vfb_height*vfb_width);
uint8_t* vector_display_frame_buffer=malloc(vfb_height*vfb_width);
memset(vector_working_frame_buffer,0,vfb_height*vfb_width);
memset(vector_display_frame_buffer,0,vfb_height*vfb_width);
float x0,y0,x1,y1;
for(uint64_t i=0;i < simdata->terminal_output_size/4;i++){
uint32_t c=simdata->terminal_output[i];
if(vector){
switch(vstate){
case 0: /*start of line*/
if(c==0x00000001)
vector=0;
else if(c==0x00000002)
memset(vector_working_frame_buffer,0,vfb_height*vfb_width);
else if(c==0x00000003)
memcpy(vector_display_frame_buffer,vector_working_frame_buffer,vfb_height*vfb_width);
else
vstate++;
break;
case 1: /*x of start*/
x0=uint32_to_ieee754_float(c);
vstate++;
break;
case 2: /*y of start*/
y0=uint32_to_ieee754_float(c);
vstate++;
break;
case 3: /*x of end*/
x1=uint32_to_ieee754_float(c);
vstate++;
break;
case 4: /*y of end*/
y1=uint32_to_ieee754_float(c);
float min_dim=(vfb_width>vfb_height)?vfb_height:vfb_width;
int xoff=0,yoff=0;
x0*=get_aspec_ratio();
x1*=get_aspec_ratio();
if(vfb_width>vfb_height)
xoff=(vfb_width-vfb_height)/2;
else
yoff=(vfb_height-vfb_width)/2;
braille_frame_buffer_line(vector_working_frame_buffer,vfb_width,vfb_height,xoff+(x0+1)*(min_dim/2),yoff+(y0+1)*(min_dim/2),xoff+(x1+1)*(min_dim/2),yoff+(y1+1)*(min_dim/2));
vstate=0;
break;
}
}else{
if(c>=' '&&c<='~'){
mvwprintw(win,term_curs_y+1,term_curs_x+1,"%c",c);
term_curs_x++;
if(term_curs_x>=width){
term_curs_x=0;
term_curs_y++;
}
if(term_curs_y>=height){
wscrl(win,1);
term_curs_y--;
for(int i=0;i<width;i++){
mvwprintw(win,term_curs_y+1,i," ");
}
}
}else{
switch(c){
case 0xffffffff:
vector=1;
break;
case 0x0a:
term_curs_x=0;
term_curs_y++;
if(term_curs_y>=vfb_height){
wscrl(win,1);
term_curs_y--;
box(win, 0 , 0);
mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
}
break;
default:
werase(win);
box(win, 0 , 0);
mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
mvwprintw(win,1,1,"Invalid output");
return 0;
}
}
}
}
if(!fullscreen){
box(win, 0 , 0);
if(!vector){
mvwchgat(win,term_curs_y+1,term_curs_x+1, 1, A_REVERSE, 0, NULL);
mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
}else{
mvwprintw(win,0,width/2-9,"[ VECTOR DISPLAY ]");
}
}else if(!vector){
mvwchgat(win,term_curs_y,term_curs_x, 1, A_REVERSE, 0, NULL);
}
if(vector)
print_frame_buffer(win,vector_display_frame_buffer,vfb_width,vfb_height,fullscreen);
free(vector_working_frame_buffer);
free(vector_display_frame_buffer);
# ifdef USE_AALIB
if(selected_fb_driver==FB_AALIB)
clean_aalib();
else
#endif
clean_braille();
return 0;
}
int update_general_terminal_output(WINDOW *win, struct simdata_t *simdata){
return update_terminal_output(win,simdata,0);
}
int update_display_terminal_output(WINDOW *win, struct simdata_t *simdata){
return update_terminal_output(win,simdata,1);
}