All changes so far

This commit is contained in:
simon.kagstrom 2008-12-31 16:20:47 +00:00
parent 2a6bece89d
commit e0a34d4066
18 changed files with 1682 additions and 51 deletions

BIN
FreeMono.ttf Normal file

Binary file not shown.

137
Makefile Normal file
View File

@ -0,0 +1,137 @@
#---------------------------------------------------------------------------------
# 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 := data
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -I$(DEVKITPRO)/SDL/include -U__unix
CXXFLAGS = $(CFLAGS)
LDFLAGS = -L$(DEVKITPRO)/SDL/lib -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lSDL_ttf -lSDL_mixer -lSDL_image -ljpeg -lz -lSDL -lfreetype -lfat -lwiiuse -lbte -logc -lm
#---------------------------------------------------------------------------------
# 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 :=
CPPFILES := Display.cpp main.cpp Prefs.cpp SID.cpp REU.cpp IEC.cpp 1541fs.cpp \
1541d64.cpp 1541t64.cpp 1541job.o SAM.cpp C64.cpp CPUC64.cpp VIC.cpp \
CIA.cpp CPU1541.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)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
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
#---------------------------------------------------------------------------------

View File

@ -18,7 +18,7 @@
#include "Display.h"
#include "Prefs.h"
#if defined(__unix) && !defined(__svgalib__)
#if defined(__unix) && !defined(__svgalib__) && !defined(HAVE_SDL)
#include "CmdPipe.h"
#endif
@ -697,8 +697,8 @@ bool C64::LoadSnapshot(char *filename)
#include "C64_Amiga.i"
#endif
#ifdef __unix
#include "C64_x.i"
#ifdef HAVE_SDL
#include "C64_SDL.i"
#endif
#ifdef __mac__
@ -712,3 +712,8 @@ bool C64::LoadSnapshot(char *filename)
#ifdef __riscos__
#include "C64_Acorn.i"
#endif
#ifdef GEKKO
#include "C64_wii.i"
#endif

View File

@ -7,6 +7,12 @@
#ifndef _C64_H
#define _C64_H
#if defined(HAVE_SDL)
/* SDL menu */
#include "menu.h"
#include <SDL_ttf.h>
#endif
#ifdef __BEOS__
#include <KernelKit.h>
#include <device/Joystick.h>
@ -90,6 +96,9 @@ public:
#ifdef FRODO_SC
uint32 CycleCounter;
#endif
void enter_menu() {
this->have_a_break = true;
}
private:
void c64_ctor1(void);
@ -135,11 +144,28 @@ private:
bool game_open, port_allocated; // Flags: gameport.device opened, game port allocated
#endif
#ifdef GEKKO
double speed_index;
int joystick_key_binding[4]; /* A, Plus, Minus, 1 */
#endif
#ifdef __unix
int joyfd[2]; // File descriptors for joysticks
double speed_index;
public:
CmdPipe *gui;
#endif
#ifdef HAVE_SDL
menu_t main_menu;
TTF_Font *menu_font;
const char *base_dir;
bool fake_key_sequence;
int fake_key_type;
int fake_key_index;
int fake_key_keytime;
void select_disc();
void bind_key();
#endif
#ifdef WIN32

508
Src/C64_SDL.i Normal file
View File

@ -0,0 +1,508 @@
/*
* C64_x.i - Put the pieces together, X specific stuff
*
* Frodo (C) 1994-1997,2002 Christian Bauer
* Unix stuff by Bernd Schmidt/Lutz Vieweg
*/
#include "main.h"
#include <sys/types.h>
#include <dirent.h>
static struct timeval tv_start;
static char *main_menu_messages[] = {
"Insert disc/tape", /* 0 */
"Load disc/tape", /* 1 */
"Reset C64", /* 2 */
"Bind key to joystick",/* 3 */
"Joystick port (kbd)", /* 4 */
"^|1|2",
"Swap joysticks", /* 6 */
" ",
"Quit", /* 8 */
NULL,
};
static char *bind_key_messages[] = {
"Bind to A", /* 0 */
"Bind to Plus", /* 1 */
"Bind to Minus", /* 2 */
"Bind to 1", /* 3 */
NULL,
};
/*
* Constructor, system-dependent things
*/
void C64::c64_ctor1(void)
{
// Initialize joystick variables
joyfd[0] = joyfd[1] = -1;
joy_minx = joy_miny = 32767;
joy_maxx = joy_maxy = -32768;
this->base_dir = ".";
this->fake_key_sequence = false;
this->fake_key_index = 0;
this->fake_key_keytime = 5;
this->fake_key_type = 0;
this->menu_font = TTF_OpenFont("FreeMono.ttf", 20);
if (!this->menu_font)
{
fprintf(stderr, "Unable to open font: %s\n", TTF_GetError() );
exit(1);
}
menu_init(&this->main_menu, this->menu_font, main_menu_messages,
0, 0, DISPLAY_X, DISPLAY_Y);
}
void C64::c64_ctor2(void)
{
gettimeofday(&tv_start, NULL);
}
/*
* Destructor, system-dependent things
*/
void C64::c64_dtor(void)
{
menu_fini(&this->main_menu);
}
void C64::select_disc()
{
DIR *d = opendir(this->base_dir);
char **file_list;
int cur = 0;
struct dirent *de;
int cnt = 16;
menu_t select_disc_menu;
if (!d)
return;
file_list = (char**)malloc(cnt * sizeof(char*));
file_list[cur++] = strdup("None");
file_list[cur++] = strdup("..");
file_list[cur] = NULL;
for (de = readdir(d);
de;
de = readdir(d))
{
/* FIXME! Add directories */
if (strstr(de->d_name, ".d64") ||
strstr(de->d_name, ".t64"))
{
char *p;
p = strdup(de->d_name);
file_list[cur++] = p;
file_list[cur] = NULL;
if (cur > cnt - 1)
{
cnt = cnt + 32;
file_list = (char**)realloc(file_list, cnt);
if (!file_list)
return;
}
}
}
closedir(d);
menu_init(&select_disc_menu, this->menu_font, file_list,
0, 0, DISPLAY_X, DISPLAY_Y);
int opt = menu_select(screen, &select_disc_menu, ~0, NULL);
if (opt >= 0)
{
char *name = file_list[opt];
Prefs *np = Frodo::reload_prefs();
if (strcmp(file_list[opt], "None") == 0)
{
strcpy(np->DrivePath[0], "\0");
}
else
{
strncpy(np->DrivePath[0], name, 255);
if (strstr(name, ".d64"))
np->DriveType[0] = DRVTYPE_D64;
else
np->DriveType[0] = DRVTYPE_T64;
}
NewPrefs(np);
ThePrefs = *np;
}
menu_fini(&select_disc_menu);
/* Cleanup everything */
for ( int i = 0; i < cur; i++ )
free(file_list[i]);
free(file_list);
}
#define MATRIX(a,b) (((a) << 3) | (b))
void C64::bind_key()
{
menu_t bind_key_menu;
menu_t key_menu;
char *keys[] = { "space", "Run/Stop", "return", "F1", "F3", "F5", "F7",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "X", "Y", "Z",
NULL };
int kcs[] = { MATRIX(7, 4), MATRIX(7, 7), MATRIX(0, 1), /* space,R/S, return */
MATRIX(0, 4), MATRIX(0, 5), MATRIX(0, 6), MATRIX(0, 3), MATRIX(4, 3), MATRIX(7, 0),
MATRIX(7, 3), MATRIX(1, 0), MATRIX(1, 3), MATRIX(2, 0), MATRIX(2, 3), MATRIX(3, 0),
MATRIX(3, 3), MATRIX(4, 0), MATRIX(1, 2), MATRIX(3, 4), MATRIX(2, 4), MATRIX(2, 2),
MATRIX(1, 6), MATRIX(2, 5), MATRIX(3, 2), MATRIX(3, 5), MATRIX(4, 1), MATRIX(4, 2),
MATRIX(4, 5), MATRIX(5, 2), MATRIX(4, 4), MATRIX(4, 7), MATRIX(4, 6), MATRIX(5, 1),
MATRIX(7, 6), MATRIX(2, 1), MATRIX(1, 5), MATRIX(2, 6), MATRIX(3, 6), MATRIX(3, 7),
MATRIX(1, 1), MATRIX(2, 7), MATRIX(3, 1), MATRIX(1, 4) };
menu_init(&bind_key_menu, this->menu_font, bind_key_messages,
0, 0, DISPLAY_X, DISPLAY_Y);
menu_init(&key_menu, this->menu_font, keys,
0, 0, DISPLAY_X, DISPLAY_Y);
int opt = menu_select(screen, &bind_key_menu, ~0, NULL);
if (opt >= 0)
{
int key = menu_select(screen, &key_menu, ~0, NULL);
#if defined(GEKKO)
this->joystick_key_binding[opt] = kcs[key];
#endif
}
menu_fini(&bind_key_menu);
menu_fini(&key_menu);
}
/*
* Start main emulation thread
*/
void C64::Run(void)
{
// Reset chips
TheCPU->Reset();
TheSID->Reset();
TheCIA1->Reset();
TheCIA2->Reset();
TheCPU1541->Reset();
// Patch kernal IEC routines
orig_kernal_1d84 = Kernal[0x1d84];
orig_kernal_1d85 = Kernal[0x1d85];
PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc);
quit_thyself = false;
thread_func();
}
/* From dreamcast port */
static const char *auto_seq[4] =
{
"\nLOAD \"*\",8,1\nRUN\n",
"\nLOAD \"*\",9,1\nRUN\n",
"\nLOAD \"*\",10,1\nRUN\n",
"\nLOAD \"*\",11,1\nRUN\n",
};
extern "C" int get_kc_from_char(char c_in, int *shifted);
/*
* Vertical blank: Poll keyboard and joysticks, update window
*/
void C64::VBlank(bool draw_frame)
{
// Poll keyboard
TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
if (TheDisplay->quit_requested)
quit_thyself = true;
if (this->fake_key_sequence)
{
int shifted;
int kc = get_kc_from_char(auto_seq[this->fake_key_type][this->fake_key_index], &shifted);
TheDisplay->FakeKeyPress(kc, shifted, TheCIA1->KeyMatrix,
TheCIA1->RevMatrix, &joykey);
this->fake_key_keytime --;
if (this->fake_key_keytime == 0)
{
this->fake_key_keytime = 1;
this->fake_key_index ++;
if (auto_seq[this->fake_key_type][this->fake_key_index] == '\0')
{
this->fake_key_sequence = false;
this->fake_key_index = 0;
this->fake_key_keytime = 5;
}
}
}
// Poll joysticks
TheCIA1->Joystick1 = poll_joystick(0);
TheCIA1->Joystick2 = poll_joystick(1);
if (ThePrefs.JoystickSwap) {
uint8 tmp = TheCIA1->Joystick1;
TheCIA1->Joystick1 = TheCIA1->Joystick2;
TheCIA1->Joystick2 = tmp;
}
// Joystick keyboard emulation
if (TheDisplay->NumLock())
TheCIA1->Joystick1 &= joykey;
else
TheCIA1->Joystick2 &= joykey;
// Count TOD clocks
TheCIA1->CountTOD();
TheCIA2->CountTOD();
// Update window if needed
if (draw_frame) {
TheDisplay->Update();
// Calculate time between VBlanks, display speedometer
struct timeval tv;
gettimeofday(&tv, NULL);
if ((tv.tv_usec -= tv_start.tv_usec) < 0) {
tv.tv_usec += 1000000;
tv.tv_sec -= 1;
}
tv.tv_sec -= tv_start.tv_sec;
double elapsed_time = (double)tv.tv_sec * 1000000 + tv.tv_usec;
speed_index = 20000 / (elapsed_time + 1) * ThePrefs.SkipFrames * 100;
// Limit speed to 100% if desired
if ((speed_index > 100) && ThePrefs.LimitSpeed) {
usleep((unsigned long)(ThePrefs.SkipFrames * 20000 - elapsed_time));
speed_index = 100;
}
gettimeofday(&tv_start, NULL);
TheDisplay->Speedometer((int)speed_index);
}
}
/*
* Open/close joystick drivers given old and new state of
* joystick preferences
*/
void C64::open_close_joysticks(bool oldjoy1, bool oldjoy2, bool newjoy1, bool newjoy2)
{
#ifdef HAVE_LINUX_JOYSTICK_H
if (oldjoy1 != newjoy1) {
joy_minx = joy_miny = 32767; // Reset calibration
joy_maxx = joy_maxy = -32768;
if (newjoy1) {
joyfd[0] = open("/dev/js0", O_RDONLY);
if (joyfd[0] < 0)
fprintf(stderr, "Couldn't open joystick 1\n");
} else {
close(joyfd[0]);
joyfd[0] = -1;
}
}
if (oldjoy2 != newjoy2) {
joy_minx = joy_miny = 32767; // Reset calibration
joy_maxx = joy_maxy = -32768;
if (newjoy2) {
joyfd[1] = open("/dev/js1", O_RDONLY);
if (joyfd[1] < 0)
fprintf(stderr, "Couldn't open joystick 2\n");
} else {
close(joyfd[1]);
joyfd[1] = -1;
}
}
#endif
}
/*
* Poll joystick port, return CIA mask
*/
uint8 C64::poll_joystick(int port)
{
#ifdef GEKKO
Uint32 held = WPAD_ButtonsHeld(port);
uint8 j = 0xff;
if (held & WPAD_BUTTON_LEFT)
j &= 0xfb; // Left
if (held & WPAD_BUTTON_RIGHT)
j &= 0xf7; // Right
if (held & WPAD_BUTTON_UP)
j &= 0xfe; // Up
if (held & WPAD_BUTTON_DOWN)
j &= 0xfd; // Down
if (held & WPAD_BUTTON_2)
j &= 0xef; // Button
if (held & WPAD_BUTTON_HOME)
this->enter_menu();
if ( (held & WPAD_BUTTON_A) && this->joystick_key_binding[0])
TheDisplay->FakeKeyPress(this->joystick_key_binding[0],
shifted, TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
if ( (held & WPAD_BUTTON_PLUS) && this->joystick_key_binding[1])
TheDisplay->FakeKeyPress(this->joystick_key_binding[1],
shifted, TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
if ( (held & WPAD_BUTTON_MINUS) && this->joystick_key_binding[2])
TheDisplay->FakeKeyPress(this->joystick_key_binding[2],
shifted, TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
if ( (held & WPAD_BUTTON_1) && this->joystick_key_binding[1])
TheDisplay->FakeKeyPress(this->joystick_key_binding[1],
shifted, TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
return j;
#endif
#ifdef HAVE_LINUX_JOYSTICK_H
JS_DATA_TYPE js;
uint8 j = 0xff;
if (joyfd[port] >= 0) {
if (read(joyfd[port], &js, JS_RETURN) == JS_RETURN) {
if (js.x > joy_maxx)
joy_maxx = js.x;
if (js.x < joy_minx)
joy_minx = js.x;
if (js.y > joy_maxy)
joy_maxy = js.y;
if (js.y < joy_miny)
joy_miny = js.y;
if (joy_maxx-joy_minx < 100 || joy_maxy-joy_miny < 100)
return 0xff;
if (js.x < (joy_minx + (joy_maxx-joy_minx)/3))
j &= 0xfb; // Left
else if (js.x > (joy_minx + 2*(joy_maxx-joy_minx)/3))
j &= 0xf7; // Right
if (js.y < (joy_miny + (joy_maxy-joy_miny)/3))
j &= 0xfe; // Up
else if (js.y > (joy_miny + 2*(joy_maxy-joy_miny)/3))
j &= 0xfd; // Down
if (js.buttons & 1)
j &= 0xef; // Button
}
}
return j;
#else
return 0xff;
#endif
}
/*
* The emulation's main loop
*/
void C64::thread_func(void)
{
int linecnt = 0;
#ifdef FRODO_SC
while (!quit_thyself) {
// The order of calls is important here
if (TheVIC->EmulateCycle())
TheSID->EmulateLine();
TheCIA1->CheckIRQs();
TheCIA2->CheckIRQs();
TheCIA1->EmulateCycle();
TheCIA2->EmulateCycle();
TheCPU->EmulateCycle();
if (ThePrefs.Emul1541Proc) {
TheCPU1541->CountVIATimers(1);
if (!TheCPU1541->Idle)
TheCPU1541->EmulateCycle();
}
CycleCounter++;
#else
while (!quit_thyself) {
// The order of calls is important here
int cycles = TheVIC->EmulateLine();
TheSID->EmulateLine();
#if !PRECISE_CIA_CYCLES
TheCIA1->EmulateLine(ThePrefs.CIACycles);
TheCIA2->EmulateLine(ThePrefs.CIACycles);
#endif
if (ThePrefs.Emul1541Proc) {
int cycles_1541 = ThePrefs.FloppyCycles;
TheCPU1541->CountVIATimers(cycles_1541);
if (!TheCPU1541->Idle) {
// 1541 processor active, alternately execute
// 6502 and 6510 instructions until both have
// used up their cycles
while (cycles >= 0 || cycles_1541 >= 0)
if (cycles > cycles_1541)
cycles -= TheCPU->EmulateLine(1);
else
cycles_1541 -= TheCPU1541->EmulateLine(1);
} else
TheCPU->EmulateLine(cycles);
} else
// 1541 processor disabled, only emulate 6510
TheCPU->EmulateLine(cycles);
#endif
linecnt++;
if (this->have_a_break) {
int submenus[1];
int opt = menu_select(screen, &this->main_menu, ~0, submenus);
switch(opt)
{
case 0: /* Insert disc/tape */
this->select_disc();
break;
case 1: /* Load disc/tape */
this->fake_key_sequence = true;
break;
case 2: /* Reset */
Reset();
break;
case 3: /* Bind keys to joystick */
this->bind_key();
break;
case 4: /* Joystick port */
break;
case 6: /* Swap joysticks */
{
uint8 tmp = TheCIA1->Joystick1;
TheCIA1->Joystick1 = TheCIA1->Joystick2;
TheCIA1->Joystick2 = tmp;
} break;
case 8: /* Quit */
quit_thyself = true;
break;
case -1:
default:
break;
}
this->have_a_break = false;
}
}
}

View File

@ -17,6 +17,7 @@
#ifdef HAVE_SDL
struct SDL_Surface;
extern SDL_Surface *screen;
#endif
#ifdef WIN32
@ -58,6 +59,10 @@ public:
void PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick, uint8 *joystick2);
#else
void PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick);
#endif
#if defined(HAVE_SDL)
void FakeKeyPress(int kc, bool shift, uint8 *CIA_key_matrix,
uint8 *CIA_rev_matrix, uint8 *joystick);
#endif
bool NumLock(void);
void InitColors(uint8 *colors);
@ -79,7 +84,7 @@ public:
Joy_Keys JoystickKeys[2]; // it's easier making the joystick keys public
#endif
#ifdef __unix
#if defined(__unix) || defined(GEKKO)
bool quit_requested;
#endif

View File

@ -13,15 +13,17 @@
// Display surface
static SDL_Surface *screen = NULL;
SDL_Surface *screen = NULL;
// Keyboard
static bool num_locked = false;
#if defined(DO_ERROR_BLINK)
// For LED error blinking
static C64Display *c64_disp;
static struct sigaction pulse_sa;
static itimerval pulse_tv;
#endif
// Colors for speedometer/drive LEDs
enum {
@ -45,7 +47,7 @@ enum {
3 V U H B 8 G Y 7
4 N O K M 0 J I 9
5 , @ : . - L P +
6 / ^ = SHR HOM ; * £
6 / ^ = SHR HOM ; * <EFBFBD>
7 R/S Q C= SPC 2 CTL <- 1
*/
@ -63,6 +65,11 @@ int init_graphics(void)
fprintf(stderr, "Couldn't initialize SDL (%s)\n", SDL_GetError());
return 0;
}
if (TTF_Init() < 0)
{
fprintf(stderr, "Unable to init TTF: %s\n", TTF_GetError() );
return 0;
}
// Open window
SDL_WM_SetCaption(VERSION_STRING, "Frodo");
@ -85,6 +92,7 @@ C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
for (int i=0; i<4; i++)
led_state[i] = old_led_state[i] = LED_OFF;
#if defined(DO_ERROR_BLINK)
// Start timer for LED error blinking
c64_disp = this;
pulse_sa.sa_handler = (void (*)(int))pulse_handler;
@ -96,6 +104,7 @@ C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
pulse_tv.it_value.tv_sec = 0;
pulse_tv.it_value.tv_usec = 400000;
setitimer(ITIMER_REAL, &pulse_tv, NULL);
#endif
}
@ -106,6 +115,7 @@ C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
C64Display::~C64Display()
{
SDL_Quit();
TTF_Quit();
}
@ -213,6 +223,7 @@ void C64Display::draw_string(SDL_Surface *s, int x, int y, const char *str, uint
* LED error blink
*/
#if defined(DO_ERROR_BLINK)
void C64Display::pulse_handler(...)
{
for (int i=0; i<4; i++)
@ -225,6 +236,7 @@ void C64Display::pulse_handler(...)
break;
}
}
#endif
/*
@ -262,6 +274,38 @@ int C64Display::BitmapXMod(void)
return screen->pitch;
}
void C64Display::FakeKeyPress(int kc, bool shift, uint8 *CIA_key_matrix,
uint8 *CIA_rev_matrix, uint8 *joystick)
{
// Clear matrices
for (int i = 0; i < 8; i ++)
{
CIA_key_matrix[i] = 0xFF;
CIA_rev_matrix[i] = 0xFF;
}
if (shift)
{
CIA_key_matrix[6] &= 0xef;
CIA_rev_matrix[4] &= 0xbf;
}
if (kc != -1)
{
int c64_byte, c64_bit, shifted;
c64_byte = kc >> 3;
c64_bit = kc & 7;
shifted = kc & 128;
c64_byte &= 7;
if (shifted)
{
CIA_key_matrix[6] &= 0xef;
CIA_rev_matrix[4] &= 0xbf;
}
CIA_key_matrix[c64_byte] &= ~(1 << c64_bit);
CIA_rev_matrix[c64_bit] &= ~(1 << c64_byte);
}
}
/*
* Poll the keyboard
@ -426,6 +470,10 @@ void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joyst
TheC64->Reset();
break;
case SDLK_HOME: // Home: Pause and enter menu
TheC64->enter_menu();
break;
case SDLK_NUMLOCK:
num_locked = true;
break;

View File

@ -7,8 +7,8 @@ REVISION = 1
CXX = g++
LIBS = -L/usr/lib -Wl,-rpath,/usr/lib -lSDL -lpthread
CFLAGS = -O2 -g -fomit-frame-pointer -Wall -Wno-unused -Wno-format -I/usr/include/SDL -D_REENTRANT -DHAVE_SDL -fno-strength-reduce -DREGPARAM="__attribute__((regparm(3)))" -I./ -DFRODO_HPUX_REV=0 -DKBD_LANG=0
LIBS = -L/usr/lib -lSDL -lSDL_ttf
CFLAGS = -O2 -g -fomit-frame-pointer -Wall -Wno-unused -Wno-format -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -DHAVE_SDL -fno-strength-reduce -DREGPARAM="__attribute__((regparm(3)))" -I./ -DFRODO_HPUX_REV=0 -DKBD_LANG=0
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@ -23,7 +23,7 @@ sysconfdir = ${prefix}/etc
## Files
OBJS = main.o Display.o Prefs.o SID.o REU.o IEC.o 1541fs.o \
1541d64.o 1541t64.o 1541job.o SAM.o CmdPipe.o
1541d64.o 1541t64.o 1541job.o SAM.o menu.o CmdPipe.o
SLOBJS = $(OBJS) C64.o CPUC64.o VIC.o CIA.o CPU1541.o
PCOBJS = $(OBJS) C64_PC.o CPUC64_PC.o VIC.o CIA.o CPU1541_PC.o
PCFLAGS = -DPRECISE_CPU_CYCLES=1 -DPRECISE_CIA_CYCLES=1 -DPC_IS_POINTER=0
@ -67,7 +67,7 @@ depend dep:
.cpp.s:
$(CC) $(INCLUDES) $(CFLAGS) $(EXTRAFLAGS) -o $@ -S $*.cpp -g0
C64_PC.o: C64.cpp C64.h C64_x.i CmdPipe.h CPUC64.h CPU1541.h VIC.h SID.h CIA.h REU.h IEC.h 1541job.h Display.h Prefs.h
C64_PC.o: C64.cpp C64.h C64_SDL.i CmdPipe.h CPUC64.h CPU1541.h VIC.h SID.h CIA.h REU.h IEC.h 1541job.h Display.h Prefs.h
$(CC) $(INCLUDES) $(CFLAGS) $(PCFLAGS) -o $@ -c $*.cpp
CPUC64_PC.o: CPUC64.cpp CPUC64.h CPU_emulline.i C64.h VIC.h SID.h CIA.h REU.h IEC.h Display.h Version.h
@ -76,7 +76,7 @@ CPUC64_PC.o: CPUC64.cpp CPUC64.h CPU_emulline.i C64.h VIC.h SID.h CIA.h REU.h IE
CPU1541_PC.o: CPU1541.cpp CPU1541.h CPU_emulline.i 1541job.h C64.h CIA.h Display.h
$(CC) $(INCLUDES) $(CFLAGS) $(PCFLAGS) -o $@ -c $*.cpp
C64_SC.o: C64_SC.cpp C64.h C64_x.i CmdPipe.h CPUC64.h CPU1541.h VIC.h SID.h CIA.h REU.h IEC.h 1541job.h Display.h Prefs.h
C64_SC.o: C64_SC.cpp C64.h C64_SDL.i CmdPipe.h CPUC64.h CPU1541.h VIC.h SID.h CIA.h REU.h IEC.h 1541job.h Display.h Prefs.h
$(CC) $(INCLUDES) $(CFLAGS) $(SCFLAGS) -o $@ -c $*.cpp
CPUC64_SC.o: CPUC64_SC.cpp CPUC64.h CPU_emulcycle.i CPU_common.h C64.h VIC.h SID.h CIA.h REU.h IEC.h Display.h Version.h
@ -93,41 +93,3 @@ CIA_SC.o: CIA_SC.cpp CIA.h CPUC64.h CPU1541.h VIC.h Prefs.h
#-------------------------------------------------------------------------
# DO NOT DELETE THIS LINE -- make depend depends on it.
main.o: sysdeps.h sysconfig.h main.h C64.h Display.h Prefs.h SAM.h
Display.o: sysdeps.h sysconfig.h Display.h main.h Prefs.h
Prefs.o: sysdeps.h sysconfig.h Prefs.h Display.h C64.h main.h
SID.o: sysdeps.h sysconfig.h SID.h Prefs.h
REU.o: sysdeps.h sysconfig.h REU.h CPUC64.h C64.h Prefs.h
IEC.o: sysdeps.h sysconfig.h IEC.h 1541fs.h 1541d64.h 1541t64.h Prefs.h
IEC.o: Display.h
1541fs.o: sysdeps.h sysconfig.h 1541fs.h IEC.h main.h Prefs.h
1541d64.o: sysdeps.h sysconfig.h 1541d64.h IEC.h Prefs.h
1541t64.o: sysdeps.h sysconfig.h 1541t64.h IEC.h Prefs.h
1541job.o: sysdeps.h sysconfig.h 1541job.h CPU1541.h CIA.h Prefs.h C64.h
SAM.o: sysdeps.h sysconfig.h SAM.h C64.h CPUC64.h CPU1541.h CIA.h Prefs.h
SAM.o: VIC.h SID.h
CmdPipe.o: CmdPipe.h
C64.o: sysdeps.h sysconfig.h C64.h CPUC64.h CPU1541.h CIA.h Prefs.h VIC.h
C64.o: SID.h REU.h IEC.h 1541job.h Display.h
C64_PC.o: C64.cpp sysdeps.h sysconfig.h C64.h CPUC64.h CPU1541.h CIA.h
C64_PC.o: Prefs.h VIC.h SID.h REU.h IEC.h 1541job.h Display.h
C64_SC.o: C64.cpp sysdeps.h sysconfig.h C64.h CPUC64.h CPU1541.h CIA.h
C64_SC.o: Prefs.h VIC.h SID.h REU.h IEC.h 1541job.h Display.h
CPUC64.o: sysdeps.h sysconfig.h CPUC64.h C64.h VIC.h SID.h CIA.h Prefs.h
CPUC64.o: REU.h IEC.h Display.h Version.h CPU_emulline.i
CPUC64_PC.o: CPUC64.cpp sysdeps.h sysconfig.h CPUC64.h C64.h VIC.h SID.h
CPUC64_PC.o: CIA.h Prefs.h REU.h IEC.h Display.h Version.h CPU_emulline.i
CPUC64_SC.o: sysdeps.h sysconfig.h CPUC64.h C64.h CPU_common.h VIC.h SID.h
CPUC64_SC.o: CIA.h Prefs.h REU.h IEC.h Display.h Version.h CPU_emulcycle.i
VIC.o: sysdeps.h sysconfig.h VIC.h C64.h CPUC64.h Display.h Prefs.h
VIC_SC.o: sysdeps.h sysconfig.h VIC.h C64.h CPUC64.h Display.h Prefs.h
CIA.o: sysdeps.h sysconfig.h CIA.h Prefs.h CPUC64.h C64.h CPU1541.h VIC.h
CIA_SC.o: sysdeps.h sysconfig.h CIA.h Prefs.h CPUC64.h C64.h CPU1541.h VIC.h
CPU1541.o: sysdeps.h sysconfig.h CPU1541.h CIA.h Prefs.h C64.h 1541job.h
CPU1541.o: Display.h CPU_emulline.i
CPU1541_PC.o: CPU1541.cpp sysdeps.h sysconfig.h CPU1541.h CIA.h Prefs.h C64.h
CPU1541_PC.o: 1541job.h Display.h CPU_emulline.i
CPU1541_SC.o: sysdeps.h sysconfig.h CPU1541.h CIA.h Prefs.h C64.h
CPU1541_SC.o: CPU_common.h 1541job.h Display.h CPU_emulcycle.i
CPU_common.o: sysdeps.h sysconfig.h CPU_common.h

View File

@ -72,6 +72,13 @@ Prefs::Prefs()
AlwaysCopy = false;
SystemKeys = true;
ShowLEDs = true;
#ifdef GEKKO
this->JoystickKeyBinding[0] = 0;
this->JoystickKeyBinding[1] = 0;
this->JoystickKeyBinding[2] = 0;
this->JoystickKeyBinding[3] = 0;
#endif
}
@ -126,6 +133,12 @@ bool Prefs::operator==(const Prefs &rhs) const
&& AlwaysCopy == rhs.AlwaysCopy
&& SystemKeys == rhs.SystemKeys
&& ShowLEDs == rhs.ShowLEDs
#ifdef GEKKO
&& this->JoystickKeyBinding[0] == rhs.JoystickKeybinding[0]
&& this->JoystickKeyBinding[1] == rhs.JoystickKeybinding[1]
&& this->JoystickKeyBinding[2] == rhs.JoystickKeybinding[2]
&& this->JoystickKeyBinding[3] == rhs.JoystickKeybinding[3]
#endif
);
}
@ -290,6 +303,16 @@ void Prefs::Load(char *filename)
SystemKeys = !strcmp(value, "TRUE");
else if (!strcmp(keyword, "ShowLEDs"))
ShowLEDs = !strcmp(value, "TRUE");
#if defined(GEKKO)
else if (!strcmp(keyword, "JoystickKeyBinding0"))
JoystickKeyBinding[0] = atoi(value);
else if (!strcmp(keyword, "JoystickKeyBinding1"))
JoystickKeyBinding[1] = atoi(value);
else if (!strcmp(keyword, "JoystickKeyBinding2"))
JoystickKeyBinding[2] = atoi(value);
else if (!strcmp(keyword, "JoystickKeyBinding3"))
JoystickKeyBinding[3] = atoi(value);
#endif
}
}
fclose(file);
@ -386,6 +409,12 @@ bool Prefs::Save(char *filename)
fprintf(file, "AlwaysCopy = %s\n", AlwaysCopy ? "TRUE" : "FALSE");
fprintf(file, "SystemKeys = %s\n", SystemKeys ? "TRUE" : "FALSE");
fprintf(file, "ShowLEDs = %s\n", ShowLEDs ? "TRUE" : "FALSE");
#if defined(GEKKO)
fprintf(file, "JoystickKeyBinding0 = %d\n", JoystickKeyBinding[0]);
fprintf(file, "JoystickKeyBinding1 = %d\n", JoystickKeyBinding[1]);
fprintf(file, "JoystickKeyBinding2 = %d\n", JoystickKeyBinding[2]);
fprintf(file, "JoystickKeyBinding3 = %d\n", JoystickKeyBinding[3]);
#endif
fclose(file);
ThePrefsOnDisk = *this;
return true;

View File

@ -114,6 +114,10 @@ private:
static char *edit_prefs_name;
static HWND hDlg;
#endif
#ifdef GEKKO
int JoystickKeyBinding[4];
#endif
};

View File

@ -64,6 +64,10 @@ class DigitalPlayer;
#define ldSINTAB 9 // size of sinus table (0 to 90 degrees)
#endif
#if defined(HAVE_SDL)
#include <SDL.h>
#endif
#ifdef USE_FIXPOINT_MATHS
#include "FixPoint.i"
@ -428,7 +432,14 @@ private:
int play_buf; // Number of buffer currently playing
#endif
#ifdef __linux__
#ifdef HAVE_SDL
void fill_audio(Uint8 *stream, int len);
static void fill_audio_helper(void *udata, Uint8 *stream, int len);
SDL_AudioSpec spec;
#endif
#if defined(__linux__) || defined(HAVE_SDL)
int devfd, sndbufsize, buffer_rate;
int16 *sound_buffer;
#endif
@ -1351,6 +1362,9 @@ void DigitalRenderer::calc_buffer(int16 *buf, long count)
#elif defined(AMIGA)
#include "SID_Amiga.i"
#elif defined(HAVE_SDL)
#include "SID_SDL.i"
#elif defined(__linux__)
#include "SID_linux.i"
@ -1369,6 +1383,9 @@ void DigitalRenderer::calc_buffer(int16 *buf, long count)
#elif defined(__riscos__)
#include "SID_Acorn.i"
#elif defined(GEKKO)
#include "SID_wii.i"
#else // No sound
void DigitalRenderer::init_sound(void) {ready = false;}
DigitalRenderer::~DigitalRenderer() {}

101
Src/char_to_kc.c Normal file
View File

@ -0,0 +1,101 @@
/*********************************************************************
*
* Copyright (C) 2008, Simon Kagstrom
*
* Filename: char_to_kc.c
* Author: Simon Kagstrom <simon.kagstrom@gmail.com>
* Description: Convert chars to keycodes
*
* $Id:$
*
********************************************************************/
#include <stdint.h>
#define MATRIX(a,b) (((a) << 3) | (b))
#define SHIFT (1<<7)
static uint8_t char_to_kc[] =
{
/* Some shifted stuff */
['\"'] = MATRIX(7, 3) | SHIFT,
/* CUD */
/* F5 */
/* F3 */
/* F1 */
/* F7 */
['\n'] = MATRIX(0, 1),
['\008'] = MATRIX(0, 0),
['E'] = MATRIX(1, 6),
['S'] = MATRIX(1, 5),
['Z'] = MATRIX(1, 4),
['4'] = MATRIX(1, 3),
['A'] = MATRIX(1, 2),
['W'] = MATRIX(1, 1),
['3'] = MATRIX(1, 0),
['X'] = MATRIX(2, 7),
['T'] = MATRIX(2, 6),
['F'] = MATRIX(2, 5),
['C'] = MATRIX(2, 4),
['6'] = MATRIX(2, 3),
['D'] = MATRIX(2, 2),
['R'] = MATRIX(2, 1),
['5'] = MATRIX(2, 0),
['V'] = MATRIX(3, 7),
['U'] = MATRIX(3, 6),
['H'] = MATRIX(3, 5),
['B'] = MATRIX(3, 4),
['8'] = MATRIX(3, 3),
['G'] = MATRIX(3, 2),
['Y'] = MATRIX(3, 1),
['7'] = MATRIX(3, 0),
['N'] = MATRIX(4, 7),
['O'] = MATRIX(4, 6),
['K'] = MATRIX(4, 5),
['M'] = MATRIX(4, 4),
['0'] = MATRIX(4, 3),
['J'] = MATRIX(4, 2),
['I'] = MATRIX(4, 1),
['9'] = MATRIX(4, 0),
[','] = MATRIX(5, 7),
['@'] = MATRIX(5, 6),
[':'] = MATRIX(5, 5),
['.'] = MATRIX(5, 4),
['-'] = MATRIX(5, 3),
['L'] = MATRIX(5, 2),
['P'] = MATRIX(5, 1),
['+'] = MATRIX(5, 0),
['/'] = MATRIX(6, 7),
['^'] = MATRIX(6, 6),
['='] = MATRIX(6, 5),
/* SHR */
/* HOM */
[';'] = MATRIX(6, 2),
['*'] = MATRIX(6, 1),
/* ?? */
/* R/S */
['Q'] = MATRIX(7, 6),
/* C= */
[' '] = MATRIX(7, 4),
['2'] = MATRIX(7, 3),
/* CTL */
/* <- */
['1'] = MATRIX(7, 0),
};
int get_kc_from_char(char c_in, int *shifted)
{
char c = char_to_kc[(int)c_in];
int out = c & (~SHIFT);
*shifted = c & SHIFT;
return out;
}

View File

@ -23,6 +23,12 @@ char AppDirPath[1024]; // Path of application directory
#define KERNAL_ROM_FILE "FrodoRsrc:Kernal_ROM"
#define CHAR_ROM_FILE "FrodoRsrc:Char_ROM"
#define FLOPPY_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 FLOPPY_ROM_FILE WII_FRODO_BASE_PATH"1541_ROM"
#else
#define BASIC_ROM_FILE "Basic ROM"
#define KERNAL_ROM_FILE "Kernal ROM"
@ -120,3 +126,8 @@ bool Frodo::load_rom_files(void)
#ifdef __PSXOS__
#include "main_PSX.i"
#endif
#ifdef GEKKO
#include "main_wii.i"
#endif

View File

@ -248,4 +248,25 @@ extern Frodo *be_app; // Pointer to Frodo object
#endif
#ifdef GEKKO
class Prefs;
class Frodo {
public:
Frodo();
void ArgvReceived(int argc, char **argv);
void ReadyToRun(void);
static Prefs *reload_prefs(void);
C64 *TheC64;
private:
bool load_rom_files(void);
static char prefs_path[256]; // Pathname of current preferences file
};
#endif
#endif

109
Src/main_wii.i Normal file
View File

@ -0,0 +1,109 @@
/*
* main_wii.i - Main program, Wii specific stuff
*
* Frodo (C) 1994-1997,2002 Christian Bauer
*/
#include "Version.h"
#include <SDL.h>
#include <fat.h>
#include <wiiuse/wpad.h>
extern int init_graphics(void);
// Global variables
char Frodo::prefs_path[256] = "";
/*
* Create application object and start it
*/
extern "C" int main(int argc, char **argv)
{
Frodo *the_app;
timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
printf("%s by Christian Bauer\n", VERSION_STRING);
if (!init_graphics())
{
fprintf(stderr, "Could not initialize graphics\n");
return 0;
}
fflush(stdout);
fatInitDefault();
if (WPAD_Init() != WPAD_ERR_NONE)
{
fprintf(stderr, "Failed initializing controllers\n");
return 0;
}
the_app = new Frodo();
the_app->ArgvReceived(argc, argv);
the_app->ReadyToRun();
delete the_app;
return 0;
}
/*
* Constructor: Initialize member variables
*/
Frodo::Frodo()
{
TheC64 = NULL;
}
/*
* Process command line arguments
*/
void Frodo::ArgvReceived(int argc, char **argv)
{
if (argc == 2)
strncpy(prefs_path, argv[1], 255);
}
/*
* Arguments processed, run emulation
*/
void Frodo::ReadyToRun(void)
{
getcwd(AppDirPath, 256);
// Load preferences
if (!prefs_path[0]) {
char *home = getenv("HOME");
if (home != NULL && strlen(home) < 240) {
strncpy(prefs_path, home, 200);
strcat(prefs_path, "/");
}
strcat(prefs_path, ".frodorc");
}
ThePrefs.Load(prefs_path);
// Create and start C64
TheC64 = new C64;
if (load_rom_files())
TheC64->Run();
delete TheC64;
}
Prefs *Frodo::reload_prefs(void)
{
static Prefs newprefs;
newprefs.Load(prefs_path);
return &newprefs;
}

436
Src/menu.c Normal file
View File

@ -0,0 +1,436 @@
/*********************************************************************
*
* Copyright (C) 2004,2008, Simon Kagstrom
*
* Filename: menu.c
* Author: Simon Kagstrom <simon.kagstrom@gmail.com>
* Description: Code for menus (originally for Mophun)
*
* $Id$
*
********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#if defined(GEKKO)
# include <wiiuse/wpad.h>
#endif
#include "menu.h"
#define KEY_UP 1
#define KEY_DOWN 2
#define KEY_LEFT 4
#define KEY_RIGHT 8
#define KEY_SELECT 16
#define KEY_ESCAPE 32
#define KEY_PAGEDOWN 64
#define KEY_PAGEUP 128
#define IS_SUBMENU(p_msg) ( (p_msg)[0] == '^' )
static submenu_t *find_submenu(menu_t *p_menu, int index)
{
int i;
for (i=0; i<p_menu->n_submenus; i++)
{
if (p_menu->p_submenus[i].index == index)
return &p_menu->p_submenus[i];
}
return NULL;
}
static void print_font(SDL_Surface *screen, TTF_Font *font, int r, int g, int b,
int x, int y, char *msg)
{
SDL_Surface *font_surf;
SDL_Rect dst = {x, y, 0, 0};
SDL_Color color = {r, g, b};
char buf[255];
int i;
memset(buf, 0, sizeof(buf));
strncpy(buf, msg, 254);
/* Fixup multi-menu option look */
for (i = 0; i < strlen(buf) ; i++)
{
if (buf[i] == '^' || buf[i] == '|')
buf[i] = ' ';
}
font_surf = TTF_RenderText_Solid(font, buf,
color);
if (!font_surf)
{
fprintf(stderr, "%s\n", TTF_GetError());
exit(1);
}
SDL_BlitSurface(font_surf, NULL, screen, &dst);
SDL_FreeSurface(font_surf);
}
static void menu_draw(SDL_Surface *screen, menu_t *p_menu)
{
int x_start = p_menu->x1 + (p_menu->x2 - p_menu->x1) / 2 - p_menu->text_w / 2;
int y_start = p_menu->y1 + (p_menu->y2 - p_menu->y1) / 2 - p_menu->text_h / 2;
int font_height = TTF_FontHeight(p_menu->p_font);
int line_height = (font_height + font_height / 4);
int cur_y = p_menu->cur_sel * line_height;
int entries_visible = p_menu->y2 / line_height;
int i;
if ( p_menu->n_entries * line_height > p_menu->y2 )
y_start = p_menu->y1;
if ( p_menu->cur_sel - p_menu->start_entry_visible > entries_visible )
p_menu->start_entry_visible += p_menu->cur_sel - entries_visible;
else if ( p_menu->cur_sel < p_menu->start_entry_visible )
p_menu->start_entry_visible = p_menu->cur_sel;
for (i = p_menu->start_entry_visible; i < p_menu->n_entries; i++)
{
char *msg = p_menu->pp_msgs[i];
int y = (i - p_menu->start_entry_visible) * line_height;
if ((p_menu->available_options & (1<<i)) == 0) /* Gray (not available) */
print_font(screen, p_menu->p_font, 128,128,128, x_start,
y_start + y, msg);
else if (p_menu->cur_sel == i) /* Selected - color */
print_font(screen, p_menu->p_font, 255,255,0, x_start,
y_start + y, msg);
else /* Otherwise white */
print_font(screen, p_menu->p_font, 255,255,255, x_start,
y_start + y, msg);
if (IS_SUBMENU(msg))
{
submenu_t *p_submenu = find_submenu(p_menu, i);
int n_pipe = 0;
int n;
for (n=0; msg[n] != '\0'; n++)
{
/* Underline the selected entry */
if (msg[n] == '|')
{
int16_t n_chars;
for (n_chars = 1; msg[n+n_chars] && msg[n+n_chars] != '|'; n_chars++);
n_pipe++;
if (p_submenu->sel == n_pipe-1)
{
SDL_Rect r;
int w;
int h;
if (TTF_SizeText(p_menu->p_font, "X", &w, &h) < 0)
{
fprintf(stderr, "%s\n", TTF_GetError());
exit(1);
}
r = (SDL_Rect) { x_start + (n+1) * w-1,
y_start + (i+1 - p_menu->start_entry_visible) * ((h + h/4)-1),
(n_chars - 1) * w,
2 };
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, 255, 0));
break;
}
}
}
}
}
}
static void select_next(menu_t *p_menu, int dx, int dy)
{
int next;
p_menu->cur_sel = (p_menu->cur_sel + dy) < 0 ? p_menu->n_entries - 1 :
(p_menu->cur_sel + dy) % p_menu->n_entries;
next = (p_menu->cur_sel + dy + 1) < 0 ? p_menu->n_entries - 1 :
(p_menu->cur_sel + dy + 1) % p_menu->n_entries;
if (p_menu->pp_msgs[p_menu->cur_sel][0] == ' ' ||
( (p_menu->available_options & (1<<p_menu->cur_sel)) == 0) ||
IS_SUBMENU(p_menu->pp_msgs[p_menu->cur_sel]) )
select_next(p_menu, dx, dy);
/* If the next is a submenu */
if (dx != 0 &&
IS_SUBMENU(p_menu->pp_msgs[next]))
{
submenu_t *p_submenu = find_submenu(p_menu, next);
p_submenu->sel = (p_submenu->sel + dx) < 0 ? p_submenu->n_entries - 1 :
(p_submenu->sel + dx) % p_submenu->n_entries;
}
}
static int is_submenu_title(menu_t *p_menu, int n)
{
if (n+1 >= p_menu->n_entries)
return 0;
else
return IS_SUBMENU(p_menu->pp_msgs[n+1]);
}
void menu_init(menu_t *p_menu, TTF_Font *p_font, char **pp_msgs,
int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
int i;
int j;
memset(p_menu, 0, sizeof(menu_t));
p_menu->pp_msgs = pp_msgs;
p_menu->p_font = p_font;
p_menu->x1 = x1;
p_menu->y1 = y1;
p_menu->x2 = x2;
p_menu->y2 = y2;
p_menu->text_w = 0;
p_menu->n_submenus = 0;
for (p_menu->n_entries = 0; p_menu->pp_msgs[p_menu->n_entries]; p_menu->n_entries++)
{
int text_w_font;
/* Is this a submenu? */
if (IS_SUBMENU(p_menu->pp_msgs[p_menu->n_entries]))
{
p_menu->n_submenus++;
continue; /* Length of submenus is unimportant */
}
if (TTF_SizeText(p_font, p_menu->pp_msgs[p_menu->n_entries], &text_w_font, NULL) != 0)
{
fprintf(stderr, "%s\n", TTF_GetError());
exit(1);
}
if (text_w_font > p_menu->text_w)
p_menu->text_w = text_w_font;
}
if ( !(p_menu->p_submenus = malloc(sizeof(submenu_t) * p_menu->n_submenus)) )
{
perror("malloc failed!\n");
exit(1);
}
j=0;
for (i=0; i<p_menu->n_submenus; i++)
{
for (; j < p_menu->n_entries; j++)
{
if (IS_SUBMENU(p_menu->pp_msgs[j]))
{
int n;
p_menu->p_submenus[i].index = j;
p_menu->p_submenus[i].sel = 0;
p_menu->p_submenus[i].n_entries = 0;
for (n=0; p_menu->pp_msgs[j][n] != '\0'; n++)
{
if (p_menu->pp_msgs[j][n] == '|')
p_menu->p_submenus[i].n_entries++;
}
}
}
}
p_menu->text_h = p_menu->n_entries * (TTF_FontHeight(p_font) + TTF_FontHeight(p_font) / 4);
}
void menu_fini(menu_t *p_menu)
{
free(p_menu->p_submenus);
}
static uint32_t wait_key_press(void)
{
SDL_Event ev;
uint32_t keys = 0;
while (1)
{
#if defined(GEKKO)
Uint32 remote_keys;
WPAD_ScanPads();
remote_keys = WPAD_ButtonsDown(WPAD_CHAN_0) | WPAD_ButtonsDown(WPAD_CHAN_1);
if (remote_keys & WPAD_BUTTON_DOWN)
keys |= KEY_DOWN;
if (remote_keys & WPAD_BUTTON_UP)
keys |= KEY_UP;
if (remote_keys & WPAD_BUTTON_LEFT)
keys |= KEY_LEFT;
if (remote_keys & WPAD_BUTTON_RIGHT)
keys |= KEY_RIGHT;
if (remote_keys & WPAD_BUTTON_PLUS)
keys |= KEY_PAGEUP;
if (remote_keys & WPAD_BUTTON_MINUS)
keys |= KEY_PAGEDOWN;
if (remote_keys & (WPAD_BUTTON_A | WPAD_BUTTON_1) )
keys |= KEY_SELECT;
if (remote_keys & (WPAD_BUTTON_1 | WPAD_BUTTON_HOME) )
keys |= KEY_ESCAPE;
#endif
if (SDL_PollEvent(&ev))
{
switch(ev.type)
{
case SDL_KEYDOWN:
switch (ev.key.keysym.sym)
{
case SDLK_UP:
keys |= KEY_UP;
break;
case SDLK_DOWN:
keys |= KEY_DOWN;
break;
case SDLK_LEFT:
keys |= KEY_LEFT;
break;
case SDLK_RIGHT:
keys |= KEY_RIGHT;
break;
case SDLK_PAGEDOWN:
keys |= KEY_PAGEDOWN;
break;
case SDLK_PAGEUP:
keys |= KEY_PAGEUP;
break;
case SDLK_RETURN:
case SDLK_SPACE:
keys |= KEY_SELECT;
break;
case SDLK_ESCAPE:
keys |= KEY_ESCAPE;
break;
default:
break;
}
break;
case SDL_QUIT:
exit(0);
break;
default:
break;
}
break;
}
SDL_Delay(10);
}
return keys;
}
int menu_select(SDL_Surface *screen, menu_t *p_menu,
uint32_t available_options, int *p_submenus)
{
p_menu->available_options = available_options;
while(1)
{
uint32_t keys;
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
menu_draw(screen, p_menu);
SDL_Flip(screen);
keys = wait_key_press();
if (keys & KEY_UP)
select_next(p_menu, 0, -1);
else if (keys & KEY_DOWN)
select_next(p_menu, 0, 1);
else if (keys & KEY_LEFT)
select_next(p_menu, -1, 0);
else if (keys & KEY_RIGHT)
select_next(p_menu, 1, 0);
else if (keys & KEY_ESCAPE)
return -1;
else if (keys & KEY_SELECT)
{
int ret = p_menu->cur_sel;
int i;
if (!is_submenu_title(p_menu, ret))
{
for (i=0; i<p_menu->n_submenus; i++)
p_submenus[i] = p_menu->p_submenus[i].sel;
p_menu->cur_sel = 0;
return ret;
}
}
}
return -1;
}
#if defined(TEST_MENU)
char *main_menu[] = {
"Insert disc",
"Reset C64",
"Joystick port",
"^|1|2",
" ",
"Quit",
NULL,
};
int main(int argc, char *argv[])
{
SDL_Surface *screen;
TTF_Font *font;
const SDL_VideoInfo *info;
int submenus[1] = {0};
int selected;
menu_t menu;
if (SDL_Init( SDL_INIT_EVERYTHING ) < 0)
{
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError() );
exit(1);
}
if (TTF_Init() < 0)
{
fprintf(stderr, "Unable to init TTF: %s\n", TTF_GetError() );
exit(1);
}
atexit(SDL_Quit);
atexit(TTF_Quit);
font = TTF_OpenFont("FreeMono.ttf", 20);
if (!font)
{
fprintf(stderr, "Unable to open font: %s\n", TTF_GetError() );
exit(1);
}
info = SDL_GetVideoInfo();
/* Open a 640x480 display with the optimal color depth */
screen = SDL_SetVideoMode(640, 480, info->vfmt->BitsPerPixel,
info->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE);
menu_init(&menu, font, main_menu, 640 / 3, 480 / 3, 400, 400);
selected = menu_select(screen, &menu, ~0, submenus);
printf("Selected: %d:%d\n",
selected, submenus[0]);
menu_fini(&menu);
return 0;
}
#endif

60
Src/menu.h Normal file
View File

@ -0,0 +1,60 @@
/*********************************************************************
*
* Copyright (C) 2004, 2008, Simon Kagstrom
*
* Filename: menu.h
* Author: Simon Kagstrom <simon.kagstrom@gmail.com>
* Description:
*
* $Id$
*
********************************************************************/
#ifndef __MENU_H__
#define __MENU_H__
#include <SDL.h>
#include <SDL_ttf.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
typedef struct
{
int n_entries;
int index;
int sel;
} submenu_t;
typedef struct
{
char **pp_msgs;
TTF_Font *p_font;
int x1,y1;
int x2,y2;
int text_w;
int text_h;
uint32_t available_options;
int n_submenus;
submenu_t *p_submenus;
int cur_sel; /* Main selection */
int start_entry_visible;
int n_entries;
} menu_t;
void menu_init(menu_t *p_menu, TTF_Font *p_font, char **pp_msgs,
int16_t x1, int16_t y1, int16_t x2, int16_t y2);
void menu_fini(menu_t *p_menu);
int menu_select(SDL_Surface *screen, menu_t *p_menu,
uint32_t available_options, int *p_submenus);
#if defined(__cplusplus)
};
#endif /* __cplusplus */
#endif /* !__MENU_H__ */

152
Src/sysconfig.h.Wii Normal file
View File

@ -0,0 +1,152 @@
/* Src/sysconfig.h for Wii */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
/* #undef _ALL_SOURCE */
#endif
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define if your struct stat has st_blocks. */
#define HAVE_ST_BLOCKS 1
/* Define if utime(file, NULL) sets file's timestamp to the present. */
#define HAVE_UTIME_NULL 1
/* Define as __inline if that's what the C compiler calls it. */
/* #undef inline */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef mode_t */
/* Define to `long' if <sys/types.h> doesn't define. */
/* #undef off_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef pid_t */
/* Define if you need to in order for stat and other things to work. */
#define _POSIX_SOURCE 1
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define if your <sys/time.h> declares struct tm. */
/* #undef TM_IN_SYS_TIME */
/* The number of bytes in a char. */
#define SIZEOF_CHAR 1
/* The number of bytes in a int. */
#define SIZEOF_INT 4
/* The number of bytes in a long. */
#define SIZEOF_LONG 4
/* The number of bytes in a long long. */
#define SIZEOF_LONG_LONG 8
/* The number of bytes in a short. */
#define SIZEOF_SHORT 2
/* Define if you have the gettimeofday function. */
#define HAVE_GETTIMEOFDAY 1
/* Define if you have SDL. */
#define HAVE_SDL 1
/* Define if you have the mkdir function. */
#define HAVE_MKDIR 1
/* Define if you have the rmdir function. */
#define HAVE_RMDIR 1
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the sigaction function. */
/*#define HAVE_SIGACTION 1*/
/* Define if you have the statfs function. */
/* #undef HAVE_STATFS */
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the strstr function. */
#define HAVE_STRSTR 1
/* Define if you have the usleep function. */
/* #undef HAVE_USLEEP */
/* Define if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <linux/joystick.h> header file. */
/* #undef HAVE_LINUX_JOYSTICK_H */
/* Define if you have the <ncurses.h> header file. */
/* #undef HAVE_NCURSES_H */
/* Define if you have the <ndir.h> header file. */
#define HAVE_NDIR_H 1
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
/* Define if you have the <sys/dir.h> header file. */
#define HAVE_SYS_DIR_H 1
/* Define if you have the <sys/mount.h> header file. */
/* #undef HAVE_SYS_MOUNT_H */
/* Define if you have the <sys/ndir.h> header file. */
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define if you have the <sys/select.h> header file. */
/* #undef HAVE_SYS_SELECT_H */
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/statfs.h> header file. */
/* #undef HAVE_SYS_STATFS_H */
/* Define if you have the <sys/statvfs.h> header file. */
/* #undef HAVE_SYS_STATVFS_H */
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define if you have the <sys/vfs.h> header file. */
/* #undef HAVE_SYS_VFS_H */
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define if you have the <values.h> header file. */
/* #undef HAVE_VALUES_H */