Changed clock on v65C02 to 64-bit, more GUI refactoring

This commit is contained in:
Shamus Hammons 2009-02-06 04:25:53 +00:00
parent a3edd96756
commit b2f84b0582
11 changed files with 139 additions and 30 deletions

View File

@ -21,7 +21,7 @@ autoSaveState = 1
#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...)
@ -45,11 +45,11 @@ autoSaveState = 1
#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
@ -68,7 +68,7 @@ floppyImage2 = ./disks/MoebiusIIB.dsk
# OpenGL options: 1 - use OpenGL rendering, 0 - use old style rendering
useOpenGL = 0
useOpenGL = 1
# OpenGL filtering type: 1 - blurry, 0 - sharp

View File

@ -754,6 +754,11 @@ static bool LoadApple2State(const char * filename)
return false;
}
//#define CPU_CLOCK_CHECKING
#ifdef CPU_CLOCK_CHECKING
uint8 counter = 0;
uint32 totalCPU = 0;
#endif
//
// Main loop
//
@ -877,8 +882,12 @@ memcpy(ram + 0xD000, ram + 0xC000, 0x1000);
//(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();
}
@ -995,8 +1004,8 @@ static void FrameCallback(void)
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();
@ -1019,16 +1028,39 @@ else if (event.key.keysym.sym == SDLK_F10)
// 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);

View File

@ -106,6 +106,7 @@ bool FloppyDrive::LoadImage(const char * filename, uint8 driveNum/*= 0*/)
fclose(fp2);
}
#endif
//writeProtected[driveNum] = true;
WriteLog("FLOPPY: Loaded image '%s' for drive #%u.\n", filename, driveNum);
return true;
@ -638,6 +639,9 @@ Which we now do. :-)
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];

View File

@ -78,11 +78,9 @@ DiskWindow::DiskWindow(FloppyDrive * fdp, uint32 x/*= 0*/, uint32 y/*= 0*/): Win
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);
@ -266,7 +264,7 @@ what you could do is like this way:
// 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)
@ -274,7 +272,7 @@ what you could do is like this way:
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)

View File

@ -137,11 +137,26 @@ SDL_Rect Element::GetExtents(void)
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)

View File

@ -113,6 +113,9 @@ void GUI::Run(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++)

View File

@ -26,7 +26,8 @@
#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)
@ -43,6 +44,8 @@ static bool speakerState = false;
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;
@ -85,6 +88,8 @@ return;
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;
@ -149,10 +154,12 @@ static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
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
@ -171,11 +178,13 @@ So... I guess what we could do is this:
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)
{
@ -190,7 +199,26 @@ 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)
{
@ -212,7 +240,12 @@ Seems like it's OK now that I've fixed the buffer-less-than-length bug...
// 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
@ -241,6 +274,24 @@ void AddToSoundTimeBase(uint32 cycles)
// 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

View File

@ -17,7 +17,10 @@
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__

View File

@ -19,7 +19,7 @@
//#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);

View File

@ -2256,8 +2256,9 @@ Let's see...
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)
@ -2402,7 +2403,8 @@ WriteLog("\n*** IRQ ***\n\n");
//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, &regs, sizeof(V65C02REGS));
}
@ -2410,7 +2412,7 @@ WriteLog("\n*** IRQ ***\n\n");
//
// Get the clock of the currently executing CPU
//
uint32 GetCurrentV65C02Clock(void)
uint64 GetCurrentV65C02Clock(void)
{
return regs.clock;
}

View File

@ -37,7 +37,8 @@ struct V65C02REGS
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
@ -50,6 +51,6 @@ extern bool dumpDis;
// 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__