/* PVR texture memory pointer; unlike the old "TA" system, PVR pointers
   in the new system are actually SH-4 compatible pointers and can
   be used directly in place of ta_txr_map(). */
typedef void * pvr_ptr_t;

/* PVR list specification */
typedef uint32 pvr_list_t;


typedef unsigned long long uint64;
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef long long int64;
typedef long int32;
typedef short int16;
typedef char int8;

/* Volatile types */
typedef volatile uint64 vuint64;
typedef volatile uint32 vuint32;
typedef volatile uint16 vuint16;
typedef volatile uint8 vuint8;
typedef volatile int64 vint64;
typedef volatile int32 vint32;
typedef volatile int16 vint16;
typedef volatile int8 vint8;

/* Pointer arithmetic types */
typedef uint32 ptr_t;

typedef unsigned char	u_char;
typedef unsigned short	u_short;
typedef unsigned int	u_int;
typedef unsigned long	u_long;
typedef unsigned short	ushort;
typedef unsigned int	uint;


typedef int size_t;
//#if 0
/* File-specific types */
typedef size_t ssize_t;
typedef size_t off_t;
//#endif

/* This type may be used for any generic handle type that is allowed
   to be negative (for errors) and has no specific bit count
   restraints. */
typedef int handle_t;

/* Thread and priority types */
typedef handle_t tid_t;
typedef handle_t prio_t;

// by SWAT for lua
size_t *size_t_new();
void size_t_delete(size_t *s);


/* Flush a range of i-cache, given a physical address range */
void icache_flush_range(uint32 start, uint32 count);

/* Invalidate a range of o-cache/d-cache, given a physical address range */
void dcache_inval_range(uint32 start, uint32 count);

/* Flush a range of o-cache/d-cache, given a physical address range */
void dcache_flush_range(uint32 start, uint32 count);

/* Replace the currently running image with whatever is at
   the pointer; note that this call will never return. */
void arch_exec_at(const void *image, uint32 length, uint32 address);
void arch_exec(const void *image, uint32 length);


/* Directory entry; all handlers must conform to this interface */
typedef struct kos_dirent {
	int	size;
	char	name[MAX_FN_LEN];
	time_t	time;
	uint32	attr;
} dirent_t;

/* File status information; like dirent, this is not the same as the *nix
   variation but it has similar information. */
struct vfs_handler;
typedef struct /*stat*/ {
	struct vfs_handler	* dev;		/* The VFS handler for this file/dir */
	uint32			unique;		/* A unique identifier on the VFS for this file/dir */
	uint32			type;		/* File/Dir type */
	uint32			attr;		/* Attributes */
	off_t			size;		/* Total file size, if applicable */
	time_t			time;		/* Last access/mod/change time (depends on VFS) */
} stat_t;

/* stat_t.unique */
#define STAT_UNIQUE_NONE	0	/* Constant to use denoting the file has no unique ID */

/* stat_t.type */
#define STAT_TYPE_NONE		0	/* Unknown / undefined / not relevant */
#define STAT_TYPE_FILE		1	/* Standard file */
#define STAT_TYPE_DIR		2	/* Standard directory */
#define STAT_TYPE_PIPE		3	/* A virtual device of some sort (pipe, socket, etc) */
#define STAT_TYPE_META		4	/* Meta data */

/* stat_t.attr */
#define STAT_ATTR_NONE		0x00	/* No attributes */
#define STAT_ATTR_R		0x01	/* Read-capable */
#define STAT_ATTR_W		0x02	/* Write-capable */
//#define STAT_ATTR_RW		(STAT_ATTR_R | STAT_ATTR_W)	/* Read/Write capable */

/* File descriptor type */
typedef int file_t;

/* Invalid file handle constant (for open failure, etc) */
//#define FILEHND_INVALID	((file_t)-1)

/* This is the number of distinct file descriptors the global table
   has in it. */
#define FD_SETSIZE	1024

/* This is the private struct that will be used as raw file handles
   underlying descriptors. */
struct fs_hnd;

/* The kernel-wide file descriptor table. These will reference to open files. */
//extern struct fs_hnd * fd_table[FD_SETSIZE];

/* Open modes */
//#include <sys/fcntl.h>
//#if 0
#define O_RDONLY	1		/* Read only */
#define O_RDWR		2		/* Read-write */
#define O_APPEND	3		/* Append to an existing file */
#define O_WRONLY	4		/* Write-only */
//#endif
//#define O_MODE_MASK	7		/* Mask for mode numbers */
#define O_MODE_MASK	0x0f		/* Mask for mode numbers */
#define O_TRUNC		0x0100		/* Truncate */
#define O_ASYNC		0x0200		/* Open for asynchronous I/O */
#define O_NONBLOCK	0x0400		/* Open for non-blocking I/O */
#define O_DIR		0x1000		/* Open as directory */
#define O_META		0x2000		/* Open as metadata */

/* Seek modes */
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

/* Standard file descriptor functions */
file_t	fs_open(const char *fn, int mode);
void	fs_close(file_t hnd);
ssize_t	fs_read(file_t hnd, void *buffer, size_t cnt);
ssize_t	fs_write(file_t hnd, const void *buffer, size_t cnt);
off_t	fs_seek(file_t hnd, off_t offset, int whence);
off_t	fs_tell(file_t hnd);
size_t	fs_total(file_t hnd);
dirent_t* fs_readdir(file_t hnd);
int	fs_ioctl(file_t hnd, void *data, size_t size);
int	fs_rename(const char *fn1, const char *fn2);
int	fs_unlink(const char *fn);
int	fs_chdir(const char *fn);
void*	fs_mmap(file_t hnd);
int	fs_complete(file_t fd, ssize_t * rv);
int	fs_stat(const char * fn, stat_t * rv);
int	fs_mkdir(const char * fn);
int	fs_rmdir(const char * fn);
file_t	fs_dup(file_t oldfd);
file_t	fs_dup2(file_t oldfd, file_t newfd);

/* Call this function to create a "transient" file descriptor. What this
   does for you is let you setup ad-hoc VFS integration for libs that
   have their own open mechanism (e.g., TCP/IP sockets). It could also be
   used to do things like generic resource management. Calling this
   function is functionally identical to fs_open, except it doesn't
   require registering a full VFS or doing a name lookup. */
file_t	fs_open_handle(vfs_handler_t * vfs, void * hnd);

/* These two functions are used to reveal "internal" info about a file
   descriptor, so that libraries can provide their own facilities using
   VFS-sponsored file descriptors (e.g., TCP/IP bind, connect, etc). */
vfs_handler_t * fs_get_handler(file_t fd);
void * fs_get_handle(file_t fd);

/* Returns the working directory of the current thread */
const char *fs_getwd();

/* Couple of util functions */

/* Copies a file from 'src' to 'dst'. The amount of the file
   actually copied without error is returned. */
ssize_t	fs_copy(const char * src, const char * dst);

/* Opens a file, allocates enough RAM to hold the whole thing,
   reads it into RAM, and closes it. The caller owns the allocated
   memory (and must free it). The file size is returned, or -1
   on failure; on success, out_ptr is filled with the address
   of the loaded buffer, and on failure it is set to NULL. */
ssize_t fs_load(const char * src, void ** out_ptr);


/* Call this function to create a new pty. The name of the pty is written
   into the user-provided buffer (if non-NULL) and two open file descriptors
   pointing to the two ends of the pty are returned. */
int fs_pty_create(char * buffer, int maxbuflen, file_t * master_out, file_t * slave_out);



/* DMA copy from SH-4 RAM to G2 bus (dir = 0) or the opposite;
   length must be a multiple of 32,
   and the source and destination addresses must be aligned on 32-byte
   boundaries. If block is non-zero, this function won't return until
   the transfer is complete. If callback is non-NULL, it will be called
   upon completion (in an interrupt context!). Returns <0 on error.

   Known working combination :

   g2chn = 0, sh4chn = 3 --> mode = 5 (but many other value seems OK ?)
   g2chn = 1, sh4chn = 1 --> mode = 0 (or 4 better ?)
   g2chn = 1, sh4chn = 0 --> mode = 3

   It seems that g2chn is not important when choosing mode, so this mode parameter is probably
   how we actually connect the sh4chn to the g2chn.

   Update : looks like there is a formula, mode = 3 + shchn

*/

/* We use sh channel 3 here to avoid conflicts with the PVR. */
#define SPU_DMA_MODE   6 /* should we use 6 instead, so that the formula is 3+shchn ?
			    6 works too, so ... */
#define SPU_DMA_G2CHN  0
#define SPU_DMA_SHCHN  3

/* For BBA : sh channel 1 (doesn't seem used) and g2 channel 1 to no conflict with SPU */
#define BBA_DMA_MODE   4
#define BBA_DMA_G2CHN  1
#define BBA_DMA_SHCHN  1

/* For BBA2 : sh channel 0 (doesn't seem used) and g2 channel 2 to no conflict with SPU */
/* This is a second DMA channels used for the BBA, just for fun and see if we can initiate
   two DMA transfers with the BBA concurently. */
#define BBA_DMA2_MODE   3
#define BBA_DMA2_G2CHN  2
#define BBA_DMA2_SHCHN  0

//typedef void (*g2_dma_callback_t)(ptr_t data);
//int g2_dma_transfer(void *from, void * dest, uint32 length, int block,
//	g2_dma_callback_t callback, ptr_t cbdata,
//	uint32 dir, uint32 mode, uint32 g2chn, uint32 sh4chn);

/* Read one byte from G2 */
uint8 g2_read_8(uint32 address);

/* Write one byte to G2 */
void g2_write_8(uint32 address, uint8 value);

/* Read one word from G2 */
uint16 g2_read_16(uint32 address);

/* Write one word to G2 */
void g2_write_16(uint32 address, uint16 value);

/* Read one dword from G2 */
uint32 g2_read_32(uint32 address);

/* Write one dword to G2 */
void g2_write_32(uint32 address, uint32 value);

/* Read a block of 8-bit values from G2 */
void g2_read_block_8(uint8 * output, uint32 address, int amt);

/* Write a block 8-bit values to G2 */
void g2_write_block_8(const uint8 * input, uint32 address, int amt);

/* Read a block of 16-bit values from G2 */
void g2_read_block_16(uint16 * output, uint32 address, int amt);

/* Write a block of 16-bit values to G2 */
void g2_write_block_16(const uint16 * input, uint32 address, int amt);

/* Read a block of 32-bit values from G2 */
void g2_read_block_32(uint32 * output, uint32 address, int amt);

/* Write a block of 32-bit values to G2 */
void g2_write_block_32(const uint32 * input, uint32 address, int amt);

/* When writing to the SPU RAM, this is required at least every 8 32-bit
   writes that you execute */
void g2_fifo_wait();


#define MODEM_SPEED_AUTO  0x0
#define MODEM_SPEED_1200  0x0
#define MODEM_SPEED_2400  0x1
#define MODEM_SPEED_4800  0x2
#define MODEM_SPEED_7200  0x3
#define MODEM_SPEED_9600  0x4
#define MODEM_SPEED_12000 0x5
#define MODEM_SPEED_14400 0x6
#define MODEM_SPEED_16800 0x7
#define MODEM_SPEED_19200 0x8
#define MODEM_SPEED_21600 0x9
#define MODEM_SPEED_24000 0xA
#define MODEM_SPEED_26400 0xB
#define MODEM_SPEED_28000 0xC
#define MODEM_SPEED_31200 0xD
#define MODEM_SPEED_33600 0xE

/* Protocols */
#define MODEM_PROTOCOL_V17    0x0
#define MODEM_PROTOCOL_V22    0x1
#define MODEM_PROTOCOL_V22BIS 0x2
#define MODEM_PROTOCOL_V32    0x3
#define MODEM_PROTOCOL_V32BIS 0x4
#define MODEM_PROTOCOL_V34    0x5
#define MODEM_PROTOCOL_V8     0x6


#define MODEM_MODE_REMOTE 0   /* Connect to a remote modem */
#define MODEM_MODE_ANSWER 1   /* Answer a call when a ring is detected */
#define MODEM_MODE_NULL   255 /* Not doing anything. Don't give this to
                                 any function! */

/* V.22 bis modes */
#define MODEM_SPEED_V22BIS_1200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22BIS, MODEM_SPEED_1200)
#define MODEM_SPEED_V22BIS_2400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22BIS, MODEM_SPEED_2400)

/* V.22 modes */
#define MODEM_SPEED_V22_1200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22, MODEM_SPEED_1200)

/* V.32 modes */
#define MODEM_SPEED_V32_4800 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32, MODEM_SPEED_4800)
#define MODEM_SPEED_V32_9600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32, MODEM_SPEED_9600)

/* V.32 bis modes */
#define MODEM_SPEED_V32BIS_7200  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_7200)
#define MODEM_SPEED_V32BIS_12000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_12000)
#define MODEM_SPEED_V32BIS_14400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_14400)

/* V.8 modes */
#define MODEM_SPEED_V8_2400  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_2400)
#define MODEM_SPEED_V8_4800  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_4800)
#define MODEM_SPEED_V8_7200  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_7200)
#define MODEM_SPEED_V8_9600  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_9600)
#define MODEM_SPEED_V8_12000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_12000)
#define MODEM_SPEED_V8_14400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_14400)
#define MODEM_SPEED_V8_16800 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_16800)
#define MODEM_SPEED_V8_19200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_19200)
#define MODEM_SPEED_V8_21600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_21600)
#define MODEM_SPEED_V8_24000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_24000)
#define MODEM_SPEED_V8_26400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_26400)
#define MODEM_SPEED_V8_28000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_28000)
#define MODEM_SPEED_V8_31200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_31200)
#define MODEM_SPEED_V8_33600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_33600)
#define MODEM_SPEED_V8_AUTO  MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_1200)

/* Event constants */
//typedef enum
//{
//    MODEM_EVENT_CONNECTION_FAILED = 0, /* The modem tried to establish a connection but failed */
//    MODEM_EVENT_CONNECTED,             /* A connection has been established */
//    MODEM_EVENT_DISCONNECTED,          /* The remote modem dropped the connection */
//    MODEM_EVENT_RX_NOT_EMPTY,          /* New data has entered the previously empty receive buffer */
//    MODEM_EVENT_OVERFLOW,              /* The receive buffer overflowed and was cleared */
//    MODEM_EVENT_TX_EMPTY               /* The transmission buffer has been emptied */
//} modemEvent_t;

//typedef void (*MODEMEVENTHANDLERPROC)(modemEvent_t event);


int           modem_init(void);
void          modem_shutdown(void);
int           modem_set_mode(int mode, modem_speed_t speed);
int           modem_wait_dialtone(int ms_timeout);
int           modem_dial(const char *digits);
//void          modem_set_event_handler(MODEMEVENTHANDLERPROC eventHandler);
void          modem_disconnect(void);
int           modem_is_connecting(void);
int           modem_is_connected(void);
unsigned long modem_get_connection_rate(void);

int modem_read_data(unsigned char *data, int size);
int modem_write_data(unsigned char *data, int size);
int modem_has_data(void);


/* Set serial parameters; this is not platform independent like I want
   it to be, but it should be generic enough to be useful. */
void scif_set_parameters(int baud, int fifo);

// The rest of these are the standard dbgio interface.
int scif_set_irq_usage(int on);
int scif_detected();
int scif_init();
int scif_shutdown();
int scif_read();
int scif_write(int c);
int scif_flush();
int scif_write_buffer(const uint8 *data, int len, int xlat);
int scif_read_buffer(uint8 *data, int len);


// CD-ROM
// Command codes (thanks maiwe)
#define CMD_PIOREAD	16
#define CMD_DMAREAD	17
#define CMD_GETTOC	18
#define CMD_GETTOC2	19
#define CMD_PLAY	20
#define CMD_PLAY2	21
#define CMD_PAUSE	22
#define CMD_RELEASE	23
#define CMD_INIT	24
#define CMD_SEEK	27
#define CMD_READ	28
#define CMD_STOP	33
#define CMD_GETSCD	34
#define CMD_GETSES	35

// Command responses
#define ERR_OK		0
#define ERR_NO_DISC	1
#define ERR_DISC_CHG	2
#define ERR_SYS		3

// CDDA Read Modes
#define CDDA_TRACKS	1
#define CDDA_SECTORS	2

// Status values
#define CD_STATUS_BUSY		0
#define CD_STATUS_PAUSED	1
#define CD_STATUS_STANDBY	2
#define CD_STATUS_PLAYING	3
#define CD_STATUS_SEEKING	4
#define CD_STATUS_SCANNING	5
#define CD_STATUS_OPEN		6
#define CD_STATUS_NO_DISC	7

// Disk types
#define CD_CDDA		0
#define CD_CDROM	0x10
#define CD_CDROM_XA	0x20
#define CD_CDI		0x30
#define CD_GDROM	0x80

// TOC structure returned by the BIOS
/*
typedef struct {
	uint32	entry[99];
	uint32	first, last;
	uint32	leadout_sector;
} CDROM_TOC;  */


/* TOC access macros */
//#define TOC_LBA(n) ((n) & 0x00ffffff)
//#define TOC_ADR(n) ( ((n) & 0x0f000000) >> 24 )
//#define TOC_CTRL(n) ( ((n) & 0xf0000000) >> 28 )
//#define TOC_TRACK(n) ( ((n) & 0x00ff0000) >> 16 )

// by SWAT for lua
uint32 TOC_LBA_(uint32 n);
uint32 TOC_ADR_(uint32 n);
uint32 TOC_CTRL_(uint32 n);
uint32 TOC_TRACK_(uint32 n);
CDROM_TOC *CDROM_TOC_new();
void CDROM_TOC_delete(CDROM_TOC *toc);


/* Command execution sequence */
int cdrom_exec_cmd(int cmd, void *param);

/* Return the status of the drive as two integers (see constants) */
int cdrom_get_status(int *status, int *disc_type);

/* Re-init the drive, e.g., after a disc change, etc */
int cdrom_reinit();

/* Read the table of contents */
int cdrom_read_toc(CDROM_TOC *toc_buffer, int session);

/* Read one or more sectors */
int cdrom_read_sectors(void *buffer, int sector, int cnt);

/* Locate the LBA sector of the data track */
uint32 cdrom_locate_data_track(CDROM_TOC *toc);

/* Play CDDA audio tracks or sectors */
int cdrom_cdda_play(uint32 start, uint32 end, uint32 loops, int mode);

/* Pause CDDA audio playback */
int cdrom_cdda_pause();

/* Resume CDDA audio playback */
int cdrom_cdda_resume();

/* Spin down the CD */
int cdrom_spin_down();

/* Initialize */
int cdrom_init();
void cdrom_shutdown();






/* The maximum number of streams which can be allocated at once */
#define SND_STREAM_MAX 4

/* The maximum buffer size for a stream */
#define SND_STREAM_BUFFER_MAX 0x10000

/* A stream handle */
typedef int snd_stream_hnd_t;

/* An invalid stream handle */
#define SND_STREAM_INVALID -1

/* Set "get data" callback */
//typedef void* (*snd_stream_callback_t)(snd_stream_hnd_t hnd, int smp_req, int * smp_recv);
void snd_stream_set_callback(snd_stream_hnd_t hnd, snd_stream_callback_t cb);

/* Add an effect filter to the sound stream chain. When the stream
   buffer filler needs more data, it starts out by calling the initial
   callback (set above). It then calls each function in the effect
   filter chain, which can modify the buffer and the amount of data
   available as well. Filters persist across multiple calls to _init()
   but will be emptied by _shutdown(). */
//typedef void (*snd_stream_filter_t)(snd_stream_hnd_t hnd, void * obj, int hz, int channels, void **buffer, int *samplecnt);
void snd_stream_filter_add(snd_stream_hnd_t hnd, snd_stream_filter_t filtfunc, void * obj);

/* Remove a filter added with the above function */
void snd_stream_filter_remove(snd_stream_hnd_t hnd, snd_stream_filter_t filtfunc, void * obj);

/* Prefill buffers -- do this before calling start() */
void snd_stream_prefill(snd_stream_hnd_t hnd);

/* Initialize stream system */
int snd_stream_init();

/* Shut everything down and free mem */
void snd_stream_shutdown();

/* Allocate and init a stream channel */
snd_stream_hnd_t snd_stream_alloc(snd_stream_callback_t cb, int bufsize);

/* Re-init a stream channel */
int snd_stream_reinit(snd_stream_hnd_t hnd, snd_stream_callback_t cb);

/* Destroy a stream channel */
void snd_stream_destroy(snd_stream_hnd_t hnd);

/* Enable / disable stream queueing */ 
void snd_stream_queue_enable(snd_stream_hnd_t hnd);
void snd_stream_queue_disable(snd_stream_hnd_t hnd);

/* Actually make it go (in queued mode) */
void snd_stream_queue_go(snd_stream_hnd_t hnd);

/* Start streaming */
void snd_stream_start(snd_stream_hnd_t hnd, uint32 freq, int st);

/* Stop streaming */
void snd_stream_stop(snd_stream_hnd_t hnd);

/* Poll streamer to load more data if neccessary */
int snd_stream_poll(snd_stream_hnd_t hnd);

/* Set the volume on the streaming channels */
void snd_stream_volume(snd_stream_hnd_t hnd, int vol);





/* Allocate a chunk of SPU RAM; we will return an offset into SPU RAM. */
uint32 snd_mem_malloc(size_t size);

/* Free a previously allocated chunk of memory */
void snd_mem_free(uint32 addr);

/* Return the number of bytes available in the largest free chunk */
uint32 snd_mem_available();

/* Reinitialize the pool with the given RAM base offset */
//int snd_mem_init(uint32 reserve);

/* Shut down the SPU allocator */
//void snd_mem_shutdown();

/* Initialize driver; note that this replaces the AICA program so that
   if you had anything else going on, it's gone now! */
//int snd_init();

/* Shut everything down and free mem */
//void snd_shutdown();

/* Queue up a request to the SH4->AICA queue; size is in uint32's */
int snd_sh4_to_aica(void *packet, uint32 size);

/* Start processing requests in the queue */
void snd_sh4_to_aica_start();

/* Stop processing requests in the queue */
void snd_sh4_to_aica_stop();

/* Transfer one packet of data from the AICA->SH4 queue. Expects to
   find AICA_CMD_MAX_SIZE dwords of space available. Returns -1
   if failure, 0 for no packets available, 1 otherwise. Failure
   might mean a permanent failure since the queue is probably out of sync. */
int snd_aica_to_sh4(void *packetout);

/* Poll for responses from the AICA. We assume here that we're not
   running in an interrupt handler (thread perhaps, of whoever
   is using us). */
void snd_poll_resp();




/* Sound effect handle type */
typedef uint32 sfxhnd_t;
#define SFXHND_INVALID 0

/* Load a sound effect from a WAV file and return a handle to it */
sfxhnd_t snd_sfx_load(const char *fn);

/* Unload a single sample */
void snd_sfx_unload(sfxhnd_t idx);

/* Unload all loaded samples and free their SPU RAM */
void snd_sfx_unload_all();

/* Play a sound effect with the given volume and panning; if the sound
   effect is in stereo, the panning is ignored. Returns the used channel
   ID (or the left channel, if stereo). */
int snd_sfx_play(sfxhnd_t idx, int vol, int pan);

/* Works like snd_sfx_play, but selects a specific channel. If the sample
   is stereo, the next channel will also be used. */
//int snd_sfx_play_chn(int chn, sfxhnd_t idx, int vol, int pan);

/* Stops a single sound effect from playing. */
//void snd_sfx_stop(int chn);

/* Stop all playing sound effects. Doesn't stop channels 0 or 1, which
   are assumed to be for streaming. */
void snd_sfx_stop_all();

/* Allocate a channel for non-sfx usage (e.g. streams). Returns -1
   on failure. */
//int snd_sfx_chn_alloc();

/* Free a channel for non-sfx usage. */
//void snd_sfx_chn_free(int chn);




/*

int sndoggvorbis_init();
int sndoggvorbis_start(const char *filename,int loop);
int sndoggvorbis_start_fd(FILE *f, int loop);
void sndoggvorbis_stop();
void sndoggvorbis_shutdown();

int sndoggvorbis_isplaying();

void sndoggvorbis_volume(int vol);

void sndoggvorbis_mainloop();
void sndoggvorbis_wait_start();

void sndoggvorbis_setbitrateinterval(int interval);
long sndoggvorbis_getbitrate();
long sndoggvorbis_getposition();

char *sndoggvorbis_getcommentbyname(const char *commentfield);
char *sndoggvorbis_getartist();
char *sndoggvorbis_gettitle();
char *sndoggvorbis_getgenre();

void sndoggvorbis_queue_enable();
void sndoggvorbis_queue_disable();

void sndoggvorbis_queue_wait();

void sndoggvorbis_queue_go();




int mp3_init();

int mp3_start(const char *fn, int loop);

int mp3_stop();

//int mp3_quit();


*/








/* Waits for the sound FIFO to empty */
//void spu_write_wait();

/* memcpy and memset designed for sound RAM; for addresses, don't
   bother to include the 0xa0800000 offset that is implied. 'length'
   must be a multiple of 4, but if it is not it will be rounded up. */
void spu_memload(uint32 to, void *from, int length);
void spu_memread(void *to, uint32 from, int length);
void spu_memset(uint32 to, uint32 what, int length);

/* DMA copy from SH-4 RAM to SPU RAM; length must be a multiple of 32,
   and the source and destination addresses must be aligned on 32-byte
   boundaries. If block is non-zero, this function won't return until
   the transfer is complete. If callback is non-NULL, it will be called
   upon completion (in an interrupt context!). Returns <0 on error. */
typedef g2_dma_callback_t spu_dma_callback_t;
int spu_dma_transfer(void * from, uint32 dest, uint32 length, int block,
	spu_dma_callback_t callback, ptr_t cbdata);

/* Enable/disable the SPU; note that disable implies reset of the
   ARM CPU core. */
void spu_enable();
void spu_disable();

/* Set CDDA volume: values are 0-15 */
void spu_cdda_volume(int left_volume, int right_volume);

/* Set CDDA panning: values are 0-31, 16=center */
void spu_cdda_pan(int left_pan, int right_pan);

/* Set master volume (0..15) and mono/stereo settings */
void spu_master_mixer(int volume, int stereo);

/* Initialize the SPU; by default it will be left in a state of
   reset until you upload a program. */
//int spu_init();

/* Shutdown SPU */
//int spu_shutdown();

/* These two are seperate because they have to be done at a different time */
//int spu_dma_init();
//void spu_dma_shutdown();






#define QACR0 (*(volatile unsigned int *)(void *)0xff000038)
#define QACR1 (*(volatile unsigned int *)(void *)0xff00003c)

/* clears n bytes at dest, dest must be 32-byte aligned */
void sq_clr(void *dest, int n);

/* copies n bytes from src to dest, dest must be 32-byte aligned */
void * sq_cpy(void *dest, void *src, int n);

/* fills n bytes at s with byte c, s must be 32-byte aligned */
void * sq_set(void *s, uint32 c, int n);

/* fills n bytes at s with short c, s must be 32-byte aligned */
void * sq_set16(void *s, uint32 c, int n);

/* fills n bytes at s with int c, s must be 32-byte aligned */
void * sq_set32(void *s, uint32 c, int n);






//-----------------------------------------------------------------------------
#define CT_ANY		-1 // <-- Used ONLY internally with vid_mode
#define CT_VGA		0
#define CT_RGB		2
#define CT_COMPOSITE	3

//-----------------------------------------------------------------------------
#define PM_RGB555	0
#define PM_RGB565	1
#define PM_RGB888	3

//-----------------------------------------------------------------------------
// These are more generic modes

enum {
	DM_GENERIC_FIRST = 0x1000,
	DM_320x240 = 0x1000,
	DM_640x480,
	DM_800x608,
	DM_256x256,
	DM_768x480,
	DM_768x576,
	DM_GENERIC_LAST = DM_768x576
};

//-----------------------------------------------------------------------------
// More specific modes (and actual indeces into the mode table)

enum {
	DM_INVALID = 0,
	// Valid modes below
	DM_320x240_VGA = 1,
	DM_320x240_NTSC,
	DM_640x480_VGA,
	DM_640x480_NTSC_IL,
	DM_800x608_VGA,
	DM_640x480_PAL_IL,
	DM_256x256_PAL_IL,
	DM_768x480_NTSC_IL,
	DM_768x576_PAL_IL,
	DM_768x480_PAL_IL,
	DM_320x240_PAL,
	// The below is only for counting..
	DM_SENTINEL,
	DM_MODE_COUNT
};


//-----------------------------------------------------------------------------
int vid_check_cable();

void vid_set_start(uint32 base);
void vid_flip(int fb);
void vid_border_color(int r, int g, int b);
void vid_clear(int r, int g, int b);
void vid_empty();
void vid_waitvbl();
void vid_set_mode(int dm, int pm);

void vid_init(int disp_mode, int pixel_mode);
//void vid_shutdown();

//-----------------------------------------------------------------------------

int vid_screen_shot(const char * destfn);




/**
  \file Implements wrappers for the BIOS flashrom syscalls, and some
  utilities to make it easier to use the flashrom info. Note that
  because the flash writing can be such a dangerous thing potentially
  (I haven't deleted my flash to see what happens, but given the
  info stored here it sounds like a Bad Idea(tm)) the syscalls for
  the WRITE and DELETE operations are not enabled by default. If you
  are 100% sure you really want to be writing to the flash and you
  know what you're doing, then you can edit flashrom.c and re-enable
  them there. */

/**
  An enumeration of partitions available in the flashrom. */
#define FLASHROM_PT_SYSTEM		0	/*< Factory settings (read-only, 8K) */
#define FLASHROM_PT_RESERVED	1	/*< reserved (all 0s, 8K) */
#define FLASHROM_PT_BLOCK_1		2	/*< Block allocated (16K) */
#define FLASHROM_PT_SETTINGS	3	/*< Game settings (block allocated, 32K) */
#define FLASHROM_PT_BLOCK_2		4	/*< Block allocated (64K) */

/**
  An enumeration of logical blocks available in the flashrom. */
#define FLASHROM_B1_SYSCFG			0x05	/*< System config (BLOCK_1) */
#define FLASHROM_B1_PW_SETTINGS_1	0x80	/*< PlanetWeb settings (BLOCK_1) */
#define FLASHROM_B1_PW_SETTINGS_2	0x81	/*< PlanetWeb settings (BLOCK_1) */
#define FLASHROM_B1_PW_SETTINGS_3	0x82	/*< PlanetWeb settings (BLOCK_1) */
#define FLASHROM_B1_PW_SETTINGS_4	0x83	/*< PlanetWeb settings (BLOCK_1) */
#define FLASHROM_B1_PW_SETTINGS_5	0x84	/*< PlanetWeb settings (BLOCK_1) */
#define FLASHROM_B1_PW_PPP1			0xC0	/*< PlanetWeb PPP settings (BLOCK_1) */
#define FLASHROM_B1_PW_PPP2			0xC1	/*< PlanetWeb PPP settings (BLOCK_1) */
#define FLASHROM_B1_PW_DNS			0xC2	/*< PlanetWeb DNS settings (BLOCK_1) */
#define FLASHROM_B1_PW_EMAIL1		0xC3	/*< PlanetWeb Email settings (BLOCK_1) */
#define FLASHROM_B1_PW_EMAIL2		0xC4	/*< PlanetWeb Email settings (BLOCK_1) */
#define FLASHROM_B1_PW_EMAIL_PROXY	0xC5	/*< PlanetWeb Email/Proxy settings (BLOCK_1) */
#define FLASHROM_B1_IP_SETTINGS		0xE0	/*< IP settings for BBA (BLOCK_1) */
#define FLASHROM_B1_EMAIL			0xE2	/*< Email address (BLOCK_1) */
#define FLASHROM_B1_SMTP			0xE4	/*< SMTP server setting (BLOCK_1) */
#define FLASHROM_B1_POP3			0xE5	/*< POP3 server setting (BLOCK_1) */
#define FLASHROM_B1_POP3LOGIN		0xE6	/*< POP3 login setting (BLOCK_1) */
#define FLASHROM_B1_POP3PASSWD		0xE7	/*< POP3 password setting + proxy (BLOCK_1) */
#define FLASHROM_B1_PPPLOGIN		0xE8	/*< PPP username + proxy (BLOCK_1) */
#define FLASHROM_B1_PPPPASSWD		0xE9	/*< PPP passwd (BLOCK_1) */

/**
  Implements the FLASHROM_INFO syscall; given a partition ID,
  return two ints specifying the beginning and the size of
  the partition (respectively) inside the flashrom. Returns zero
  if successful, -1 otherwise. */
int flashrom_info(int part, int * start_out, int * size_out);

/**
  Implements the FLASHROM_READ syscall; given a flashrom offset,
  an output buffer, and a count, this reads data from the
  flashrom. Returns the number of bytes read if successful,
  or -1 otherwise. */
int flashrom_read(int offset, void * buffer_out, int bytes);

/**
  Implements the FLASHROM_WRITE syscall; given a flashrom offset,
  an input buffer, and a count, this writes data to the flashrom.
  Returns the number of bytes written if successful, -1 otherwise.

  NOTE: It is not possible to write ones to the flashrom over zeros.
  If you want to do this, you must save the old data in the flashrom,
  delete it out, and save the new data back. */
int flashrom_write(int offset, void * buffer, int bytes);

/**
  Implements the FLASHROM_DELETE syscall; given a partition offset,
  that entire partition of the flashrom will be deleted and all data
  will be reset to FFs. Returns zero if successful, -1 on failure. */
int flashrom_delete(int offset);


/* Medium-level functions */
/**
  Returns a numbered logical block from the requested partition. The newest
  data is returned. 'buffer_out' must have enough room for 60 bytes of
  data. */
//int flashrom_get_block(int partid, int blockid, uint8 * buffer_out);


/* Higher level functions */

/**
  Language settings possible in the BIOS menu. These will be returned
  from flashrom_get_language(). */
#define FLASHROM_LANG_JAPANESE	0
#define FLASHROM_LANG_ENGLISH	1
#define FLASHROM_LANG_GERMAN	2
#define FLASHROM_LANG_FRENCH	3
#define FLASHROM_LANG_SPANISH	4
#define FLASHROM_LANG_ITALIAN	5

/**
  This struct will be filled by calling the flashrom_get_syscfg call
  below. */
typedef struct flashrom_syscfg {
	int	language;	/*< Language setting (see defines above) */
	int	audio;		/*< 0 == mono, 1 == stereo */
	int	autostart;	/*< 0 == off, 1 == on */
} flashrom_syscfg_t;

/**
  Retrieves the current syscfg settings and fills them into the struct
  passed in to us. */
int flashrom_get_syscfg(flashrom_syscfg_t * out);


/**
  Region settings possible in the system flash (partition 0). */
#define FLASHROM_REGION_UNKNOWN	0
#define FLASHROM_REGION_JAPAN	1
#define FLASHROM_REGION_US	2
#define FLASHROM_REGION_EUROPE	3

/**
  Retrieves the console's region code. This is still somewhat 
  experimental, it may not function 100% on all DCs. Returns
  one of the codes above or -1 on error. */
int flashrom_get_region();