Minor refactoring on V65C02 core (fixed EA_ABS_* macros), changed sound to

work with signed samples (in preparation for the move to 16-bit signed). Also,
colorized the Makefile for more mirth.
This commit is contained in:
Shamus Hammons 2009-01-19 16:09:37 +00:00
parent 555db5cdcd
commit 8f4768bdc1
7 changed files with 77 additions and 77 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -16,8 +16,10 @@
* 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;

View File

@ -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;//*/
}

View File

@ -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.
@ -46,13 +47,18 @@
#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;
}
/*

View File

@ -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);