mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-26 13:34:22 +01:00
Cleanup
This commit is contained in:
parent
5ae81fc5bf
commit
580a876773
418
Src/C64_Be.h
418
Src/C64_Be.h
@ -1,418 +0,0 @@
|
|||||||
/*
|
|
||||||
* C64_Be.h - Put the pieces together, Be specific stuff
|
|
||||||
*
|
|
||||||
* 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 <KernelKit.h>
|
|
||||||
#include <device/Joystick.h>
|
|
||||||
#include <device/DigitalPort.h>
|
|
||||||
|
|
||||||
#undef PROFILING
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Constructor, system-dependent things
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::c64_ctor1(void)
|
|
||||||
{
|
|
||||||
joy[0] = joy[1] = NULL;
|
|
||||||
joy_geek_port[0] = joy_geek_port[1] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void C64::c64_ctor2(void)
|
|
||||||
{
|
|
||||||
// Initialize joystick variables
|
|
||||||
joy_minx = joy_miny = 32767;
|
|
||||||
joy_maxx = joy_maxy = 0;
|
|
||||||
|
|
||||||
// Initialize semaphores (initially acquired)
|
|
||||||
pause_sem = create_sem(0, "Frodo Pause Semaphore");
|
|
||||||
sound_sync_sem = create_sem(0, "Frodo Sound Sync Semaphore");
|
|
||||||
|
|
||||||
// Preset speedometer start time
|
|
||||||
start_time = system_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destructor, system-dependent things
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::c64_dtor(void)
|
|
||||||
{
|
|
||||||
delete_sem(pause_sem);
|
|
||||||
delete_sem(sound_sync_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
// Start the CPU thread
|
|
||||||
the_thread = spawn_thread(thread_invoc, "Frodo 6510", B_URGENT_DISPLAY_PRIORITY, this);
|
|
||||||
thread_running = true;
|
|
||||||
quit_thyself = false;
|
|
||||||
have_a_break = false;
|
|
||||||
resume_thread(the_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop main emulation thread
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::Quit(void)
|
|
||||||
{
|
|
||||||
long ret;
|
|
||||||
|
|
||||||
// Ask the thread to quit itself if it is running
|
|
||||||
if (thread_running) {
|
|
||||||
if (have_a_break)
|
|
||||||
Resume();
|
|
||||||
quit_thyself = true;
|
|
||||||
wait_for_thread(the_thread, &ret);
|
|
||||||
thread_running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pause main emulation thread
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::Pause(void)
|
|
||||||
{
|
|
||||||
// Ask the thread to pause and wait for acknowledge
|
|
||||||
if (thread_running && !have_a_break) {
|
|
||||||
have_a_break = true;
|
|
||||||
acquire_sem(pause_sem);
|
|
||||||
TheSID->PauseSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Resume main emulation thread
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::Resume(void)
|
|
||||||
{
|
|
||||||
if (thread_running && have_a_break) {
|
|
||||||
have_a_break = false;
|
|
||||||
release_sem(pause_sem);
|
|
||||||
TheSID->ResumeSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Vertical blank: Poll keyboard and joysticks, update window
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::VBlank(bool draw_frame)
|
|
||||||
{
|
|
||||||
bigtime_t elapsed_time;
|
|
||||||
long speed_index;
|
|
||||||
|
|
||||||
// To avoid deadlocks on quitting
|
|
||||||
if (quit_thyself) return;
|
|
||||||
|
|
||||||
// Pause requested?
|
|
||||||
if (have_a_break) {
|
|
||||||
release_sem(pause_sem); // Acknowledge pause
|
|
||||||
acquire_sem(pause_sem); // Wait for resume
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll keyboard
|
|
||||||
TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
elapsed_time = system_time() - start_time;
|
|
||||||
speed_index = 20000 * 100 * ThePrefs.SkipFrames / (elapsed_time + 1);
|
|
||||||
|
|
||||||
// Limit speed to 100% if desired (20ms/frame)
|
|
||||||
// If the SID emulation is on and no frames are skipped, synchronize to the SID
|
|
||||||
if (ThePrefs.LimitSpeed && speed_index > 100) {
|
|
||||||
if (ThePrefs.SIDType == SIDTYPE_DIGITAL && ThePrefs.SkipFrames == 1) {
|
|
||||||
long l;
|
|
||||||
get_sem_count(sound_sync_sem, &l);
|
|
||||||
if (l > 0) // Avoid C64 lagging behind
|
|
||||||
acquire_sem_etc(sound_sync_sem, l+1, 0, 0);
|
|
||||||
else
|
|
||||||
acquire_sem(sound_sync_sem);
|
|
||||||
} else
|
|
||||||
snooze(ThePrefs.SkipFrames * 20000 - elapsed_time);
|
|
||||||
speed_index = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
start_time = system_time();
|
|
||||||
|
|
||||||
TheDisplay->Speedometer(speed_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called by SID after playing 1/50 sec of sound
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::SoundSync(void)
|
|
||||||
{
|
|
||||||
release_sem(sound_sync_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open/close joystick drivers given old and new state of
|
|
||||||
* joystick preferences
|
|
||||||
*/
|
|
||||||
|
|
||||||
void C64::open_close_joystick(int port, int oldjoy, int newjoy)
|
|
||||||
{
|
|
||||||
if (oldjoy != newjoy) {
|
|
||||||
joy_minx = joy_miny = 32767; // Reset calibration
|
|
||||||
joy_maxx = joy_maxy = 0;
|
|
||||||
if (joy[port]) {
|
|
||||||
if (joy_geek_port[port]) {
|
|
||||||
((BDigitalPort *)joy[port])->Close();
|
|
||||||
delete (BDigitalPort *)joy[port];
|
|
||||||
} else {
|
|
||||||
((BJoystick *)joy[port])->Close();
|
|
||||||
delete (BJoystick *)joy[port];
|
|
||||||
}
|
|
||||||
joy[port] = NULL;
|
|
||||||
}
|
|
||||||
switch (newjoy) {
|
|
||||||
case 1:
|
|
||||||
joy[port] = new BJoystick;
|
|
||||||
((BJoystick *)joy[port])->Open("joystick1");
|
|
||||||
joy_geek_port[port] = false;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
joy[port] = new BJoystick;
|
|
||||||
((BJoystick *)joy[port])->Open("joystick2");
|
|
||||||
joy_geek_port[port] = false;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
joy[port] = new BDigitalPort;
|
|
||||||
((BDigitalPort *)joy[port])->Open("DigitalA");
|
|
||||||
joy_geek_port[port] = true;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
joy[port] = new BDigitalPort;
|
|
||||||
((BDigitalPort *)joy[port])->Open("DigitalB");
|
|
||||||
joy_geek_port[port] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void C64::open_close_joysticks(int oldjoy1, int oldjoy2, int newjoy1, int newjoy2)
|
|
||||||
{
|
|
||||||
open_close_joystick(0, oldjoy1, newjoy1);
|
|
||||||
open_close_joystick(1, oldjoy2, newjoy2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Poll joystick port, return CIA mask
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 C64::poll_joystick(int port)
|
|
||||||
{
|
|
||||||
uint8 j = 0xff;
|
|
||||||
|
|
||||||
if (joy[port] == NULL)
|
|
||||||
return j;
|
|
||||||
|
|
||||||
if (joy_geek_port[port]) {
|
|
||||||
|
|
||||||
// GeekPort
|
|
||||||
uint8 val;
|
|
||||||
if (((BDigitalPort *)joy[port])->Read(&val) == 1)
|
|
||||||
j = val | 0xe0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Joystick port
|
|
||||||
BJoystick *p = (BJoystick *)joy[port];
|
|
||||||
if (p->Update() != B_ERROR) {
|
|
||||||
if (p->horizontal > joy_maxx)
|
|
||||||
joy_maxx = p->horizontal;
|
|
||||||
if (p->horizontal < joy_minx)
|
|
||||||
joy_minx = p->horizontal;
|
|
||||||
if (p->vertical > joy_maxy)
|
|
||||||
joy_maxy = p->vertical;
|
|
||||||
if (p->vertical < joy_miny)
|
|
||||||
joy_miny = p->vertical;
|
|
||||||
|
|
||||||
if (!p->button1)
|
|
||||||
j &= 0xef; // Button
|
|
||||||
|
|
||||||
if (joy_maxx-joy_minx < 100 || joy_maxy-joy_miny < 100)
|
|
||||||
return j;
|
|
||||||
|
|
||||||
if (p->horizontal < (joy_minx + (joy_maxx-joy_minx)/3))
|
|
||||||
j &= 0xf7; // Right
|
|
||||||
else if (p->horizontal > (joy_minx + 2*(joy_maxx-joy_minx)/3))
|
|
||||||
j &= 0xfb; // Left
|
|
||||||
|
|
||||||
if (p->vertical < (joy_miny + (joy_maxy-joy_miny)/3))
|
|
||||||
j &= 0xfd; // Down
|
|
||||||
else if (p->vertical > (joy_miny + 2*(joy_maxy-joy_miny)/3))
|
|
||||||
j &= 0xfe; // Up
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The emulation's main loop
|
|
||||||
*/
|
|
||||||
|
|
||||||
long C64::thread_invoc(void *obj)
|
|
||||||
{
|
|
||||||
((C64 *)obj)->thread_func();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void C64::thread_func(void)
|
|
||||||
{
|
|
||||||
#ifdef PROFILING
|
|
||||||
static bigtime_t vic_time_acc = 0;
|
|
||||||
static bigtime_t sid_time_acc = 0;
|
|
||||||
static bigtime_t cia_time_acc = 0;
|
|
||||||
static bigtime_t cpu_time_acc = 0;
|
|
||||||
#endif
|
|
||||||
#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
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t start_time = system_time();
|
|
||||||
#endif
|
|
||||||
int cycles = TheVIC->EmulateLine();
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t vic_time = system_time();
|
|
||||||
#endif
|
|
||||||
TheSID->EmulateLine();
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t sid_time = system_time();
|
|
||||||
#endif
|
|
||||||
#if !PRECISE_CIA_CYCLES
|
|
||||||
TheCIA1->EmulateLine(ThePrefs.CIACycles);
|
|
||||||
TheCIA2->EmulateLine(ThePrefs.CIACycles);
|
|
||||||
#endif
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t cia_time = system_time();
|
|
||||||
#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);
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t cpu_time = system_time();
|
|
||||||
vic_time_acc += vic_time - start_time;
|
|
||||||
sid_time_acc += sid_time - vic_time;
|
|
||||||
cia_time_acc += cia_time - sid_time;
|
|
||||||
cpu_time_acc += cpu_time - cia_time;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PROFILING
|
|
||||||
bigtime_t total_time = vic_time_acc + sid_time_acc + cia_time_acc + cpu_time_acc;
|
|
||||||
printf("VIC: %Ld\n", vic_time_acc * 100 / total_time);
|
|
||||||
printf("SID: %Ld\n", sid_time_acc * 100 / total_time);
|
|
||||||
printf("CIA: %Ld\n", cia_time_acc * 100 / total_time);
|
|
||||||
printf("CPU: %Ld\n", cpu_time_acc * 100 / total_time);
|
|
||||||
#endif
|
|
||||||
}
|
|
181
Src/CmdPipe.cpp
181
Src/CmdPipe.cpp
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* CmdPipe.cpp
|
|
||||||
*
|
|
||||||
* 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 "CmdPipe.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#if defined(__alpha__)
|
|
||||||
#include <cma.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(AIX)
|
|
||||||
#include <sys/select.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kaputt(const char * c1, const char * c2) {
|
|
||||||
fprintf(stderr,"error: %s%s\n",c1,c2);
|
|
||||||
exit(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
Pipe::Pipe(void) : fail(true) {
|
|
||||||
|
|
||||||
fds[0] = 0;
|
|
||||||
fds[1] = 1;
|
|
||||||
|
|
||||||
if (-1 == pipe(fds)) {
|
|
||||||
kaputt("Pipe: ","unable to create pipe");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fail = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pipe::~Pipe(void) {
|
|
||||||
|
|
||||||
if (! fail) {
|
|
||||||
close(fds[0]);
|
|
||||||
close(fds[1]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long Pipe::ewrite(const void * buf, unsigned long len) {
|
|
||||||
|
|
||||||
unsigned long wsum = 0;
|
|
||||||
while (len) {
|
|
||||||
long wlen;
|
|
||||||
|
|
||||||
wlen = ::write(fds[1], buf, (long) len);
|
|
||||||
if (wlen <= 0) {
|
|
||||||
kaputt("Pipe::ewrite ","write-error");
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= wlen;
|
|
||||||
buf = (void*) ((char*) buf + wlen);
|
|
||||||
wsum += wlen;
|
|
||||||
}
|
|
||||||
return wsum;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long Pipe::eread(void * buf, unsigned long len) {
|
|
||||||
|
|
||||||
unsigned long rsum = 0;
|
|
||||||
while (len) {
|
|
||||||
long rlen;
|
|
||||||
|
|
||||||
rlen = ::read(fds[0], buf, (long) len);
|
|
||||||
|
|
||||||
if (rlen <= 0) {
|
|
||||||
kaputt("Pipe::eread ","read-error");
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= rlen;
|
|
||||||
buf = (void*) ((char*) buf + rlen);
|
|
||||||
rsum += rlen;
|
|
||||||
}
|
|
||||||
return rsum;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Pipe::probe(void) const {
|
|
||||||
|
|
||||||
fd_set set;
|
|
||||||
FD_ZERO(&set);
|
|
||||||
FD_SET(fds[0], &set);
|
|
||||||
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
|
|
||||||
int res;
|
|
||||||
// Use the following commented line for HP-UX < 10.20
|
|
||||||
// res = select(FD_SETSIZE, (int *)&set, (int *)0, (int *)0, &tv);
|
|
||||||
res = select(FD_SETSIZE, &set, (fd_set *)0, (fd_set *)0, &tv);
|
|
||||||
|
|
||||||
if (res > 0) return -1;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CmdPipe::CmdPipe(const char * command, const char * arg, int nicediff) : childpid(0), fail(true) {
|
|
||||||
|
|
||||||
if (tocmd.fail || fromcmd.fail) {
|
|
||||||
kaputt("CmdPipe: ","unable to initialize pipes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
childpid = fork();
|
|
||||||
|
|
||||||
if (childpid == -1) {
|
|
||||||
childpid = 0;
|
|
||||||
kaputt("CmdPipe: ","unable to fork process");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (childpid == 0) {
|
|
||||||
|
|
||||||
if (nicediff) {
|
|
||||||
if (-1 == nice(nicediff)) {
|
|
||||||
fprintf(stderr,"CmdPipe: unable to change nice-level (non-fatal)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dup2(tocmd.get_read_fd(), STDIN_FILENO);
|
|
||||||
|
|
||||||
dup2(fromcmd.get_write_fd(), STDOUT_FILENO);
|
|
||||||
execlp(command, "Frodo_GUI", arg, (char *)0);
|
|
||||||
kaputt("CmdPipe: unable to execute child process ",command);
|
|
||||||
_exit(0); // exit (and do NOT call destructors etc..)
|
|
||||||
}
|
|
||||||
|
|
||||||
fail = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CmdPipe::~CmdPipe(void) {
|
|
||||||
|
|
||||||
if (childpid) {
|
|
||||||
int status;
|
|
||||||
waitpid(childpid, &status, 0);
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
fprintf(stderr,"~CmdPipe child process returned error\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* CmdPipe.h
|
|
||||||
*
|
|
||||||
* 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 CmdPipe_h
|
|
||||||
#define CmdPipe_h
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
class Pipe {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
int fds[2];
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool fail;
|
|
||||||
|
|
||||||
Pipe(void);
|
|
||||||
Pipe(int fdin, int fdout) : fail(false) {
|
|
||||||
fds[0] = fdin;
|
|
||||||
fds[1] = fdout;
|
|
||||||
}
|
|
||||||
~Pipe(void);
|
|
||||||
|
|
||||||
unsigned long ewrite(const void * buf, unsigned long len);
|
|
||||||
unsigned long eread (void * buf, unsigned long len);
|
|
||||||
|
|
||||||
int get_read_fd(void) const {
|
|
||||||
return fds[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_write_fd(void) const {
|
|
||||||
return fds[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
int probe(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CmdPipe {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Pipe tocmd;
|
|
||||||
Pipe fromcmd;
|
|
||||||
|
|
||||||
int childpid;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool fail;
|
|
||||||
|
|
||||||
CmdPipe(const char * command, const char * arg, int nicediff = 0);
|
|
||||||
~CmdPipe(void);
|
|
||||||
|
|
||||||
unsigned long ewrite(const void * buf, unsigned long len) {
|
|
||||||
return tocmd.ewrite(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long eread (void * buf, unsigned long len) {
|
|
||||||
return fromcmd.eread(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_read_fd(void) const {
|
|
||||||
return fromcmd.get_read_fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_write_fd(void) const {
|
|
||||||
return tocmd.get_write_fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
int probe(void) const {
|
|
||||||
return fromcmd.probe();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CmdPipe_h
|
|
298
Src/SID_Amiga.h
298
Src/SID_Amiga.h
@ -1,298 +0,0 @@
|
|||||||
/*
|
|
||||||
* SID_Amiga.h - 6581 emulation, Amiga specific stuff
|
|
||||||
*
|
|
||||||
* 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 <dos/dostags.h>
|
|
||||||
#include <hardware/cia.h>
|
|
||||||
#include <proto/exec.h>
|
|
||||||
#include <proto/dos.h>
|
|
||||||
#include <proto/ahi.h>
|
|
||||||
#include <proto/graphics.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Library bases
|
|
||||||
struct Library *AHIBase;
|
|
||||||
|
|
||||||
// CIA-A base
|
|
||||||
extern struct CIA ciaa;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialization, create sub-process
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DigitalRenderer::init_sound(void)
|
|
||||||
{
|
|
||||||
// Find our (main) task
|
|
||||||
main_task = FindTask(NULL);
|
|
||||||
|
|
||||||
// Create signal for communication
|
|
||||||
main_sig = AllocSignal(-1);
|
|
||||||
|
|
||||||
// Create sub-process and wait until it is ready
|
|
||||||
if ((sound_process = CreateNewProcTags(
|
|
||||||
NP_Entry, (ULONG)&sub_invoc,
|
|
||||||
NP_Name, (ULONG)"Frodo Sound Process",
|
|
||||||
NP_Priority, 1,
|
|
||||||
NP_ExitData, (ULONG)this, // Easiest way to supply sub_invoc with this pointer
|
|
||||||
TAG_DONE)) != NULL)
|
|
||||||
Wait(1 << main_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destructor, delete sub-process
|
|
||||||
*/
|
|
||||||
|
|
||||||
DigitalRenderer::~DigitalRenderer()
|
|
||||||
{
|
|
||||||
// Tell sub-process to quit and wait for completion
|
|
||||||
if (sound_process != NULL) {
|
|
||||||
Signal(&(sound_process->pr_Task), 1 << quit_sig);
|
|
||||||
Wait(1 << main_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free signal
|
|
||||||
FreeSignal(main_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sample volume (for sampled voice)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DigitalRenderer::EmulateLine(void)
|
|
||||||
{
|
|
||||||
sample_buf[sample_in_ptr] = volume;
|
|
||||||
sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pause sound output
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DigitalRenderer::Pause(void)
|
|
||||||
{
|
|
||||||
if (sound_process != NULL)
|
|
||||||
Signal(&(sound_process->pr_Task), 1 << pause_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Resume sound output
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DigitalRenderer::Resume(void)
|
|
||||||
{
|
|
||||||
if (sound_process != NULL)
|
|
||||||
Signal(&(sound_process->pr_Task), 1 << resume_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sound sub-process
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DigitalRenderer::sub_invoc(void)
|
|
||||||
{
|
|
||||||
// Get pointer to the DigitalRenderer object and call sub_func()
|
|
||||||
DigitalRenderer *r = (DigitalRenderer *)((struct Process *)FindTask(NULL))->pr_ExitData;
|
|
||||||
r->sub_func();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DigitalRenderer::sub_func(void)
|
|
||||||
{
|
|
||||||
ahi_port = NULL;
|
|
||||||
ahi_io = NULL;
|
|
||||||
ahi_ctrl = NULL;
|
|
||||||
sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
|
|
||||||
ready = FALSE;
|
|
||||||
|
|
||||||
// Create signals for communication
|
|
||||||
quit_sig = AllocSignal(-1);
|
|
||||||
pause_sig = AllocSignal(-1);
|
|
||||||
resume_sig = AllocSignal(-1);
|
|
||||||
ahi_sig = AllocSignal(-1);
|
|
||||||
|
|
||||||
// Open AHI
|
|
||||||
if ((ahi_port = CreateMsgPort()) == NULL)
|
|
||||||
goto wait_for_quit;
|
|
||||||
if ((ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest))) == NULL)
|
|
||||||
goto wait_for_quit;
|
|
||||||
ahi_io->ahir_Version = 2;
|
|
||||||
if (OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, NULL))
|
|
||||||
goto wait_for_quit;
|
|
||||||
AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device;
|
|
||||||
|
|
||||||
// Initialize callback hook
|
|
||||||
sf_hook.h_Entry = sound_func;
|
|
||||||
|
|
||||||
// Open audio control structure
|
|
||||||
if ((ahi_ctrl = AHI_AllocAudio(
|
|
||||||
AHIA_AudioID, 0x0002000b,
|
|
||||||
AHIA_MixFreq, SAMPLE_FREQ,
|
|
||||||
AHIA_Channels, 1,
|
|
||||||
AHIA_Sounds, 2,
|
|
||||||
AHIA_SoundFunc, (ULONG)&sf_hook,
|
|
||||||
AHIA_UserData, (ULONG)this,
|
|
||||||
TAG_DONE)) == NULL)
|
|
||||||
goto wait_for_quit;
|
|
||||||
|
|
||||||
// Prepare SampleInfos and load sounds (two sounds for double buffering)
|
|
||||||
sample[0].ahisi_Type = AHIST_M16S;
|
|
||||||
sample[0].ahisi_Length = SAMPLE_FREQ / CALC_FREQ;
|
|
||||||
sample[0].ahisi_Address = AllocVec(SAMPLE_FREQ / CALC_FREQ * 2, MEMF_PUBLIC | MEMF_CLEAR);
|
|
||||||
sample[1].ahisi_Type = AHIST_M16S;
|
|
||||||
sample[1].ahisi_Length = SAMPLE_FREQ / CALC_FREQ;
|
|
||||||
sample[1].ahisi_Address = AllocVec(SAMPLE_FREQ / CALC_FREQ * 2, MEMF_PUBLIC | MEMF_CLEAR);
|
|
||||||
if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
|
|
||||||
goto wait_for_quit;
|
|
||||||
AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
|
|
||||||
AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
|
|
||||||
|
|
||||||
// Set parameters
|
|
||||||
play_buf = 0;
|
|
||||||
AHI_SetVol(0, 0x10000, 0x8000, ahi_ctrl, AHISF_IMM);
|
|
||||||
AHI_SetFreq(0, SAMPLE_FREQ, ahi_ctrl, AHISF_IMM);
|
|
||||||
AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
|
|
||||||
|
|
||||||
// Start audio output
|
|
||||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
|
|
||||||
|
|
||||||
// We are now ready for commands
|
|
||||||
ready = TRUE;
|
|
||||||
Signal(main_task, 1 << main_sig);
|
|
||||||
|
|
||||||
// Accept and execute commands
|
|
||||||
for (;;) {
|
|
||||||
ULONG sigs = Wait((1 << quit_sig) | (1 << pause_sig) | (1 << resume_sig) | (1 << ahi_sig));
|
|
||||||
|
|
||||||
// Quit sub-process
|
|
||||||
if (sigs & (1 << quit_sig))
|
|
||||||
goto quit;
|
|
||||||
|
|
||||||
// Pause sound output
|
|
||||||
if (sigs & (1 << pause_sig))
|
|
||||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_DONE);
|
|
||||||
|
|
||||||
// Resume sound output
|
|
||||||
if (sigs & (1 << resume_sig))
|
|
||||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_DONE);
|
|
||||||
|
|
||||||
// Calculate next buffer
|
|
||||||
if (sigs & (1 << ahi_sig))
|
|
||||||
calc_buffer((int16 *)(sample[play_buf].ahisi_Address), sample[play_buf].ahisi_Length * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_quit:
|
|
||||||
// Initialization failed, wait for quit signal
|
|
||||||
Wait(1 << quit_sig);
|
|
||||||
|
|
||||||
quit:
|
|
||||||
// Free everything
|
|
||||||
if (ahi_ctrl != NULL) {
|
|
||||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_DONE);
|
|
||||||
AHI_FreeAudio(ahi_ctrl);
|
|
||||||
CloseDevice((struct IORequest *)ahi_io);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeVec(sample[0].ahisi_Address);
|
|
||||||
FreeVec(sample[1].ahisi_Address);
|
|
||||||
|
|
||||||
if (ahi_io != NULL)
|
|
||||||
DeleteIORequest((struct IORequest *)ahi_io);
|
|
||||||
|
|
||||||
if (ahi_port != NULL)
|
|
||||||
DeleteMsgPort(ahi_port);
|
|
||||||
|
|
||||||
FreeSignal(quit_sig);
|
|
||||||
FreeSignal(pause_sig);
|
|
||||||
FreeSignal(resume_sig);
|
|
||||||
FreeSignal(ahi_sig);
|
|
||||||
|
|
||||||
// Quit (synchronized with main task)
|
|
||||||
Forbid();
|
|
||||||
Signal(main_task, 1 << main_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AHI sound callback, play next buffer and signal sub-process
|
|
||||||
*/
|
|
||||||
|
|
||||||
ULONG DigitalRenderer::sound_func(void)
|
|
||||||
{
|
|
||||||
register struct AHIAudioCtrl *ahi_ctrl asm ("a2");
|
|
||||||
DigitalRenderer *r = (DigitalRenderer *)ahi_ctrl->ahiac_UserData;
|
|
||||||
r->play_buf ^= 1;
|
|
||||||
AHI_SetSound(0, r->play_buf, 0, 0, ahi_ctrl, 0);
|
|
||||||
Signal(&(r->sound_process->pr_Task), 1 << (r->ahi_sig));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Renderer for SID card
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Renderer class
|
|
||||||
class SIDCardRenderer : public SIDRenderer {
|
|
||||||
public:
|
|
||||||
SIDCardRenderer();
|
|
||||||
virtual ~SIDCardRenderer();
|
|
||||||
|
|
||||||
virtual void Reset(void);
|
|
||||||
virtual void EmulateLine(void) {}
|
|
||||||
virtual void WriteRegister(uint16 adr, uint8 byte);
|
|
||||||
virtual void NewPrefs(Prefs *prefs) {}
|
|
||||||
virtual void Pause(void) {}
|
|
||||||
virtual void Resume(void) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
UBYTE *sid_base; // SID card base pointer
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constructor: Reset SID
|
|
||||||
SIDCardRenderer::SIDCardRenderer()
|
|
||||||
{
|
|
||||||
sid_base = (UBYTE *)0xa00001;
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor: Reset SID
|
|
||||||
SIDCardRenderer::~SIDCardRenderer()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset SID
|
|
||||||
void SIDCardRenderer::Reset(void)
|
|
||||||
{
|
|
||||||
WaitTOF();
|
|
||||||
ciaa.ciapra |= CIAF_LED;
|
|
||||||
WaitTOF();
|
|
||||||
ciaa.ciapra &= ~CIAF_LED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to register
|
|
||||||
void SIDCardRenderer::WriteRegister(uint16 adr, uint8 byte)
|
|
||||||
{
|
|
||||||
sid_base[adr << 1] = byte;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user