/*###################################################################################################
**
**	TMS34010: Portable Texas Instruments TMS34010 emulator
**
**	Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998
**	 Parts based on code by Aaron Giles
**
**#################################################################################################*/

#ifndef _34010OPS_H
#define _34010OPS_H

#include "osd_cpu.h"
#include "memory.h"

#include <retro_inline.h>


/* Size of the memory buffer allocated for the shiftr register */
#define SHIFTREG_SIZE			(8 * 512 * sizeof(UINT16))



/*###################################################################################################
**	MEMORY I/O MACROS
**#################################################################################################*/

#define TMS34010_RDMEM(A)			((unsigned)cpu_readmem29      (A))
#define TMS34010_RDMEM_WORD(A)		((unsigned)cpu_readmem29_word (A))
#define TMS34010_RDMEM_DWORD(A)		((unsigned)cpu_readmem29_dword(A))

#define TMS34010_WRMEM(A,V)			(cpu_writemem29(A,V))
#define TMS34010_WRMEM_WORD(A,V)	(cpu_writemem29_word(A,V))
#define TMS34010_WRMEM_DWORD(A,V)	(cpu_writemem29_dword(A,V))



/*###################################################################################################
**	INTERNAL I/O CONSTANTS
**#################################################################################################*/

enum
{
	REG_HESYNC = 0,
	REG_HEBLNK,
	REG_HSBLNK,
	REG_HTOTAL,
	REG_VESYNC,
	REG_VEBLNK,
	REG_VSBLNK,
	REG_VTOTAL,
	REG_DPYCTL,
	REG_DPYSTRT,
	REG_DPYINT,
	REG_CONTROL,
	REG_HSTDATA,
	REG_HSTADRL,
	REG_HSTADRH,
	REG_HSTCTLL,
	REG_HSTCTLH,
	REG_INTENB,
	REG_INTPEND,
	REG_CONVSP,
	REG_CONVDP,
	REG_PSIZE,
	REG_PMASK,
	REG_UNK23,
	REG_UNK24,
	REG_UNK25,
	REG_UNK26,
	REG_DPYTAP,
	REG_HCOUNT,
	REG_VCOUNT,
	REG_DPYADR,
	REG_REFCNT
};

/* Interrupts that are generated by the processor internally */
#define TMS34010_NMI         0x0100    /* NMI Interrupt */
#define TMS34010_HI          0x0200    /* Host Interrupt */
#define TMS34010_DI          0x0400    /* Display Interrupt */
#define TMS34010_WV          0x0800    /* Window Violation Interrupt */

/* IO registers accessor */
#define IOREG(reg)				(state.IOregs[reg])
#define CONTEXT_IOREG(c,reg)	((c)->IOregs[reg])
#define PBH 					(IOREG(REG_CONTROL) & 0x0100)
#define PBV 					(IOREG(REG_CONTROL) & 0x0200)



/*###################################################################################################
**	FIELD WRITE MACROS
**#################################################################################################*/

#define WFIELDMAC(MASK,MAX) 														\
	UINT32 shift = offset & 0x0f;     												\
	UINT32 masked_data = data & (MASK);												\
	UINT32 old;				   														\
																					\
	offset = TOBYTE(offset & 0xfffffff0);											\
																					\
	if (shift >= MAX)																\
	{																				\
		old = (UINT32)TMS34010_RDMEM_DWORD(offset) & ~((MASK) << shift); 			\
		TMS34010_WRMEM_DWORD(offset, (masked_data << shift) | old);					\
	}																				\
	else																			\
	{																				\
		old = (UINT32)TMS34010_RDMEM_WORD(offset) & ~((MASK) << shift); 			\
		TMS34010_WRMEM_WORD(offset, ((masked_data & (MASK)) << shift) | old);		\
	}																				\

#define WFIELDMAC_BIG(MASK,MAX)														\
	UINT32 shift = offset & 0x0f;     												\
	UINT32 masked_data = data & (MASK);												\
	UINT32 old;				   														\
																					\
	offset = TOBYTE(offset & 0xfffffff0);											\
																					\
	old = (UINT32)TMS34010_RDMEM_DWORD(offset) & ~(UINT32)((MASK) << shift);		\
	TMS34010_WRMEM_DWORD(offset, (UINT32)(masked_data << shift) | old);				\
	if (shift >= MAX)																\
	{																				\
		shift = 32 - shift;															\
		old = (UINT32)TMS34010_RDMEM_WORD(offset + 4) & ~((MASK) >> shift);			\
		TMS34010_WRMEM_WORD(offset, (masked_data >> shift) | old);					\
	}																				\

#define WFIELDMAC_8																	\
	if (offset & 0x07)																\
	{																				\
		WFIELDMAC(0xff,9);															\
	}																				\
	else																			\
		TMS34010_WRMEM(TOBYTE(offset), data);										\

#define RFIELDMAC_8																	\
	if (offset & 0x07)																\
	{																				\
		RFIELDMAC(0xff,9);															\
	}																				\
	else																			\
		return TMS34010_RDMEM(TOBYTE(offset));										\

#define WFIELDMAC_32																\
	if (offset & 0x0f)																\
	{																				\
		UINT32 shift = offset&0x0f;													\
		UINT32 old;																	\
		UINT32 hiword;																\
		offset &= 0xfffffff0;														\
		old =    ((UINT32) TMS34010_RDMEM_DWORD (TOBYTE(offset     ))&(0xffffffff>>(0x20-shift)));	\
		hiword = ((UINT32) TMS34010_RDMEM_DWORD (TOBYTE(offset+0x20))&(0xffffffff<<shift));		\
		TMS34010_WRMEM_DWORD(TOBYTE(offset     ),(data<<      shift) |old);			\
		TMS34010_WRMEM_DWORD(TOBYTE(offset+0x20),(data>>(0x20-shift))|hiword);		\
	}																				\
	else																			\
		TMS34010_WRMEM_DWORD(TOBYTE(offset),data);									\



/*###################################################################################################
**	FIELD READ MACROS
**#################################################################################################*/

#define RFIELDMAC(MASK,MAX)															\
	UINT32 shift = offset & 0x0f;													\
	offset = TOBYTE(offset & 0xfffffff0);											\
																					\
	if (shift >= MAX)																\
		ret = (TMS34010_RDMEM_DWORD(offset) >> shift) & (MASK);						\
	else																			\
		ret = (TMS34010_RDMEM_WORD(offset) >> shift) & (MASK);						\

#define RFIELDMAC_BIG(MASK,MAX)														\
	UINT32 shift = offset & 0x0f;													\
	offset = TOBYTE(offset & 0xfffffff0);											\
																					\
	ret = (UINT32)TMS34010_RDMEM_DWORD(offset) >> shift;							\
	if (shift >= MAX)																\
		ret |= (TMS34010_RDMEM_WORD(offset + 4) << (32 - shift));					\
	ret &= MASK;																	\

#define RFIELDMAC_32																\
	if (offset&0x0f)																\
	{																				\
		UINT32 shift = offset&0x0f;													\
		offset &= 0xfffffff0;														\
		return (((UINT32)TMS34010_RDMEM_DWORD (TOBYTE(offset     ))>>      shift) |	\
			            (TMS34010_RDMEM_DWORD (TOBYTE(offset+0x20))<<(0x20-shift)));\
	}																				\
	else																			\
		return TMS34010_RDMEM_DWORD(TOBYTE(offset));								\



#endif /* _34010OPS_H */
