/*SMS emulation core

missing features
- Lightgun support
- savestate support
- cheat support

- SG-1000, SC-3000
- game gear emulation
- additional yamaha sound chip
*/
#ifndef interface_h
#define interface_h

#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>

using namespace std;

#ifdef _WIN32
	#define dllexport __declspec(dllexport)
#else
	#define dllexport
#endif

#define free_mem(__m) if(__m) { delete[](__m); __m = 0; }
#define dx_release(__m) if(__m) { __m->Release(); __m = 0; }

template<typename T> inline T _minmax(const T x, const T min, const T max) {
	return (x < min) ? min : ((x > max) ? max : x);
}

char* concatStr(int num, ...);

typedef signed char i8;
typedef unsigned char u8;
typedef signed long long i64;
typedef unsigned long long u64;

template<int> struct Type {};

template<> struct Type< 1  > { typedef signed   int   i16; };
template<> struct Type< 2  > { typedef signed   short i16; };
template<> struct Type< 3  > { typedef signed   long  i16; };
template<> struct Type< 4  > { typedef unsigned int   u16; };
template<> struct Type< 5  > { typedef unsigned short u16; };
template<> struct Type< 6  > { typedef unsigned long  u16; };
template<> struct Type< 7  > { typedef signed   int   i32; };
template<> struct Type< 8  > { typedef signed   short i32; };
template<> struct Type< 9  > { typedef signed   long  i32; };
template<> struct Type< 10 > { typedef unsigned int   u32; };
template<> struct Type< 11 > { typedef unsigned short u32; };
template<> struct Type< 12 > { typedef unsigned long  u32; };

typedef Type<sizeof(int) == 2 ?  1 : sizeof(short) == 2 ?  2 : sizeof(long) == 2 ?  3 : 0>::i16 i16;
typedef Type<sizeof(int) == 2 ?  4 : sizeof(short) == 2 ?  5 : sizeof(long) == 2 ?  6 : 0>::u16 u16;
typedef Type<sizeof(int) == 4 ?  7 : sizeof(short) == 4 ?  8 : sizeof(long) == 4 ?  9 : 0>::i32 i32;
typedef Type<sizeof(int) == 4 ? 10 : sizeof(short) == 4 ? 11 : sizeof(long) == 4 ? 12 : 0>::u32 u32;

class _System;
class Bus;
class Cpu;
class Vdp;
class SN76489;
class DVideo;
class DSound;
class DInput;
class Inputmanager;
class Color;
class Filter;

#include "mem.h"
#include "colorInterface/color.h"
#include "system/inputmanager.h"
#include "lib/libco/libco.h"
#include "directX/directx.h"
#include "bus/bus.h"
#include "cpu/core/z80.h"
#include "cpu/cpu.h"
#include "vdp/vdp.h"
#include "lib/blip_buffer/Blip_Buffer.h"
#include "lib/sms_ntsc/sms_ntsc.h"
#include "apu/sn76489.h"
#include "system/system.h"

#ifdef MAIN
	_System _system;
#else
	extern _System _system;
#endif
	
extern "C"
{
	//check if the dll is responding
	dllexport void test();
	//give pointer and size for rom, sram and / or bios rom
	dllexport void setCartMemory( u8*, u32,  u8*, u32,  u8*, u32 );
	//provide pointer to main main window
	dllexport void setHwnd(HWND hwnd);
	//hard reset
	dllexport void power();
	//soft reset
	dllexport void reset();
	//run emulation for one frame
	dllexport void enter();
	//set mapper of rom (standard = 11, codemasters = 12 or korean = 13), region( USA = 0, JAPAN = 1, EUROPE = 2) and Sms unit (SMS1 = 0, SMS2 = 1)
	dllexport void map(Bus::Type, _System::Region, _System::Unit);
	//init DirectVideo
	dllexport bool initVideo(HWND hwnd, int width, int height, bool vsync, bool fullscreen);
	//init DirectSound (speed in %, 100% pal = 50 frames, 100% ntsc = 60 frames)
	dllexport bool initSound(bool _audio_active, unsigned _speed, unsigned _frequency, unsigned _volume);
	//update color, filter type 0 = normal, 1 = Blargg's ntsc filter, ntsc_filter_cable: 0 = composite, 1 = svideo, 2 = rgb
	dllexport void updateColor(int contrast, int gamma, int brightness, int filter_type, int ntsc_filter_cable);
	//Hardware filtering, should not be merged with the ntsc filter
	dllexport void setHWFilter(int filter);
	//activate the frame counter
	dllexport void setCounter(bool state);
	//show scanlines, intensity in %
	dllexport void setScanlines(bool state, unsigned intensity);
	//show a display message, like savestate written or whatever, display_frames = how many frames visible, critical = display it in red
	dllexport void setDisplayMes(char* display_mes, int display_frames, bool critical);
	//pause audio
	dllexport void pauseAudio();
	//play audio
	dllexport void playAudio();
	//clear video
	dllexport void clearVideo();
	//clear audio
	dllexport void clearAudio();

	//init DirectInput
	dllexport bool initInput();
	//gets all configurable input devices by Id, returns device count
	dllexport unsigned getInputDeviceIdList(u8* deviceIdList);
	//returns the name of the input device
	dllexport void getInputDeviceName(Inputmanager::DeviceID deviceId, char* name);
	//get the port of the input device
	dllexport Inputmanager::Device::Port getInputDevicePort(Inputmanager::DeviceID deviceId);
	//get all configurable input objects by Id of a selected device, returns object count
	dllexport unsigned getInputDeviceObjectIdList(Inputmanager::DeviceID deviceId, u8* iobjectIdList);
	//get a mapping description of an input object
	dllexport void getInputDeviceObjectEntry(Inputmanager::DeviceID deviceId, Inputmanager::IObjectID iobjectId, char* entry);
	//map input object of a device, e.g. from a configuration file
	dllexport void updateInputMap(Inputmanager::DeviceID deviceId, Inputmanager::IObjectID iobjectId, unsigned element);
	//get mapped element of input object, e.g. read new value after a remap in order to save it in configuration file
	dllexport unsigned readInputMap(Inputmanager::DeviceID deviceId, Inputmanager::IObjectID iobjectId);
	//remove entire object mapping of a device
	dllexport void unmapInput(Inputmanager::DeviceID deviceid);
	//set input device for a port
	dllexport void setInputPort(Inputmanager::Device::Port port, Inputmanager::DeviceID deviceId);
	//prepare input object of a device for remap
	dllexport void captureReady(Inputmanager::DeviceID deviceId,  Inputmanager::IObjectID iobjectId);
	//check if remap capturing is in process
	dllexport bool isInputCapturing();
	//end remap capturing process, e.g. there is no input in a specific time
	dllexport void endInputCapturing();
	//poll Input
	dllexport void pollInput();
}

#endif