Version 2.2

Solved issues # 20, 21,23, 25, 29.

Added the possibility to show a smaller screen (so also the borders are shown), the preferences are saved manually and not automatically on exit, when a gameshot is saved also some preferences (key bindings, game name, 1541 emulation, screen dimension) related to the game are saved.
This commit is contained in:
fabio.olimpieri 2011-06-02 20:50:48 +00:00
parent 17d70cc3ef
commit 8085fee39c
17 changed files with 3617 additions and 3457 deletions

View File

@ -1,161 +1,163 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := frodo
BUILD := build
SOURCES := Src
DATA :=
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PCFLAGS = -DPRECISE_CPU_CYCLES=1 -DPRECISE_CIA_CYCLES=1 -DPC_IS_POINTER=0
SCFLAGS = $(PCFLAGS) -DFRODO_SC
CFLAGS = -O3 -g -Wall $(MACHDEP) $(INCLUDE) -U__unix -DHAVE_SDL $(SCFLAGS) -I$(LIBOGC_INC)/SDL -I$(PWD)/Src/
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lSDL_ttf -lSDL_image -lpng -ljpeg -lz -lSDL -lfreetype -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := gcaudio.c d64-read.c gui/menu_messages.c
CPPFILES := Display.cpp main.cpp Prefs.cpp SID.cpp REU.cpp IEC.cpp 1541fs.cpp \
1541d64.cpp 1541t64.cpp 1541job.cpp C64_SC.cpp CPUC64_SC.cpp VIC_SC.cpp \
CIA_SC.cpp CPU1541_SC.cpp CPU_common.cpp \
Network.cpp gui/dialogue_box.cpp gui/widget.cpp utils.cpp \
gui/game_info.cpp gui/status_bar.cpp gui/gui.cpp gui/listener.cpp \
timer.cpp utils.cpp gui/virtual_keyboard.cpp gui/menu.cpp \
gui/file_browser.cpp data_store.cpp gui/network_server_messages.cpp
sFILES :=
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB) -L/opt/devkitpro/libogc/lib
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@ $@/gui
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol Src/*.o \
FrodoSC FrodoPC dist
dist: $(BUILD)
rm -rf $@
install -d $@/apps/frodo
install -d $@/frodo/images
install -d $@/frodo/saves
install -d $@/frodo/metadata
install -d $@/frodo/tmp
echo "a" > $@/frodo/tmp/dummy
touch $@/apps/frodo/frodorc
cp $(TARGET).dol $@/apps/frodo/boot.dol
cp -rap themes $@/frodo/themes
cp meta.xml $@/apps/frodo/
cp icon.png $@/apps/frodo/
find $@ -name ".svn" | xargs rm -rf
cd $@ && tar -czf ../c64-network.org-wii-bin.tar.gz *
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o : %.jpg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := frodo
BUILD := build
SOURCES := Src
DATA :=
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PCFLAGS = -DPRECISE_CPU_CYCLES=1 -DPRECISE_CIA_CYCLES=1 -DPC_IS_POINTER=0 -DWII_PORT
SCFLAGS = $(PCFLAGS) -DFRODO_SC
CFLAGS = -O3 -g -Wall $(MACHDEP) $(INCLUDE) -DHAVE_SDL $(SCFLAGS) -I$(LIBOGC_INC)/SDL
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lSDL_ttf -lSDL_image -lpng -ljpeg -lz -lSDL -lfreetype -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := gcaudio.c d64-read.c gui/menu_messages.c
CPPFILES := Display.cpp main.cpp Prefs.cpp SID.cpp REU.cpp IEC.cpp 1541fs.cpp \
1541d64.cpp 1541t64.cpp 1541job.cpp C64_SC.cpp CPUC64_SC.cpp VIC_SC.cpp \
CIA_SC.cpp CPU1541_SC.cpp CPU_common.cpp \
Network.cpp gui/dialogue_box.cpp gui/widget.cpp utils.cpp \
gui/game_info.cpp gui/status_bar.cpp gui/gui.cpp gui/listener.cpp \
timer.cpp utils.cpp gui/virtual_keyboard.cpp gui/menu.cpp \
gui/file_browser.cpp data_store.cpp gui/network_server_messages.cpp
sFILES :=
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC) \
-I$(CURDIR)/Src \
-I$(PORTLIBS)/include
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB) -L/opt/devkitpro/libogc/lib
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@ $@/gui
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol Src/*.o \
FrodoSC FrodoPC dist
dist: $(BUILD)
rm -rf $@
install -d $@/apps/frodo
install -d $@/frodo/images
install -d $@/frodo/saves
install -d $@/frodo/metadata
install -d $@/frodo/tmp
echo "a" > $@/frodo/tmp/dummy
touch $@/apps/frodo/frodorc
cp $(TARGET).dol $@/apps/frodo/boot.dol
cp -rap themes $@/frodo/themes
cp meta.xml $@/apps/frodo/
cp icon.png $@/apps/frodo/
find $@ -name ".svn" | xargs rm -rf
cd $@ && tar -czf ../c64-network.org-wii-bin.tar.gz *
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o : %.jpg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -303,8 +303,8 @@ void C64::VBlank(bool draw_frame)
Gui::gui->runLogic();
if (this->quit_thyself)
ThePrefs.Save(ThePrefs.PrefsPath);
//if (this->quit_thyself)
// ThePrefs.Save(ThePrefs.PrefsPath);
#if defined(GEKKO)
if (this->quit_thyself && Network::networking_started == true)
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +1,190 @@
/*
* Prefs.h - Global preferences
*
* Frodo (C) 1994-1997,2002-2005 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _PREFS_H
#define _PREFS_H
#define SPEED_95 30
#define SPEED_100 25
#define SPEED_110 18
#define MAX_JOYSTICK_AXES 16
#define MAX_JOYSTICK_BUTTONS 32
#define MAX_JOYSTICK_HATS 8
// SID types
enum {
SIDTYPE_NONE, // SID emulation off
SIDTYPE_DIGITAL, // Digital SID emulation
SIDTYPE_SIDCARD // SID card
};
// REU sizes
enum {
REU_NONE, // No REU
REU_128K, // 128K
REU_256K, // 256K
REU_512K // 512K
};
// Display types
enum {
DISPTYPE_WINDOW, // Window
DISPTYPE_SCREEN // Fullscreen
};
enum {
/* ASCII values before these */
JOY_NONE = 0,
JOY_HORIZ = 256,
JOY_VERT = 258,
JOY_FIRE = 259,
};
enum {
HAT_PLAIN = 0,
HAT_ROTATED_90 = 1,
HAT_ROTATED_180 = 2,
HAT_ROTATED_270 = 2,
};
// Key bindings (WII)
enum {
WIIMOTE_UP,
WIIMOTE_DOWN,
WIIMOTE_LEFT,
WIIMOTE_RIGHT,
WIIMOTE_2,
WIIMOTE_1,
WIIMOTE_A,
WIIMOTE_B,
WIIMOTE_PLUS,
WIIMOTE_MINUS,
CLASSIC_UP,
CLASSIC_DOWN,
CLASSIC_LEFT,
CLASSIC_RIGHT,
CLASSIC_A,
CLASSIC_B,
CLASSIC_X,
CLASSIC_Y,
CLASSIC_L,
CLASSIC_R,
CLASSIC_ZR,
CLASSIC_ZL,
N_WIIMOTE_BINDINGS
};
// Preferences data
class Prefs {
public:
Prefs();
bool ShowEditor(bool startup, char *prefs_name);
void Check(void);
void Load(const char *filename);
bool Save(const char *filename);
bool operator==(const Prefs &rhs) const;
bool operator!=(const Prefs &rhs) const;
void SetupJoystickDefaults();
char BasePath[256]; // Where theme data etc are found
char PrefsPath[256]; // Where the prefs will be stored
int NormalCycles; // Available CPU cycles in normal raster lines
int BadLineCycles; // Available CPU cycles in Bad Lines
int CIACycles; // CIA timer ticks per raster line
int FloppyCycles; // Available 1541 CPU cycles per line
int SkipFrames; // Draw every n-th frame
char DrivePath[4][256]; // Path for drive 8..11
char ViewPort[256]; // Size of the C64 screen to display (Win32)
char DisplayMode[256]; // Video mode to use for full screen (Win32)
int SIDType; // SID emulation type
int REUSize; // Size of REU
int DisplayType; // Display type (BeOS)
int Joystick1Port; // Port that joystick 1 is connected to (0 = no joystick, all other values are system dependant)
int Joystick2Port; // Port that joystick 2 is connected to
int LatencyMin; // Min msecs ahead of sound buffer (Win32)
int LatencyMax; // Max msecs ahead of sound buffer (Win32)
int LatencyAvg; // Averaging interval in msecs (Win32)
int ScalingNumerator; // Window scaling numerator (Win32)
int ScalingDenominator; // Window scaling denominator (Win32)
bool SpritesOn; // Sprite display is on
bool SpriteCollisions; // Sprite collision detection is on
bool JoystickSwap; // Swap joysticks 1<->2
bool LimitSpeed; // Limit speed to 100%
bool FastReset; // Skip RAM test on reset
bool CIAIRQHack; // Write to CIA ICR clears IRQ
bool MapSlash; // Map '/' in C64 filenames
bool Emul1541Proc; // Enable processor-level 1541 emulation
bool SIDFilters; // Emulate SID filters
bool DoubleScan; // Double scan lines (BeOS, if DisplayType == DISPTYPE_SCREEN)
bool JoystickGeekPort; // Enable GeekPort joystick adapter
bool HideCursor; // Hide mouse cursor when visible (Win32)
bool DirectSound; // Use direct sound (instead of wav) (Win32)
bool ExclusiveSound; // Use exclusive mode with direct sound (Win32)
bool AutoPause; // Auto pause when not foreground app (Win32)
bool PrefsAtStartup; // Show prefs dialog at startup (Win32)
bool SystemMemory; // Put view work surface in system mem (Win32)
bool AlwaysCopy; // Always use a work surface (Win32)
bool SystemKeys; // Enable system keys and menu keys (Win32)
bool ShowLEDs; // Show LEDs (Win32)
uint32 MsPerFrame;
int JoystickAxes[MAX_JOYSTICK_AXES];
int JoystickHats[MAX_JOYSTICK_HATS];
int JoystickButtons[MAX_JOYSTICK_BUTTONS];
int MenuJoystickHats[MAX_JOYSTICK_HATS];
int MenuJoystickButtons[MAX_JOYSTICK_BUTTONS];
char NetworkName[32];
char NetworkServer[64];
int NetworkRegion;
int NetworkPort;
int NetworkKey;
uint16 NetworkAvatar;
char Theme[128];
bool CursorKeysForJoystick;
};
// These are the active preferences
extern Prefs ThePrefs;
// Theses are the preferences on disk
extern Prefs ThePrefsOnDisk;
// Theses are the default preferences
extern Prefs TheDefaultPrefs;
#endif
/*
* Prefs.h - Global preferences
*
* Frodo (C) 1994-1997,2002-2005 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _PREFS_H
#define _PREFS_H
#define SPEED_95 30
#define SPEED_100 25
#define SPEED_110 18
#define MAX_JOYSTICK_AXES 16
#define MAX_JOYSTICK_BUTTONS 32
#define MAX_JOYSTICK_HATS 8
// SID types
enum {
SIDTYPE_NONE, // SID emulation off
SIDTYPE_DIGITAL, // Digital SID emulation
SIDTYPE_SIDCARD // SID card
};
// REU sizes
enum {
REU_NONE, // No REU
REU_128K, // 128K
REU_256K, // 256K
REU_512K // 512K
};
// Display types
enum {
DISPTYPE_WINDOW, // Window
DISPTYPE_SCREEN // Fullscreen
};
enum {
/* ASCII values before these */
JOY_NONE = 0,
JOY_HORIZ = 256,
JOY_VERT = 258,
JOY_FIRE = 259,
};
enum {
HAT_PLAIN = 0,
HAT_ROTATED_90 = 1,
HAT_ROTATED_180 = 2,
HAT_ROTATED_270 = 2,
};
// Key bindings (WII)
enum {
WIIMOTE_UP,
WIIMOTE_DOWN,
WIIMOTE_LEFT,
WIIMOTE_RIGHT,
WIIMOTE_2,
WIIMOTE_1,
WIIMOTE_A,
WIIMOTE_B,
WIIMOTE_PLUS,
WIIMOTE_MINUS,
CLASSIC_UP,
CLASSIC_DOWN,
CLASSIC_LEFT,
CLASSIC_RIGHT,
CLASSIC_A,
CLASSIC_B,
CLASSIC_X,
CLASSIC_Y,
CLASSIC_L,
CLASSIC_R,
CLASSIC_ZR,
CLASSIC_ZL,
N_WIIMOTE_BINDINGS
};
// Preferences data
class Prefs {
public:
Prefs();
bool ShowEditor(bool startup, char *prefs_name);
void Check(void);
void Load(const char *filename);
bool Save(const char *filename);
bool Save_game(const char *filename);
bool operator==(const Prefs &rhs) const;
bool operator!=(const Prefs &rhs) const;
void SetupJoystickDefaults();
char BasePath[256]; // Where theme data etc are found
char PrefsPath[256]; // Where the prefs will be stored
int NormalCycles; // Available CPU cycles in normal raster lines
int BadLineCycles; // Available CPU cycles in Bad Lines
int CIACycles; // CIA timer ticks per raster line
int FloppyCycles; // Available 1541 CPU cycles per line
int SkipFrames; // Draw every n-th frame
char DrivePath[4][256]; // Path for drive 8..11
char ViewPort[256]; // Size of the C64 screen to display (Win32)
char DisplayMode[256]; // Video mode to use for full screen (Win32)
int SIDType; // SID emulation type
int REUSize; // Size of REU
int DisplayType; // Display type (BeOS)
int Joystick1Port; // Port that joystick 1 is connected to (0 = no joystick, all other values are system dependant)
int Joystick2Port; // Port that joystick 2 is connected to
int LatencyMin; // Min msecs ahead of sound buffer (Win32)
int LatencyMax; // Max msecs ahead of sound buffer (Win32)
int LatencyAvg; // Averaging interval in msecs (Win32)
int ScalingNumerator; // Window scaling numerator (Win32)
int ScalingDenominator; // Window scaling denominator (Win32)
bool SpritesOn; // Sprite display is on
bool SpriteCollisions; // Sprite collision detection is on
bool JoystickSwap; // Swap joysticks 1<->2
bool LimitSpeed; // Limit speed to 100%
bool FastReset; // Skip RAM test on reset
bool CIAIRQHack; // Write to CIA ICR clears IRQ
bool MapSlash; // Map '/' in C64 filenames
bool Emul1541Proc; // Enable processor-level 1541 emulation
bool SIDFilters; // Emulate SID filters
bool DoubleScan; // Double scan lines (BeOS, if DisplayType == DISPTYPE_SCREEN)
bool JoystickGeekPort; // Enable GeekPort joystick adapter
bool HideCursor; // Hide mouse cursor when visible (Win32)
bool DirectSound; // Use direct sound (instead of wav) (Win32)
bool ExclusiveSound; // Use exclusive mode with direct sound (Win32)
bool AutoPause; // Auto pause when not foreground app (Win32)
bool PrefsAtStartup; // Show prefs dialog at startup (Win32)
bool SystemMemory; // Put view work surface in system mem (Win32)
bool AlwaysCopy; // Always use a work surface (Win32)
bool SystemKeys; // Enable system keys and menu keys (Win32)
bool ShowLEDs; // Show LEDs (Win32)
uint32 MsPerFrame;
int JoystickAxes[MAX_JOYSTICK_AXES];
int JoystickHats[MAX_JOYSTICK_HATS];
int JoystickButtons[MAX_JOYSTICK_BUTTONS];
int MenuJoystickHats[MAX_JOYSTICK_HATS];
int MenuJoystickButtons[MAX_JOYSTICK_BUTTONS];
char NetworkName[32];
char NetworkServer[64];
int NetworkRegion;
int NetworkPort;
int NetworkKey;
uint16 NetworkAvatar;
char Theme[128];
bool CursorKeysForJoystick;
};
// These are the active preferences
extern Prefs ThePrefs;
// Theses are the preferences on disk
extern Prefs ThePrefsOnDisk;
// Theses are the default preferences
extern Prefs TheDefaultPrefs;
#endif

View File

@ -1,429 +1,429 @@
#include "gui.hh"
#include "menu.hh"
#include "help_box.hh"
#include "dialogue_box.hh"
#include "virtual_keyboard.hh"
class BindKeysMenu;
class AnalogueBindListener : public DialogueListener
{
public:
AnalogueBindListener(BindKeysMenu *menu)
{
this->menu = menu;
}
void escapeCallback(DialogueBox *which, int selected)
{
delete this;
}
void selectCallback(DialogueBox *which, int selected);
private:
BindKeysMenu *menu;
};
class BindKeysView;
class BindKeysMenu : public Menu, public KeyboardListener
{
/* This is a very popular class with many friends */
friend class BindKeysView;
friend class AnalogueBindListener;
public:
BindKeysMenu(Font *font, HelpBox *help) : Menu(font)
{
this->help = help;
memset(this->hm, 0, sizeof(this->hm));
this->setText(bind_key_menu_messages);
}
~BindKeysMenu()
{
this->freeHelpMessages();
}
virtual void selectCallback(int which)
{
int *ck = NULL;
/* Either the virtual keyboard or the analogue menu */
bool use_virtkbd = true;
switch(which)
{
case 0: /* Wiimote */
switch (this->p_submenus[0].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[0]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[1]; break;
case 2: ck = &Gui::gui->np->JoystickButtons[2]; break;
case 3: ck = &Gui::gui->np->JoystickButtons[3]; break;
case 4: ck = &Gui::gui->np->JoystickButtons[5]; break;
case 5: ck = &Gui::gui->np->JoystickButtons[4]; break;
default:
panic("Wiimote: impossible selection %d", this->p_submenus[0].sel); break;
}
break;
case 2: /* Nunchuk */
switch (this->p_submenus[1].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[7]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[8]; break;
default:
panic("Nunchuk: impossible selection %d", this->p_submenus[1].sel); break;
}
break;
case 4: /* Classic */
switch (this->p_submenus[2].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[9]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[10]; break;
case 2: ck = &Gui::gui->np->JoystickButtons[11]; break;
case 3: ck = &Gui::gui->np->JoystickButtons[12]; break;
case 4: ck = &Gui::gui->np->JoystickButtons[13]; break;
case 5: ck = &Gui::gui->np->JoystickButtons[14]; break;
case 6: ck = &Gui::gui->np->JoystickButtons[15]; break;
case 7: ck = &Gui::gui->np->JoystickButtons[16]; break;
case 8: ck = &Gui::gui->np->JoystickButtons[18]; break;
case 9: ck = &Gui::gui->np->JoystickButtons[17]; break;
default:
panic("Classic: impossible selection %d", this->p_submenus[2].sel); break;
}
break;
case 7:
Gui::gui->np->SetupJoystickDefaults();
this->updateHelpMessages();
return;
default:
panic("Impossible menu option\n");
break;
}
this->cur_key = ck;
if (use_virtkbd)
{
VirtualKeyboard::kbd->activate(false);
VirtualKeyboard::kbd->registerListener(this);
}
else
{
AnalogueBindListener *bl = new AnalogueBindListener(this);
DialogueBox *dlg = new DialogueBox(select_analogue_dlg);
dlg->registerListener(bl);
Gui::gui->pushDialogueBox(dlg);
}
}
virtual void hoverCallback(int which)
{
this->help->updateHelpMessage(which);
}
virtual void escapeCallback(int which)
{
Gui::gui->popView();
}
virtual void keyCallback(bool shift, const char *str)
{
panic_if(!this->cur_key, "No key selected but keyboard active???\n");
*this->cur_key = this->stringToKeycode(str);
this->updateHelpMessages();
this->help->updateHelpMessage(this->cur_sel);
VirtualKeyboard::kbd->deactivate();
this->cur_key = NULL;
}
void updateHelpMessages()
{
this->freeHelpMessages();
this->hm[0] = this->addOne(this->hm[0], this->allocOne("1: %s", stringToPtr_Wiimote("1")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("2: %s", stringToPtr_Wiimote("2")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("A: %s", stringToPtr_Wiimote("A")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("B: %s", stringToPtr_Wiimote("B")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("+: %s", stringToPtr_Wiimote("+")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("-: %s", stringToPtr_Wiimote("-")));
/* Nunchuk */
this->hm[2] = this->addOne(this->hm[2], this->allocOne("Z: %s", stringToPtr_Nunchuk("Z")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("C: %s", stringToPtr_Nunchuk("C")));
/* Classic */
this->hm[4] = this->addOne(this->hm[4], this->allocOne("a: %s", stringToPtr_Classic("a")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("b: %s", stringToPtr_Classic("b")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("x: %s", stringToPtr_Classic("x")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("y: %s", stringToPtr_Classic("y")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("L: %s", stringToPtr_Classic("L")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("R: %s", stringToPtr_Classic("R")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zl: %s", stringToPtr_Classic("Zl")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zr: %s", stringToPtr_Classic("Zr")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("+: %s", stringToPtr_Classic("+")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("-: %s", stringToPtr_Classic("-")));
/*
this->hm[2] = this->addOne(this->hm[2], this->allocOne("l: %s", stringToPtr_Classic("l")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("r: %s", stringToPtr_Classic("r")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("R-toggle: %s", stringToPtr_Classic("RA")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("L-toggle: %s", stringToPtr_Classic("LA")));
*/
this->hm[7] = this->addOne(this->hm[11], xstrdup("Revert to defaults"));
this->help->setHelpMessages(this->hm);
}
private:
void freeHelpMessages()
{
for (unsigned i = 0; i < ARRAY_SIZE(this->hm); i++)
{
if (this->hm[i])
{
for (int j = 0; this->hm[i][j]; j++)
free((void*)this->hm[i][j]);
free(this->hm[i]);
}
this->hm[i] = NULL;
}
}
#define EQ(b) (strcmp(str, b) == 0)
int *stringToPtr_Classic(const char *str)
{
if (EQ("Up"))
return &Gui::gui->np->JoystickHats[0];
if (EQ("Down"))
return &Gui::gui->np->JoystickHats[1];
if (EQ("Left"))
return &Gui::gui->np->JoystickHats[2];
if (EQ("Right"))
return &Gui::gui->np->JoystickHats[3];
if (EQ("LAH"))
return &Gui::gui->np->JoystickAxes[0];
if (EQ("LAV"))
return &Gui::gui->np->JoystickAxes[1];
if (EQ("RAH"))
return &Gui::gui->np->JoystickAxes[2];
if (EQ("RAV"))
return &Gui::gui->np->JoystickAxes[3];
if (EQ("RA"))
return &Gui::gui->np->JoystickAxes[4];
if (EQ("LA"))
return &Gui::gui->np->JoystickAxes[5];
if (EQ("a"))
return &Gui::gui->np->JoystickButtons[9];
if (EQ("b"))
return &Gui::gui->np->JoystickButtons[10];
if (EQ("x"))
return &Gui::gui->np->JoystickButtons[11];
if (EQ("y"))
return &Gui::gui->np->JoystickButtons[12];
if (EQ("L"))
return &Gui::gui->np->JoystickButtons[13];
if (EQ("R"))
return &Gui::gui->np->JoystickButtons[14];
if (EQ("Zl"))
return &Gui::gui->np->JoystickButtons[15];
if (EQ("Zr"))
return &Gui::gui->np->JoystickButtons[16];
if (EQ("-"))
return &Gui::gui->np->JoystickButtons[17];
if (EQ("+"))
return &Gui::gui->np->JoystickButtons[18];
if (EQ("Home"))
return &Gui::gui->np->JoystickButtons[19];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
int *stringToPtr_Nunchuk(const char *str)
{
if (EQ("Horiz"))
return &Gui::gui->np->JoystickAxes[0];
if (EQ("Vert"))
return &Gui::gui->np->JoystickAxes[1];
if (EQ("Z"))
return &Gui::gui->np->JoystickButtons[7];
if (EQ("C"))
return &Gui::gui->np->JoystickButtons[8];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
int *stringToPtr_Wiimote(const char *str)
{
if (EQ("Up"))
return &Gui::gui->np->JoystickHats[0];
if (EQ("Down"))
return &Gui::gui->np->JoystickHats[1];
if (EQ("Left"))
return &Gui::gui->np->JoystickHats[2];
if (EQ("Right"))
return &Gui::gui->np->JoystickHats[3];
if (EQ("A"))
return &Gui::gui->np->JoystickButtons[0];
if (EQ("B"))
return &Gui::gui->np->JoystickButtons[1];
if (EQ("1"))
return &Gui::gui->np->JoystickButtons[2];
if (EQ("2"))
return &Gui::gui->np->JoystickButtons[3];
if (EQ("-"))
return &Gui::gui->np->JoystickButtons[4];
if (EQ("+"))
return &Gui::gui->np->JoystickButtons[5];
if (EQ("Home"))
return &Gui::gui->np->JoystickButtons[6];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
#undef EQ
const char **addOne(const char **dst, const char *what)
{
int cur;
int n = 0;
if (dst != NULL)
{
for (n = 0; dst[n]; n++)
;
}
cur = n;
n++;
dst = (const char **)xrealloc(dst, (n+1) * sizeof(const char*));
dst[cur] = what;
dst[n] = NULL;
return dst;
}
const char *allocOne(const char *fmt, int *what)
{
const char *str = this->bindingToString(*what);
size_t len = strlen(str) + strlen(fmt) + 2;
char *out = (char *)xmalloc(len);
sprintf(out, fmt, str);
return out;
}
int stringToKeycode(const char *str)
{
if (strcmp(str, "None") == 0)
return 0;
/* default: */
return VirtualKeyboard::kbd->stringToKeycode(str);
}
const char *bindingToString(int val)
{
switch(val)
{
case JOY_NONE:
return "None";
case JOY_HORIZ:
return "Horizontal";
case JOY_VERT:
return "Vertical";
case JOY_FIRE:
return "Fire";
default:
break;
}
/* default: */
return VirtualKeyboard::kbd->keycodeToString(val);
}
HelpBox *help;
int *cur_key;
const char **hm[14];
};
void AnalogueBindListener::selectCallback(DialogueBox *which, int selected)
{
switch(selected)
{
case 1:
*menu->cur_key = JOY_HORIZ; break;
case 2:
*menu->cur_key = JOY_VERT; break;
case 0:
default:
*menu->cur_key = JOY_NONE; break;
}
this->menu->updateHelpMessages();
this->menu->help->updateHelpMessage(this->menu->cur_sel);
delete this;
}
class BindKeysView : public GuiView
{
public:
BindKeysView() : GuiView()
{
this->help = new HelpBox(Gui::gui->small_font, NULL);
this->menu = new BindKeysMenu(Gui::gui->small_font, this->help);
}
~BindKeysView()
{
delete this->help;
delete this->menu;
}
void viewPushCallback()
{
this->menu->updateHelpMessages();
this->help->updateHelpMessage(0);
}
void runLogic()
{
this->menu->runLogic();
}
void pushEvent(event_t ev)
{
this->menu->pushEvent(ev);
}
void draw(SDL_Surface *where)
{
SDL_Rect dst;
/* Blit the backgrounds */
dst = (SDL_Rect){20,45,300,400};
SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst);
dst = (SDL_Rect){350,13,0,0};
SDL_BlitSurface(Gui::gui->bind_key_box, NULL, where, &dst);
this->menu->draw(where, 50, 70, 300, 400);
this->help->draw(where, 358, 28, 264, 210);
}
protected:
BindKeysMenu *menu;
HelpBox *help;
};
#include "gui.hh"
#include "menu.hh"
#include "help_box.hh"
#include "dialogue_box.hh"
#include "virtual_keyboard.hh"
class BindKeysMenu;
class AnalogueBindListener : public DialogueListener
{
public:
AnalogueBindListener(BindKeysMenu *menu)
{
this->menu = menu;
}
void escapeCallback(DialogueBox *which, int selected)
{
delete this;
}
void selectCallback(DialogueBox *which, int selected);
private:
BindKeysMenu *menu;
};
class BindKeysView;
class BindKeysMenu : public Menu, public KeyboardListener
{
/* This is a very popular class with many friends */
friend class BindKeysView;
friend class AnalogueBindListener;
public:
BindKeysMenu(Font *font, HelpBox *help) : Menu(font)
{
this->help = help;
memset(this->hm, 0, sizeof(this->hm));
this->setText(bind_key_menu_messages);
}
~BindKeysMenu()
{
this->freeHelpMessages();
}
virtual void selectCallback(int which)
{
int *ck = NULL;
/* Either the virtual keyboard or the analogue menu */
bool use_virtkbd = true;
switch(which)
{
case 0: /* Wiimote */
switch (this->p_submenus[0].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[0]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[1]; break;
case 2: ck = &Gui::gui->np->JoystickButtons[2]; break;
case 3: ck = &Gui::gui->np->JoystickButtons[3]; break;
case 4: ck = &Gui::gui->np->JoystickButtons[5]; break;
case 5: ck = &Gui::gui->np->JoystickButtons[4]; break;
default:
panic("Wiimote: impossible selection %d", this->p_submenus[0].sel); break;
}
break;
case 2: /* Nunchuk */
switch (this->p_submenus[1].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[7]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[8]; break;
default:
panic("Nunchuk: impossible selection %d", this->p_submenus[1].sel); break;
}
break;
case 4: /* Classic */
switch (this->p_submenus[2].sel)
{
case 0: ck = &Gui::gui->np->JoystickButtons[9]; break;
case 1: ck = &Gui::gui->np->JoystickButtons[10]; break;
case 2: ck = &Gui::gui->np->JoystickButtons[11]; break;
case 3: ck = &Gui::gui->np->JoystickButtons[12]; break;
case 4: ck = &Gui::gui->np->JoystickButtons[13]; break;
case 5: ck = &Gui::gui->np->JoystickButtons[14]; break;
case 6: ck = &Gui::gui->np->JoystickButtons[15]; break;
case 7: ck = &Gui::gui->np->JoystickButtons[16]; break;
case 8: ck = &Gui::gui->np->JoystickButtons[18]; break;
case 9: ck = &Gui::gui->np->JoystickButtons[17]; break;
default:
panic("Classic: impossible selection %d", this->p_submenus[2].sel); break;
}
break;
case 7:
Gui::gui->np->SetupJoystickDefaults();
this->updateHelpMessages();
return;
default:
panic("Impossible menu option\n");
break;
}
this->cur_key = ck;
if (use_virtkbd)
{
VirtualKeyboard::kbd->activate(false);
VirtualKeyboard::kbd->registerListener(this);
}
else
{
AnalogueBindListener *bl = new AnalogueBindListener(this);
DialogueBox *dlg = new DialogueBox(select_analogue_dlg);
dlg->registerListener(bl);
Gui::gui->pushDialogueBox(dlg);
}
}
virtual void hoverCallback(int which)
{
this->help->updateHelpMessage(which);
}
virtual void escapeCallback(int which)
{
Gui::gui->popView();
}
virtual void keyCallback(bool shift, const char *str)
{
panic_if(!this->cur_key, "No key selected but keyboard active???\n");
*this->cur_key = this->stringToKeycode(str);
this->updateHelpMessages();
this->help->updateHelpMessage(this->cur_sel);
VirtualKeyboard::kbd->deactivate();
this->cur_key = NULL;
}
void updateHelpMessages()
{
this->freeHelpMessages();
this->hm[0] = this->addOne(this->hm[0], this->allocOne("1: %s", stringToPtr_Wiimote("1")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("2: %s", stringToPtr_Wiimote("2")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("A: %s", stringToPtr_Wiimote("A")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("B: %s", stringToPtr_Wiimote("B")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("+: %s", stringToPtr_Wiimote("+")));
this->hm[0] = this->addOne(this->hm[0], this->allocOne("-: %s", stringToPtr_Wiimote("-")));
/* Nunchuk */
this->hm[2] = this->addOne(this->hm[2], this->allocOne("Z: %s", stringToPtr_Nunchuk("Z")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("C: %s", stringToPtr_Nunchuk("C")));
/* Classic */
this->hm[4] = this->addOne(this->hm[4], this->allocOne("a: %s", stringToPtr_Classic("a")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("b: %s", stringToPtr_Classic("b")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("x: %s", stringToPtr_Classic("x")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("y: %s", stringToPtr_Classic("y")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("L: %s", stringToPtr_Classic("L")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("R: %s", stringToPtr_Classic("R")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zl: %s", stringToPtr_Classic("Zl")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zr: %s", stringToPtr_Classic("Zr")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("+: %s", stringToPtr_Classic("+")));
this->hm[4] = this->addOne(this->hm[4], this->allocOne("-: %s", stringToPtr_Classic("-")));
/*
this->hm[2] = this->addOne(this->hm[2], this->allocOne("l: %s", stringToPtr_Classic("l")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("r: %s", stringToPtr_Classic("r")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("R-toggle: %s", stringToPtr_Classic("RA")));
this->hm[2] = this->addOne(this->hm[2], this->allocOne("L-toggle: %s", stringToPtr_Classic("LA")));
*/
this->hm[7] = this->addOne(this->hm[11], xstrdup("Revert to defaults"));
this->help->setHelpMessages(this->hm);
}
private:
void freeHelpMessages()
{
for (unsigned i = 0; i < ARRAY_SIZE(this->hm); i++)
{
if (this->hm[i])
{
for (int j = 0; this->hm[i][j]; j++)
free((void*)this->hm[i][j]);
free(this->hm[i]);
}
this->hm[i] = NULL;
}
}
#define EQ(b) (strcmp(str, b) == 0)
int *stringToPtr_Classic(const char *str)
{
if (EQ("Up"))
return &Gui::gui->np->JoystickHats[0];
if (EQ("Down"))
return &Gui::gui->np->JoystickHats[1];
if (EQ("Left"))
return &Gui::gui->np->JoystickHats[2];
if (EQ("Right"))
return &Gui::gui->np->JoystickHats[3];
if (EQ("LAH"))
return &Gui::gui->np->JoystickAxes[0];
if (EQ("LAV"))
return &Gui::gui->np->JoystickAxes[1];
if (EQ("RAH"))
return &Gui::gui->np->JoystickAxes[2];
if (EQ("RAV"))
return &Gui::gui->np->JoystickAxes[3];
if (EQ("RA"))
return &Gui::gui->np->JoystickAxes[4];
if (EQ("LA"))
return &Gui::gui->np->JoystickAxes[5];
if (EQ("a"))
return &Gui::gui->np->JoystickButtons[9];
if (EQ("b"))
return &Gui::gui->np->JoystickButtons[10];
if (EQ("x"))
return &Gui::gui->np->JoystickButtons[11];
if (EQ("y"))
return &Gui::gui->np->JoystickButtons[12];
if (EQ("L"))
return &Gui::gui->np->JoystickButtons[13];
if (EQ("R"))
return &Gui::gui->np->JoystickButtons[14];
if (EQ("Zl"))
return &Gui::gui->np->JoystickButtons[15];
if (EQ("Zr"))
return &Gui::gui->np->JoystickButtons[16];
if (EQ("-"))
return &Gui::gui->np->JoystickButtons[17];
if (EQ("+"))
return &Gui::gui->np->JoystickButtons[18];
if (EQ("Home"))
return &Gui::gui->np->JoystickButtons[19];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
int *stringToPtr_Nunchuk(const char *str)
{
if (EQ("Horiz"))
return &Gui::gui->np->JoystickAxes[0];
if (EQ("Vert"))
return &Gui::gui->np->JoystickAxes[1];
if (EQ("Z"))
return &Gui::gui->np->JoystickButtons[7];
if (EQ("C"))
return &Gui::gui->np->JoystickButtons[8];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
int *stringToPtr_Wiimote(const char *str)
{
if (EQ("Up"))
return &Gui::gui->np->JoystickHats[0];
if (EQ("Down"))
return &Gui::gui->np->JoystickHats[1];
if (EQ("Left"))
return &Gui::gui->np->JoystickHats[2];
if (EQ("Right"))
return &Gui::gui->np->JoystickHats[3];
if (EQ("A"))
return &Gui::gui->np->JoystickButtons[0];
if (EQ("B"))
return &Gui::gui->np->JoystickButtons[1];
if (EQ("1"))
return &Gui::gui->np->JoystickButtons[2];
if (EQ("2"))
return &Gui::gui->np->JoystickButtons[3];
if (EQ("-"))
return &Gui::gui->np->JoystickButtons[4];
if (EQ("+"))
return &Gui::gui->np->JoystickButtons[5];
if (EQ("Home"))
return &Gui::gui->np->JoystickButtons[6];
/* Shound never happen! */
panic("Illegal string %s\n", str);
return NULL;
}
#undef EQ
const char **addOne(const char **dst, const char *what)
{
int cur;
int n = 0;
if (dst != NULL)
{
for (n = 0; dst[n]; n++)
;
}
cur = n;
n++;
dst = (const char **)xrealloc(dst, (n+1) * sizeof(const char*));
dst[cur] = what;
dst[n] = NULL;
return dst;
}
const char *allocOne(const char *fmt, int *what)
{
const char *str = this->bindingToString(*what);
size_t len = strlen(str) + strlen(fmt) + 2;
char *out = (char *)xmalloc(len);
sprintf(out, fmt, str);
return out;
}
int stringToKeycode(const char *str)
{
if (strcmp(str, "None") == 0)
return 0;
/* default: */
return VirtualKeyboard::kbd->stringToKeycode(str);
}
const char *bindingToString(int val)
{
switch(val)
{
case JOY_NONE:
return "None";
case JOY_HORIZ:
return "Horizontal";
case JOY_VERT:
return "Vertical";
case JOY_FIRE:
return "Fire";
default:
break;
}
/* default: */
return VirtualKeyboard::kbd->keycodeToString(val);
}
HelpBox *help;
int *cur_key;
const char **hm[14];
};
void AnalogueBindListener::selectCallback(DialogueBox *which, int selected)
{
switch(selected)
{
case 1:
*menu->cur_key = JOY_HORIZ; break;
case 2:
*menu->cur_key = JOY_VERT; break;
case 0:
default:
*menu->cur_key = JOY_NONE; break;
}
this->menu->updateHelpMessages();
this->menu->help->updateHelpMessage(this->menu->cur_sel);
delete this;
}
class BindKeysView : public GuiView
{
public:
BindKeysView() : GuiView()
{
this->help = new HelpBox(Gui::gui->small_font, NULL);
this->menu = new BindKeysMenu(Gui::gui->small_font, this->help);
}
~BindKeysView()
{
delete this->help;
delete this->menu;
}
void viewPushCallback()
{
this->menu->updateHelpMessages();
this->help->updateHelpMessage(0);
}
void runLogic()
{
this->menu->runLogic();
}
void pushEvent(event_t ev)
{
this->menu->pushEvent(ev);
}
void draw(SDL_Surface *where)
{
SDL_Rect dst;
/* Blit the backgrounds */
dst = (SDL_Rect){20,45,300,400};
SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst);
dst = (SDL_Rect){350,13,0,0};
SDL_BlitSurface(Gui::gui->bind_key_box, NULL, where, &dst);
this->menu->draw(where, 50, 70, 300, 400);
this->help->draw(where, 358, 28, 264, 230);
}
protected:
BindKeysMenu *menu;
HelpBox *help;
};

View File

@ -72,6 +72,7 @@ class StartGameListener : public TimeoutHandler
public:
StartGameListener()
{
Gui::gui->status_bar->queueMessage("Resetting the C64");
TheC64->Reset();
TimerController::controller->arm(this, 4500);

View File

@ -228,7 +228,8 @@ GameInfo::GameInfo(GameInfo *gi)
this->genre = gi->genre;
if (gi->screenshot)
this->screenshot = SDL_DisplayFormat(gi->screenshot);
// this->screenshot = SDL_DisplayFormat(gi->screenshot);
this->screenshot = sdl_surface_8bit_copy(gi->screenshot);
}
GameInfo::~GameInfo()

View File

@ -355,8 +355,8 @@ void Gui::exitMenu()
prefs_changed = ThePrefs != *this->np;
ThePrefs = *this->np;
if (prefs_changed)
ThePrefs.Save(ThePrefs.PrefsPath);
//if (prefs_changed)
// ThePrefs.Save(ThePrefs.PrefsPath);
this->saveGameInfo(this->metadata_base_path, this->cur_gameInfo->filename);
}

View File

@ -70,7 +70,7 @@ public:
case 0: /* Insert disc */
Gui::gui->dv->setDirectory(Gui::gui->game_base_path);
Gui::gui->pushView(Gui::gui->dv);
Gui::gui->dv->runStartSequence(this->p_submenus[0].sel == 0);
break;
case 2: /* Load/save states */
@ -115,6 +115,11 @@ public:
case 9: /* Options */
Gui::gui->pushView(Gui::gui->ov);
break;
case 10: /* Save Prefs */
ThePrefs = *Gui::gui->np;
ThePrefs.Save(ThePrefs.PrefsPath);
Gui::gui->pushDialogueBox(new DialogueBox(save_prefs_done));
break;
case 11: /* Exit */
DialogueBox *exit_dialogue = new DialogueBox(exit_dialogue_messages);
exit_dialogue->registerListener(new ExitListener());

View File

@ -13,6 +13,17 @@ const char *exit_dialogue_messages[8] = {
NULL
};
const char *save_prefs_done[8] = {
/*00*/ "Preferences saved!",
/*01*/ "#",
/*02*/ "#", /* Empty line */
/*03*/ "#",
/*04*/ "#",
/*05*/ "#",
/*06*/ "^|OK",
NULL
};
const char *save_state_done[8] = {
/*00*/ "Game state saved!",
/*01*/ "#",
@ -138,7 +149,7 @@ const char *main_menu_messages[14] = {
/*07*/ "Game info",
/*08*/ "Networking",
/*09*/ "Options",
/*10*/ " ",
/*10*/ "Save prefs",
/*11*/ "Quit",
NULL
};
@ -182,7 +193,10 @@ const char **main_menu_help[14] = {
"Configure Frodo",
NULL,
},
NULL,
(const char*[]){
"Save general preferences",
NULL,
},
(const char*[]){
"Quit Frodo",
NULL,
@ -244,13 +258,9 @@ const char **options_menu_help[14] = {
NULL,
(const char*[]){
"Select display settings.",
"Fullscreen attemts to run",
"in fullscreen mode, while.",
"windowed uses a window.",
"Activated on next restart.",
" ",
"On the Wii, fullscreen is",
"always used",
"Fullscreen runs in",
"double size mode, while",
"window in streched mode.",
NULL,
},
NULL,
@ -262,7 +272,10 @@ const char **options_menu_help[14] = {
NULL,
},
NULL,
NULL,
(const char*[]){
"Reset the c64.",
NULL,
},
NULL,
(const char*[]){
"Setup theme for the Frodo",
@ -320,6 +333,7 @@ const char **network_menu_help[9] = {
};
const char *game_info_menu_messages[11] = {
/*00*/ "Capture game screenshot",
/*01*/ " ",
@ -334,6 +348,8 @@ const char *game_info_menu_messages[11] = {
NULL
};
const char *genre_dlg[8] = {
/*00*/ "Action",
/*01*/ "Adventure",

View File

@ -26,5 +26,6 @@ extern const char *game_info_bad_number_dlg[];
extern const char *genre_dlg[];
extern const char *players_dlg[];
extern const char *save_state_done[];
extern const char *save_prefs_done[];
#endif

View File

@ -2,7 +2,7 @@
#define NETWORK_USER_MENU_HH
#include <SDL.h>
#include <Network.h>
#include "../Network.h"
class GuiView;
class NetworkUserMenu;

View File

@ -77,15 +77,16 @@ public:
if (this->loadSnapshot)
{
int display_type = Gui::gui->np->DisplayType;
//int display_type = Gui::gui->np->DisplayType;
TheC64->Reset();
TheC64->LoadSnapshot(new_path);
this->updateGameInfo(fileName);
Gui::gui->updateGameInfo(Gui::gui->sgv->gameInfo->gi);
Gui::gui->np->Load(prefs_path);
/* Don't change display type */
Gui::gui->np->DisplayType = display_type;
//Gui::gui->np->DisplayType = display_type;
} else
unlink(new_path);
free(prefs_path);
@ -162,6 +163,7 @@ void SaveGameView::saveSnapshot()
char *prefs_name;
char *save;
/*
if (strlen(Gui::gui->np->DrivePath[0]) != 0)
name = Gui::gui->np->DrivePath[0];
out_name = strrchr(name, '/');
@ -169,6 +171,12 @@ void SaveGameView::saveSnapshot()
out_name = name;
else
out_name++;
*/
//take the filename from gameinfo instead from drivepath
out_name = Gui::gui->cur_gameInfo->filename;
if (!out_name)
out_name = name;
save = (char*)xmalloc( strlen(Gui::gui->save_game_path) + strlen(out_name) + 6 );
prefs_name = (char*)xmalloc( strlen(Gui::gui->save_game_path) + strlen(out_name) + 12 );
@ -182,9 +190,12 @@ void SaveGameView::saveSnapshot()
if (!was_paused)
TheC64->Resume();
//Take the screenshot from the one saved when the gui was activacted
Gui::gui->cur_gameInfo->setScreenshot(sdl_surface_8bit_copy(Gui::gui->screenshot));
Gui::gui->saveGameInfo(Gui::gui->save_game_path, out_name);
ThePrefs.Save(prefs_name);
ThePrefs = *Gui::gui->np;
ThePrefs.Save_game(prefs_name);
Gui::gui->pushDialogueBox(new DialogueBox(save_state_done));

View File

@ -1,278 +1,303 @@
/*
* main.cpp - Main program
*
* Frodo (C) 1994-1997,2002-2005 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <SDL.h>
#include <SDL_ttf.h>
#include "sysdeps.h"
#include "main.h"
#include "C64.h"
#include "Display.h"
#include "Prefs.h"
#include "SAM.h"
#include "gui/gui.hh"
#include "data_store.hh"
#include "utils.hh"
#if defined(GEKKO)
#include "fat.h"
#endif
// Global variables
extern int init_graphics(void);
// Global variables
C64 *TheC64 = NULL; // Global C64 object
char AppDirPath[1024]; // Path of application directory
// ROM file names
#ifndef DATADIR
#define DATADIR
#endif
#ifdef __riscos__
#define BASIC_ROM_FILE "FrodoRsrc:Basic_ROM"
#define KERNAL_ROM_FILE "FrodoRsrc:Kernal_ROM"
#define CHAR_ROM_FILE "FrodoRsrc:Char_ROM"
#define DRIVE_ROM_FILE "FrodoRsrc:1541_ROM"
#elif GEKKO
#define WII_FRODO_BASE_PATH "/apps/frodo/"
#define BASIC_ROM_FILE WII_FRODO_BASE_PATH"Basic_ROM"
#define KERNAL_ROM_FILE WII_FRODO_BASE_PATH"Kernal_ROM"
#define CHAR_ROM_FILE WII_FRODO_BASE_PATH"Char_ROM"
#define DRIVE_ROM_FILE WII_FRODO_BASE_PATH"1541_ROM"
#else
#define BASIC_ROM_FILE DATADIR "Basic ROM"
#define KERNAL_ROM_FILE DATADIR "Kernal ROM"
#define CHAR_ROM_FILE DATADIR "Char ROM"
#define DRIVE_ROM_FILE DATADIR "1541 ROM"
#endif
// Builtin ROMs
#include "Basic_ROM.h"
#include "Kernal_ROM.h"
#include "Char_ROM.h"
#include "1541_ROM.h"
/*
* Load C64 ROM files
*/
void Frodo::load_rom(const char *which, const char *path, uint8 *where, size_t size, const uint8 *builtin)
{
FILE *f = fopen(path, "rb");
if (f) {
size_t actual = fread(where, 1, size, f);
fclose(f);
if (actual == size)
return;
}
// Use builtin ROM
printf("%s ROM file (%s) not readable, using builtin.\n", which, path);
memcpy(where, builtin, size);
}
void Frodo::load_rom_files()
{
load_rom("Basic", BASIC_ROM_FILE, TheC64->Basic, BASIC_ROM_SIZE, builtin_basic_rom);
load_rom("Kernal", KERNAL_ROM_FILE, TheC64->Kernal, KERNAL_ROM_SIZE, builtin_kernal_rom);
load_rom("Char", CHAR_ROM_FILE, TheC64->Char, CHAR_ROM_SIZE, builtin_char_rom);
load_rom("1541", DRIVE_ROM_FILE, TheC64->ROM1541, DRIVE_ROM_SIZE, builtin_drive_rom);
}
/*
* Create application object and start it
*/
extern "C" int main(int argc, char **argv)
{
timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
// Init SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "Couldn't initialize SDL (%s)\n", SDL_GetError());
return 1;
}
if (TTF_Init() < 0)
{
fprintf(stderr, "Unable to init TTF: %s\n", TTF_GetError() );
return 1;
}
fflush(stdout);
Frodo *the_app = new Frodo();
the_app->ArgvReceived(argc, argv);
the_app->ReadyToRun();
delete the_app;
return 0;
}
/*
* Constructor: Initialize member variables
*/
Frodo::Frodo()
{
Prefs p;
TheC64 = NULL;
ThePrefs = p; /* Silly workaround to fix joystick bug */
TheDefaultPrefs = p;
}
/*
* Process command line arguments
*/
char *network_server_connect = 0;
void Frodo::ArgvReceived(int argc, char **argv)
{
if (argc == 2)
network_server_connect = argv[1];
}
const char *try_path(const char *path, const char *file)
{
if (path == NULL || file == NULL)
return NULL;
char *what = (char *)xmalloc(strlen(path) + strlen(file) + 3);
struct stat st;
const char *out = NULL;
sprintf(what, "%s/%s", path, file);
if (stat(what, &st) == 0)
out = what;
return out;
}
void Frodo::LoadFrodorc()
{
const char *paths[] = {
"/frodo", // Wii
".",
"/apps/frodo", // Wii
"frodo",
NULL, // Filled in below
NULL, // also filled in below
"/usr/share/frodo",
NULL,
};
const char *prefs_path = NULL;
const char *prefs_name = NULL;
const char *total_name = NULL;
char home_1[255];
char home_2[255];
int i;
if (getenv("HOME"))
{
snprintf(home_1, sizeof(home_1), "%s/.frodo", getenv("HOME"));
snprintf(home_2, sizeof(home_2), "%s/frodo", getenv("HOME"));
}
else
{
strcpy(home_1, "");
strcpy(home_2, "");
}
paths[4] = home_1;
paths[5] = home_2;
for (i = 0; paths[i]; i++)
{
const char *p;
const char *name = "frodorc";
p = try_path(paths[i], name);
if (p)
{
prefs_path = paths[i];
prefs_name = name;
total_name = p;
break;
}
free((void*)p);
}
// Load preferences
if (total_name)
{
ThePrefs.Load(total_name);
strncpy(ThePrefs.PrefsPath, total_name, sizeof(ThePrefs.PrefsPath));
} else
printf("No frodorc, using default\n");
free((void*)total_name);
}
/*
* Arguments processed, run emulation
*/
void Frodo::ReadyToRun(void)
{
if (getcwd(AppDirPath, 256) == NULL)
strcpy(AppDirPath, "");
this->LoadFrodorc();
if (network_server_connect)
strncpy(ThePrefs.NetworkServer, network_server_connect,
sizeof(ThePrefs.NetworkServer));
panic_if (!init_graphics(),
"Can't initialize graphics!\n");
// Create and start C64
TheC64 = new C64;
DataStore::ds = new DataStore();
TimerController::init();
Gui::init();
load_rom_files();
TheC64->Run();
delete TheC64;
#if defined(GEKKO)
fatUnmount("sd:");
#endif
}
/*
* Determine whether path name refers to a directory
*/
bool IsDirectory(const char *path)
{
struct stat st;
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
}
/*
* main.cpp - Main program
*
* Frodo (C) 1994-1997,2002-2005 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <SDL.h>
#include <SDL_ttf.h>
#include "sysdeps.h"
#include "main.h"
#include "C64.h"
#include "Display.h"
#include "Prefs.h"
#include "SAM.h"
#include "gui/gui.hh"
#include "data_store.hh"
#include "utils.hh"
#include <fat.h>
#if defined(GEKKO)
#include "fat.h"
#endif
// Global variables
extern int init_graphics(void);
// Global variables
C64 *TheC64 = NULL; // Global C64 object
char AppDirPath[1024]; // Path of application directory
// ROM file names
#ifndef DATADIR
#define DATADIR
#endif
#ifdef __riscos__
#define BASIC_ROM_FILE "FrodoRsrc:Basic_ROM"
#define KERNAL_ROM_FILE "FrodoRsrc:Kernal_ROM"
#define CHAR_ROM_FILE "FrodoRsrc:Char_ROM"
#define DRIVE_ROM_FILE "FrodoRsrc:1541_ROM"
#elif GEKKO
#define WII_FRODO_BASE_PATH "/apps/frodo/"
#define BASIC_ROM_FILE WII_FRODO_BASE_PATH"Basic_ROM"
#define KERNAL_ROM_FILE WII_FRODO_BASE_PATH"Kernal_ROM"
#define CHAR_ROM_FILE WII_FRODO_BASE_PATH"Char_ROM"
#define DRIVE_ROM_FILE WII_FRODO_BASE_PATH"1541_ROM"
#else
#define BASIC_ROM_FILE DATADIR "Basic ROM"
#define KERNAL_ROM_FILE DATADIR "Kernal ROM"
#define CHAR_ROM_FILE DATADIR "Char ROM"
#define DRIVE_ROM_FILE DATADIR "1541 ROM"
#endif
// Builtin ROMs
#include "Basic_ROM.h"
#include "Kernal_ROM.h"
#include "Char_ROM.h"
#include "1541_ROM.h"
/*
* Load C64 ROM files
*/
void Frodo::load_rom(const char *which, const char *path, uint8 *where, size_t size, const uint8 *builtin)
{
FILE *f = fopen(path, "rb");
if (f) {
size_t actual = fread(where, 1, size, f);
fclose(f);
if (actual == size)
return;
}
// Use builtin ROM
printf("%s ROM file (%s) not readable, using builtin.\n", which, path);
memcpy(where, builtin, size);
}
void Frodo::load_rom_files()
{
load_rom("Basic", BASIC_ROM_FILE, TheC64->Basic, BASIC_ROM_SIZE, builtin_basic_rom);
load_rom("Kernal", KERNAL_ROM_FILE, TheC64->Kernal, KERNAL_ROM_SIZE, builtin_kernal_rom);
load_rom("Char", CHAR_ROM_FILE, TheC64->Char, CHAR_ROM_SIZE, builtin_char_rom);
load_rom("1541", DRIVE_ROM_FILE, TheC64->ROM1541, DRIVE_ROM_SIZE, builtin_drive_rom);
}
/*
* Create application object and start it
*/
extern "C" int main(int argc, char **argv)
{
DIR_ITER *dir_tmp;
timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
// Init SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "Couldn't initialize SDL (%s)\n", SDL_GetError());
return 1;
}
if (TTF_Init() < 0)
{
fprintf(stderr, "Unable to init TTF: %s\n", TTF_GetError() );
return 1;
}
fflush(stdout);
#ifdef WII_PORT
printf("\x1b[2;0H");
//initialize libfat library
if (!fatInitDefault())
{
printf("Couldn't initialize fat subsytem\n");
sleep(3);
exit(0);
}
//create tmp directory if it does not exist
dir_tmp = diropen("/frodo/tmp");
if (!dir_tmp) {mkdir("/frodo/tmp",0777);printf("Making tmp directory\n");sleep(3);} else dirclose(dir_tmp);
#endif
Frodo *the_app = new Frodo();
the_app->ArgvReceived(argc, argv);
the_app->ReadyToRun();
delete the_app;
#ifdef WII_PORT
fatUnmount(0);
#endif
return 0;
}
/*
* Constructor: Initialize member variables
*/
Frodo::Frodo()
{
Prefs p;
TheC64 = NULL;
ThePrefs = p; /* Silly workaround to fix joystick bug */
TheDefaultPrefs = p;
}
/*
* Process command line arguments
*/
char *network_server_connect = 0;
void Frodo::ArgvReceived(int argc, char **argv)
{
if (argc == 2)
network_server_connect = argv[1];
}
const char *try_path(const char *path, const char *file)
{
if (path == NULL || file == NULL)
return NULL;
char *what = (char *)xmalloc(strlen(path) + strlen(file) + 3);
struct stat st;
const char *out = NULL;
sprintf(what, "%s/%s", path, file);
if (stat(what, &st) == 0)
out = what;
return out;
}
void Frodo::LoadFrodorc()
{
const char *paths[] = {
"/frodo", // Wii
".",
"/apps/frodo", // Wii
"frodo",
NULL, // Filled in below
NULL, // also filled in below
"/usr/share/frodo",
NULL,
};
const char *prefs_path = NULL;
const char *prefs_name = NULL;
const char *total_name = NULL;
char home_1[255];
char home_2[255];
int i;
if (getenv("HOME"))
{
snprintf(home_1, sizeof(home_1), "%s/.frodo", getenv("HOME"));
snprintf(home_2, sizeof(home_2), "%s/frodo", getenv("HOME"));
}
else
{
strcpy(home_1, "");
strcpy(home_2, "");
}
paths[4] = home_1;
paths[5] = home_2;
for (i = 0; paths[i]; i++)
{
const char *p;
const char *name = "frodorc";
p = try_path(paths[i], name);
if (p)
{
prefs_path = paths[i];
prefs_name = name;
total_name = p;
break;
}
free((void*)p);
}
// Load preferences
if (total_name)
{
ThePrefs.Load(total_name);
strncpy(ThePrefs.PrefsPath, total_name, sizeof(ThePrefs.PrefsPath));
} else
printf("No frodorc, using default\n");
free((void*)total_name);
}
/*
* Arguments processed, run emulation
*/
void Frodo::ReadyToRun(void)
{
if (getcwd(AppDirPath, 256) == NULL)
strcpy(AppDirPath, "");
this->LoadFrodorc();
if (network_server_connect)
strncpy(ThePrefs.NetworkServer, network_server_connect,
sizeof(ThePrefs.NetworkServer));
panic_if (!init_graphics(),
"Can't initialize graphics!\n");
// Create and start C64
TheC64 = new C64;
DataStore::ds = new DataStore();
TimerController::init();
Gui::init();
load_rom_files();
TheC64->Run();
delete TheC64;
#if defined(GEKKO)
fatUnmount("sd:");
#endif
}
/*
* Determine whether path name refers to a directory
*/
bool IsDirectory(const char *path)
{
struct stat st;
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB