home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 18
/
aminetcdnumber181997.iso
/
Aminet
/
misc
/
emu
/
gbuk.lha
/
src
/
OPTIONS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-08
|
71KB
|
2,899 lines
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "picture.h"
#include "gb.h"
#include "gfxfunc.h"
#include "font.h"
#include "options.h"
#include "main.h"
#include "prefs.h"
#include "keycodes.h"
#include "system.h"
#define DEMO 1
#define DEMO_TIME (60*10+3) // 10 minutes 3 seconds
// Palette layout
// 0-15 Colors used by fonts, cursor, backdrop
// 16-31 Gameboy display palette
// 32-47 Workspace for palette prefs screen
// 48-79 Backdrop palette
// 80-111 Gadgets palette
// 112+ Unused
//***************************************************//
//* *//
//* DEFINES *//
//* *//
//***************************************************//
// Where different bits are situated in the palette
#define GAMEBOY_BASE 16
#define BACKDROP_BASE 48
#define GADGETS_BASE 80
#define ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
#define KILLMEM(x) if(x)GXFreeMem(x);
#define KEYOPTIONS_TITLE_Y 10
#define KEYOPTIONS_Y 30
#define KEYOPTIONS_DY 16
#define ITEM_STRING 0
#define ITEM_COLORFILL 1
#define GAMEBOY_X 0
#define GAMEBOY_Y 0
#define DISPLAY_X 0
#define DISPLAY_Y 0
#define PALETTE_PICTURE_X 4
#define PALETTE_PICTURE_Y 20
#define SLIDEBOTTOM_X 6
#define SLIDEBOTTOM_Y 185
#define DIRECTORYNAME_X 5
#define DIRECTORYNAME_Y 3
#define DIRECTORYNAME_WIDTH 212
#define DIRECTORYNAME_HEIGHT 12
#define SIDEPANEL_X 230
#define SIDEPANEL_Y 0
#define UPARROW_X 208
#define UPARROW_Y 21
#define DOWNARROW_X 208
#define DOWNARROW_Y 181
#define BUTTONS_X 234
#define BUTTONS_Y 66
#define BUTTONS_DY 23
#define BUTTONID_DOWNARROW 0
#define BUTTONID_UPARROW 1
#define BUTTONID_PARENT 2
#define BUTTONID_VOLUMES 3
#define BUTTONID_OK 4
#define BUTTONID_CANCEL 5
#define BUTTONID_LIST 6
#define BUTTONID_STRINGGADGET 7
#define LISTTYPE_FILES 0
#define LISTTYPE_VOLUMES 1
#define MAINBUTTON_LOAD 0
#define MAINBUTTON_PALETTE 1
#define MAINBUTTON_KEYS 2
#define MAINBUTTON_SAVE 3
#define MAINBUTTON_GRAB 4
#define MAINBUTTON_QUIT 5
#define MAINBUTTON_CANCEL 6
#define MAINBUTTON_NUMBER 7
#define MAINBUTTON_DUMPGFX 7
#define MENUBUTTON_Y 26
//************************************************************
// Stuff to do with palette requestor
//************************************************************
#define COLOR0_X 244
#define COLOR0_Y 27
#define COLOR_WIDTH 9
#define COLOR_HEIGHT 9
#define COLORSEPERATION_X 16
#define COLORSEPERATION_Y 19
#define PALETTE_OKAY_X 4
#define PALETTE_OKAY_Y 170
#define PALETTE_CANCEL_X 89
#define PALETTE_CANCEL_Y 170
#define RGB_X 239
#define RGB_Y 111
#define RGB_DY 29
#define PALETTE_SECTION_X 205
#define PALETTE_SECTION_Y 31
#define PALETTE_SECTION_DY 19
#define RGB_SLIDER_MINX 168
#define RGB_SLIDER_MAXX 304
#define RGB_SLIDER_Y 118
#define RGB_SLIDER_DY 29
#define SLIDER_RANGE (RGB_SLIDER_MAXX-RGB_SLIDER_MINX)
#define RGB_SLIDER_GFX_X 168
#define RGB_SLIDER_GFX_Y 104
#define RGB_SLIDER_GFX_DY 29
#define RGB_PALETTE_LINE_GFX_X 168
#define RGB_PALETTE_LINE_GFX_Y 22
#define RGB_PALETTE_LINE_GFX_DY 19
//***************************************************//
//* *//
//* STRUCTURES *//
//* *//
//***************************************************//
typedef struct{
int Type;
GXOBLONG Oblong;
char *String;
int Color;
int BackColor;
TXFONT *Font;
int File;
int ListOrder;
}ITEMDATA;
typedef struct{
int X,Y;
int MaxX,MaxY;
int Width,Height;
TXFONT *Font;
char *Text;
GXIMAGE *Image;
int NItem;
ITEMDATA **Item;
int BackColor;
}SCROLLWINDOW;
typedef struct{
GXIMAGE *Image;
long MinX,MinY;
long MaxX,MaxY;
long X,Y;
long Width,Height;
long Vertical;
long Position;
long BackColor;
}SLIDER;
typedef struct{
UBYTE Grab;
long X; //x coordinate of slider relative to origin
}RGBSLIDER;
typedef struct{
GXOBLONG Area;
char *String;
int CursorPosition;
}STRINGGADGET;
//***************************************************//
//* *//
//* PROTOTYPES *//
//* *//
//***************************************************//
void PrintLoadingMessage(void);
void UpdateSlider(SLIDER *s, long fraction, GXIMAGE *screen);
int MakeFileList(SCROLLWINDOW *window, char *dir);
void MakeVolumeList(SCROLLWINDOW *window);
void ScrollWindow(SCROLLWINDOW *window, int x, int y);
SCROLLWINDOW *MakeScrollWindow(int width, int height);
void KillScrollWindow(SCROLLWINDOW *window);
int UpdateButtons(GXOBLONG *button, int nbutton);
void DrawLine(SCROLLWINDOW *window, int ydraw);
void DrawWindow(SCROLLWINDOW *window, int x, int y, GXIMAGE *image);
int GetFileSelection(int y, ITEMDATA **list);
void RedrawItem(SCROLLWINDOW *window, ITEMDATA *item);
ITEMDATA **MakeItemData(int NItem, char **name, TXFONT **font, int *ListOrder);
void KillWindowItemData(SCROLLWINDOW *window);
int ListHeight(ITEMDATA **ItemList);
void PrintDirectoryName(GXIMAGE *Screen, TXFONT *TheFont, char *name);
void ClearWindow(SCROLLWINDOW *window, long color);
void SaveScreen(void);
void RestoreScreen(void);
int DoMenu(char *title, char **options, int NOptions);
void PalettePrefs(void);
void DrawPalette(int j, GXIMAGE *image, int highlight);
void ResetButtons(void);
void MoveSlider(int is, int NewX, GXIMAGE *ToImage);
void KeyOptions(void);
void DrawButton(GXIMAGE *dest, char *text, long x, long y);
char *KeyName(long RawCode);
STRINGGADGET *MakeStringGadget(char *StartString, GXOBLONG *Area, GXIMAGE *ToImage);
void UpdateStringGadge(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage);
int RawToAscii(int RawKey);
int SaveSnapshot(char *name);
int LoadSnapshot(char *name);
void ChangeKeySelection(int selection, int NewSelection, GXIMAGE *ScreenImage);
void PrintStringGadget(STRINGGADGET *sg, GXIMAGE *ToImage, int cursoron);
void UpdateStringGadget(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage,
int active);
void ChangeStringGadget(char *str, STRINGGADGET *sg, GXIMAGE *ToImage);
char *GetStringGadget(STRINGGADGET *sg);
void KillStringGadget(STRINGGADGET *sg);
int MouseClick(void);
void MakeWaitMessageList(SCROLLWINDOW *window);
void TimeOutCheck();
void TimeOutMessage(void);
void WaitNoKeys(void);
void DrawSlider(int is, int x, GXIMAGE *ToImage);
void DrawBackground(GXIMAGE *image, GXOBLONG *area);
//***************************************************//
//* *//
//* STATIC STUFF *//
//* *//
//***************************************************//
GXIMAGE *GameBoyImage=0,*GadgetsImage=0;
TXFONT *BlackFont,*RedFont,*WhiteFont;
GXPALETTE White={0xff,0xff,0xff,0};
GXPALETTE Black={0x00,0x00,0x00,0};
GXPALETTE Red={0xff,0x00,0x00,0};
GXPALETTE Orange={255, 156, 0, 0};
GXPALETTE Grey={112,112,112,0};
int WhiteIndex,BlackIndex,RedIndex,OrangeIndex,GreyIndex;
// Location of all the buttons & stuff in the source gfx
GXOBLONG FileSelector={0,0,320,196};
GXOBLONG SidePanel={230,19,90,200};
GXOBLONG ButtonUp={0,197,75,17};
GXOBLONG SliderDown={76,197,10,11};
GXOBLONG SliderUp={76,209,10,11};
GXOBLONG AcrossKnob={76,221,19,6};
GXOBLONG DownKnob={87,203,6,13};
GXOBLONG MessageBox={122,197,198,59};
GXOBLONG PaletteRequestor={0,234,320,196};
GXOBLONG PaletteNormal={132,203,15,15};
GXOBLONG PaletteHighlight={178,203,15,15};
GXOBLONG StringGadget={5,181,201,12};
GXOBLONG FileTitle={12,3,301,12};
GXOBLONG TitleBox={0,0,320,18};
GXOBLONG List={10,20,192,156};
GXOBLONG SlideSide={209,32,8,149};
GXOBLONG CornerTL={232,203,7,7};
GXOBLONG CornerTR={239,203,7,7};
GXOBLONG CornerBR={239,211,7,7};
GXOBLONG CornerBL={232,211,7,7};
GXOBLONG PaletteSlider={177,255-29,142,30};
GXOBLONG PaletteLine={1,511-276,142,20};
GXOBLONG BackTile={145,218,31,31};
long ScreenWidth,ScreenHeight;
GXOBLONG GameBoyDisplay={64+32,33,160,144};
GXOBLONG MainButtonLocation[MAINBUTTON_NUMBER];
long BackdropX=8+32,BackdropY=0; //where the backrop image is drawn to
int CurrentButton=-1;
GXIMAGE *ScreenSaveImage=0;
#if DEMO
//**********************************************************************
// TimeOutCheck()
//**********************************************************************
// Description: Halt the game after a short period for demo version
// Input: None
// Output: None
//**********************************************************************
void TimeOutCheck()
{
int DemoTime;
static long TimeOut=DEMO_TIME,StartTime=0;
if(!StartTime){
StartTime=GXTimer();
}else{
DemoTime=(GXTimer()-StartTime)/GXTicksPerSecond();
if(DemoTime>TimeOut){
TimeOutMessage();
GXQuitCode("Done\n");
}
}
}
//**********************************************************************
// TimeOutMessage()
//**********************************************************************
// Description: Print goodbye message for demo version
// Input: None
// Output: None
//**********************************************************************
void TimeOutMessage(void)
{
GXIMAGE *ScreenImage;
long x,y,StartTime,seconds;
GXMOUSEINFO MouseInfo;
int LeftReleased=0,MiddleReleased=0,RightReleased=0,j;
SaveScreen();
ScreenImage=GXStartDrawing(0);
DrawBackground(ScreenImage, 0);
y=(ScreenHeight-NTimeOutStrings*TXFONTHeight(RedFont))/2;
for(j=0; j<NTimeOutStrings; j++){
x=(ScreenWidth-TXStringWidth(TimeOutStrings[j], RedFont))/2;
TXPrintString(TimeOutStrings[j], x, y, ScreenImage, RedFont);
y+=TXFONTHeight(RedFont);
}
GXDoBlit();
StartTime=GXTimer();
do{
GXSystemUpdate();
// quit after 10 seconds
seconds=(GXTimer()-StartTime)/GXTicksPerSecond();
if(seconds>10)break;
// When any mouse button is pressed after being released,
// exit.
GXReadMouse(&MouseInfo);
if(!MouseInfo.LeftButton)LeftReleased=1;
if(!MouseInfo.MiddleButton)MiddleReleased=1;
if(!MouseInfo.RightButton)RightReleased=1;
if(MouseInfo.LeftButton&&LeftReleased)break;
if(MouseInfo.MiddleButton&&MiddleReleased)break;
if(MouseInfo.RightButton&&RightReleased)break;
}while(1);
RestoreScreen();
}
#endif
void ResetButtons(void)
{
CurrentButton=-1;
}
//**********************************************************************
// UpdateButtons()
//**********************************************************************
// Description: Find out if any buttons have been pressed
// Input: arrays telling where the buttons are, number of buttons,
// output for structure to be filled with button info
// Output: Button pressed?
//**********************************************************************
int UpdateButtons(GXOBLONG *button, int nbutton)
{
long x,y;
long ibutton=-1;
int j;
GXMOUSEINFO mouse;
GXReadMouse(&mouse);
for(j=0; j<nbutton; j++,button++){
x=mouse.X-button->X;
if(x<0)continue;
if(x>button->Width)continue;
y=mouse.Y-button->Y;
if(y<0)continue;
if(y>button->Height)continue;
ibutton=j;
break;
}
return ibutton;
}
//**********************************************************************
// DrawWindow()
//**********************************************************************
// Description: Copy window to image
// Input: window, location to be drawn to in image, image
// Output: none
//**********************************************************************
void DrawWindow(SCROLLWINDOW *window, int x, int y, GXIMAGE *image)
{
GXBLITLIST *b;
int xp,yp,xm,ym;
xp=window->X%window->Width;
yp=window->Y%window->Height;
xm=window->Width-xp;
ym=window->Height-yp;
if(xm&&ym){
// Part A
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=window->Image;
b->ToImage=image;
b->From.Width=xm;
b->From.Height=ym;
b->From.X=xp;
b->From.Y=yp;
b->XTo=x;
b->YTo=y;
}
if(xp&&ym){
// Part B
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=window->Image;
b->ToImage=image;
b->From.Width=xp;
b->From.Height=ym;
b->From.X=0;
b->From.Y=yp;
b->XTo=xm+x;
b->YTo=y;
}
if(xm&&yp){
// Part C
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=window->Image;
b->ToImage=image;
b->From.Width=xm;
b->From.Height=yp;
b->From.X=xp;
b->From.Y=0;
b->XTo=x;
b->YTo=y+ym;
}
if(xp&&yp){
// Part D
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=window->Image;
b->ToImage=image;
b->From.Width=xp;
b->From.Height=yp;
b->From.X=0;
b->From.Y=0;
b->XTo=x+xm;
b->YTo=y+ym;
}
}
//**********************************************************************
// ScrollWindow()
//**********************************************************************
// Description: Move the corner of the window
// Input: window, coordinates wanted for screen corner
// Output: none
//**********************************************************************
void ScrollWindow(SCROLLWINDOW *window, int x, int y)
{
int nloop,ydraw;
//////////////////////////////////
// Y Scrolling //
//////////////////////////////////
nloop=y-window->Y;
if(nloop>0){
if(nloop>window->Height){ //dont draw more than a whole screen
ydraw=y;
nloop=window->Height;
}else{
ydraw=window->Y+window->Height;
}
do{
DrawLine(window, ydraw);
ydraw++;
nloop--;
}while(nloop);
}else if(nloop<0){
if(nloop>window->Height){ //dont draw more than a whole screen
nloop=window->Height;
ydraw=y+window->Height-1;
}else{
nloop*=-1;
ydraw=window->Y-1;
}
do{
DrawLine(window, ydraw);
ydraw--;
nloop--;
}while(nloop);
}
window->Y=y;
}
//**********************************************************************
// DrawLine()
//**********************************************************************
// Description: Draw line on window
// Input: window, y value of line to draw
// Output: none
//**********************************************************************
void DrawLine(SCROLLWINDOW *window, int ydraw)
{
ITEMDATA *item,**ItemList;
TXFONT *font;
unsigned char *str,letter;
TXCUTDATA *CutData,*cut;
GXBLITLIST *b;
int YItem,xs,xe,x0,x1,yto;
yto=ydraw%window->Height;
ItemList=window->Item;
if(!ItemList){
return;
}
while(1){
item=*ItemList++;
if(!item){
break;
}
YItem=ydraw-item->Oblong.Y;
if( (YItem>=0) && (YItem<item->Oblong.Height) ){
if(item->Type==ITEM_STRING){
//////////////////////////////
// Draw a string //
//////////////////////////////
// Draw background
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->ToImage=window->Image;
b->From.Width=window->Width;
b->From.Height=1;
b->XTo=0;
b->YTo=yto;
b->Color=item->BackColor;
xs=item->Oblong.X - window->X;
str=(unsigned char *)item->String;
font=item->Font;
CutData=font->Cut;
while(letter=*str++){
if(xs>=window->Width)
break; //gone past end of window
cut=CutData+letter;
if(cut->Control){
// Control character
xs+=font->Width;
}else{
// Normal character
xe=xs+cut->Oblong.Width-1; //=x value last pixel drawn
if(xe>=0){ //inside left edge
if(xs<0){
x0=0;
}else{
x0=xs;
}
if(xe>=window->Width){
x1=window->Width-1;
}else{
x1=xe;
}
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=font->Image;
b->ToImage=window->Image;
b->From.X=x0-xs+cut->Oblong.X;
b->From.Y=YItem;
b->From.Width=x1-x0+1;
b->From.Height=1;
b->XTo=x0;
b->YTo=yto;
}
xs+=(cut->Oblong.Width+cut->XOffset);
}
}
}else{
//////////////////////////
// Draw a rectangle //
//////////////////////////
GXQuitCode("Called dodgy code\n");
xs=item->Oblong.X - window->X;
if(xs<window->Width){
if(xs<0){
x0=0;
}else{
x0=xs;
}
xe=xs+item->Oblong.Width-1;
if(xe>=0){
if(xe>=window->Width){
x1=window->Width-1;
}else{
x1=xe;
}
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->ToImage=window->Image;
b->From.Width=x1-x0+1;
b->From.Height=1;
b->XTo=x0;
b->YTo=yto;
b->Color=item->Color;
}
}
}
}
}
}
//**********************************************************************
// MakeScrollWindow()
//**********************************************************************
// Description: Make scrollwindow
// Input: size
// Output: window
//**********************************************************************
SCROLLWINDOW *MakeScrollWindow(int width, int height)
{
SCROLLWINDOW *window=0;
window=(SCROLLWINDOW *)GXGetMem(sizeof(SCROLLWINDOW), MEMF_ABORT|MEMF_ZERO);
window->Image=GXMakeImage(width, height);
if(!window->Image){
GXPrintf("MakeScrollWindow(): Couldnt make image\n");
goto fail;
}
window->Width=width;
window->Height=height;
window->X=window->Y=0;
window->BackColor=WhiteIndex;
return window;
fail:
GXQuitCode("Failed in scroll window creation\n");
return 0;
}
//**********************************************************************
// KillScrollWindow()
//**********************************************************************
// Description: Kill window made above
// Input: window
// Output: none
//**********************************************************************
void KillScrollWindow(SCROLLWINDOW *window)
{
GXKillImage(window->Image);
GXFreeMem(window);
}
//**********************************************************************
// SetupGFX()
//**********************************************************************
// Description: Load in all the graphics and fonts needed
// Input: none
// Output: none
//**********************************************************************
void SetupGFX(void)
{
GXPICTURE *GadgetsPic,*GameBoyPic,*pic;
GXIMAGE *ScreenImage;
int j;
ScreenImage=GXStartDrawing(0);
ScreenWidth=GXImageWidth(ScreenImage);
ScreenHeight=GXImageHeight(ScreenImage);
for(j=0; j<256; j++){
GXSetPaletteRange(&Black, j, 1);
}
GXSetPaletteRange(GameBoyPalette, GAMEBOY_BASE, 16);
GXReserveColors(0, 256, 0);
GXReserveColors(GAMEBOY_BASE, 32, 1);
GXReserveColors(0, 1, 1);
GXSetPaletteRange(&Black, 1, 1);
BlackIndex=1;
GXSetPaletteRange(&White, 2, 1);
WhiteIndex=2;
GXSetPaletteRange(&Red, 3, 1);
RedIndex=3;
GXSetPaletteRange(&Orange, 4, 1);
OrangeIndex=4;
GXSetPaletteRange(&Grey, 5, 1);
GreyIndex=5;
// Load pics
GadgetsPic=LoadPicture("gfx/gadgets.pic");
if(!GadgetsPic)goto fail;
GameBoyPic=LoadPicture("gfx/gameboy.pic");
if(!GameBoyPic)goto fail;
// Set palette range used by gadgets & gameboy
GXSetPaletteRange(GadgetsPic->Palette, GADGETS_BASE, 32);
GXSetPaletteRange(GameBoyPic->Palette, BACKDROP_BASE, 32);
// Create gadgets & gameboy images
GadgetsImage=GXPictureToImage(GadgetsPic, 1, 0);
if(!GadgetsImage)goto fail;
GameBoyImage=GXPictureToImage(GameBoyPic, 0, 0);
if(!GameBoyImage)goto fail;
KillPicture(GadgetsPic);
KillPicture(GameBoyPic);
// Load fonts
pic=LoadPicture(FontGfxName);
BlackFont=TXLoadFont(pic, FontCutName, &Black);
if(!BlackFont)goto fail;
RedFont=TXLoadFont(pic, FontCutName, &Red);
if(!RedFont)goto fail;
WhiteFont=TXLoadFont(pic, FontCutName, &White);
if(!WhiteFont)goto fail;
KillPicture(pic);
return;
fail:
GXQuitCode("Failed to find setup graphics\n");
}
//**********************************************************************
// ClearWindow()
//**********************************************************************
// Description: Fill window with given color
// Input: window, color
// Output: none
//**********************************************************************
void ClearWindow(SCROLLWINDOW *window, long color)
{
GXBLITLIST *b;
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=window->Width;
b->From.Height=window->Height;
b->Color=color;
b->XTo=0;
b->YTo=0;
b->ToImage=window->Image;
GXDoBlit();
}
//**********************************************************************
// MakeWaitMessageList()
//**********************************************************************
// Description: Set up list to show "Loading..." message
// Input: window
// Output: none
//**********************************************************************
void MakeWaitMessageList(SCROLLWINDOW *window)
{
char *list[1];
int ListOrder[]={1};
TXFONT *font[1];
list[0]=FileStrings[4];
font[0]=BlackFont;
window->Item=MakeItemData(1, list, font, ListOrder);
}
//**********************************************************************
// MakeVolumeList()
//**********************************************************************
// Description: Make item data for list of volumes and attach it to
// a window
// Input: window
// Output: none
//**********************************************************************
void MakeVolumeList(SCROLLWINDOW *window)
{
GXVOLUME *Volume;
long NVolume;
char **strings;
TXFONT **fonts;
int *ListOrder;
int NItem,j;
Volume=GXMakeVolumeInfo(&NVolume);
strings=(char **)GXGetMem(NVolume*sizeof(char *), MEMF_ABORT);
fonts=(TXFONT **)GXGetMem(NVolume*sizeof(TXFONT *), MEMF_ABORT);
ListOrder=(int *)GXGetMem(NVolume*sizeof(int), MEMF_ABORT);
NItem=NVolume;
for(j=0; j<NItem; j++){
strings[j]=Volume[j].Name;
fonts[j]=BlackFont;
ListOrder[j]=0;
}
window->Item=MakeItemData(NItem, strings, fonts, ListOrder);
GXKillVolumeInfo(Volume);
GXFreeMem(strings);
GXFreeMem(fonts);
GXFreeMem(ListOrder);
ClearWindow(window, WhiteIndex);
for(j=0; j<window->Height; j++){
DrawLine(window, j);
}
window->MaxY=ListHeight(window->Item)-window->Height;
if(window->MaxY<0)window->MaxY=0;
}
//**********************************************************************
// MakeFileList()
//**********************************************************************
// Description: Make item data for directory listing and attach it to
// a window
// Input: window, directory name
// Output: Did i get a list?
//**********************************************************************
int MakeFileList(SCROLLWINDOW *window, char *dir)
{
GXFILEINFO *FileInfo=0,*info;
int NItem,j;
char **strings;
TXFONT **fonts;
int *ListOrder;
ITEMDATA **ItemList;
if(!GXMakeDirectoryInfo(dir, &FileInfo)){
return 0;
}
info=FileInfo;
if(!info){
window->MaxY=0;
ClearWindow(window, WhiteIndex);
GXDoBlit();
return 1;
}
NItem=0;
while(info){
NItem++;
info=(GXFILEINFO *)info->Next;
}
strings=(char **)GXGetMem(NItem*sizeof(char *), MEMF_ABORT);
fonts=(TXFONT **)GXGetMem(NItem*sizeof(TXFONT *), MEMF_ABORT);
ListOrder=(int *)GXGetMem(NItem*sizeof(int), MEMF_ABORT);
info=FileInfo;
for(j=0; j<NItem; j++){
strings[j]=info->Name;
if(info->File){
ListOrder[j]=0;
fonts[j]=BlackFont;
}else{
ListOrder[j]=1;
fonts[j]=RedFont;
}
info=(GXFILEINFO *)info->Next;
}
ItemList=MakeItemData(NItem, strings, fonts, ListOrder);
GXKillDirectoryInfo(FileInfo);
GXFreeMem(strings);
GXFreeMem(fonts);
GXFreeMem(ListOrder);
window->Item=ItemList;
// Get scroll limits
window->MaxY=ListHeight(window->Item)-window->Height;
if(window->MaxY<0)window->MaxY=0;
GXPrintf("MaxY=%d\n",window->MaxY);
ClearWindow(window, WhiteIndex);
for(j=0; j<window->Height; j++){
DrawLine(window, j);
}
GXDoBlit();
return 1;
}
//**********************************************************************
// MakeItemData()
//**********************************************************************
// Description: Make item data for scroll window
// Input: number of items, array of name, array of fonts, array
// giving priority in list
// Output: item data or zero if it went wrong
//**********************************************************************
ITEMDATA **MakeItemData(int NItem, char **name, TXFONT **font, int *ListOrder)
{
ITEMDATA **ItemList,*item,*item2;
size_t size;
int j,k;
long y;
char *str,*str2,letter,letter2;
int swap;
size=(NItem + 1)*sizeof(ITEMDATA *);
ItemList=(ITEMDATA **)GXGetMem(size, MEMF_ABORT);
for(j=0; j<NItem; j++){
size=sizeof(ITEMDATA) + strlen(name[j]) + 1;
ItemList[j]=item=(ITEMDATA *)GXGetMem(size, MEMF_ABORT|MEMF_ZERO);
item->String=(char *)(item+1);
strcpy(item->String, name[j]);
item->Font=font[j];
item->Type=ITEM_STRING;
item->ListOrder=ListOrder[j];
item->BackColor=WhiteIndex;
}
ItemList[j]=0;
// Sort entries
for(j=0; j<(NItem-1); j++){
item=ItemList[j];
for(k=j+1; k<NItem; k++){
item2=ItemList[k];
if(item2->ListOrder>item->ListOrder){
// Directories come before files
ItemList[k]=item;
ItemList[j]=item2;
item=item2;
}else if(item2->ListOrder==item->ListOrder){
// Entries are of same type so compare alpabetically
str=item->String;
str2=item2->String;
while(1){
letter=*str++;
letter2=*str2++;
if(!letter2){
swap=1;
break;
}
if(!letter){
swap=0;
break;
}
if( (letter>='a')&&(letter<='z') ){
letter+=('A'-'a');
}
if( (letter2>='a')&&(letter2<='z') ){
letter2+=('A'-'a');
}
if(letter2<letter){
swap=1;
break;
}else if(letter2>letter){
swap=0;
break;
}
}
if(swap){
ItemList[k]=item;
ItemList[j]=item2;
item=item2;
}
}
}
}
// Figure out positions
y=0;
for(j=0; j<NItem; j++){
item=ItemList[j];
item->Oblong.X=0;
item->Oblong.Y=y;
item->Oblong.Width=TXStringWidth(item->String, item->Font);
item->Oblong.Height=item->Font->Height;
y+=item->Font->Height;
}
return ItemList;
}
//**********************************************************************
// KillWindowItemData()
//**********************************************************************
// Description: Free up item list made with above functions
// Input: item list
// Output: none
//**********************************************************************
void KillWindowItemData(SCROLLWINDOW *window)
{
ITEMDATA *item,**from;
if(!window->Item){
return;
}
from=window->Item;
while(item=*from++){
GXFreeMem(item);
}
GXFreeMem(window->Item);
window->Item=0;
}
//**********************************************************************
// ListHeight()
//**********************************************************************
// Description: Find maximum y value for item list
// Input: item list
// Output: maximum y
//**********************************************************************
int ListHeight(ITEMDATA **ItemList)
{
ITEMDATA *item;
while(*ItemList++)
;
item=*(ItemList-2);
return (item->Oblong.Y+item->Oblong.Height);
}
//**********************************************************************
// PrintDirectoryName()
//**********************************************************************
// Description: Print directory name at top of screen
// Input: screen image, font, directory
// Output: none
//**********************************************************************
void PrintDirectoryName(GXIMAGE *Screen, TXFONT *TheFont, char *name)
{
long XPlot,YPlot;
GXBLITLIST *b;
char *DirName=" ";
if(*name){
DirName=name;
}
while(*DirName){
if( TXStringWidth(DirName, TheFont) <= DIRECTORYNAME_WIDTH ){
break;
}
DirName++;
}
if(!(*DirName)){
GXQuitCode("PrintDirectoryName(): Couldnt get Directory name to fit\n");
}
// Figure out plot position
XPlot=(DIRECTORYNAME_WIDTH - TXStringWidth(DirName, TheFont))/2;
if(XPlot<0){
XPlot=DIRECTORYNAME_X;
}else{
XPlot+=DIRECTORYNAME_X;
}
YPlot=(DIRECTORYNAME_HEIGHT - TXFONTHeight(TheFont))/2;
if(YPlot<0){
YPlot=DIRECTORYNAME_Y;
}else{
YPlot+=DIRECTORYNAME_Y;
}
// Clear out last string
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=DIRECTORYNAME_WIDTH;
b->From.Height=DIRECTORYNAME_HEIGHT;
b->Color=WhiteIndex;
b->XTo=DIRECTORYNAME_X;
b->YTo=DIRECTORYNAME_Y;
b->ToImage=Screen;
GXDoBlit();
// Print new string
TXPrintString(DirName, XPlot, YPlot, Screen, TheFont);
}
//**********************************************************************
// GetFileSelection()
//**********************************************************************
// Description: Find what item correspnds to a given Y value in a
// window.
// Input: y value, items
// Output: Number of item or -1 if none found
//**********************************************************************
int GetFileSelection(int y, ITEMDATA **list)
{
int yy,n;
ITEMDATA *item;
if(!list){
return -1;
}
n=0;
while(item=*list++){
yy=y-item->Oblong.Y;
if( (yy>0) && (yy<item->Oblong.Height) ){
return n;
}
n++;
}
return -1;
}
//*****************************************************************************
// WaitNoKeys()
//*****************************************************************************
// Description: Wait until no keys are pressed
// input: None
// output: None
//*****************************************************************************
void WaitNoKeys(void)
{
long j;
// Wait till no keys are pressed
do{
GXSystemUpdate();
for(j=0; j<256; j++){
if(GXKeyDown(j)){
break;
}
}
}while(j!=256);
// Empty keyboard buffer
while(GXNextKey())
;
}
//*****************************************************************************
// DoMenu()
//*****************************************************************************
// Description: Let the user choose from options on a side panel
// input: menu title, strings for options, number of options
// output: option chosen or -1 if none
//*****************************************************************************
#define CLICK_SELECT 30 //how quick double click must be to select
int DoMenu(char *title, char **options, int NOptions)
{
GXBLITLIST *b;
long x,y,j;
GXOBLONG *Buttons=0;
GXMOUSEINFO MouseInfo,LastMouseInfo;
GXIMAGE *ScreenImage;
long selection;
long frame=0,JustPressed=0,NewSelection,delay,xx,tt,number;
long DoubleClick,DoubleClickDelay,moving;
WaitNoKeys();
SaveScreen();
ScreenImage=GXStartDrawing(0);
// Draw backdrop
DrawBackground(ScreenImage, 0);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=TitleBox;
b->XTo=b->YTo=0;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
// Print title
x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(title, BlackFont)/2;
y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
TXPrintString(title, x, y, ScreenImage, BlackFont);
// Print menu options & initialize button data
Buttons=(GXOBLONG *)GXGetMem(NOptions*sizeof(GXOBLONG), MEMF_ZERO|MEMF_ABORT);
for(j=0; j<NOptions; j++){
y=KEYOPTIONS_Y+KEYOPTIONS_DY*j;
Buttons[j].Width=TXStringWidth(options[j], BlackFont);
Buttons[j].Height=TXFONTHeight(BlackFont);
Buttons[j].X=(ScreenWidth-Buttons[j].Width)/2;
Buttons[j].Y=y;
if(j){
TXPrintString(options[j], Buttons[j].X, Buttons[j].Y, ScreenImage, BlackFont);
}else{
TXPrintString(options[j], Buttons[j].X, Buttons[j].Y, ScreenImage, RedFont);
}
y+=Buttons[j].Height;
}
selection=0;
delay=GXTicksPerSecond()/60;
DoubleClickDelay=CLICK_SELECT+1;
if(!delay)delay=1;
GXReadMouse(&LastMouseInfo);
moving=0;
do{
// Wait till next sixtieth to do next frame
xx=GXTimer();
do{
tt=GXTimer()-xx;
if(tt<0)break;
}while(tt< delay );
frame++;
// Update everything
GXSystemUpdate();
GXReadMouse(&MouseInfo);
GXDoBlit();
while(GXNextKey())
;
// Update menu selection due to mouse
NewSelection=selection;
JustPressed=MouseInfo.LeftButton&(!LastMouseInfo.LeftButton);
if( (number=UpdateButtons(Buttons, NOptions)) != -1 ){
if(JustPressed){
NewSelection=number;
}
}
DoubleClick=0;
if(JustPressed){
if( (DoubleClickDelay<CLICK_SELECT) && (NewSelection==selection) ){
DoubleClick=1;
}
DoubleClickDelay=0;
}else{
DoubleClickDelay++;
}
// Update menu selection due to keyboard/joypad
if( (frame==20) || (!moving) ){
if(GXKeyDown(KeyPrefs[3])){
if(selection==(NOptions-1)){
NewSelection=0;
}else{
NewSelection=selection+1;
}
moving=1;
}else if(GXKeyDown(KeyPrefs[2])){
if(!selection){
NewSelection=NOptions-1;
}else{
NewSelection=selection-1;
}
moving=1;
}else{
moving=0;
}
frame=0;
}
// Check for menu exit
if( DoubleClick || GXKeyDown(KeyPrefs[4]) || GXKeyDown(KEY_RETURN) ){
break;
}
// Update highlighted option
if(selection!=NewSelection){
TXPrintString(options[selection],
Buttons[selection].X, Buttons[selection].Y, ScreenImage, BlackFont);
selection=NewSelection;
TXPrintString(options[selection],
Buttons[selection].X, Buttons[selection].Y, ScreenImage, RedFont);
}
// Save mouse input for use next frame
LastMouseInfo=MouseInfo;
}while(1);
// Free up everything and restore screen
if(Buttons)GXFreeMem(Buttons);
RestoreScreen();
return selection;
}
//*****************************************************************************
// MakeGameScreen()
//*****************************************************************************
// Description: Draw the in-game screen
// input: none
// output: none
//*****************************************************************************
void MakeGameScreen(void)
{
GXBLITLIST *b;
GXIMAGE *ScreenImage;
long GameBoyY;
long xx,width,height,YStep;
ScreenImage=GXStartDrawing(0);
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=ScreenWidth;
b->From.Height=ScreenHeight;
b->Color=BlackIndex;
b->XTo=0;
b->YTo=0;
b->ToImage=ScreenImage;
// Scroll in gameboy
width=GXImageWidth(GameBoyImage);
xx=ScreenWidth-BackdropX;
if(xx<width){
width=xx;
}
GameBoyY=ScreenHeight-1;
YStep=ScreenHeight/25; //scroll up in 50 frames
if(!YStep)YStep=1;
do{
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From.X=b->From.Y=0;
b->From.Width=width;
height=GXImageHeight(GameBoyImage);
xx=ScreenHeight-GameBoyY;
if(xx<height)height=xx;
b->From.Height=height;
b->XTo=BackdropX;
b->YTo=GameBoyY;
b->FromImage=GameBoyImage;
b->ToImage=ScreenImage;
GXDoBlit();
if(GameBoyY==BackdropY)break;
GameBoyY-=YStep;
if(GameBoyY<BackdropY)GameBoyY=BackdropY;
GXSystemUpdate();
}while(1);
// Clear out area to be drawn to by gameboy
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From=GameBoyDisplay;
b->Color=GAMEBOY_BASE;
b->XTo=GameBoyDisplay.X;
b->YTo=GameBoyDisplay.Y;
b->ToImage=ScreenImage;
GXDoBlit();
}
GXIMAGE *ScreenImage;
//*****************************************************************************
// FileRequestor()
//*****************************************************************************
// Description: Gets file name selection
// input: address of output string
// output: file chosen ?
//*****************************************************************************
int FileRequestor(char *output, char *title)
{
GXBLITLIST *b;
GXMOUSEINFO MouseInfo,OldMouseInfo;
SCROLLWINDOW *window=0;
ITEMDATA *item;
long Y;
int j;
long yy,xx,ScrollY,Grab;
SLIDER Up;
GXOBLONG Buttons[8];
char letter;
int selection;
long ClickInterval;
long ListType;
static char DirectoryString[256]="";
static char FileString[256]="";
static char DeviceString[256]="";
char ss[256];
char *from;
int NSlash;
int finished,Highlight;
STRINGGADGET *sg=0;
int ActiveGadget,key;
int JustPressed,number;
int success=0;
// Set parameters for sliders
Up.Width=DownKnob.Width;
Up.Height=DownKnob.Height;
Up.MinX=Up.MaxX=SlideSide.X+1;
Up.MinY=SlideSide.Y+1;
Up.MaxY=Up.MinY+SlideSide.Height-Up.Height-2;
Up.Vertical=1;
Up.Position=0;
Up.X=Up.MinX;
Up.Y=Up.MinY;
Up.BackColor=WhiteIndex;
//////////////////////////////////
// Set up the scroll window //
//////////////////////////////////
window=MakeScrollWindow(List.Width,List.Height);
sprintf(ss,"%s%s",DeviceString,DirectoryString);
if(!MakeFileList(window, ss)){
strcpy(DeviceString,"");
strcpy(DirectoryString,""); //fixit
if(!MakeFileList(window, ss)){
GXQuitCode(ErrorString[1]);
}
}
ListType=LISTTYPE_FILES;
ScreenImage=GXStartDrawing(0);
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=GXImageWidth(ScreenImage);
b->From.Height=GXImageHeight(ScreenImage);
b->Color=BlackIndex;
b->XTo=0;
b->YTo=0;
b->ToImage=ScreenImage;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=FileSelector;
b->XTo=0;
b->YTo=0;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
DrawWindow(window, List.X, List.Y, ScreenImage);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=SliderUp;
b->XTo=UPARROW_X;
b->YTo=UPARROW_Y;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=SliderDown;
b->XTo=DOWNARROW_X;
b->YTo=DOWNARROW_Y;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
sprintf(ss,"%s%s",DeviceString,DirectoryString);
// DrawButtons
for(j=0; j<4; j++){
DrawButton(ScreenImage, FileStrings[j], BUTTONS_X, BUTTONS_Y+j*BUTTONS_DY);
}
// Title
xx=(FileTitle.Width/2) - TXStringWidth(title, BlackFont)/2 + FileTitle.X;
yy=(FileTitle.Height/2) - TXFONTHeight(BlackFont)/2 + FileTitle.Y;
TXPrintString(title, xx, yy, ScreenImage, BlackFont);
// Make buttons
Buttons[0]=SliderDown;
Buttons[0].X=DOWNARROW_X;
Buttons[0].Y=DOWNARROW_Y;
Buttons[1]=SliderUp;
Buttons[1].X=UPARROW_X;
Buttons[1].Y=UPARROW_Y;
// Parent button
Buttons[2]=ButtonUp;
Buttons[2].X=BUTTONS_X;
Buttons[2].Y=BUTTONS_Y;
// Volumes button
Buttons[3]=Buttons[2];
Buttons[3].Y+=BUTTONS_DY;
// OK button
Buttons[4]=Buttons[3];
Buttons[4].Y+=BUTTONS_DY;
// CANCEL
Buttons[5]=Buttons[4];
Buttons[5].Y+=BUTTONS_DY;
// LIST BOX
Buttons[6].X=List.X;
Buttons[6].Y=List.Y;
Buttons[6].Width=List.Width;
Buttons[6].Height=List.Height;
// STRING GADGET
Buttons[7]=StringGadget;
sg=MakeStringGadget(FileString, &StringGadget, ScreenImage);
/************************************************/
/* */
/* INPUT LOOP */
/* */
/************************************************/
#define LIST_VOLUMES { \
PrintLoadingMessage(); \
MakeVolumeList(window); \
ListType=LISTTYPE_VOLUMES; \
ScrollY=0; \
Y=Up.MinY; \
Highlight=-1; \
break; \
}
ScrollY=0;
GXReadMouse(&OldMouseInfo);
Y=Up.MinY;
Grab=0;
Highlight=-1;
selection=-1;
ClickInterval=0;
finished=0;
ActiveGadget=-1;
while(!finished){
//********************************************
// Update input devices and system
//********************************************
ClickInterval++;
GXSystemUpdate();
GXReadMouse(&MouseInfo);
JustPressed=MouseClick();
key=GXNextKey();
while(GXNextKey())
;
//********************************************
// Update string gadget
//********************************************
UpdateStringGadget(sg, RawToAscii(key), ScreenImage, (ActiveGadget==7));
//********************************************
// Update slider
//********************************************
if(JustPressed){
// Check for grabbing slider
xx=MouseInfo.X-Up.X;
if( (xx>=0) && (xx<Up.Width) ){
yy=MouseInfo.Y-Up.Y;
if( (yy>=0) && (yy<Up.Height) ){
Grab=1;
}
}
}
if(!MouseInfo.LeftButton){
Grab=0;
}
if(Grab){
Y+=(MouseInfo.Y-OldMouseInfo.Y);
if(Y<Up.MinY){
Y=Up.MinY;
}else if(Y>Up.MaxY){
Y=Up.MaxY;
}
ScrollY=(Y-Up.MinY)*window->MaxY/(Up.MaxY-Up.MinY);
}else if( (number=UpdateButtons(Buttons, 8)) != -1 ){
//********************************************
// Update buttons
//********************************************
if(JustPressed){
ActiveGadget=number;
}
switch(number){
case BUTTONID_STRINGGADGET:
break;
case BUTTONID_DOWNARROW:
if(!MouseInfo.LeftButton)break;
if(window->MaxY){
ScrollY++;
if(ScrollY>window->MaxY){
ScrollY=window->MaxY;
}
Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
Y+=Up.MinY;
}
break;
case BUTTONID_UPARROW:
if(!MouseInfo.LeftButton)break;
if(window->MaxY){
ScrollY--;
if(ScrollY<0){
ScrollY=0;
}
Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
Y+=Up.MinY;
}
break;
case BUTTONID_PARENT:
if(!JustPressed){
break;
}
Highlight=-1;
KillWindowItemData(window);
PrintLoadingMessage();
if( !DirectoryString[0] ){
MakeVolumeList(window);
ListType=LISTTYPE_VOLUMES;
ScrollY=0;
Y=Up.MinY;
break;
}else{
from=DirectoryString;
NSlash=0;
while(letter=*from++){
if(letter=='/')NSlash++;
}
if(NSlash>1){
from=DirectoryString+strlen(DirectoryString)-2;
while(letter=*from--){
if(letter=='/')break;
}
from[2]=0;
}else{
DirectoryString[0]=0;
}
}
sprintf(ss,"%s%s",DeviceString,DirectoryString);
//PrintDirectoryName(ScreenImage, BlackFont, ss);
PrintLoadingMessage();
if(!MakeFileList(window, ss)){
LIST_VOLUMES
break;
}
ListType=LISTTYPE_FILES;
Y=Up.MinY;
ScrollY=0;
break;
case BUTTONID_VOLUMES:
if(JustPressed){
KillWindowItemData(window);
LIST_VOLUMES
}
break;
case BUTTONID_OK:
if(JustPressed){
if( ListType==LISTTYPE_FILES ){
success=1;
finished=1;
}
}
break;
case BUTTONID_CANCEL:
if(JustPressed){
*output=0;
finished=1;
}
break;
case BUTTONID_LIST:
if(!JustPressed){
break;
}
xx=GetFileSelection(MouseInfo.Y-List.Y+window->Y, window->Item);
if(xx==-1)break;
selection=xx;
if(selection==Highlight){ //clicked twice on same item
if(ClickInterval<GXTicksPerSecond()){
//****************************************
// Double clicked
//****************************************
if(ListType==LISTTYPE_FILES){
item=window->Item[selection];
if(item->ListOrder==1){
// directory
strcat(DirectoryString, item->String);
strcat(DirectoryString, "/");
KillWindowItemData(window);
sprintf(ss,"%s%s",DeviceString,DirectoryString);
//PrintDirectoryName(ScreenImage, BlackFont, ss);
PrintLoadingMessage();
if(!MakeFileList(window, ss)){
GXPrintf("*** Failed to make list of files!!\n");
LIST_VOLUMES;
break;
}else{
GXPrintf("*** Made file list\n");
}
ListType=LISTTYPE_FILES;
Y=Up.MinY;
ScrollY=0;
Highlight=-1;
}else{
// file
success=1;
finished=1;
}
}else{
strcpy(DeviceString, window->Item[selection]->String);
strcpy(DirectoryString,"");
KillWindowItemData(window);
//PrintDirectoryName(ScreenImage, BlackFont, DeviceString);
PrintLoadingMessage();
if(!MakeFileList(window, DeviceString)){
LIST_VOLUMES;
break;
}
ListType=LISTTYPE_FILES;
Y=Up.MinY;
ScrollY=0;
GXPrintf("Volume selected!!\n");
GXPrintf("%s\n",DeviceString);
Highlight=-1;
}
}
}else{
item=window->Item[selection];
if( (ListType==LISTTYPE_FILES) && (item->ListOrder==0)){
ChangeStringGadget(item->String, sg, ScreenImage);
}
if(item->ListOrder==0){
item->BackColor=BlackIndex;
}else{
item->BackColor=RedIndex;
}
item->Font=WhiteFont;
RedrawItem(window, item);
if(Highlight!=-1){
item=window->Item[Highlight];
if(item->ListOrder==0){
item->Font=BlackFont;
}else{
item->Font=RedFont;
}
item->BackColor=WhiteIndex;
RedrawItem(window, item);
}
Highlight=selection;
}
ClickInterval=0;
break;
case -1:
break;
default:
GXQuitCode("Invalid button\n");
}
}
// Check cursor keys
if(GXKeyDown(KEY_CURSORDOWN)){
if(window->MaxY){
ScrollY+=2;
if(ScrollY>window->MaxY){
ScrollY=window->MaxY;
}
Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
Y+=Up.MinY;
}
}
if(GXKeyDown(KEY_CURSORUP)){
if(window->MaxY){
ScrollY-=2;
if(ScrollY<0){
ScrollY=0;
}
Y=(Up.MaxY-Up.MinY)*ScrollY/window->MaxY;
Y+=Up.MinY;
}
}
if(GXKeyDown(KEY_RETURN)){
if(ListType==LISTTYPE_FILES){
success=1;
finished=1;
}
}
ScrollWindow(window, 0, ScrollY);
DrawWindow(window, List.X, List.Y, ScreenImage);
UpdateSlider(&Up, Y, ScreenImage);
GXDoBlit();
OldMouseInfo=MouseInfo;
}
if(success){
sprintf(output, "%s%s%s",
DeviceString, DirectoryString, GetStringGadget(sg));
}else{
*output=0;
}
KillWindowItemData(window);
KillScrollWindow(window);
if(sg)KillStringGadget(sg);
return success;
}
int MouseClick(void)
{
int jj;
GXMOUSEINFO mouse;
static GXMOUSEINFO LastMouse;
GXReadMouse(&mouse);
jj=(mouse.LeftButton)&(!LastMouse.LeftButton);
LastMouse=mouse;
return jj;
}
//**********************************************************************
// PrintLoadingMessage()
//**********************************************************************
// Description:print "READING..." message in the file list to let
// the user know that a directory or volume list is being
// read.
// Input: none
// Output: none
//**********************************************************************
void PrintLoadingMessage(void)
{
GXBLITLIST *b;
// Clear out list window then print message
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=List.Width;
b->From.Height=List.Height;
b->XTo=List.X;
b->YTo=List.Y;
b->ToImage=ScreenImage;
b->Color=WhiteIndex;
TXPrintString(FileStrings[4], List.X, List.Y, ScreenImage, BlackFont);
GXDoBlit();
GXSystemUpdate(); //could possibly mess up input.
}
//**********************************************************************
// RedrawItem()
//**********************************************************************
// Description: Redraw and item in a window
// Input: window, item
// Output: none
//**********************************************************************
void RedrawItem(SCROLLWINDOW *window, ITEMDATA *item)
{
int y0,y1,y,n;
y=item->Oblong.Y;
y0=window->Y;
y1=window->Y+window->Height;
for(n=item->Oblong.Height; n; n--){
if( (y>=y0)&&(y<y1) ){
DrawLine(window, y);
}
y++;
}
}
//**********************************************************************
// UpdateSlider()
//**********************************************************************
// Description: Move slider to new position on screen
// Input: slider data, new y value wanted, screen image
// Output: none
//**********************************************************************
void UpdateSlider(SLIDER *s, long y, GXIMAGE *screen)
{
GXBLITLIST *b;
long height;
if(y<s->MinY){
y=s->MinY;
}else if(y>s->MaxY){
y=s->MaxY;
}
height=y-s->Y;
if(height>0){
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=DownKnob.Width;
b->From.Height=height;
b->XTo=s->X;
b->YTo=s->Y;
b->ToImage=screen;
b->Color=s->BackColor;
}else if(height<0){
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->From.Width=DownKnob.Width;
b->From.Height=-height;
b->XTo=s->X;
b->YTo=y+DownKnob.Height;
b->ToImage=screen;
b->Color=s->BackColor;
}
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=DownKnob;
b->XTo=s->X;
b->YTo=y;
b->FromImage=GadgetsImage;
b->ToImage=screen;
s->Y=y;
}
//**********************************************************************
// IngameUpdate()
//**********************************************************************
// Description: routine called to update menus etc.. while game is
// running. called from end of ScreenRefresh()
// Input: none
// Output: none
//**********************************************************************
void IngameUpdate(void)
{
GXMOUSEINFO MouseInfo;
int option;
char LoadGame[256];
GXPICTURE *pic;
GXSystemUpdate();
#if DEMO
TimeOutCheck();
#endif
GXReadMouse(&MouseInfo);
if( MouseInfo.RightButton || GXKeyDown(KEY_F2) ){
switch( option=DoMenu(MenuStrings[0], &MenuStrings[1], MAINBUTTON_NUMBER) ){
case MAINBUTTON_GRAB:
SaveScreen();
if( FileRequestor(LoadGame, TitleStrings[2]) ){
pic=GXGetPicture(ScreenSaveImage, &GameBoyDisplay);
SavePicture(LoadGame, pic, PICTURE_LBM);
KillPicture(pic); //assume this is alright for killing
}
RestoreScreen();
break;
case MAINBUTTON_LOAD:
SaveScreen();
if( FileRequestor(LoadGame, TitleStrings[0]) ){
CPURunning=0;
strcpy(GameToLoad, LoadGame);
GameOption=GAMEOPTION_LOAD;
}
RestoreScreen();
break;
case MAINBUTTON_QUIT:
CPURunning=0;
GameOption=GAMEOPTION_QUIT;
break;
case MAINBUTTON_PALETTE:
PalettePrefs();
break;
case MAINBUTTON_KEYS:
KeyOptions();
break;
case MAINBUTTON_SAVE:
SaveScreen();
if(FileRequestor(LoadGame,TitleStrings[1])){
SaveSnapshot(LoadGame);
}
RestoreScreen();
break;
case MAINBUTTON_CANCEL:
case -1:
break;
default:
GXQuitCode("Unknown menu option\n");
}
}
}
void SaveScreen(void)
{
GXIMAGE *ScreenImage;
GXBLITLIST *b;
ScreenImage=GXStartDrawing(0);
ScreenSaveImage=GXMakeImage(ScreenWidth, ScreenHeight);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=ScreenImage;
b->ToImage=ScreenSaveImage;
b->From.Width=ScreenWidth;
b->From.Height=ScreenHeight;
b->From.X=0;
b->From.Y=0;
b->XTo=0;
b->YTo=0;
GXDoBlit();
}
void RestoreScreen(void)
{
GXIMAGE *ScreenImage;
GXBLITLIST *b;
ScreenImage=GXStartDrawing(0);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=ScreenSaveImage;
b->ToImage=ScreenImage;
b->From.Width=ScreenWidth;
b->From.Height=ScreenHeight;
b->From.X=0;
b->From.Y=0;
b->XTo=0;
b->YTo=0;
GXDoBlit();
GXKillImage(ScreenSaveImage);
}
//******************************************************
// DrawBackground()
//******************************************************
// Tile background on given are on given image
// input: image to tile on to, area to be tiled
// output: none
//******************************************************
void DrawBackground(GXIMAGE *image, GXOBLONG *area)
{
GXBLITLIST *b;
long width,height,nx,ny,xplot,yplot,ix,iy,xx;
long ImageWidth,ImageHeight,x0,y0,x1,y1, xend, yend;
long xfrom, yfrom, xto, yto;
ImageWidth=GXImageWidth(image);
ImageHeight=GXImageHeight(image);
if(!area){
x0=0;
y0=0;
x1=ImageWidth;
y1=ImageHeight;
}else{
x0=area->X;
y0=area->Y;
x1=x0+area->Width;
y1=y0+area->Height;
}
//Draw tiles
nx=(ImageWidth/BackTile.Width);
if( (ImageWidth%BackTile.Width) ){
nx++;
}
ny=(ImageHeight/BackTile.Height);
if( (ImageHeight%BackTile.Height) ){
ny++;
}
yplot=0;
for(iy=ny; iy; iy--,yplot+=BackTile.Height){
if(yplot>=y1)break;
yend=yplot+BackTile.Height;
if(yend<=y0)continue;
if(yplot<y0){
if(yend>y1){
height=area->Height;
}else{
height=yend-y0;
}
yto=y0;
yfrom=y0-yplot+BackTile.Y;
}else if(yend>y1){
yto=yplot;
height=y1-yplot;
yfrom=BackTile.Y;
}else{
yto=yplot;
height=BackTile.Height;
yfrom=BackTile.Y;
}
xplot=0;
for(ix=nx; ix; ix--,xplot+=BackTile.Width){
if(xplot>=x1)break;
xend=xplot+BackTile.Width;
if(xend<=x0)continue;
if(xplot<x0){
if(xend>x1){
width=area->Width;
}else{
width=xend-x0;
}
xto=x0;
xfrom=x0-xplot+BackTile.X;
}else if(xend>x1){
xto=xplot;
width=x1-xplot;
xfrom=BackTile.X;
}else{
xto=xplot;
width=BackTile.Width;
xfrom=BackTile.X;
}
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=GadgetsImage;
b->ToImage=image;
b->XTo=xto;
b->YTo=yto;
b->From.X=xfrom;
b->From.Y=yfrom;
b->From.Width=width;
b->From.Height=height;
}
}
// Draw corners
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=GadgetsImage;
b->ToImage=image;
b->XTo=b->YTo=0;
b->From=CornerTL;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=GadgetsImage;
b->ToImage=image;
b->XTo=ImageWidth-CornerTR.Width;
b->YTo=0;
b->From=CornerTR;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=GadgetsImage;
b->ToImage=image;
b->XTo=ImageWidth-CornerBR.Width;
b->YTo=ImageHeight-CornerBR.Height;
b->From=CornerBR;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->FromImage=GadgetsImage;
b->ToImage=image;
b->XTo=0;
b->YTo=ImageHeight-CornerBL.Height;
b->From=CornerBL;
}
void ErrorMessage(char *message)
{
GXIMAGE *ScreenImage;
long x,y;
GXMOUSEINFO MouseInfo;
int LeftReleased=0,MiddleReleased=0,RightReleased=0;
SaveScreen();
ScreenImage=GXStartDrawing(0);
DrawBackground(ScreenImage, 0);
x=(ScreenWidth-TXStringWidth(message, RedFont))/2;
y=(ScreenHeight-TXFONTHeight(RedFont))/2;
TXPrintString(message, x, y, ScreenImage, RedFont);
GXDoBlit();
GXPrintf(message);
do{
GXSystemUpdate();
GXReadMouse(&MouseInfo);
// When any mouse button is pressed after being released,
// exit.
if(!MouseInfo.LeftButton)LeftReleased=1;
if(!MouseInfo.MiddleButton)MiddleReleased=1;
if(!MouseInfo.RightButton)RightReleased=1;
if(MouseInfo.LeftButton&&LeftReleased)break;
if(MouseInfo.MiddleButton&&MiddleReleased)break;
if(MouseInfo.RightButton&&RightReleased)break;
}while(1);
RestoreScreen();
}
RGBSLIDER slider[3];
void PalettePrefs(void)
{
GXIMAGE *ScreenImage;
GXBLITLIST *b;
GXMOUSEINFO MouseInfo;
int j, ix, iy, x, y, is;
int SelectedColor=0;
GXOBLONG *buttons=0;
RGBSLIDER *pslider;
int StartMouseX, StartSliderX;
GXPALETTE color,*OldPalette=0,*GameBoyPalette2=0;
int JustPressed;
int number,changed=0;
// Save screen & palette
SaveScreen();
OldPalette=(GXPALETTE *)GXGetMem(16*sizeof(GXPALETTE), MEMF_ZERO|MEMF_ABORT);
GameBoyPalette2=(GXPALETTE *)GXGetMem(16*sizeof(GXPALETTE), MEMF_ZERO|MEMF_ABORT);
memcpy(GameBoyPalette2, GameBoyPalette, 16*sizeof(GXPALETTE));
GXGetPaletteRange(OldPalette, GAMEBOY_BASE, 16);
GXSetPaletteRange(GameBoyPalette2, GAMEBOY_BASE+16, 16);
ScreenImage=GXStartDrawing(0);
DrawBackground(ScreenImage, 0);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=TitleBox;
b->XTo=b->YTo=0;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=GameBoyDisplay;
b->XTo=PALETTE_PICTURE_X;
b->YTo=PALETTE_PICTURE_Y;
b->FromImage=ScreenSaveImage;
b->ToImage=ScreenImage;
// Draw slider background
for(j=0; j<3; j++){
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=PaletteSlider;
b->XTo=RGB_SLIDER_GFX_X;
b->YTo=RGB_SLIDER_GFX_Y+RGB_SLIDER_GFX_DY*j;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
}
// Draw palette buttons background
for(j=0; j<4; j++){
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=PaletteLine;
b->XTo=RGB_PALETTE_LINE_GFX_X;
b->YTo=RGB_PALETTE_LINE_GFX_Y+j*RGB_PALETTE_LINE_GFX_DY;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
}
for(j=0; j<16; j++){
DrawPalette(j, ScreenImage, j==SelectedColor);
}
// Make up buttons
buttons=(GXOBLONG *)GXGetMem(21*sizeof(GXOBLONG), MEMF_ZERO|MEMF_ABORT);
for(j=0; j<16; j++){
ix=j%4;
iy=j/4;
buttons[j].X=COLOR0_X + ix*COLORSEPERATION_X;
buttons[j].Y=COLOR0_Y + iy*COLORSEPERATION_Y;
buttons[j].Width=COLOR_WIDTH;
buttons[j].Height=COLOR_HEIGHT;
}
buttons[16]=ButtonUp;
buttons[16].X=PALETTE_OKAY_X;
buttons[16].Y=PALETTE_OKAY_Y;
buttons[17]=ButtonUp;
buttons[17].X=PALETTE_CANCEL_X;
buttons[17].Y=PALETTE_CANCEL_Y;
for(j=0; j<3; j++){
buttons[j+18]=DownKnob;
buttons[j+18].X=RGB_SLIDER_MINX;
buttons[j+18].Y=RGB_SLIDER_Y+RGB_SLIDER_DY*j;
}
// Print palette section names
x=PALETTE_SECTION_X;
y=PALETTE_SECTION_Y;
for(j=0; j<4; j++){
TXPrintString( PaletteStrings[j+5],
(x-TXStringWidth(PaletteStrings[j+5], BlackFont)/2),
(y-TXFONTHeight(BlackFont)/2),
ScreenImage, BlackFont);
y+=PALETTE_SECTION_DY;
}
// Print title
x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(TitleStrings[3], BlackFont)/2;
y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
TXPrintString(TitleStrings[3], x, y, ScreenImage, BlackFont);
// Draw okay & cancel buttons
DrawButton(ScreenImage, PaletteStrings[3], PALETTE_OKAY_X, PALETTE_OKAY_Y);
DrawButton(ScreenImage, PaletteStrings[4], PALETTE_CANCEL_X, PALETTE_CANCEL_Y);
// initialize sliders
memset(slider, 0, sizeof(slider));
color=GameBoyPalette2[SelectedColor];
x=((int)color.Red)*SLIDER_RANGE/255;
DrawSlider(0, x, ScreenImage);
buttons[18].X=slider[0].X+RGB_SLIDER_MINX;
buttons[18].Y=RGB_SLIDER_Y;
x=((int)color.Green)*SLIDER_RANGE/255;
DrawSlider(1, x, ScreenImage);
buttons[19].X=slider[1].X+RGB_SLIDER_MINX;
buttons[19].Y=RGB_SLIDER_Y+RGB_SLIDER_DY;
x=((int)color.Red)*SLIDER_RANGE/255;
DrawSlider(2, x, ScreenImage);
buttons[20].X=slider[2].X+RGB_SLIDER_MINX;
buttons[20].Y=RGB_SLIDER_Y+2*RGB_SLIDER_DY;
GXDoBlit();
ResetButtons();
is=-1;
do{
GXSystemUpdate();
GXReadMouse(&MouseInfo);
JustPressed=MouseClick();
if( (number=UpdateButtons(buttons, 21)) != -1){
if(JustPressed){
if( (number>=0) &&
(number<16) ){
DrawPalette(SelectedColor, ScreenImage, 0);
SelectedColor=number;
DrawPalette(SelectedColor, ScreenImage, 1);
color=GameBoyPalette2[SelectedColor];
x=((long)color.Red)*SLIDER_RANGE/255;
MoveSlider(0, x, ScreenImage);
buttons[18].X=x+RGB_SLIDER_MINX;
buttons[18].Y=RGB_SLIDER_Y;
x=((long)color.Green)*SLIDER_RANGE/255;
MoveSlider(1, x, ScreenImage);
buttons[19].X=x+RGB_SLIDER_MINX;
buttons[19].Y=RGB_SLIDER_Y+RGB_SLIDER_DY;
x=((long)color.Blue)*SLIDER_RANGE/255;
MoveSlider(2, x, ScreenImage);
buttons[20].X=x+RGB_SLIDER_MINX;
buttons[20].Y=RGB_SLIDER_Y+2*RGB_SLIDER_DY;
}else if(number==16){
// OKAY PRESSED.
// Save palette & quit
changed=1;
break;
}else if(number==17){
// CANCEL PRESSED
// Restore old palette & quit
break;
}else if( (number>17) && (number<21) ){
is=number-18;
StartMouseX=MouseInfo.X;
StartSliderX=slider[is].X;
}
}
}
// Update sliders
if( is!=-1){
if(!MouseInfo.LeftButton){
is=-1;
}else{
x=MouseInfo.X-StartMouseX+StartSliderX;
if(x>SLIDER_RANGE)x=SLIDER_RANGE;
if(x<0)x=0;
if(x!=slider[is].X){
MoveSlider(is, x, ScreenImage);
buttons[18+is].X=RGB_SLIDER_MINX+x;
buttons[18+is].Y=RGB_SLIDER_Y+RGB_SLIDER_DY*is;
color.Red=slider[0].X*255/SLIDER_RANGE;
color.Green=slider[1].X*255/SLIDER_RANGE;
color.Blue=slider[2].X*255/SLIDER_RANGE;
GXSetPaletteRange(&color, SelectedColor+16+GAMEBOY_BASE, 1);
for(j=0; j<16; j++){
if(SourceColor(j)==SelectedColor){
GXSetPaletteRange(&color, j+GAMEBOY_BASE, 1);
}
}
GameBoyPalette2[SelectedColor]=color;
}
}
}
GXDoBlit();
}while(1);
if(changed){
// Save new palette to prefs
memcpy(GameBoyPalette, GameBoyPalette2, 16*sizeof(GXPALETTE));
SavePrefs();
}else{
// Restore old palette
GXSetPaletteRange(OldPalette, GAMEBOY_BASE, 16);
}
// Free stuff used
KILLMEM(buttons);
KILLMEM(OldPalette);
KILLMEM(GameBoyPalette2);
RestoreScreen();
}
void MoveSlider(int is, int x, GXIMAGE *ToImage)
{
GXBLITLIST *b;
RGBSLIDER *s;
s=&slider[is];
if(x>SLIDER_RANGE)x=SLIDER_RANGE;
if(x<0)x=0;
if(x!=s->X){
// Draw over last place that slider was at
// Could go wrong if slider range is too big
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From.X=PaletteSlider.X + s->X + RGB_SLIDER_MINX - RGB_SLIDER_GFX_X;
b->From.Y=PaletteSlider.Y + RGB_SLIDER_Y - RGB_SLIDER_GFX_Y;
b->From.Width=DownKnob.Width;
b->From.Height=DownKnob.Height;
b->XTo=s->X+RGB_SLIDER_MINX;
b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
b->FromImage=GadgetsImage;
b->ToImage=ToImage;
// Draw new slider
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=DownKnob;
b->XTo=x+RGB_SLIDER_MINX;
b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
b->FromImage=GadgetsImage;
b->ToImage=ToImage;
s->X=x;
}
}
void DrawSlider(int is, int x, GXIMAGE *ToImage)
{
GXBLITLIST *b;
RGBSLIDER *s;
long xplot,yplot;
s=&slider[is];
if(x>SLIDER_RANGE)x=SLIDER_RANGE;
if(x<0)x=0;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=PaletteSlider;
b->XTo=RGB_SLIDER_GFX_X;
b->YTo=RGB_SLIDER_GFX_Y+RGB_SLIDER_GFX_DY*is;
b->FromImage=GadgetsImage;
b->ToImage=ToImage;
xplot=RGB_X;
yplot=RGB_Y+RGB_DY*is;
TXPrintString( PaletteStrings[is],
(xplot-TXStringWidth(PaletteStrings[is], BlackFont)/2),
(yplot-TXFONTHeight(BlackFont)/2),
ToImage, BlackFont);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=DownKnob;
b->XTo=x+RGB_SLIDER_MINX;
b->YTo=RGB_SLIDER_Y+is*RGB_SLIDER_DY;
b->FromImage=GadgetsImage;
b->ToImage=ToImage;
s->X=x;
}
void DrawPalette(int j, GXIMAGE *image, int highlight)
{
int ix,iy,x,y;
GXBLITLIST *b;
ix=j%4;
iy=j/4;
x=COLOR0_X + ix*COLORSEPERATION_X;
y=COLOR0_Y + iy*COLORSEPERATION_Y;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->XTo=x-3;
b->YTo=y-3;
if(highlight){
b->From=PaletteHighlight;
}else{
b->From=PaletteNormal;
}
b->FromImage=GadgetsImage;
b->ToImage=image;
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->Color=j+16+GAMEBOY_BASE;
b->XTo=x;
b->YTo=y;
b->From.Width=COLOR_WIDTH;
b->From.Height=COLOR_HEIGHT;
b->ToImage=image;
}
long NewKeys[8];
void KeyOptions(void)
{
GXBLITLIST *b;
GXIMAGE *ScreenImage;
GXMOUSEINFO MouseInfo;
int x,y,j,moving;
GXOBLONG Buttons[10];
int selection,editing,jj;
long xx,tt,delay;
long key,frame=0;
int number;
int JustPressed;
GXOBLONG area;
WaitNoKeys();
SaveScreen();
ScreenImage=GXStartDrawing(0);
for(j=0; j<8; j++)
NewKeys[j]=KeyPrefs[j];
// Draw backdrop
DrawBackground(ScreenImage, 0);
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=TitleBox;
b->XTo=b->YTo=0;
b->FromImage=GadgetsImage;
b->ToImage=ScreenImage;
// Print title
x=TitleBox.Width/2 + TitleBox.X - TXStringWidth(KeyStrings[8], BlackFont)/2;
y=TitleBox.Height/2 + TitleBox.Y - TXFONTHeight(BlackFont)/2;
TXPrintString(KeyStrings[8], x, y, ScreenImage, BlackFont);
// Set up okay & cancel buttons
Buttons[8]=Buttons[9]=ButtonUp;
Buttons[8].X=(ScreenWidth-ButtonUp.Width*2)/4;
Buttons[9].X=ScreenWidth-Buttons[8].X-ButtonUp.Width;
Buttons[8].Y=Buttons[9].Y=ScreenHeight-20;
DrawButton(ScreenImage, "Okay", Buttons[8].X, ScreenHeight-20);
DrawButton(ScreenImage, "Cancel", Buttons[9].X, ScreenHeight-20);
for(j=0; j<NKeyPrefs; j++){
y=KEYOPTIONS_Y+KEYOPTIONS_DY*j;
TXPrintString(KeyStrings[j],
(ScreenWidth/2)-TXStringWidth(KeyStrings[j], BlackFont)-10,
y, ScreenImage, BlackFont);
if(j){
TXPrintString(KeyName(NewKeys[j]), ScreenWidth/2+10, y, ScreenImage, BlackFont);
}else{
TXPrintString(KeyName(NewKeys[j]), ScreenWidth/2+10, y, ScreenImage, RedFont);
}
Buttons[j].X=10;
Buttons[j].Width=ScreenWidth-20;
Buttons[j].Y=y;
Buttons[j].Height=TXFONTHeight(BlackFont);
}
selection=0;
editing=0;
delay=GXTicksPerSecond()/60;
if(!delay)delay=1;
do{
xx=GXTimer();
do{
tt=GXTimer()-xx;
if(tt<0)break;
}while(tt< delay );
frame++;
GXSystemUpdate();
GXReadMouse(&MouseInfo);
GXDoBlit();
JustPressed=MouseClick();
key=GXNextKey();
while(GXNextKey())
;
if( (number=UpdateButtons(Buttons, 10)) != -1 ){
if(JustPressed){
if(number==8){
for(j=0; j<8; j++)
KeyPrefs[j]=NewKeys[j];
SavePrefs();
break;
}else if(number==9){
break;
}else{
ChangeKeySelection(selection, number, ScreenImage);
selection=number;
editing=0;
}
}
}
if(!editing){
if( GXKeyDown(KeyPrefs[3]) ){
if( (!moving) || (frame==20) ){
moving=1;
jj=(selection+1)&0x07;
ChangeKeySelection(selection, jj, ScreenImage);
selection=jj;
frame=0;
}
}else if( GXKeyDown(KeyPrefs[2]) ){
if( (!moving) || (frame==20) ){
moving=1;
jj=(selection-1)&0x07;
ChangeKeySelection(selection, jj, ScreenImage);
selection=jj;
frame=0;
}
}else{
moving=0;
}
}else{
y=KEYOPTIONS_Y+KEYOPTIONS_DY*selection;
xx=GXTimer();
xx=xx%GXTicksPerSecond();
if( xx < (GXTicksPerSecond()/2) ){
TXPrintString(KeyName(NewKeys[selection]),
ScreenWidth/2+10, y, ScreenImage, RedFont);
}else{
area.X=ScreenWidth/2+10;
area.Y=y;
area.Width=TXStringWidth(KeyName(NewKeys[selection]), RedFont);
area.Height=TXFONTHeight(RedFont);
DrawBackground(ScreenImage, &area);
}
}
if( editing && key && (key!=-1) ){
area.X=ScreenWidth/2+10;
area.Y=y;
area.Width=TXStringWidth(KeyName(NewKeys[selection]), RedFont);
area.Height=TXFONTHeight(RedFont);
DrawBackground(ScreenImage, &area);
NewKeys[selection]=key;
editing=0;
TXPrintString(KeyName(NewKeys[selection]),
ScreenWidth/2+10, y, ScreenImage, RedFont);
}else if( (key==KEY_RETURN) && (selection!=-1) ){
editing=1;
}
}while(1);
RestoreScreen();
}
void DrawButton(GXIMAGE *dest, char *text, long x, long y)
{
GXBLITLIST *b;
b=GXNextBlit();
b->Type=BLIT_IMAGE;
b->From=ButtonUp;
b->XTo=x;
b->YTo=y;
b->FromImage=GadgetsImage;
b->ToImage=dest;
TXPrintString(text,
b->XTo+(b->From.Width-TXStringWidth(text,BlackFont))/2,
b->YTo+(b->From.Height-TXFONTHeight(BlackFont))/2,
dest,
BlackFont);
}
char *KeyName(long RawCode)
{
KEYNAMES *names;
int j;
names=KeyNames;
for(j=0; j<NKeyNames; j++){
if(names->RawCode==RawCode){
return names->Name;
}
names++;
}
return KeyStrings[9]; //string for unknown key
}
void ChangeKeySelection(int selection, int NewSelection, GXIMAGE *ScreenImage)
{
int y;
if(selection!=-1){
y=KEYOPTIONS_Y+KEYOPTIONS_DY*selection;
TXPrintString(KeyName(NewKeys[selection]),
ScreenWidth/2+10, y, ScreenImage, BlackFont);
}
y=KEYOPTIONS_Y+KEYOPTIONS_DY*NewSelection;
TXPrintString(KeyName(NewKeys[NewSelection]),
ScreenWidth/2+10, y, ScreenImage, RedFont);
}
void KillStringGadget(STRINGGADGET *sg)
{
if(sg){
if(sg->String)GXFreeMem(sg->String);
GXFreeMem(sg);
}
}
int CursorIsOn=0;
STRINGGADGET *MakeStringGadget(char *StartString, GXOBLONG *Area, GXIMAGE *ToImage)
{
STRINGGADGET *sg;
CursorIsOn=0;
sg=(STRINGGADGET *)GXGetMem(sizeof(STRINGGADGET), MEMF_ZERO|MEMF_ABORT);
sg->String=(char *)GXGetMem(256*sizeof(char), MEMF_ZERO|MEMF_ABORT);
sg->Area=*Area;
ChangeStringGadget(StartString, sg, ToImage);
return sg;
}
void ChangeStringGadget(char *str, STRINGGADGET *sg, GXIMAGE *ToImage)
{
sg->CursorPosition=strlen(str);
strcpy(sg->String, str);
PrintStringGadget(sg, ToImage, 0);
}
char *GetStringGadget(STRINGGADGET *sg)
{
return sg->String;
}
void PrintStringGadget(STRINGGADGET *sg, GXIMAGE *ToImage, int cursoron)
{
char *from,*to;
int j,x,y,width,width1,width2;
GXBLITLIST *b;
static char string1[64],string2[64];
CursorIsOn=cursoron;
from=sg->String;
to=string1;
for(j=sg->CursorPosition; j; j--){
*to++=*from++;
}
*to++=0;
strcpy(string2, from);
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->Color=WhiteIndex;
b->From=sg->Area;
b->XTo=sg->Area.X;
b->YTo=sg->Area.Y;
b->ToImage=ToImage;
width1=TXStringWidth(string1, BlackFont);
width2=TXStringWidth(string2, BlackFont);
width=width1+width2+BlackFont->Width;
x=(sg->Area.Width/2) - (width/2) + sg->Area.X;
y=(sg->Area.Height/2) - TXFONTHeight(BlackFont)/2 + sg->Area.Y;
TXPrintString(string1, x, y, ToImage, BlackFont);
x+=width1;
if(cursoron){
b=GXNextBlit();
b->Type=BLIT_COLORFILL;
b->Color=OrangeIndex;
b->From.Width=BlackFont->Width;
b->From.Height=BlackFont->Height;
b->XTo=x;
b->YTo=y;
b->ToImage=ToImage;
}
x+=BlackFont->Width;
TXPrintString(string2, x, y, ToImage, BlackFont);
}
void UpdateStringGadget(STRINGGADGET *sg, int AsciiKey, GXIMAGE *ToImage,
int active)
{
int StringLength,nloop;
char *from,*to;
int DrawCursor;
DrawCursor=(GXTimer()%GXTicksPerSecond());
DrawCursor=DrawCursor<(GXTicksPerSecond()/2);
if(!active){
if(!CursorIsOn){
PrintStringGadget(sg, ToImage, 1);
}
return;
}
StringLength=strlen(sg->String);
if(AsciiKey==0x1c){
//cursor right
sg->CursorPosition++;
if( sg->CursorPosition > StringLength ){
sg->CursorPosition=StringLength;
}
}else if(AsciiKey==0x1d){
//cursor left
if(sg->CursorPosition){
sg->CursorPosition--;
}
}else if(AsciiKey==0x7f){
//delete
if(sg->CursorPosition<StringLength){
to=sg->String + sg->CursorPosition;
from=to+1;
while(*from){
*to++=*from++;
}
*to=0;
}
}else if(AsciiKey==0x01){
//BackSpace
if(sg->CursorPosition){
from=sg->String + sg->CursorPosition;
to=from-1;
while(*from){
*to++=*from++;
}
*to=0;
sg->CursorPosition--;
}
}else if( ((AsciiKey>='a')&&(AsciiKey<='z'))||
((AsciiKey>='0')&&(AsciiKey<='9'))||
(AsciiKey=='.')||
(AsciiKey==' ') ){
if(StringLength>=16){
return;
}
from=sg->String+StringLength;
to=from+1;
nloop=StringLength-sg->CursorPosition+1;
while(nloop){
*to--=*from--;
nloop--;
}
*to=AsciiKey;
sg->CursorPosition++;
}else{
if(DrawCursor!=CursorIsOn){
PrintStringGadget(sg, ToImage, DrawCursor);
return;
}
}
PrintStringGadget(sg, ToImage, DrawCursor);
}
int RawToAscii(int RawKey)
{
struct{
UBYTE AsciiKey;
UBYTE RawKey;
}KeyInfo[]={
{'a',KEY_A},
{'b',KEY_B},
{'c',KEY_C},
{'d',KEY_D},
{'e',KEY_E},
{'f',KEY_F},
{'g',KEY_G},
{'h',KEY_H},
{'i',KEY_I},
{'j',KEY_J},
{'k',KEY_K},
{'l',KEY_L},
{'m',KEY_M},
{'n',KEY_N},
{'o',KEY_O},
{'p',KEY_P},
{'q',KEY_Q},
{'r',KEY_R},
{'s',KEY_S},
{'t',KEY_T},
{'u',KEY_U},
{'v',KEY_V},
{'w',KEY_W},
{'x',KEY_X},
{'y',KEY_Y},
{'z',KEY_Z},
{'0',KEY_0},
{'1',KEY_1},
{'2',KEY_2},
{'3',KEY_3},
{'4',KEY_4},
{'5',KEY_5},
{'6',KEY_6},
{'7',KEY_7},
{'8',KEY_8},
{'9',KEY_9},
{'0',KEY_NUMPAD0},
{'1',KEY_NUMPAD1},
{'2',KEY_NUMPAD2},
{'3',KEY_NUMPAD3},
{'4',KEY_NUMPAD4},
{'5',KEY_NUMPAD5},
{'6',KEY_NUMPAD6},
{'7',KEY_NUMPAD7},
{'8',KEY_NUMPAD8},
{'9',KEY_NUMPAD9},
{'.',KEY_FULLSTOP},
{' ',KEY_SPACE},
{' ',KEY_TAB},
{',',KEY_COMMA},
{0x1c,KEY_CURSORRIGHT},
{0x1d,KEY_CURSORLEFT},
{0x1e,KEY_CURSORUP},
{0x1f,KEY_CURSORDOWN},
{0x7f,KEY_DELETE},
{0x01,KEY_BACKSPACE},
};
static UBYTE *ConversionTable=0;
int j;
if(!ConversionTable){
ConversionTable=(UBYTE *)GXGetMem(256*sizeof(UBYTE), MEMF_ZERO|MEMF_ABORT);
for(j=0; j<ELEMENTS(KeyInfo); j++){
ConversionTable[ KeyInfo[j].RawKey]=KeyInfo[j].AsciiKey;
}
}
return ConversionTable[RawKey];
}