Commit 9bb36f82 authored by MJaoune's avatar MJaoune
Browse files

Initial commit

parents
This diff is collapsed.
STATIC_LINKING := 0
AR := ar
CC := g++
ifeq ($(platform),)
platform = unix
ifeq ($(shell uname -a),)
platform = win
else ifneq ($(findstring MINGW,$(shell uname -a)),)
platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx
else ifneq ($(findstring win,$(shell uname -a)),)
platform = win
endif
endif
# system platform
system_platform = unix
ifeq ($(shell uname -a),)
EXE_EXT = .exe
system_platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
system_platform = osx
arch = intel
ifeq ($(shell uname -p),powerpc)
arch = ppc
endif
else ifneq ($(findstring MINGW,$(shell uname -a)),)
system_platform = win
endif
TARGET_NAME := vemulator
LIBM = -lm
ifeq ($(ARCHFLAGS),)
ifeq ($(archs),ppc)
ARCHFLAGS = -arch ppc -arch ppc64
else
ARCHFLAGS = -arch i386 -arch x86_64
endif
endif
ifeq ($(platform), osx)
ifndef ($(NOUNIVERSAL))
CFLAGS += $(ARCHFLAGS)
LFLAGS += $(ARCHFLAGS)
endif
endif
ifeq ($(STATIC_LINKING), 1)
EXT := a
endif
ifeq ($(platform), unix)
EXT ?= so
TARGET := $(TARGET_NAME)_libretro.$(EXT)
fpic := -fPIC
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
else ifeq ($(platform), linux-portable)
TARGET := $(TARGET_NAME)_libretro.$(EXT)
fpic := -fPIC -nostdlib
SHARED := -shared -Wl,--version-script=link.T
LIBM :=
else ifneq (,$(findstring osx,$(platform)))
TARGET := $(TARGET_NAME)_libretro.dylib
fpic := -fPIC
SHARED := -dynamiclib
else ifneq (,$(findstring ios,$(platform)))
TARGET := $(TARGET_NAME)_libretro_ios.dylib
fpic := -fPIC
SHARED := -dynamiclib
ifeq ($(IOSSDK),)
IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path)
endif
DEFINES := -DIOS
CC = CC -arch armv7 -isysroot $(IOSSDK)
ifeq ($(platform),ios9)
CC += -miphoneos-version-min=8.0
CFLAGS += -miphoneos-version-min=8.0
else
CC += -miphoneos-version-min=5.0
CFLAGS += -miphoneos-version-min=5.0
endif
else ifneq (,$(findstring qnx,$(platform)))
TARGET := $(TARGET_NAME)_libretro_qnx.so
fpic := -fPIC
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
else ifeq ($(platform), emscripten)
TARGET := $(TARGET_NAME)_libretro_emscripten.bc
fpic := -fPIC
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
else ifeq ($(platform), vita)
TARGET := $(TARGET_NAME)_vita.a
CC = arm-vita-eabi-g++
AR = arm-vita-eabi-ar
CFLAGS += -Wl,-q -Wall -O3
STATIC_LINKING = 1
else
CC = g++
TARGET := $(TARGET_NAME)_libretro.dll
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T -Wl,--no-undefined
endif
LDFLAGS += $(LIBM)
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -g
else
CFLAGS += -O3
endif
OBJECTS := *.cpp
CFLAGS += -Wall -pedantic $(fpic)
ifneq (,$(findstring qnx,$(platform)))
CFLAGS += -Wc,-std=c++99
else
CFLAGS += -std=gnu++99
endif
all: $(TARGET)
$(TARGET): $(OBJECTS)
ifeq ($(STATIC_LINKING), 1)
$(AR) rcs $@ $(OBJECTS)
else
$(CC) $(fpic) $(SHARED) $(INCLUDES) -o $@ $(OBJECTS) $(LDFLAGS)
endif
%.o: %.cpp
$(CC) $(CFLAGS) $(fpic) -c -o $@ $<
clean:
rm -f *.so *.o
.PHONY: clean
/*
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
Copyright (C) 2018 Mahmoud Jaoune
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "audio.h"
VE_VMS_AUDIO::VE_VMS_AUDIO(VE_VMS_CPU *_cpu, VE_VMS_RAM *_ram)
{
T1LR_reg = 0;
T1LC_reg = 128;
IsEnabled = false;
T1LR_old = -1;
ram = _ram;
cpu = _cpu;
sampleArray = (int16_t *)calloc(2*SAMPLE_RATE, sizeof(int16_t)); //Multiplied by 2 because 2 channels
frequency = 146539.3;
}
VE_VMS_AUDIO::~VE_VMS_AUDIO()
{
free(sampleArray);
}
void VE_VMS_AUDIO::generateSignal(retro_audio_sample_t &audio_cb)
{
if(!IsEnabled)
{
audio_cb(0, 0);
return;
}
double T1LC_reg_D = T1LC_reg;
double T1LR_reg_D = T1LR_reg;
//1 second is equal to 32768 samples
int16_t waveWidth = (int16_t) ((256 - T1LR_reg_D) * (SAMPLE_RATE / frequency)); //1 Wave (In samples not seconds)
double lowLevelWidth = abs((((T1LC_reg_D - T1LR_reg_D)/(256 - T1LR_reg_D)) * waveWidth));
//lowLevelWidth = 0.5 * waveWidth; //Many mini-games don't care about T1LD, 0.5 would play a sound close to the original.
for(int i = 0; i < SAMPLE_RATE / FPS; i++)
{
int16_t amplitude = 0x7FFF;
if(waveWidth != 0)
{
if((i%waveWidth) < lowLevelWidth) amplitude = 0;
}
audio_cb(amplitude, amplitude);
}
}
void VE_VMS_AUDIO::setAudioFrequency(double f)
{
frequency = f;
}
void VE_VMS_AUDIO::setT1(int b)
{
T1LR_reg = b & 0xFF;
}
void VE_VMS_AUDIO::setT1C(int b)
{
T1LC_reg = b & 0xFF;
}
void VE_VMS_AUDIO::setEnabled(bool e)
{
IsEnabled = e;
}
void VE_VMS_AUDIO::runAudioCheck()
{
if(!IsEnabled)
{
size_t count = SAMPLE_RATE * 2;
//Empty signal (No sound)
for(size_t i = 0; i < count; i++)
sampleArray[i] = 0;
T1LR_old = -1;
}
else if(T1LR_old != T1LR_reg)
//generateSignal();
T1LR_old = T1LR_reg;
}
int16_t *VE_VMS_AUDIO::getSignal()
{
return sampleArray;
}
/*
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
Copyright (C) 2018 Mahmoud Jaoune
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _AUDIO_H_
#define _AUDIO_H_
#include <math.h>
#include "libretro.h"
#include "common.h"
#include "cpu.h"
#include "ram.h"
class VE_VMS_AUDIO
{
public:
VE_VMS_AUDIO(VE_VMS_CPU *_cpu, VE_VMS_RAM *_ram);
~VE_VMS_AUDIO();
void generateSignal(retro_audio_sample_t &audio_cb);
void setAudioFrequency(double f);
void setT1(int b);
void setT1C(int b);
void setEnabled(bool e);
void runAudioCheck();
int16_t *getSignal();
private:
int T1LR_reg;
int T1LC_reg;
bool IsEnabled;
int T1LR_old;
double frequency; //This is supposed to be the CPU's frequency, but we have made the CPU's clock fixed
int16_t *sampleArray;
VE_VMS_CPU *cpu;
VE_VMS_RAM *ram;
};
#endif // _AUDIO_H_
/*
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
Copyright (C) 2018 Mahmoud Jaoune
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "basetimer.h"
VE_VMS_BASETIMER::VE_VMS_BASETIMER(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu)
{
ram = _ram;
intHandler = _intHandler;
cpu = _cpu;
BTR = 0;
}
VE_VMS_BASETIMER::~VE_VMS_BASETIMER()
{
}
void VE_VMS_BASETIMER::runTimer()
{
int BTCR_data = ram->readByte_RAW(BTCR);
bool BTStarted = (BTCR_data & 64) != 0;
bool Int0Enabled = (BTCR_data & 1) != 0;
bool Int1Enabled = (BTCR_data & 4) != 0;
int int1cycle;
int cycleControl = ((BTCR_data & 16) >> 4) | ((BTCR_data & 32) >> 4);
switch (cycleControl)
{
case 0:
int1cycle = 32;
break;
case 1:
int1cycle = 128;
break;
case 2:
int1cycle = 512;
break;
case 3:
int1cycle = 2048;
break;
default:
int1cycle = 2048;
}
if(BTStarted)
{
BTR += 32786.0 / cpu->getCurrentFrequency();
//Throw interrupt 1 source when cycle chosen is reached
if(BTR >= int1cycle)
{
BTCR_data |= 8;
ram->writeByte_RAW(BTCR, BTCR_data);
if (Int1Enabled)
intHandler->setINT3();
}
if((BTR > 16383) || (BTR > 63 && ((BTCR_data & 128) != 0)))
{
//Throw full (14-bit) overflow interrupt (Interrupt 0 source)
BTCR_data |= 2;
ram->writeByte_RAW(BTCR, BTCR_data);
if(Int0Enabled)
intHandler->setINT3();
if(BTR > 16383) BTR = 0;
}
}
}
/*
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
Copyright (C) 2018 Mahmoud Jaoune
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BASETIMER_H_
#define _BASETIMER_H_
#include "ram.h"
#include "interrupts.h"
#include "cpu.h"
class VE_VMS_BASETIMER
{
public:
VE_VMS_BASETIMER(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu);
~VE_VMS_BASETIMER();
void runTimer();
private:
double BTR; //14-bit
VE_VMS_RAM *ram;
VE_VMS_INTERRUPTS *intHandler;
VE_VMS_CPU *cpu;
};
#endif // _BASETIMER_H_
/*
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
Copyright (C) 2018 Mahmoud Jaoune
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "bitwisemath.h"
//Flags [0|0|0|0|0|O|A|C/B]
//This is an 8-bit adder. Returns sum as first in array, then flags.
void add8(byte i1, byte i2, byte carry, byte *result)
{
byte op1 = i1 & 0xFF;
byte op2 = i2 & 0xFF;
byte s = 0; //8-bits
byte c = carry; //Assume its 1-bit
byte flags = 0;
byte c6 = 0;
byte c7 = 0;
//Start operation
for(byte i = 0; i < 8; ++i)
{
//Take next bit
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
//Sum them together
byte z1 = (bit1 ^ bit2) & 0xFF;
s |= ((c ^ z1) << i) & 0xFF;
//Calculate carry
byte c1 = (c & z1) & 0xFF;
byte c2 = (bit1 & bit2) & 0xFF;
c = (c1 | c2) & 0xFF;
//Auxiliary flag set
if(c != 0 && i == 3)
flags |= 0x2;
if(i == 6) c6 = c & 1;
else if(i == 7) c7 = c & 1;
}
c &= 1;
//Check carry
if(c == 1)
flags |= 0x1;
//Check overflow
if(c6 != c7)
flags |= 0x4;
result[0] = s & 0xFF;
result[1] = flags & 0xFF;
}
void sub8(byte i1, byte i2, byte carry, byte *result)
{
byte op1 = i1 & 0xFF;
byte op2 = i2 & 0xFF;
op2 ^= 0xFF; //2's Complement
op2 &= 0xFF;
byte s = 0; //8-bits
byte c = carry ^ 0xFF; //Assume its 1-bit
c &= 1;
byte flags = 0;
byte c6 = 0;
byte c7 = 0;
//Start operation
for(byte i = 0; i < 8; ++i)
{
//Take next bit
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
//Sum them together
byte z1 = (bit1 ^ bit2) & 0xFF;
s |= ((c ^ z1) << i) & 0xFF;
//Calculate carry
byte c1 = (c & z1) & 0xFF;
byte c2 = (bit1 & bit2) & 0xFF;
c = (c1 | c2) & 0xFF;
//Auxiliary flag set
if(c == 0 && i == 3)
flags |= 0x2;
if(i == 6) c6 = c & 1;
else if(i == 7) c7 = c & 1;
}
c ^= 0xFF;
c &= 1;
//Check carry
if(c == 1)
flags |= 0x1;
//Check overflow
if(c6 != c7)
flags |= 0x4;
result[0] = s & 0xFF;
result[1] = flags & 0xFF;
}
//This is an 8-bit subtractor (op1 - op2). Returns difference as first in array, then flags.
void sub8_old(byte i1, byte i2, byte *result)
{
byte op1 = i1 & 0xFF;
byte op2 = i2 & 0xFF;
byte d = 0; //8-bits
byte b = 0; //Assume its 1-bit
byte flags = 0;
//Those following two will be used to calculate overflow flag later
byte MSB1 = (op1 & 0x80) & 0xFF; //No need to shift them, since all of them are in the same place
byte MSB2 = (op2 & 0x80) & 0xFF;
for(byte i = 0; i < 8; ++i)
{
//Take next bit
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
//Sub them from each other
byte z1 = (bit1 ^ bit2) & 0xFF;
d |= ((b ^ z1) << i) & 0xFF;
//Calculate borrow
byte bit1_neg = (~bit1) & 0xF; //Invert the bit (Only the bit)
byte z1_neg = (~z1) & 0xF;
byte b1 = (z1_neg & b) & 0xFF;
byte b2 = (bit1_neg & bit2) & 0xFF;
b = (b1 | b2) & 0xFF;
//Auxiliary flag set
if(b != 0 && i == 1)
flags |= 0x2;
}
//Check carry flag
if(b == 1)
flags |= 0x1;
//Check overflow
byte resultMSB = (d & 0x80) & 0xFF;
if((MSB1 == MSB2) && MSB1 != resultMSB)
flags |= 0x4;
result[0] = d & 0xFF;
result[1] = flags & 0xFF;
}
//Take complement
byte comp8(byte op)
{
return (((~op) & 0xFF) + 1) & 0xFF;
}
//Convert to signed
byte toSigned8(byte op)