]> Shamusworld >> Repos - apple2/blobdiff - src/apple2.cpp
Added Prodos detection for .dsk images, fixes to 80STORE switch.
[apple2] / src / apple2.cpp
index 12eb8c92181d9263bebb61435e5d0e13778bad51..f886a7d1c65fcb333acbf77f90104356001d2988 100755 (executable)
@@ -1,7 +1,7 @@
 //
 // Apple 2 SDL Portable Apple Emulator
 //
-// by James L. Hammons
+// by James Hammons
 // (C) 2005 Underground Software
 //
 // Loosely based on AppleWin by Tom Charlesworth which was based on AppleWin by
@@ -9,7 +9,7 @@
 // also derived from ApplePC. Too bad it was closed source--it could have been
 // *the* premier Apple II emulator out there.
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // WHO  WHEN        WHAT
 // ---  ----------  ------------------------------------------------------------
@@ -17,6 +17,7 @@
 // JLH  11/18/2005  Wired up graphic soft switches
 // JLH  12/02/2005  Setup timer subsystem for more accurate time keeping
 // JLH  12/12/2005  Added preliminary state saving support
+// JLH  09/24/2013  Added //e support
 //
 
 // STILL TO DO:
@@ -25,7 +26,7 @@
 // - GUI goodies
 // - Weed out unneeded functions [DONE]
 // - Disk I/O [DONE]
-// - 128K IIe related stuff
+// - 128K IIe related stuff [DONE]
 // - State loading/saving
 //
 
@@ -48,6 +49,7 @@
 #include "timing.h"
 #include "floppy.h"
 #include "firmware.h"
+#include "mmu.h"
 
 #include "gui/gui.h"
 #include "gui/window.h"
 
 uint8_t ram[0x10000], rom[0x10000];                            // RAM & ROM spaces
 uint8_t ram2[0x10000];                                                 // Auxillary RAM
-uint8_t diskRom[0x100];                                                        // Disk ROM space
+//uint8_t diskRom[0x100];                                                      // Disk ROM space
 V65C02REGS mainCPU;                                                            // v65C02 execution context
 uint8_t appleType = APPLE_TYPE_IIE;
 FloppyDrive floppyDrive;
 
 // Local variables
 
-static uint8_t lastKeyPressed = 0;
-static bool keyDown = false;
-static bool openAppleDown = false;
-static bool closedAppleDown = false;
-static bool store80Mode = false;
-static bool vbl = false;
-static bool slotCXROM = false;
-static bool slotC3ROM = false;
-static bool ramrd = false;
-static bool ramwrt = false;
-static bool altzp = false;
-static bool ioudis = true;
+uint8_t lastKeyPressed = 0;
+bool keyDown = false;
+bool openAppleDown = false;
+bool closedAppleDown = false;
+bool store80Mode = false;
+bool vbl = false;
+bool slotCXROM = false;
+bool slotC3ROM = false;
+bool ramrd = false;
+bool ramwrt = false;
+bool altzp = false;
+bool ioudis = true;
 bool dhires = false;
 
 //static FloppyDrive floppyDrive;
@@ -98,6 +100,7 @@ static bool writeRAM = false;
 
 static bool running = true;                                            // Machine running state flag...
 static uint32_t startTicks;
+static bool pauseMode = false;
 
 static GUI * gui = NULL;
 
@@ -123,7 +126,6 @@ static SDL_sem * mainSem = NULL;
 static bool cpuFinished = false;
 static bool cpuSleep = false;
 
-
 // NB: Apple //e Manual sez 6502 is running @ 1,022,727 Hz
 
 // Let's try a thread...
@@ -197,35 +199,26 @@ WriteLog("CPU: Execute65C02(&mainCPU, cycles);\n");
 
                        Execute65C02(&mainCPU, cycles);
                        WriteSampleToBuffer();
+
+                       // Dunno if this is correct (seems to be close enough)...
+                       vbl = (i < 670 ? true : false);
                }
 #endif
 
-//WriteLog("CPUThread: Supposedly end of frame...\n");
-
 #ifdef THREAD_DEBUGGING
 WriteLog("CPU: SDL_mutexP(cpuMutex);\n");
 #endif
                SDL_mutexP(cpuMutex);
-#if 0
-               if (SDL_CondWait(cpuCond, cpuMutex) != 0)
-               {
-                       printf("SDL_CondWait != 0! (Error: '%s')\n", SDL_GetError());
-                       exit(-1);
-               }
-#else
 // increment mainSem...
 #ifdef THREAD_DEBUGGING
 WriteLog("CPU: SDL_SemPost(mainSem);\n");
 #endif
-SDL_SemPost(mainSem);
-//             SDL_CondSignal(mainCond);       // In case something is waiting on us...
-
+               SDL_SemPost(mainSem);
 #ifdef THREAD_DEBUGGING
 WriteLog("CPU: SDL_CondWait(cpuCond, cpuMutex);\n");
 #endif
                SDL_CondWait(cpuCond, cpuMutex);
 
-#endif
 #ifdef THREAD_DEBUGGING
 WriteLog("CPU: SDL_mutexV(cpuMutex);\n");
 #endif
@@ -372,6 +365,8 @@ WriteLog("80STORE (read)\n");
 #ifdef SOFT_SWITCH_DEBUGGING
 WriteLog("VBL (read)\n");
 #endif
+// NB: The doco suggests that this signal goes LOW when in the VBI.
+// Which means that we need to control this by counting lines somewhere.
                return (vbl ? 0x80 : 0x00);
        }
        else if (addr == 0xC01A)
@@ -418,24 +413,7 @@ WriteLog("80COL (read)\n");
        }
        else if ((addr & 0xFFF0) == 0xC030)             // Read $C030-$C03F
        {
-/*
-This is problematic, mainly because the v65C02 removes actual cycles run after each call.
-Therefore, we don't really have a reliable method of sending a timestamp to the sound routine.
-How to fix?
-
-What we need to send is a delta T value but related to the IRQ buffer routine. E.g., if the buffer
-hasn't had any changes in it then we just fill it with the last sample value and are done. Then
-we need to adjust our delta T accordingly. What we could do is keep a running total of time since the
-last change and adjust it accordingly, i.e., whenever a sound IRQ happens.
-How to keep track?
-
-Have deltaT somewhere. Then, whenever there's a toggle, backfill buffer with last spkr state and reset
-deltaT to zero. In the sound IRQ, if deltaT > buffer size, then subtract buffer size from deltaT. (?)
-
-
-
-*/
-               ToggleSpeaker(GetCurrentV65C02Clock());
+               ToggleSpeaker();
 //should it return something else here???
                return 0x00;
        }
@@ -782,6 +760,8 @@ if (showpath)
        }
        else
        {
+// 80STORE only works for WRITING, not READING!
+#if 0
                // Check for 80STORE mode (STORE80 takes precedence over RAMRD/WRT)...
                if ((((addr >= 0x0400) && (addr <= 0x07FF)) || ((addr >= 0x2000) && (addr <= 0x3FFF))) && store80Mode)
                {
@@ -792,6 +772,7 @@ if (showpath)
 
                        return b;
                }
+#endif
 
                // Finally, check for auxillary/altzp write switches
                if (addr < 0x0200)
@@ -1034,6 +1015,13 @@ WriteLog("ALTCHARSET on (write)\n");
 //But leaving this out seems to fuck up the key handling of some games...
                keyDown = false;
        }
+       else if ((addr & 0xFFF0) == 0xC030)             // Read $C030-$C03F
+       {
+//Likewise, the speaker is supposed to do nothing if you write to it, and
+//for the same reason. But without this, you get no sound in David's
+//Midnight Magic...
+               ToggleSpeaker();
+       }
        else if (addr == 0xC050)
        {
 #ifdef SOFT_SWITCH_DEBUGGING
@@ -1236,15 +1224,7 @@ WriteLog("LC(R): $C08B 49291 OECG RR Read/Write RAM bank 1\n");
        {
                floppyDrive.SetWriteMode();
        }
-//Still need to add missing I/O switches here...
 
-//DEEE: BD 10 BF       LDA   $BF10,X    [PC=DEF1, SP=01F4, CC=--.B-IZ-, A=00, X=0C, Y=07]
-#if 0
-if (addr >= 0xD000 && addr <= 0xD00F)
-{
-       WriteLog("*** Write to $%04X: $%02X (writeRAM=%s, PC=%04X, ram$D000=%02X)\n", addr, b, (writeRAM ? "T" : "F"), mainCPU.pc, ram[0xC000]);
-}
-#endif
        if (addr >= 0xC000 && addr <= 0xCFFF)
                return; // Protect LC bank #1 from being written to!
 
@@ -1304,6 +1284,12 @@ if (addr >= 0xD000 && addr <= 0xD00F)
        if (addr < 0x0200)
 //     if (addr < 0x0200 || addr >= 0xD000)
        {
+#if 0
+if (addr == 0x38)
+       WriteLog("Write $38: $%02X\n", b);
+else if (addr == 0x39)
+       WriteLog("Write $39: $%02X\n", b);
+#endif
                if (altzp)
                        ram2[addr] = b;
                else
@@ -1363,15 +1349,22 @@ int main(int /*argc*/, char * /*argv*/[])
        srand(time(NULL));                                                                      // Initialize RNG
 
        // Zero out memory
-//Need to bankify this stuff for the IIe emulation...
        memset(ram, 0, 0x10000);
        memset(rom, 0, 0x10000);
        memset(ram2, 0, 0x10000);
 
+#if 1
+       // Set up MMU
+       SetupAddressMap();
+
        // Set up V65C02 execution context
        memset(&mainCPU, 0, sizeof(V65C02REGS));
+       mainCPU.RdMem = AppleReadMem;
+       mainCPU.WrMem = AppleWriteMem;
+#else
        mainCPU.RdMem = RdMem;
        mainCPU.WrMem = WrMem;
+#endif
        mainCPU.cpuFlags |= V65C02_ASSERT_LINE_RESET;
 
 //     alternateCharset = true;
@@ -1614,6 +1607,7 @@ static void FrameCallback(void)
        {
                switch (event.type)
                {
+// Problem with using SDL_TEXTINPUT is that it causes key delay. :-/
                case SDL_TEXTINPUT:
 //Need to do some key translation here, and screen out non-apple keys as well...
 //(really, could do it all in SDL_KEYDOWN, would just have to get symbols &
@@ -1671,6 +1665,22 @@ static void FrameCallback(void)
                        if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod & KMOD_ALT))
                                running = false;
 
+                       if (event.key.keysym.sym == SDLK_PAUSE)
+                       {
+                               pauseMode = !pauseMode;
+
+                               if (pauseMode)
+                               {
+                                       SoundPause();
+                                       SpawnMessage("*** PAUSED ***");
+                               }
+                               else
+                               {
+                                       SoundResume();
+                                       SpawnMessage("*** RESUME ***");
+                               }
+                       }
+
                        // Paddle buttons 0 & 1
                        if (event.key.keysym.sym == SDLK_INSERT)
                                openAppleDown = true;
@@ -1801,7 +1811,8 @@ if (counter == 60)
 //let's wait, then signal...
 //works longer, but then still falls behind...
 #ifdef THREADED_65C02
-       SDL_CondSignal(cpuCond);//OK, let the CPU go another frame...
+       if (!pauseMode)
+               SDL_CondSignal(cpuCond);//OK, let the CPU go another frame...
 #endif
 }