]> Shamusworld >> Repos - apple2/commitdiff
Minor refactoring on V65C02 core (fixed EA_ABS_* macros), changed sound to
authorShamus Hammons <jlhamm@acm.org>
Mon, 19 Jan 2009 16:09:37 +0000 (16:09 +0000)
committerShamus Hammons <jlhamm@acm.org>
Mon, 19 Jan 2009 16:09:37 +0000 (16:09 +0000)
work with signed samples (in preparation for the move to 16-bit signed). Also,
colorized the Makefile for more mirth.

Makefile
apple2.cfg
src/floppy.cpp
src/sdlemu_config.cpp
src/sound.cpp
src/v65c02.cpp
src/video.cpp

index e94b4a61eed517abc5adf25ffeeacdeda8a231fc..311d13e57afc14bfd06d2afe276efee39234aa9d 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -98,36 +98,36 @@ OBJS = \
 
 all: checkenv message obj $(TARGET)$(EXESUFFIX)
        @echo
-       @echo "*** Looks like it compiled OK... Give it a whirl!"
+       @echo -e "\033[01;33m***\033[00;32m Looks like it compiled OK... Give it a whirl!\033[00m"
 
 # Check the compilation environment, barf if not appropriate
 
 checkenv:
        @echo
-       @echo -n "*** Checking compilation environment... "
+       @echo -en "\033[01;33m***\033[00;32m Checking compilation environment... \033[00m"
 ifeq "" "$(shell which sdl-config)"
        @echo
        @echo
-       @echo "It seems that you don't have the SDL development libraries installed. If you"
-       @echo "have installed them, make sure that the sdl-config file is somewhere in your"
-       @echo "path and is executable."
+       @echo -e "\033[01;33mIt seems that you don't have the SDL development libraries installed.
+       @echo -e "have installed them, make sure that the sdl-config file is somewhere in your"
+       @echo -e "path and is executable.\033[00m"
        @echo
 #Is there a better way to break out of the makefile?
        @break
 else
-       @echo "OK"
+       @echo -e "\033[01;37mOK\033[00m"
 endif
 
 message:
        @echo
-       @echo "*** Building Apple 2 SDL for $(MSG)..."
+       @echo -e "\033[01;33m***\033[00;32m Building Apple2 SDL for $(MSG)...\033[00m"
        @echo
 
 clean:
-       @echo -n "*** Cleaning out the garbage..."
+       @echo -en "\033[01;33m***\033[00;32m Cleaning out the garbage...\033[00m"
        @rm -rf obj
        @rm -f ./$(TARGET)$(EXESUFFIX)
-       @echo "done!"
+       @echo -e "\033[01;37mdone!\033[00m"
 
 obj:
        @mkdir obj
@@ -136,25 +136,25 @@ obj:
 
 ifneq "" "$(ICON)"
 $(ICON): res/$(TARGET).rc res/$(TARGET).ico
-       @echo "*** Processing icon..."
+       @echo -e "\033[01;33m***\033[00;32m Processing icon...\033[00m"
        @windres -i res/$(TARGET).rc -o $(ICON) --include-dir=./res
 endif
 
 obj/%.o: src/%.c
-       @echo "*** Compiling $<..."
+       @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m"
        @$(CC) $(CFLAGS) $(INCS) -c $< -o $@
 
 obj/%.o: src/%.cpp
-       @echo "*** Compiling $<..."
+       @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m"
        @$(CC) $(CPPFLAGS) $(INCS) -c $< -o $@
 
 #GUI compilation...
 obj/%.o: src/gui/%.cpp
-       @echo "*** Compiling $<..."
+       @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m"
        @$(CC) $(CPPFLAGS) $(INCS) -c $< -o $@
 
 $(TARGET)$(EXESUFFIX): $(OBJS)
-       @echo "*** Linking it all together..."
+       @echo -e "\033[01;33m***\033[00;32m Linking it all together...\033[00m"
        @$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
 #      strip --strip-all vj$(EXESUFFIX)
 #      upx -9 vj$(EXESUFFIX)
index c2aee792f666a897a142af9262aa0741cf49bcdf..5ee931d0347e38a04436c63e8e4527a4641bbd2d 100755 (executable)
@@ -24,7 +24,7 @@ autoSaveState = 1
 floppyImage1 = ./disks/bt1_boot.dsk
 # Yes
 #floppyImage1 = ./disks/bt2_boot.dsk
-# No
+# No (gets stuck on 1st track)
 #floppyImage1 = ./disks/bt3_boot.dsk
 # Yes
 #floppyImage1 = ./disks/Sabotage.dsk
@@ -40,7 +40,7 @@ floppyImage1 = ./disks/bt1_boot.dsk
 #floppyImage1 = ./disks/MidnightMagic_etc.dsk
 # ??? (PRODOS 8 V1.4 - UNABLE TO LOAD ATINIT FILE)
 #floppyImage1 = ./disks/battle_chess_1.dsk
-# Yes 
+# Yes
 #floppyImage1 = ./disks/MoebiusI-1.dsk
 # Yes, but crashes on the attract mode
 #floppyImage1 = ./disks/MoebiusIIA.dsk
@@ -88,7 +88,7 @@ frameSkip = 0
 
 useJoystick = 0
 
-# Joyport option: If joystick is enabled above, set the port (0 - 3) here 
+# Joyport option: If joystick is enabled above, set the port (0 - 3) here
 
 joyport = 0
 
index e811bb0f53d67d58ef17aa7b222e6ce4ef7361e2..59c9e6dfc1a872f938b33deae7f8af4a93b64920 100755 (executable)
@@ -16,7 +16,7 @@
 #include "floppy.h"
 
 #include <stdio.h>
-#include <string>
+#include <string.h>
 #include "apple2.h"
 #include "log.h"
 #include "applevideo.h"                                        // For message spawning... Though there's probably a better approach than this!
@@ -135,6 +135,7 @@ bool FloppyDrive::SaveImage(uint8 driveNum/*= 0*/)
 bool FloppyDrive::SaveImageAs(const char * filename, uint8 driveNum/*= 0*/)
 {
 //WARNING: Buffer overflow possibility
+#warning "Buffer overflow possible--!!! FIX !!!"
        strcpy(imageName[driveNum], filename);
        return SaveImage(driveNum);
 }
@@ -470,7 +471,7 @@ bit 0 is the "do something" bit.
 SpawnMessage("Stepping to track %u...", track);
        }
 
-//     return something if read mode...        
+//     return something if read mode...
 }
 
 void FloppyDrive::ControlMotor(uint8 addr)
index 75d764430dd98880da08d3fd0725178fad24dfb5..77fd67afebd54b139c2178e4224c46bbe04d25a1 100755 (executable)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <string>
 #include <list>
 #include "sdlemu_config.h"
@@ -76,11 +78,11 @@ int sdlemu_init_config(const char *filename)
 {
        FILE *f = fopen(filename, "r");
        if(!f) return 0;
-       
+
        fseek(f, 0, SEEK_END);
        int len = ftell(f);
        fseek(f, 0, SEEK_SET);
-       
+
        char *s = new char[len];
        fread(s, 1, len, f);
        string str(s);
@@ -115,7 +117,7 @@ const char *sdlemu_getval_string(const char *key_string, const char *default_str
 {
        list<token_list>::iterator p;
        for(p = vec.begin(); p != vec.end(); p++) {
-               
+
                if(strcmp((*p).Token().c_str(), key_string) == 0)
                        return (*p).Value().c_str();
        }
@@ -126,7 +128,7 @@ int sdlemu_getval_int(const char *key_string, int default_int)
 {
        list<token_list>::iterator p;
        for(p = vec.begin(); p != vec.end(); p++) {
-               
+
                if(strcmp((*p).Token().c_str(), key_string) == 0) {
                        const char *ret = (*p).Value().c_str();
                        if(ret) return atoi(ret);
@@ -139,7 +141,7 @@ int sdlemu_getval_bool(const char *key_string, int default_int)
 {
        list<token_list>::iterator p;
        for(p = vec.begin(); p != vec.end(); p++) {
-               
+
                if(strcmp((*p).Token().c_str(), key_string) == 0) {
                        const char *ret = (*p).Value().c_str();
                        if(ret) return atoi(ret)>0;
index ab7802b8adb4ba9d84518ab3cca2d4db28af3881..9158db6d3d97f22bd188395cb85441620a23e002 100755 (executable)
@@ -25,7 +25,8 @@
 #include <SDL.h>
 #include "log.h"
 
-using namespace std;
+
+#define AMPLITUDE      (32)                                            // -32 - +32 seems to be plenty loud!
 
 // Global variables
 
@@ -34,9 +35,6 @@ using namespace std;
 
 static SDL_AudioSpec desired;
 static bool soundInitialized = false;
-static uint8 amplitude = 0x88;                                 // $78 - $88 seems to be plenty loud!
-//static uint8 lastValue;
-
 static bool speakerState;
 static uint8 soundBuffer[4096];
 static uint32 soundBufferPos;
@@ -59,23 +57,23 @@ return;
 #endif
 
        desired.freq = 44100;                                           // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
-       desired.format = AUDIO_U8;                                      // This uses the native endian (for portability)...
+       desired.format = AUDIO_S8;                                      // This uses the native endian (for portability)...
+//     desired.format = AUDIO_S16SYS;                          // This uses the native endian (for portability)...
        desired.channels = 1;
 //     desired.samples = 4096;                                         // Let's try a 4K buffer (can always go lower)
-       desired.samples = 2048;                                         // Let's try a 2K buffer (can always go lower)
+//     desired.samples = 2048;                                         // Let's try a 2K buffer (can always go lower)
+       desired.samples = 1024;                                         // Let's try a 1K buffer (can always go lower)
        desired.callback = SDLSoundCallback;
 
        if (SDL_OpenAudio(&desired, NULL) < 0)          // NULL means SDL guarantees what we want
        {
                WriteLog("Sound: Failed to initialize SDL sound.\n");
-//             exit(1);
                return;
        }
 
        conditional = SDL_CreateCond();
        mutex = SDL_CreateMutex();
        SDL_mutexP(mutex);                                                      // Must lock the mutex for the cond to work properly...
-//     lastValue = (speakerState ? amplitude : 0xFF - amplitude);
        soundBufferPos = 0;
        sampleBase = 0;
 
@@ -106,6 +104,9 @@ static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
 {
        // The sound buffer should only starve when starting which will cause it to
        // lag behind the emulation at most by around 1 frame...
+       // (Actually, this should never happen since we fill the buffer beforehand.)
+       // (But, then again, if the sound hasn't been toggled for a while, then this
+       //  makes perfect sense as the buffer won't have been filled at all!)
 
        if (soundBufferPos < (uint32)length)            // The sound buffer is starved...
        {
@@ -113,15 +114,13 @@ static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
 //fflush(stdout);
                for(uint32 i=0; i<soundBufferPos; i++)
                        buffer[i] = soundBuffer[i];
+
                // Fill buffer with last value
-               uint8 lastValue = (speakerState ? amplitude : 0xFF - amplitude);
-//             uint8 lastValue = (speakerState ? amplitude : amplitude ^ 0xFF);
-//             memset(buffer, lastValue, length);              // Fill buffer with last value
-               memset(buffer + soundBufferPos, lastValue, length - soundBufferPos);
+               memset(buffer + soundBufferPos, (uint8)(speakerState ? AMPLITUDE : -AMPLITUDE), length - soundBufferPos);
                soundBufferPos = 0;                                             // Reset soundBufferPos to start of buffer...
                sampleBase = 0;                                                 // & sampleBase...
 //Ick. This should never happen!
-SDL_CondSignal(conditional);                           // Wake up any threads waiting for the buffer to drain...
+SDL_CondSignal(conditional);                   // Wake up any threads waiting for the buffer to drain...
                return;                                                                 // & bail!
        }
 
@@ -169,12 +168,11 @@ if (time > 95085)//(time & 0x80000000)
 }
 #endif
 
-// 1.024 MHz / 60 = 17066.6... cycles (23.2199 cycles per sample)
-// Need the last frame position in order to calculate correctly...
+       // 1.024 MHz / 60 = 17066.6... cycles (23.2199 cycles per sample)
+       // Need the last frame position in order to calculate correctly...
+       // (or do we?)
 
        SDL_LockAudio();
-       uint8 sample = (speakerState ? amplitude : 0xFF - amplitude);
-//     uint8 sample = (speakerState ? amplitude : amplitude ^ 0xFF);
        uint32 currentPos = sampleBase + (uint32)((double)time / 23.2199);
 
        if (currentPos > 4095)
@@ -196,17 +194,17 @@ Seems like it's OK now that I've fixed the buffer-less-than-length bug...
 */
                SDL_UnlockAudio();
                SDL_CondWait(conditional, mutex);
-
-//             while (currentPos > 4095)                               // Spin until buffer empties a bit...
-               currentPos = sampleBase + (uint32)((double)time / 23.2199);
                SDL_LockAudio();
+               currentPos = sampleBase + (uint32)((double)time / 23.2199);
 #if 0
 WriteLog("--> after spinlock (sampleBase=%u)...\n", sampleBase);
 #endif
        }
 
+       int8 sample = (speakerState ? AMPLITUDE : -AMPLITUDE);
+
        while (soundBufferPos < currentPos)
-               soundBuffer[soundBufferPos++] = sample;
+               soundBuffer[soundBufferPos++] = (uint8)sample;
 
        speakerState = !speakerState;
        SDL_UnlockAudio();
@@ -220,14 +218,4 @@ void HandleSoundAtFrameEdge(void)
        SDL_LockAudio();
        sampleBase += 735;
        SDL_UnlockAudio();
-/*     uint8 sample = (speakerState ? amplitude : 0xFF - amplitude);
-
-//This shouldn't happen (buffer overflow), but it seems like it *is* happening...
-       if (sampleBase >= 4096)
-//             sampleBase = 4095;
-//Kludge, for now... Until I can figure out why it's still stomping on the buffer...
-               sampleBase = 0;
-
-       while (soundBufferPos < sampleBase)
-               soundBuffer[soundBufferPos++] = sample;//*/
 }
index 24ba4a8926ad05de5bf41b0cf452d67e61eadb28..b86f738ac66e3933f8ae65952a83ce6786950b95 100755 (executable)
@@ -9,6 +9,7 @@
 // WHO  WHEN        WHAT
 // ---  ----------  ------------------------------------------------------------
 // JLH  01/04/2006  Added changelog ;-)
+// JLH  01/18/2009  Fixed EA_ABS_* macros
 //
 
 //OK, the wraparound bug exists in both the Apple and Atari versions of Ultima II.
 #define SET_ZNC_CMP(a,b,r)     SET_N(r); SET_Z(r); SET_C_CMP(a,b)
 
 //Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!!
+//NB: It's properly handled by everything that uses it, so it works, even if it's klunky
+//Small problem with fixing it is that you can't do it in a single instruction, i.e.,
+//you have to read the value THEN you have to increment the PC. Unless there's another
+//way to do that
+//[DONE]
 #define EA_IMM                         regs.pc++
 #define EA_ZP                          regs.RdMem(regs.pc++)
 #define EA_ZP_X                                (regs.RdMem(regs.pc++) + regs.x) & 0xFF
 #define EA_ZP_Y                                (regs.RdMem(regs.pc++) + regs.y) & 0xFF
-#define EA_ABS                         RdMemW(regs.pc)
-#define EA_ABS_X                       RdMemW(regs.pc) + regs.x
-#define EA_ABS_Y                       RdMemW(regs.pc) + regs.y
+#define EA_ABS                         FetchMemW(regs.pc)
+#define EA_ABS_X                       FetchMemW(regs.pc) + regs.x
+#define EA_ABS_Y                       FetchMemW(regs.pc) + regs.y
 #define EA_IND_ZP_X                    RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF)
 #define EA_IND_ZP_Y                    RdMemW(regs.RdMem(regs.pc++)) + regs.y
 #define EA_IND_ZP                      RdMemW(regs.RdMem(regs.pc++))
@@ -61,9 +67,9 @@
 #define READ_ZP                                regs.RdMem(EA_ZP)
 #define READ_ZP_X                      regs.RdMem(EA_ZP_X)
 #define READ_ZP_Y                      regs.RdMem(EA_ZP_Y)
-#define READ_ABS                       regs.RdMem(EA_ABS);     regs.pc += 2
-#define READ_ABS_X                     regs.RdMem(EA_ABS_X);   regs.pc += 2
-#define READ_ABS_Y                     regs.RdMem(EA_ABS_Y);   regs.pc += 2
+#define READ_ABS                       regs.RdMem(EA_ABS)
+#define READ_ABS_X                     regs.RdMem(EA_ABS_X)
+#define READ_ABS_Y                     regs.RdMem(EA_ABS_Y)
 #define READ_IND_ZP_X          regs.RdMem(EA_IND_ZP_X)
 #define READ_IND_ZP_Y          regs.RdMem(EA_IND_ZP_Y)
 #define READ_IND_ZP                    regs.RdMem(EA_IND_ZP)
@@ -71,9 +77,9 @@
 #define READ_IMM_WB(v)         uint16 addr = EA_IMM;      v = regs.RdMem(addr)
 #define READ_ZP_WB(v)          uint16 addr = EA_ZP;       v = regs.RdMem(addr)
 #define READ_ZP_X_WB(v)                uint16 addr = EA_ZP_X;     v = regs.RdMem(addr)
-#define READ_ABS_WB(v)         uint16 addr = EA_ABS;      v = regs.RdMem(addr); regs.pc += 2
-#define READ_ABS_X_WB(v)       uint16 addr = EA_ABS_X;    v = regs.RdMem(addr); regs.pc += 2
-#define READ_ABS_Y_WB(v)       uint16 addr = EA_ABS_Y;    v = regs.RdMem(addr); regs.pc += 2
+#define READ_ABS_WB(v)         uint16 addr = EA_ABS;      v = regs.RdMem(addr)
+#define READ_ABS_X_WB(v)       uint16 addr = EA_ABS_X;    v = regs.RdMem(addr)
+#define READ_ABS_Y_WB(v)       uint16 addr = EA_ABS_Y;    v = regs.RdMem(addr)
 #define READ_IND_ZP_X_WB(v)    uint16 addr = EA_IND_ZP_X; v = regs.RdMem(addr)
 #define READ_IND_ZP_Y_WB(v)    uint16 addr = EA_IND_ZP_Y; v = regs.RdMem(addr)
 #define READ_IND_ZP_WB(v)      uint16 addr = EA_IND_ZP;   v = regs.RdMem(addr)
@@ -87,7 +93,7 @@ static V65C02REGS regs;
 //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!!
 //Also this doesn't take into account the extra cycle it takes when an indirect fetch
 //(ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD add/subtract...
-#warning Cycle counts are not accurate--!!! FIX !!!
+#warning "Cycle counts are not accurate--!!! FIX !!!"
 static uint8 CPUCycles[256] = {
        7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1,
        2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1,
@@ -109,15 +115,25 @@ static uint8 CPUCycles[256] = {
 // Private function prototypes
 
 static uint16 RdMemW(uint16);
+static uint16 FetchMemW(uint16 addr);
 
 //
 // Read a uint16 out of 65C02 memory (big endian format)
 //
-static uint16 RdMemW(uint16 address)
+static inline uint16 RdMemW(uint16 address)
 {
        return (uint16)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0);
 }
 
+//
+// Read a uint16 out of 65C02 memory (big endian format) and increment PC
+//
+static inline uint16 FetchMemW(uint16 address)
+{
+       regs.pc += 2;
+       return (uint16)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0);
+}
+
 
 //
 // 65C02 OPCODE IMPLEMENTATION
@@ -1498,7 +1514,7 @@ static void Op7A(void)                                                    // PLY
 }
 
 /*
-The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear. 
+The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
   zp  07  17  27  37  47  57  67  77
      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
@@ -1828,7 +1844,7 @@ static void Op78(void)                                                    // SEI
 }
 
 /*
-The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear. 
+The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
   zp  07  17  27  37  47  57  67  77
      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
@@ -1927,19 +1943,16 @@ static void Op95(void)
 static void Op8D(void)
 {
        regs.WrMem(EA_ABS, regs.a);
-       regs.pc += 2;
 }
 
 static void Op9D(void)
 {
        regs.WrMem(EA_ABS_X, regs.a);
-       regs.pc += 2;
 }
 
 static void Op99(void)
 {
        regs.WrMem(EA_ABS_Y, regs.a);
-       regs.pc += 2;
 }
 
 static void Op81(void)
@@ -1978,7 +1991,6 @@ static void Op96(void)
 static void Op8E(void)
 {
        regs.WrMem(EA_ABS, regs.x);
-       regs.pc += 2;
 }
 
 /*
@@ -2002,7 +2014,6 @@ static void Op94(void)
 static void Op8C(void)
 {
        regs.WrMem(EA_ABS, regs.y);
-       regs.pc += 2;
 }
 
 /*
@@ -2027,13 +2038,11 @@ static void Op74(void)
 static void Op9C(void)
 {
        regs.WrMem(EA_ABS, 0x00);
-       regs.pc += 2;
 }
 
 static void Op9E(void)
 {
        regs.WrMem(EA_ABS_X, 0x00);
-       regs.pc += 2;
 }
 
 /*
index b30379606b3a6a9246fd306c1ff56f2180d70087..7f6891ebcaaa8fa9bb27788e02d33f2fa2f87a2b 100755 (executable)
@@ -56,7 +56,7 @@ bool InitVideo(void)
        }
 
        //Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
-       SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128, 
+       SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128,
                MASK_R, MASK_G, MASK_B, MASK_A);
        SDL_WM_SetIcon(iconSurf, NULL);
        SDL_FreeSurface(iconSurf);