/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-1-1/backends/platform/n64/osys_n64.h $
 * $Id: osys_n64.h 48108 2010-02-21 19:02:45Z Hkz $
 *
 */

#ifndef __OSYS_N64_H__
#define __OSYS_N64_H__

#include "common/rect.h"
#include "common/config-manager.h"

#include "backends/base-backend.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"

#include "base/main.h"

#include "graphics/surface.h"
#include "graphics/colormasks.h"
#include "graphics/pixelformat.h"

#include "sound/mixer_intern.h"

#include <libn64.h>
#include <n64utils.h>

#define DEFAULT_SOUND_SAMPLE_RATE 8000 // 8 kHz
//#define DEFAULT_SOUND_SAMPLE_RATE 11025 // 11 kHz

#define N64_PAL_FPS 25
#define N64_NTSC_FPS 30

typedef int (*TimerProc)(int interval);

// Interrupt callback functions
void vblCallback(void);
void sndCallback(void);
void refillAudioBuffers(void);

// External utility functions
void enableAudioPlayback(void);
void disableAudioPlayback(void);
void checkTimers(void);
int timer_handler(int t);

static volatile bool _audioEnabled = false; // Used by interrupt callbacks

/* Graphic mode identifiers */
enum GraphicModeID {
	OVERS_NTSC_340X240,
	NORM_NTSC_320X240,
	NORM_PAL_320X240,
	OVERS_PAL_340X240,
	NORM_MPAL_320X240,
	OVERS_MPAL_340X240
};

class OSystem_N64 : public BaseBackend {
protected:
	Common::SaveFileManager *_savefile;
	Audio::MixerImpl *_mixer;
	Common::TimerManager *_timer;
	FilesystemFactory *_fsFactory;

	struct display_context * _dc; // Display context for N64 on screen buffer switching

	Graphics::Surface _framebuffer;

	uint16 *_offscreen_hic; // Offscreen converted to 16bit surface
	uint8  *_offscreen_pal; // Offscreen with palette indexes
	OverlayColor *_overlayBuffer; // Offscreen for the overlay (16 bit)

	uint16 *_screenPalette; // Array for palette entries (256 colors max)
	uint16 _cursorPalette[256]; // Palette entries for the cursor

	int _graphicMode; // Graphic mode
	uint16 _screenWidth, _screenHeight;
	uint16 _gameWidth, _gameHeight;
	uint16 _frameBufferWidth; // Width of framebuffer in N64 memory
	uint8 _offscrPixels; // Pixels to skip on each line before start drawing, used to center image
	uint8 _maxFps;

	int _shakeOffset;

	uint8 *_cursor_pal; // Cursor buffer, palettized
	uint16 *_cursor_hic; // Cursor buffer, 16bit
	bool _cursorPaletteDisabled;
	bool _dirtyPalette;

	int _cursorWidth, _cursorHeight;
	int _cursorKeycolor;

	uint16	_overlayHeight, _overlayWidth;
	bool	_overlayVisible;

	bool	_disableFpsLimit; // When this is enabled, the system doesn't limit screen updates

	bool _mouseVisible;
	volatile int _mouseX, _mouseY;
	volatile float _tempMouseX, _tempMouseY;
	volatile int _mouseMaxX, _mouseMaxY;
	int _mouseHotspotX, _mouseHotspotY;

	uint8 _controllerPort;
	int8 _mousePort;
	bool _controllerHasRumble;

	bool _dirtyOffscreen;

public:

	/* These have to be accessed by interrupt callbacks */
	uint16 _audioBufferSize;
	uint32 _viClockRate; // Clock rate of video system, depending on VI mode

	int _timerCallbackNext;
	int _timerCallbackTimer;
	TimerProc _timerCallback;
	/* *** */

	OSystem_N64();
	virtual ~OSystem_N64();

	virtual void initBackend();

	virtual bool hasFeature(Feature f);
	virtual void setFeatureState(Feature f, bool enable);
	virtual bool getFeatureState(Feature f);
	virtual const GraphicsMode *getSupportedGraphicsModes() const;
	virtual int getDefaultGraphicsMode() const;
	bool setGraphicsMode(const char *name);
	virtual bool setGraphicsMode(int mode);
	virtual int getGraphicsMode() const;
	virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format);
	virtual int16 getHeight();
	virtual int16 getWidth();
	virtual void setPalette(const byte *colors, uint start, uint num);
	virtual void grabPalette(byte *colors, uint start, uint num);
	virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
	virtual void updateScreen();
	virtual Graphics::Surface *lockScreen();
	virtual void unlockScreen();
	virtual void setShakePos(int shakeOffset);

	virtual void showOverlay();
	virtual void hideOverlay();
	virtual void clearOverlay();
	virtual void grabOverlay(OverlayColor *buf, int pitch);
	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
	virtual int16 getOverlayHeight();
	virtual int16 getOverlayWidth();
	virtual Graphics::PixelFormat getOverlayFormat() const {
		return Graphics::createPixelFormat<555>();
	}

	virtual bool showMouse(bool visible);

	virtual void warpMouse(int x, int y);
	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
	virtual void setCursorPalette(const byte *colors, uint start, uint num);
	virtual void disableCursorPalette(bool disable);

	virtual bool pollEvent(Common::Event &event);
	virtual uint32 getMillis();
	virtual void delayMillis(uint msecs);

	virtual MutexRef createMutex(void);
	virtual void lockMutex(MutexRef mutex);
	virtual void unlockMutex(MutexRef mutex);
	virtual void deleteMutex(MutexRef mutex);

	virtual void quit();

	virtual Common::SaveFileManager *getSavefileManager();
	virtual Audio::Mixer *getMixer();
	virtual void getTimeAndDate(TimeDate &t) const;
	virtual Common::TimerManager *getTimerManager();
	virtual void setTimerCallback(TimerProc callback, int interval);
	FilesystemFactory *getFilesystemFactory();

	void rebuildOffscreenGameBuffer(void);
	void rebuildOffscreenMouseBuffer(void);
	void switchGraphicModeId(int mode);

	void setupMixer(void);

	void detectControllers(void);
	void readControllerAnalogInput(void); // read controller analog nub position
};

#endif /* __OSYS_N64_H__ */

