mirror of
https://github.com/robmcmullen/apple2.git
synced 2024-06-01 17:41:36 +00:00
Changed clock on v65C02 to 64-bit, more GUI refactoring
This commit is contained in:
parent
a3edd96756
commit
b2f84b0582
12
apple2.cfg
12
apple2.cfg
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®s, 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;
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
Loading…
Reference in New Issue
Block a user