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
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)
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
#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
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
#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!
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);
}
SpawnMessage("Stepping to track %u...", track);
}
-// return something if read mode...
+// return something if read mode...
}
void FloppyDrive::ControlMotor(uint8 addr)
* 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"
{
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);
{
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();
}
{
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);
{
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;
#include <SDL.h>
#include "log.h"
-using namespace std;
+
+#define AMPLITUDE (32) // -32 - +32 seems to be plenty loud!
// Global variables
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;
#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;
{
// 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...
{
//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!
}
}
#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)
*/
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();
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;//*/
}
// 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++))
#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)
#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)
//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,
// 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
}
/*
-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
}
/*
-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
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)
static void Op8E(void)
{
regs.WrMem(EA_ABS, regs.x);
- regs.pc += 2;
}
/*
static void Op8C(void)
{
regs.WrMem(EA_ABS, regs.y);
- regs.pc += 2;
}
/*
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;
}
/*
}
//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);