📄 guicore.cpp
字号:
/*
SNEeSe, an Open Source Super NES emulator.
Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.
This is free software. See 'LICENSE' for details.
You must read and accept the license prior to use.
*/
/*
GUIcore.cc
Contains most (eventually all) GUI core code - emulator specific GUI code
plugs into this!
Some stuff from helper.c will be moved here!
This GUI has been mostly rewritten to have two parts:
GUI core code
Emulator specific GUI code
The core has been written in C++, taking advantage of OOP to a
great extent - however, in its current state, it is far from
portable.
The core primarily consists of a few basic classes:
CTL
a generic GUI 'control', which relies on four basic methods:
attach() - init code when control is attached to a WINDOW
detach() - deinit code when control is detached from its WINDOW
refresh() - refresh the visual appearance of the control
process() - periodic maintenance routine, which will eventually
be able to respond to messages passed in from the core
all four methods are defined virtual with no bodies in the CTL
class definition
WINDOW - associates an object with an area of the screen, and allows
CTLs to link to that object and screen area
*/
#include <stdio.h>
#include <stdlib.h>
#include "wrapaleg.h"
#include "guicore.h"
/* ------------------------- DIRECTORY STUFF ------------------------- */
#include <unistd.h>
#include <string.h>
EXTERN char start_dir[MAXPATH]; /* defined in dos.c */
unsigned char GUI_ENABLED;
const char *GUI_error_table[] =
{
"Continue",
"Normal exit",
"Screen setup failure",
"Memory allocation failure"
};
int max_listed_files = 1024;
FILELIST *DirList;
int fncmp(const FILELIST *f1, const FILELIST *f2){
if (f2->Directory && !f1->Directory) return -1;
if (f1->Directory && !f2->Directory) return 1;
return stricmp(f1->Name, f2->Name);
}
// This fills an array of FILELIST with file information
// from the path given, starting at file number Offset
// and with a maximum number of files of max_listed_files
int GetDirList(char *Path, FILELIST *&Files, int Offset){
al_ffblk FileInfo;
int FilesRead;
int done = al_findfirst(Path, &FileInfo, FA_ARCH | FA_DIREC | FA_RDONLY);
if (done)
{
al_findclose(&FileInfo);
return 0; // empty dir returns 0
}
strcpy(Files[0].Name, "..");
// Small dirs are 4096 bytes in size on GNU/Linux, haven't tried other OS'es.
// Is file size for dirs important?
Files[0].Size = 4096;
Files[0].Directory = FA_DIREC;
FilesRead = 1;
do {
if (FilesRead == max_listed_files - 26)
{
FILELIST *tempFiles;
tempFiles = (FILELIST *) realloc(Files, sizeof(FILELIST[max_listed_files += 128]));
if (!tempFiles)
{
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
printf("Fatal error: Failure allocating memory for directory\n");
exit(EXIT_FAILURE);
}
else
{
Files = tempFiles;
}
}
if (strcmp(".", FileInfo.name) != 0 && strcmp("..", FileInfo.name) != 0){
strcpy(Files[FilesRead].Name, FileInfo.name);
Files[FilesRead].Size = FileInfo.size;
Files[FilesRead].Directory = FileInfo.attrib & FA_DIREC;
FilesRead++;
}
done = al_findnext(&FileInfo);
} while (!done); // while more files and more wanted
al_findclose(&FileInfo);
// Sort starting one entry after the entry for ".."
qsort(&Files[1], FilesRead - 1, sizeof(FILELIST),
(int (*)(const void *,const void *))fncmp);
#if defined(ALLEGRO_DOS) || defined(ALLEGRO_WINDOWS)
for (int a = 0; a < 26; a++){
sprintf(Files[FilesRead].Name, "%c:", a + 'A');
Files[FilesRead].Size = 0;
Files[FilesRead].Directory = FA_DIREC;
FilesRead++;
}
#endif
return FilesRead;
}
/* ------------------------- GUI STUFF ------------------------- */
#include "romload.h"
#include "types.h"
#include "font.h"
#include "helper.h"
RGB GUIPal[16]={{ 0, 0, 0, 0},{ 0, 0,31, 0},{ 0,31, 0, 0},{ 0,31,31, 0},
{31, 0, 0, 0},{31, 0,31, 0},{39,23, 0, 0},{47,47,47, 0},
{31,31,31, 0},{ 0, 0,63, 0},{ 0,63, 0, 0},{ 0,63,63, 0},
{63, 0, 0, 0},{63, 0,63, 0},{63,63, 0, 0},{63,63,63, 0}};
GUI_FONT ZSNES_Font(
Xlat_ZSNES_6x6,Font_ZSNES_6x6,
Font_Width_ZSNES,Font_Height_ZSNES,
Font_WidthSpace_ZSNES,Font_HeightSpace_ZSNES);
GUI_FONT Modified_Font(
Xlat_ZSNES_6x6,Font_Modified_6x6,
Font_Width_ZSNES,Font_Height_ZSNES,
Font_WidthSpace_ZSNES,Font_HeightSpace_ZSNES);
GUI_FONT Old_Font(
Xlat_6x8,Font_6x8,
Font_Width_Old,Font_Height_Old,
Font_WidthSpace_Old,Font_HeightSpace_Old);
GUI_FONT *default_font=&Modified_Font;
int GUI_ScreenWidth=320,GUI_ScreenHeight=240;
BITMAP *GUI_Bitmap=0;
unsigned char *GUI_Screen;
static char err_create_scrn_buf[]="Error creating GUI screen buffer.\n";
char *GUI_core_init(){
DirList = (FILELIST *) malloc(sizeof(FILELIST[max_listed_files]));
GUI_Bitmap=create_bitmap_ex(8,GUI_ScreenWidth,GUI_ScreenHeight);
if(!GUI_Bitmap) return err_create_scrn_buf;
clear(GUI_Bitmap);
GUI_Screen=(unsigned char *)GUI_Bitmap->dat;
return 0;
}
void CopyGUIScreen(){
acquire_screen();
blit(Allegro_Bitmap,screen,0,0,0,0,ScreenX,ScreenY);
release_screen();
}
int WINDOW::add(CTL *control){
if ((numctls + 1) == 0) return control->handle = 0;
CTL *temp = 0, *last = 0;
unsigned handle = 1;
if (!first){
first = control;
} else {
for (temp = first; temp; temp = (last = temp)->next){
if (temp->handle == handle){
handle++; if (!handle) return control->handle = 0; temp = first;
}
}
last->next=control;
}
numctls++; control->next = 0; control->attach(this);
return control->handle = handle;
}
int WINDOW::sub(unsigned handle){
int found = 0;
CTL *temp, *last;
if (first){
while (first->handle == handle){
found = -1;
numctls--;
first = first->next;
first->detach(this);
}
last = first;
for (temp = first->next; temp; temp = (last = temp)->next){
while (temp->handle == handle){
found = -1;
numctls--;
last->next = temp->next;
temp->detach(this);
}
}
}
return found;
}
void WINDOW::refresh(){ refresh((WINDOW *)0); };
void WINDOW::refresh(WINDOW *parent){
CTL::refresh(parent);
rewind();
CTL *control;
while((control = next()) != 0){
control->refresh(this);
}
}
void CTL_CLEAR::refresh(WINDOW *parent){
CTL::refresh(parent);
int x = parent->get_visible_x(), width = parent->get_width();
int y = parent->get_visible_y(), height = parent->get_height();
if (parent->get_visible_x() < 0){ width += x; x = 0; }
if (x + width > GUI_ScreenWidth) width = GUI_ScreenWidth - x;
if (parent->get_visible_y() < 0){ height += y; y = 0; }
if (y + height > GUI_ScreenHeight) height = GUI_ScreenHeight - y;
if (height > 0) for (int v = y; v < y + height; v++){
if (width > 0) memset(GUI_Screen + x + GUI_ScreenWidth * v, color, width);
}
}
void CTL_BORDER::refresh(WINDOW *parent){
CTL::refresh(parent);
const int
cBorder_TL=240+15,cBorder_T=240+15,cBorder_TR=240+7,
cBorder_L =240+15,cBorder_R=240+ 8,
cBorder_BL=240+ 7,cBorder_B=240+ 8,cBorder_BR=240+8;
if(parent->get_x()>=GUI_ScreenWidth ||
parent->get_y()>=GUI_ScreenHeight) return;
// left/middle/right, outer/inner, x position/width
int lox,low,mox,mow,rox,row;
int lix,liw,mix,miw,rix,riw;
lox=parent->get_x(); low=1;
lix=lox+low; liw=1;
mox=lox+low; mow=parent->get_width()+parent->get_gap_x()+liw*2;
mix=lix+liw; miw=parent->get_width()+parent->get_gap_x();
rox=mox+mow; row=1;
rix=mix+miw; riw=1;
if(lox<0){ low+=lox; lox=0; }
if((lox+low)>GUI_ScreenWidth) low=GUI_ScreenWidth-lox;
if(mox<0){ mow+=mox; mox=0; }
if((mox+mow)>GUI_ScreenWidth) mow=GUI_ScreenWidth-mox;
if(rox<0){ row+=rox; rox=0; }
if((rox+row)>GUI_ScreenWidth) row=GUI_ScreenWidth-rox;
if(lix<0){ liw+=lix; lix=0; }
if((lix+liw)>GUI_ScreenWidth) liw=GUI_ScreenWidth-lix;
if(mix<0){ miw+=mix; mix=0; }
if((mix+miw)>GUI_ScreenWidth) miw=GUI_ScreenWidth-mix;
if(rix<0){ riw+=rix; rix=0; }
if((rix+riw)>GUI_ScreenWidth) riw=GUI_ScreenWidth-rix;
// top/middle/bottom, outer/inner, y position/height
int toy,toh,moy,moh,boy,boh;
int tiy,tih,miy,mih,biy,bih;
toy=parent->get_y(); toh=1;
tiy=toy+toh; tih=1;
moy=toy+toh; moh=parent->get_height()+parent->get_gap_y()+tih*2;
miy=tiy+tih; mih=parent->get_height()+parent->get_gap_y();
boy=moy+moh; boh=1;
biy=miy+mih; bih=1;
if(toy<0){ toh+=toy; toy=0; }
if((toy+toh)>GUI_ScreenHeight) toh=GUI_ScreenHeight-toy;
if(moy<0){ moh+=moy; moy=0; }
if((moy+moh)>GUI_ScreenHeight) moh=GUI_ScreenHeight-moy;
if(boy<0){ boh+=boy; boy=0; }
if((boy+boh)>GUI_ScreenHeight) boh=GUI_ScreenHeight-boy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -