#floppyImage1 = ./disks/temp.nib
#floppyImage1 = ./disks/temp.dsk
# Yes
-#floppyImage1 = ./disks/bt1_boot.dsk
+floppyImage1 = ./disks/bt1_boot.dsk
# Yes
#floppyImage1 = ./disks/bt2_boot.dsk
# Yes (but segfaults in the timer routine in the title screen--NB: Not anymore...)
#floppyImage1 = ./disks/MoebiusI-1.dsk
#floppyImage2 = ./disks/MoebiusI-2.dsk
# Yes, but crashes on the attract mode (does the same in AppleWin)
-# Also, has keyboard troubles... no, write problems
+# Also, write problems
#floppyImage1 = ./disks/moebiusiia.dsk
-floppyImage1 = ./disks/MoebiusIIA.dsk
-floppyImage2 = ./disks/MoebiusIIB.dsk
-# Yes, but segfaults on title screen
+#floppyImage1 = ./disks/MoebiusIIA.dsk
+#floppyImage2 = ./disks/MoebiusIIB.dsk
+# Yes
#floppyImage1 = ./disks/wind_walker_1.dsk
# Yes
#floppyImage1 = ./disks/dino_eggs.dsk
# OpenGL options: 1 - use OpenGL rendering, 0 - use old style rendering
-useOpenGL = 0
+useOpenGL = 1
# OpenGL filtering type: 1 - blurry, 0 - sharp
return false;
}
+//#define CPU_CLOCK_CHECKING
+#ifdef CPU_CLOCK_CHECKING
+uint8 counter = 0;
+uint32 totalCPU = 0;
+#endif
//
// Main loop
//
//(Fix so that this is not a requirement!)
//Fixed, but mainCPU.clock is destroyed in the bargain. Oh well.
// mainCPU.clock -= USEC_TO_M6502_CYCLES(timeToNextEvent);
+#ifdef CPU_CLOCK_CHECKING
+totalCPU += USEC_TO_M6502_CYCLES(timeToNextEvent);
+#endif
// Handle CPU time delta for sound...
- AddToSoundTimeBase(USEC_TO_M6502_CYCLES(timeToNextEvent));
+//Don't need this anymore now that we use absolute time...
+// AddToSoundTimeBase(USEC_TO_M6502_CYCLES(timeToNextEvent));
HandleNextEvent();
}
if (event.key.keysym.sym == SDLK_F12)
dumpDis = !dumpDis; // Toggle the disassembly process
- else if (event.key.keysym.sym == SDLK_F11)
- floppyDrive.LoadImage("./disks/bt1_char.dsk");//Kludge to load char disk...
+// else if (event.key.keysym.sym == SDLK_F11)
+// floppyDrive.LoadImage("./disks/bt1_char.dsk");//Kludge to load char disk...
else if (event.key.keysym.sym == SDLK_F9)
{
floppyDrive.CreateBlankImage();
// to quit completely... !!! FIX !!!
gui->Run();
+ if (event.key.keysym.sym == SDLK_F5)
+ {
+ VolumeDown();
+ char volStr[10] = "*********";
+ volStr[GetVolume()] = 0;
+ SpawnMessage("Volume: %s", volStr);
+ }
+ else if (event.key.keysym.sym == SDLK_F6)
+ {
+ VolumeUp();
+ char volStr[10] = "*********";
+ volStr[GetVolume()] = 0;
+ SpawnMessage("Volume: %s", volStr);
+ }
+
break;
case SDL_QUIT:
running = false;
}
}
-//ick. HandleSoundAtFrameEdge(); // Sound stuff... (ick)
RenderVideoFrame();
SetCallbackTime(FrameCallback, 16666.66666667);
+#ifdef CPU_CLOCK_CHECKING
+counter++;
+if (counter == 60)
+{
+ printf("Executed %u cycles...\n", totalCPU);
+ totalCPU = 0;
+ counter = 0;
+}
+#endif
//Instead of this, we should yield remaining time to other processes... !!! FIX !!!
//lessee...
//nope. SDL_Delay(10);
fclose(fp2);
}
#endif
+//writeProtected[driveNum] = true;
WriteLog("FLOPPY: Loaded image '%s' for drive #%u.\n", filename, driveNum);
return true;
nybblizedImage[activeDrive][(track * 6656) + currentPos] = latchValue;
imageDirty[activeDrive] = true;
}
+ else
+//doesn't seem to do anything
+ return 0;//is this more like it?
}
uint8 diskByte = nybblizedImage[activeDrive][(track * 6656) + currentPos];
writeProtect1 = new Button(4, 176, "WriteProt1", this);
writeProtect2 = new Button(4, 196, "WriteProt2", this);
swap = new Button(4, 220, "Swap Disks", this);
-//Weird... It's showing an initial state of write-protected even though
-//the constructor of FloppyDrive sets it to false!
-#warning "Write protection state is wrong. !!! FIX !!!"
- writeProtect1->SetText((floppyDrive->DiskIsWriteProtected(0) ? "write" : "no write"));
- writeProtect2->SetText((floppyDrive->DiskIsWriteProtected(1) ? "write" : "no write"));
+
+ writeProtect1->SetText((floppyDrive->DiskIsWriteProtected(0) ? "no write" : "write"));
+ writeProtect2->SetText((floppyDrive->DiskIsWriteProtected(1) ? "no write" : "write"));
AddElement(newDisk1);
AddElement(newDisk2);
// floppyDrive->SetWriteProtect(true, 0);
// Housekeeping
- writeProtect1->SetText((floppyDrive->DiskIsWriteProtected(0) ? "write" : "no write"));
+ writeProtect1->SetText((floppyDrive->DiskIsWriteProtected(0) ? "no write" : "write"));
Draw();
}
else if (e == writeProtect2)
floppyDrive->SetWriteProtect((floppyDrive->DiskIsWriteProtected(1) ? false : true), 1);
// Housekeeping
- writeProtect2->SetText((floppyDrive->DiskIsWriteProtected(1) ? "write" : "no write"));
+ writeProtect2->SetText((floppyDrive->DiskIsWriteProtected(1) ? "no write" : "write"));
Draw();
}
else if (e == swap)
return extents;
}
+//kludge
+#include "settings.h"
void Element::CreateBackstore(void)
{
backstore = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
MASK_R, MASK_G, MASK_B, 0x00);
+//#define TEST_GL
+#ifdef TEST_GL
+printf("Element: About to do SDL_BlitSurface...\n");
+#endif
+//kludge
+if (settings.useOpenGL)
+ return;
+
+//Since screen is the main screen surface, OpenGL doesn't like it being touched.
+//How to fix? Dunno.
SDL_BlitSurface(screen, &extents, backstore, NULL);
+#ifdef TEST_GL
+printf("Element: SDL_BlitSurface...Done.\n");
+#endif
}
void Element::RestoreScreenFromBackstore(void)
SDL_EnableKeyRepeat(150, 75);
+ // Also: Need to pick up backbuffer (for those windows that have them)
+ // BEFORE drawing...
+
// Initial update... [Now handled correctly in the constructor]
// Uh, still needed here, though... Only makes sense that it should
for(i=windowList.begin(); i!=windowList.end(); i++)
#include "log.h"
-#define SAMPLE_RATE (44100.0)
+//#define SAMPLE_RATE (44100.0)
+#define SAMPLE_RATE (48000.0)
#define SAMPLES_PER_FRAME (SAMPLE_RATE / 60.0)
#define CYCLES_PER_SAMPLE (1024000.0 / SAMPLE_RATE)
#define SOUND_BUFFER_SIZE (8192)
static uint8 soundBuffer[SOUND_BUFFER_SIZE];
static uint32 soundBufferPos;
static uint32 sampleBase;
+static uint64 lastToggleCycles;
+static uint64 samplePosition;
static SDL_cond * conditional = NULL;
static SDL_mutex * mutex = NULL;
static SDL_mutex * mutex2 = NULL;
SDL_mutexP(mutex); // Must lock the mutex for the cond to work properly...
soundBufferPos = 0;
sampleBase = 0;
+ lastToggleCycles = 0;
+ samplePosition = 0;
SDL_PauseAudio(false); // Start playback!
soundInitialized = true;
soundBuffer[i] = soundBuffer[length + i];
}
+ // Update our sample position
+ samplePosition += length;
// Free the mutex...
SDL_mutexV(mutex2);
// Wake up any threads waiting for the buffer to drain...
-// SDL_CondSignal(conditional);
+ SDL_CondSignal(conditional);
}
// Need some interface functions here to take care of flipping the
the time position back (or copies data down from what it took out)
*/
-void ToggleSpeaker(uint32 time)
+void ToggleSpeaker(uint64 elapsedCycles)
{
if (!soundInitialized)
return;
+ uint64 deltaCycles = elapsedCycles - lastToggleCycles;
+
#if 0
if (time > 95085)//(time & 0x80000000)
{
// SDL_LockAudio();
SDL_mutexP(mutex2);
- uint32 currentPos = sampleBase + (uint32)((double)time / CYCLES_PER_SAMPLE);
+// uint32 currentPos = sampleBase + (uint32)((double)elapsedCycles / CYCLES_PER_SAMPLE);
+ uint32 currentPos = (uint32)((double)deltaCycles / CYCLES_PER_SAMPLE);
+
+/*
+The problem:
+
+ ______ | ______________ | ______
+____| | | |_______
+
+Speaker is toggled, then not toggled for a while. How to find buffer position in the
+last frame?
+
+IRQ buffer len is 1024.
+
+Could check current CPU clock, take delta. If delta > 1024, then ...
+
+Could add # of cycles in IRQ to lastToggleCycles, then currentPos will be guaranteed
+to fall within acceptable limits.
+*/
+
if (currentPos > SOUND_BUFFER_SIZE - 1)
{
// SDL_UnlockAudio();
// SDL_CondWait(conditional, mutex);
// SDL_LockAudio();
- currentPos = sampleBase + (uint32)((double)time / CYCLES_PER_SAMPLE);
+// Hm.
+SDL_mutexV(mutex2);//Release it so sound thread can get it,
+SDL_CondWait(conditional, mutex);//Sleep/wait for the sound thread
+SDL_mutexP(mutex2);//Re-lock it until we're done with it...
+
+ currentPos = sampleBase + (uint32)((double)elapsedCycles / CYCLES_PER_SAMPLE);
#if 0
WriteLog("--> after spinlock (sampleBase=%u)...\n", sampleBase);
#endif
// SDL_UnlockAudio();
}
+void VolumeUp(void)
+{
+ // Currently set for 8-bit samples
+ if (ampPtr < 8)
+ ampPtr++;
+}
+
+void VolumeDown(void)
+{
+ if (ampPtr > 0)
+ ampPtr--;
+}
+
+uint8 GetVolume(void)
+{
+ return ampPtr;
+}
+
/*
HOW IT WORKS
void SoundInit(void);
void SoundDone(void);
-void ToggleSpeaker(uint32 time);
-void AddToSoundTimeBase(uint32 cycles);
+void ToggleSpeaker(uint64 elapsedCycles);
+void AddToSoundTimeBase(uint64 cycles);
+void VolumeUp(void);
+void VolumeDown(void);
+uint8 GetVolume(void);
#endif // __SOUND_H__
//#define USEC_TO_RISC_CYCLES(u) (uint32)(((u) / RISC_CYCLE_IN_USEC) + 0.5)
//#define USEC_TO_M68K_CYCLES(u) (uint32)(((u) / M68K_CYCLE_IN_USEC) + 0.5)
-#define USEC_TO_M6502_CYCLES(u) (uint32)(((u) / M6502_CYCLE_IN_USEC) + 0.5)
+#define USEC_TO_M6502_CYCLES(u) ((uint32)(((u) / M6502_CYCLE_IN_USEC) + 0.5))
void InitializeEventList(void);
void SetCallbackTime(void (* callback)(void), double time);
if (regs.clock + cycles > 0xFFFFFFFF)
wraparound = true;
*/
+ uint64 endCycles = regs.clock + (uint64)cycles;
- while (regs.clock < cycles)
+ while (regs.clock < endCycles)
{
#if 0
/*if (regs.pc == 0x4007)
//This is a lame way of doing it, but in the end the simplest--however, it destroys any
//record of elasped CPU time. Not sure that it's important to keep track, but there it is.
- regs.clock -= cycles;
+// Now we use a 64-bit integer, so it won't wrap for about 500 millenia. ;-)
+// regs.clock -= cycles;
myMemcpy(context, ®s, sizeof(V65C02REGS));
}
//
// Get the clock of the currently executing CPU
//
-uint32 GetCurrentV65C02Clock(void)
+uint64 GetCurrentV65C02Clock(void)
{
return regs.clock;
}
uint8 a; // 65C02 A register
uint8 x; // 65C02 X index register
uint8 y; // 65C02 Y register
- uint32 clock; // 65C02 clock (@ 1 MHz, wraps at 71.5 minutes)
+// uint32 clock; // 65C02 clock (@ 1 MHz, wraps at 71.5 minutes)
+ uint64 clock; // 65C02 clock (@ 1 MHz, wraps at 570842 years)
uint8 (* RdMem)(uint16); // Address of BYTE read routine
void (* WrMem)(uint16, uint8); // Address of BYTE write routine
uint16 cpuFlags; // v65C02 IRQ/RESET flags
// Function prototypes
void Execute65C02(V65C02REGS *, uint32); // Function to execute 65C02 instructions
-uint32 GetCurrentV65C02Clock(void); // Get the clock of the currently executing CPU
+uint64 GetCurrentV65C02Clock(void); // Get the clock of the currently executing CPU
#endif // __V65C02_H__