예제 #1
0
파일: WD2793.c 프로젝트: imclab/CocoaMSX
int wd2793GetDataRequest(WD2793* wd)
{
    sync(wd);
	if (((wd->regCommand & 0xF0) == 0xF0) && ((wd->regStatus & ST_BUSY) || wd->dataReady)) {
        UInt32 pulses = (boardSystemTime() - wd->dataRequsetTime) / (boardFrequency() / 5);
		if (wd->dataReady) {
			wd->dataRequest = 1;
		} 
		if (pulses > 0) {
			wd->dataReady = 1;
		}
		if (pulses > 1) {
			wd->dataAvailable = 0;
			wd->sectorOffset  = 0;
			wd->dataRequest   = 0;
	        wd->intRequest    = 1;
	        wd->regStatus    &= ~ST_BUSY;
		}
	}

    if ((wd->regCommand & 0xe0) == 0x80 && (wd->regStatus & ST_BUSY)) {
        UInt32 pulses = (boardSystemTime() - wd->dataRequsetTime) / (boardFrequency() / 25);
		if (wd->dataReady) {
			wd->dataRequest = 1;
		}
		if (pulses > 0) {
            wd->dataReady = 1;
        }
    }

    return wd->dataRequest;
}
예제 #2
0
static UInt8 getTimerCounter(RomMapperTurboRPcm* rm)
{
    UInt64 elapsed;
    UInt32 systemTime = boardSystemTime();

    elapsed      = 15750 * (UInt64)(systemTime - rm->refTime) + rm->refFrag;
    rm->refTime  = systemTime;
    rm->refFrag  = (UInt32)(elapsed % boardFrequency());
    rm->time += (UInt8)(elapsed / boardFrequency());

    return rm->time & 0x03;
}
예제 #3
0
static UInt16 counterGetElapsedTime(Counter* counter)
{
    UInt64 elapsed;
    UInt32 elapsedTime;
    UInt32 systemTime = boardSystemTime();

    elapsed          = counter->frequency * (UInt64)(systemTime - counter->refTime) + counter->refFrag;
    counter->refTime = systemTime;
    counter->refFrag = (UInt32)(elapsed % boardFrequency());
    elapsedTime      = (UInt32)(elapsed / boardFrequency());

    return (UInt16)elapsedTime;
}
예제 #4
0
파일: Board.c 프로젝트: juvenal/CocoaMSX
//------------------------------------------------------
// Board supports one external periodic timer (can be
// used to sync external components with the emulation)
// The callback needs to be added before the emulation
// starts in order to be called.
//------------------------------------------------------
void boardSetPeriodicCallback(BoardTimerCb cb, void* ref, UInt32 freq)
{
    periodicCb       = cb;
    periodicRef      = ref;
    if (periodicCb != NULL && freq > 0) {
        periodicInterval = boardFrequency() / freq;
    }
}
예제 #5
0
static void ym2148WriteCommand(YM2148* midi, UInt8 value)
{
    midi->command = value;

    if (value & 0x02) {
    }

    if (value & CMD_RST) {
        ym2148Reset(midi);
    }

    midi->charTime = (UInt32)((UInt64)144 * boardFrequency() / 500000);
}
예제 #6
0
UInt8 coinDeviceRead(CoinDevice* coinDev) 
{
    if(coinDev->time == 0 && inputEventGetState(EC_C)) {
        coinDev->time = boardSystemTime();
    }

    if (coinDev->time != 0) {
        if ((boardSystemTime() - coinDev->time) < boardFrequency() * 2 / 10) {
            return 0;
        }
        coinDev->time = 0;
    }
    return 1;
}
예제 #7
0
파일: RTC.c 프로젝트: meesokim/bluemsx-wii
static void rtcUpdateRegs(RTC* rtc)
{
    int carryDays;
    int carryYears;
    UInt64 elapsed;
    UInt32 elapsedTime;
    UInt32 systemTime = boardSystemTime();

    elapsed      = 16384 * (UInt64)(systemTime - rtc->refTime) + rtc->refFrag;
    rtc->refTime = systemTime;
    rtc->refFrag = (UInt32)(elapsed % boardFrequency());
    elapsedTime  = (UInt32)(elapsed / boardFrequency());
    
    rtc->fraction += (rtc->modeReg & MODE_TIMERENABLE) ? elapsedTime : 0;
    rtc->seconds  += (rtc->testReg & TEST_SECONDS) ? elapsedTime : rtc->fraction / 16384; 
    rtc->fraction %= 16384;
    rtc->minutes  += (rtc->testReg & TEST_MINUTES) ? elapsedTime : rtc->seconds / 60; 
    rtc->seconds  %= 60;
    rtc->hours    += rtc-> minutes / 60;   
    rtc->minutes  %= 60;
    carryDays      = (rtc->testReg & TEST_DAYS) ? elapsedTime : rtc->hours / 24; 
    rtc->days     += carryDays;
    rtc->hours    %= 24;
    rtc->dayWeek   = (rtc->dayWeek + carryDays) % 7;
    
    while (rtc->days >= daysInMonth[rtc->leapYear][rtc->months]) {
        rtc->days -= daysInMonth[rtc->leapYear][rtc->months];
        rtc->months++;
    }

    carryYears    = (rtc->testReg & TEST_YEARS) ? elapsedTime : rtc->months / 12;
    rtc->years    = (rtc->years + carryYears) % 100; 
    rtc->months  %= 12;
    rtc->leapYear = (rtc->leapYear + carryYears) % 4;
    
    rtcSetRegisters(rtc);
}
예제 #8
0
void philipsMidiReset(PhilipsMidi* midi)
{
    midi->status = STAT_TXEMPTY;
    midi->txPending = 0;
    midi->rxPending = 0;
    midi->command = 0;
    midi->timeRecv = 0;
    midi->timeTrans = 0;
    midi->charTime = 10 * boardFrequency() / 31250;

    boardTimerRemove(midi->timerRecv);
    boardTimerRemove(midi->timerTrans);
    
    midi->timeRecv = boardSystemTime() + midi->charTime;
    boardTimerAdd(midi->timerRecv, midi->timeRecv);
}
예제 #9
0
파일: WD2793.c 프로젝트: imclab/CocoaMSX
UInt8 wd2793PeekStatusReg(WD2793* wd)
{
    UInt8 regStatus;

    sync(wd);

    regStatus = wd->regStatus;

	if (((wd->regCommand & 0x80) == 0) || ((wd->regCommand & 0xf0) == 0xd0)) {
		regStatus &= ~(ST_INDEX | ST_TRACK00 | ST_HEAD_LOADED | ST_WRITE_PROTECTED);
    	if (diskEnabled(wd->drive)) {
            if (diskPresent(wd->drive)) {
                if ((UInt64)160 * boardSystemTime() / boardFrequency() & 0x1e) {
			        regStatus |= ST_INDEX;
		        }
            }
		    if (wd->diskTrack == 0) {
			    regStatus |=  ST_TRACK00;
		    }
            if (wd->headLoaded) {
    		    regStatus |=  ST_HEAD_LOADED;
            }
        }
        else {
    		regStatus |= ST_WRITE_PROTECTED;
        }
	} 
    else {
		if (wd2793PeekDataRequest(wd)) {
			regStatus |=  ST_DATA_REQUEST;
		} 
        else {
			regStatus &= ~ST_DATA_REQUEST;
		}
	}

	if (diskPresent(wd->drive)) {
		regStatus &= ~ST_NOT_READY;
	} 
    else {
		regStatus |=  ST_NOT_READY;
	}

	return regStatus;
}
예제 #10
0
static void counterSetTimeout(Counter* counter)
{
    int nextTimeout = 0;
    int mode = counter->mode;

    // If counter is disabled, just return
    if (mode != 1 && mode != 5 && counter->gate == 0) {
        return;
    }

    if (counter->outPhase == 1) {
        nextTimeout = counter->countingElement - counter->endOutPhase1;
    }
    else if (counter->outPhase == 2) {
        nextTimeout = counter->countingElement - counter->endOutPhase2;
    }
    
    if (nextTimeout != 0) {
        counter->time = boardSystemTime() + 
                      (UInt64)boardFrequency() * nextTimeout / counter->frequency;
        boardTimerAdd(counter->timer, counter->time);
    }
}
예제 #11
0
파일: WD2793.c 프로젝트: imclab/CocoaMSX
int wd2793PeekDataRequest(WD2793* wd)
{
    int dataRequest = wd->dataRequest;

	if (((wd->regCommand & 0xF0) == 0xF0) && ((wd->regStatus & ST_BUSY) || wd->dataReady)) {
        UInt32 pulses = (boardSystemTime() - wd->dataRequsetTime) / (boardFrequency() / 5);
		if (wd->dataReady) {
			dataRequest = 1;
		} 
		if (pulses > 1) {
			dataRequest   = 0;
		}
	}

    if ((wd->regCommand & 0xe0) == 0x80 && (wd->regStatus & ST_BUSY)) {
//        UInt32 pulses = (boardSystemTime() - wd->dataRequsetTime) / (boardFrequency() / 25);
		if (wd->dataReady) {
			dataRequest = 1;
		}
    }

    return dataRequest;
}
예제 #12
0
void philipsMidiWriteCommand(PhilipsMidi* midi, UInt8 value)
{
    int baudrate      = 1;
    int dataBits      = 8;
    int parityEnable  = 0;
    int stopBits      = 1;
    UInt64 charLength;

    midi->command = value;

    switch (value & 0x03) {
    case 0:
        baudrate = 1;
        break;
    case 1:
        baudrate = 16;
        break;
    case 2:
        baudrate = 64;
        break;
    case 3:
        philipsMidiReset(midi);
        break;
    }
    
    switch (value & 0x1c) {
    case 0:
        dataBits     = 7;
        parityEnable = 1;
        stopBits     = 2;
        break;
    case 1:
        dataBits     = 7;
        parityEnable = 1;
        stopBits     = 2;
        break;
    case 2:
        dataBits     = 7;
        parityEnable = 1;
        stopBits     = 1;
        break;
    case 3:
        dataBits     = 7;
        parityEnable = 1;
        stopBits     = 1;
        break;
    case 4:
        dataBits     = 8;
        parityEnable = 0;
        stopBits     = 2;
        break;
    case 5:
        dataBits     = 8;
        parityEnable = 0;
        stopBits     = 1;
        break;
    case 6:
        dataBits     = 8;
        parityEnable = 0;
        stopBits     = 1;
        break;
    case 7:
        dataBits     = 8;
        parityEnable = 1;
        stopBits     = 1;
        break;
    }

	charLength = (dataBits + parityEnable + stopBits) * baudrate;
    midi->charTime = (UInt32)(charLength * boardFrequency() / 500000);
    
    midi->timeRecv = boardSystemTime() + midi->charTime;
    boardTimerAdd(midi->timerRecv, midi->timeRecv);
}
예제 #13
0
void mixerSync(Mixer* mixer)
{
    UInt32 systemTime = boardSystemTime();
    Int16* buffer   = mixer->buffer;
    Int32* chBuff[MAX_CHANNELS];
    UInt32 count;
    UInt64 elapsed;
    int i;

    elapsed        = mixer->rate * (UInt64)(systemTime - mixer->refTime) + mixer->refFrag;
    mixer->refTime = systemTime;
    mixer->refFrag = (UInt32)(elapsed % (mixerCPUFrequency * (boardFrequency() / 3579545)));
    count          = (UInt32)(elapsed / (mixerCPUFrequency * (boardFrequency() / 3579545)));

    if (count == 0 || count > AUDIO_MONO_BUFFER_SIZE) {
        return;
    }

    if (!mixer->enable) {
        while (count--) {
            if (mixer->stereo) {
                buffer[mixer->index++] = 0;
                buffer[mixer->index++] = 0;
            }
            else {
                buffer[mixer->index++] = 0;
            }

            if (mixer->index == mixer->fragmentSize) {
                if (mixer->writeCallback != NULL) {
                    mixer->writeCallback(mixer->writeRef, buffer, mixer->fragmentSize);
                }
                if (mixer->logging) {
                    fwrite(buffer, 2 * mixer->fragmentSize, 1, mixer->file);
                }
                mixer->index = 0;
            }
        }
        return;
    }
    
    for (i = 0; i < mixer->channelCount; i++) {
        if (mixer->channels[i].updateCallback != NULL) {
            chBuff[i] = mixer->channels[i].updateCallback(mixer->channels[i].ref, count);
        }
        else {
            chBuff[i] = NULL;
        }
    }

    if (mixer->stereo) {
        while (count--) {
            Int32 left = 0;
            Int32 right = 0;

            for (i = 0; i < mixer->channelCount; i++) {
                Int32 chanLeft;
                Int32 chanRight;

                if (chBuff[i] == NULL) {
                    continue;
                }

                if (mixer->channels[i].stereo) {
                    chanLeft = mixer->channels[i].volumeLeft * *chBuff[i]++;
                    chanRight = mixer->channels[i].volumeRight * *chBuff[i]++;
                }
                else {
                    Int32 tmp = *chBuff[i]++;
                    chanLeft = mixer->channels[i].volumeLeft * tmp;
                    chanRight = mixer->channels[i].volumeRight * tmp;
                }

                mixer->channels[i].volCntLeft  += (chanLeft  > 0 ? chanLeft  : -chanLeft)  / 2048;
                mixer->channels[i].volCntRight += (chanRight > 0 ? chanRight : -chanRight) / 2048;

                left  += chanLeft;
                right += chanRight;
            }

            left  /= 4096;
            right /= 4096;

            mixer->volCntLeft  += left  > 0 ? left  : -left;
            mixer->volCntRight += right > 0 ? right : -right;

            if (left  >  32767) { left  = 32767; }
            if (left  < -32767) { left  = -32767; }
            if (right >  32767) { right = 32767; }
            if (right < -32767) { right = -32767; }

            buffer[mixer->index++] = (Int16)left;
            buffer[mixer->index++] = (Int16)right;

            if (mixer->index == mixer->fragmentSize) {
                if (mixer->writeCallback != NULL) {
                    mixer->writeCallback(mixer->writeRef, buffer, mixer->fragmentSize);
                }
                if (mixer->logging) {
                    fwrite(buffer, 2 * mixer->fragmentSize, 1, mixer->file);
                }
                mixer->index = 0;
            }

            mixer->volIndex++;
        }
    }
    else {
        while (count--) {
            Int32 left = 0;

            for (i = 0; i < mixer->channelCount; i++) {
                Int32 chanLeft;

                if (chBuff[i] == NULL) {
                    continue;
                }

                if (mixer->channels[i].stereo) {
                    Int32 tmp = *chBuff[i]++;
                    chanLeft = mixer->channels[i].volumeLeft * (tmp + *chBuff[i]++) / 2;
                }
                else {
                    chanLeft = mixer->channels[i].volumeLeft * *chBuff[i]++;
                }
            
                mixer->channels[i].volCntLeft  += (chanLeft > 0 ? chanLeft : -chanLeft) / 2048;
                mixer->channels[i].volCntRight += (chanLeft > 0 ? chanLeft : -chanLeft) / 2048;
                left  += chanLeft;
            }

            left  /= 4096;

            mixer->volCntLeft  += left > 0 ? left : -left;
            mixer->volCntRight += left > 0 ? left : -left;

            if (left  >  32767) left  = 32767;
            if (left  < -32767) left  = -32767;

            buffer[mixer->index++] = (Int16)left;
            
            if (mixer->index == mixer->fragmentSize) {
                if (mixer->writeCallback != NULL) {
                    mixer->writeCallback(mixer->writeRef, buffer, mixer->fragmentSize);
                }
                if (mixer->logging) {
                    fwrite(buffer, 2 * mixer->fragmentSize, 1, mixer->file);
                }
                mixer->index = 0;
            }

            mixer->volIndex++;
        }
    }

    if (mixer->volIndex >= 441) {
        Int32 newVolumeLeft  = mixer->volCntLeft  / mixer->volIndex / 164;
        Int32 newVolumeRight = mixer->volCntRight / mixer->volIndex / 164;
    
        if (newVolumeLeft > 100) {
            newVolumeLeft = 100;
        }
        if (newVolumeLeft > mixer->volIntLeft) {
            mixer->volIntLeft  = newVolumeLeft;
        }

        if (newVolumeRight > 100) {
            newVolumeRight = 100;
        }
        if (newVolumeRight > mixer->volIntRight) {
            mixer->volIntRight  = newVolumeRight;
        }

        mixer->volCntLeft  = 0;
        mixer->volCntRight = 0;

        for (i = 0; i < mixer->channelCount; i++) {
            Int32 newVolumeLeft  = (Int32)(mixer->channels[i].volCntLeft  / mixer->masterVolume / mixer->volIndex / 328);
            Int32 newVolumeRight = (Int32)(mixer->channels[i].volCntRight / mixer->masterVolume / mixer->volIndex / 328);

            if (newVolumeLeft > 100) {
                newVolumeLeft = 100;
            }
            if (newVolumeLeft > mixer->channels[i].volIntLeft) {
                mixer->channels[i].volIntLeft  = newVolumeLeft;
            }

            if (newVolumeRight > 100) {
                newVolumeRight = 100;
            }
            if (newVolumeRight > mixer->channels[i].volIntRight) {
                mixer->channels[i].volIntRight  = newVolumeRight;
            }

            mixer->channels[i].volCntLeft  = 0;
            mixer->channels[i].volCntRight = 0;

            if (chBuff[i] && chBuff[i][0]) {
                mixer->channels[i].active++;
            }
        }
        mixer->volIndex = 0;
    }
}
예제 #14
0
파일: WD2793.c 프로젝트: imclab/CocoaMSX
static void sync(WD2793* wd)
{
    if (wd->step) {
        const UInt64 timePerStep[4] = { 200, 100, 66, 50 };

        UInt32 steps = (UInt32)(timePerStep[wd->regCommand & 3] * (boardSystemTime() - wd->stepTime) / boardFrequency());

        while (wd->curStep < steps) {
            wd->curStep++;
	        if ((wd->regCommand & 0x10) || ((wd->regCommand & 0xe0) == 0x00)) {
		        wd->regTrack += wd->stepDirection;
            }

            if (diskEnabled(wd->drive) && 
                ((wd->stepDirection == -1 && wd->diskTrack > 0) || wd->stepDirection == 1)) {
		        wd->diskTrack += wd->stepDirection;
            }
            if (wd->regCommand & 0xe0) {
	            wd->intRequest = 1;
	            wd->regStatus &= ~ST_BUSY;
                wd->step       = 0;
                break;
            } 
            if (wd->stepDirection == -1 && diskEnabled(wd->drive) && wd->diskTrack == 0) {
                wd->regTrack   = 0;
	            wd->intRequest = 1;
	            wd->regStatus &= ~ST_BUSY;
                wd->step       = 0;
                break;
            }
            
            if (wd->regTrack == wd->regData) {
	            wd->intRequest = 1;
	            wd->regStatus &= ~ST_BUSY;
                wd->step       = 0;
                break;
            }
        }
    }
}
예제 #15
0
파일: Board.c 프로젝트: juvenal/CocoaMSX
#include "RomLoader.h"
#include "JoystickPort.h"
#include <string.h>
#include <stdlib.h>
#include <time.h>

extern void PatchReset(BoardType boardType);

static int pendingInt;
static int boardType;
static Mixer* boardMixer = NULL;
static int (*syncToRealClock)(int, int) = NULL;
UInt32* boardSysTime;
static UInt64 boardSysTime64;
static UInt32 oldTime;
static UInt32 boardFreq = boardFrequency();
static int fdcTimingEnable = 1;
static int fdcActive       = 0;
static BoardTimer* fdcTimer;
static BoardTimer* syncTimer;
static BoardTimer* mixerTimer;
static BoardTimer* stateTimer;
static BoardDeviceInfo* boardDeviceInfo;
static Machine* boardMachine;
static BoardInfo boardInfo;
static UInt32 boardRamSize;
static UInt32 boardVramSize;
static int boardRunning = 0;

static HdType hdType[MAX_HD_COUNT];