]> Shamusworld >> Repos - apple2/commitdiff
Changed clock on v65C02 to 64-bit, more GUI refactoring
authorShamus Hammons <jlhamm@acm.org>
Fri, 6 Feb 2009 04:25:53 +0000 (04:25 +0000)
committerShamus Hammons <jlhamm@acm.org>
Fri, 6 Feb 2009 04:25:53 +0000 (04:25 +0000)
apple2.cfg
src/apple2.cpp
src/floppy.cpp
src/gui/diskwindow.cpp
src/gui/element.cpp
src/gui/gui.cpp
src/sound.cpp
src/sound.h
src/timing.h
src/v65c02.cpp
src/v65c02.h

index bd3016bf1133a96cb6e13655903e192a5cd921ad..9e2b2c1bd0e34d95e74b5c85f6c869ac4ddd9989 100755 (executable)
@@ -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
 
index fa7323a6d217adb2a8ddfb32a6a87b32c0432409..42f59e4b8377fe6691eb6847844d35cd11bb97af 100755 (executable)
@@ -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);
index d4037140d5e652b6474af8a585c0e9889da2934e..810960448331fe2067885d033e17c29373972f9b 100755 (executable)
@@ -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];
index 25e7537e16f59176c1797b443081539c3e2725b4..7b33dbc37040417f5a89bc57ee8f15a72e0ee396 100644 (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)
index cf60ac3af3a6f45a9c526e97ea6202ab484f5ca3..1c65b2db6feb01418f66b3bc9d03f79902b3743e 100755 (executable)
@@ -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)
index 7c6e219782d001fbd2c7c7680964c0abb341b267..5bbd85e24eb9e778f5b8d6cd8d45a2f6b23f49c4 100755 (executable)
@@ -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++)
index b39fb82a992984ea11fdcb8a0b1db3daa16c6207..b708b2dd14704532546a8ddfd3152e9c7cffa776 100755 (executable)
@@ -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
 
index 3d3c442366b08d1912edb8f2bd4965140f42b60c..9983eaa6d99cd4a7581f92449f8fd3b8cffacd7a 100755 (executable)
 
 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__
index 352583bcac866aaf4a0f19bb6cf44f245e984221..12139471731bda968dfb1664197ce12f21926980 100755 (executable)
@@ -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);
index 59cc4157f03c716ef4e1e6155e97e87207e7a9c6..6f2c969d8681a3c074a97763dd6a2f97d4efb4f0 100755 (executable)
@@ -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;
 }
index 7a557ab5848ca567a128adbc1a41dae58021f0e8..c8803317806674ad39207a81661a9a2fbaaca049 100755 (executable)
@@ -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__