
#include <PalmOS.h>
#include <PCENativeCall.h>
#include <PNOLoader.h>
#include <VfsMgr.h>
#include <PalmOSGlue.h>
#include "StarterRsc.h"
#include "host68k.h"
#include "pnobridge.h"
#include "starter.h"
#include <TwChars.h>
#include "zodiac.h"

#include <tapwave.h>
#undef keyBitNavLeft
#define keyBitNavLeft           0x01000000
#undef keyBitNavRight
#define keyBitNavRight          0x02000000
#undef keyBitNavSelect
#define keyBitNavSelect         0x04000000

UInt8 g_paused = 0;

UInt16 palm_vfs_count ( void ) {
  UInt16 volref = 0;
  UInt32 voliter = vfsIteratorStart;
  UInt16 count = 0;

  if ( VFSVolumeEnumerate ( &volref,  &voliter ) != errNone ) {
    return ( 0 ); // error
  }

  count = 1;

  while ( VFSVolumeEnumerate ( &volref,  &voliter ) == errNone ) {
    //if ( voliter != vfsIteratorStop ) {
    count++;
    //}
  }

  return ( count );
}

UInt16 palm_vfs_iter ( void ) {
  UInt16 volref = 0;
  UInt32 voliter = vfsIteratorStart;
  FileRef file;
  UInt16 firstvolref;

  // can we enumerate at all?
  if ( VFSVolumeEnumerate ( &volref,  &voliter ) != errNone ) {
    return ( 0 );
  }

  // store first succeeding volume
  firstvolref = volref;

  // can we open our directory? If so, we found our directory :)
  if ( VFSFileOpen ( volref, VFSPATH, vfsModeRead, &file ) == errNone ) {
    VFSFileClose ( file );
    return ( volref );
  }

  // look through other volumes, trying to find our directory
  while ( VFSVolumeEnumerate ( &volref,  &voliter ) == errNone ) {

    if ( VFSFileOpen ( volref, VFSPATH, vfsModeRead, &file ) == errNone ) {
      VFSFileClose ( file );
      return ( volref );
    }

  }

  //return ( voliter );
  return ( firstvolref );
}

void *hw_query_vram ( void ) {
  WinHandle winh;
  BitmapType *winb;

  winh = WinGetDisplayWindow();
  winb = WinGetBitmap ( winh );

  return ( BmpGetBits ( winb ) );
}

/* set screen to 16bpp mode */
UInt8 hw_set16bpp ( void ) {
  UInt32 depth = 16;
  Boolean colp = true;

  if ( WinScreenMode ( winScreenModeSet, NULL, NULL, &depth, &colp ) 
         != errNone )
  {
    return ( 0 );
  }

  return ( 1 );
}

int update_field ( FormPtr f, int obid, char *newtext ) {
  MemHandle newhandle, oldhandle;
  FieldPtr field;

  newhandle = MemHandleNew ( StrLen ( newtext ) + 1 );

  if ( ! newhandle ) {
    return ( 0 );
  }

  StrCopy ( MemHandleLock ( newhandle ), newtext );
  MemHandleUnlock ( newhandle );

  field = FrmGetObjectPtr ( f, FrmGetObjectIndex ( f, obid ) );

  oldhandle = FldGetTextHandle ( field );

  FldSetTextHandle ( field, newhandle );

  if ( oldhandle ) {
    MemHandleFree ( oldhandle );
  }

  return ( 1 );
}

UInt32 pnobridge_retval = 0;
UInt32 pnobridge_mask = 0;

UInt32 host_event_handler ( UInt32 arg, UInt32 arg2 ) {
  UInt8 f;
  UInt32 a;
  static UInt32 accum = 0;

  // clear retval
  pnobridge_retval = 0;

  // normalize args
  f = arg & BRIDGEMASK;
  a = arg >> BRIDGESHIFT;

  if ( f == BRIDGE_MemGluePtrNew ) 
  {
    // memglueptrnew
    //DEBUGS("MemGluePtrNew");
    //DEBUGU32(a);
    pnobridge_retval = (UInt32) MemGluePtrNew ( a );
  } 
  else if ( f == BRIDGE_bigalloc ) 
  {

  } 
  else if ( f == BRIDGE_zodiacblit ) {
#if 0
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;      
    if ( data->a == 0 ) {
      pnobridge_retval = tw_gfx_lock();
      if ( ! pnobridge_retval ) {
		DEBUGS ( "Couldn't lock display surface!" );
      }
    }else if ( data->a == 1 ) {
      tw_gfx_unlock();
    }else if (data->a == 2) {
  	  tw_gfx_blit(data->b,data->c);
  	}else if (data->a == 3) {
	  tw_gfx_blit2(data->b,data->c,data->d);
  	}
#endif  	   
  } else if ( f == BRIDGE_bigfree ) 
  {
  
  } 
  else if ( f == BRIDGE_progress ) 
  {
    WinDrawLine ( 0, 158, a * 160 / 10, 158 );
    WinDrawLine ( 0, 159, a * 160 / 10, 159 );
  } else if ( f == BRIDGE_debugu32 ) 
  {
    //DEBUGU32(a);
  } else if ( f == BRIDGE_printfu32 ) 
  {
    char b [ 40 ];
    StrPrintF ( b, "%lu", a );
    WinDrawChars ( b, StrLen ( b ), 0, 0 );
  } else if ( f == BRIDGE_accum ) 
  {
    accum = a;
  } else if ( f == BRIDGE_debugs ) 
  {
    UInt32 poop = ( accum << 16 ) | a;
    char *p = (char*)poop;
    //DEBUGS(p);
  } else if ( f == BRIDGE_printfs ) 
  {
    UInt32 poop = ( accum << 16 ) | a;
    char *p = (char*)poop;
    WinDrawChars ( p, StrLen ( p ), 0, 0 );
  } else if ( f == BRIDGE_error )   {
    //DEBUGS ( "error" );
    /*
     * BRIDGE COMMANDS HERE
     */

  } else if ( f == BRIDGE_menu_button )  {
  } else if ( f == BRIDGE_menu_message )  {
  } else if ( f == BRIDGE_menu_bar )  {
  } else if ( f == BRIDGE_menu_messageRaw )  {
  } else if ( f == BRIDGE_filter_event ) {
  	//clear the event queue
	  EventType *data;
	  EventType myevent;
	  data=(EventType*)arg2;
	  pnobridge_retval=0;
	  
      while ( EvtEventAvail()) {            
	  	EvtGetEvent(&myevent,0); 
		if (myevent.eType==nilEvent) break; 
		
		switch (myevent.eType) 
		{				 
			case keyDownEvent:
/*					*data=myevent;				
					pnobridge_retval=1;*/
			case keyUpEvent:
			case keyHoldEvent:
			case penDownEvent: 
			case penUpEvent: 
			case penMoveEvent: 			
			case appStopEvent: 
			case frmUpdateEvent: 
			case winExitEvent: 
			case winEnterEvent:				
				break; 
			default: 
			{	 
				//copy the event to handle
				//and go back to pno to pause the emu
				//and then handle the sysevent by the following function
				*data=myevent;				
				pnobridge_retval=1;
			}
		}
		if (pnobridge_retval) break;
	  }
	  
  } else if ( f == BRIDGE_handle_sysevent ) {
  	//handle system event
  	EventType *data;
	data=(EventType*)arg2;
//	WinPushDrawState(); 
//DEBUGS("Yo1");
	SysHandleEvent(data); 
//	WinPopDrawState();
  } else if ( f == BRIDGE_SndStreamCreateExtended )  {
  	bighostcall_t *data;
  	data=(bighostcall_t*)arg2;
  	
  	pnobridge_retval=SndStreamCreateExtended((SndStreamRef*)(data->a),
  					(SndStreamMode)(data->b),
  					(SndFormatType)(data->c),
  					(UInt32)(data->d),
  					(SndSampleType)(data->e),
  					(SndStreamWidth)(data->f),
  					(SndStreamVariableBufferCallback)(data->g),
  					(void *)(data->h),
  					(UInt32)(data->i),
  					true/*(Boolean)(data->j)*/ //-->fixed to do ARM callback to avoid breaking compatibility with other modules, at least for now --tinnus
  					);
  } else if ( f == BRIDGE_SndStreamCreate )  {
  	bighostcall_t *data;
  	data=(bighostcall_t*)arg2;
  	
  	pnobridge_retval=SndStreamCreate((SndStreamRef*)(data->a),
  					(SndStreamMode)(data->b),
  					(UInt32)(data->c),
  					(SndSampleType)(data->d),
  					(SndStreamWidth)(data->e),
  					(SndStreamBufferCallback)(data->f),
  					(void *)(data->g),
  					(UInt32)(data->h),
  					(Boolean)(data->i)
  					);
	
  }else if ( f == BRIDGE_SndStreamStart )  {
  	pnobridge_retval=SndStreamStart((SndStreamRef)arg2);
  }else if ( f == BRIDGE_SndStreamStop )  {
  	pnobridge_retval=SndStreamStop((SndStreamRef)arg2);
  }else if ( f == BRIDGE_SndStreamDelete )  {
  	pnobridge_retval=SndStreamDelete((SndStreamRef)arg2);
  }else if ( f == BRIDGE_SndStreamGetVolume )  {
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;  	
  	pnobridge_retval=SndStreamGetVolume((SndStreamRef)(data->a),
  				(Int32*)(data->b));
  }
  else if ( f == BRIDGE_SndStreamSetVolume )  {
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;  	
  	pnobridge_retval=SndStreamSetVolume((SndStreamRef)(data->a),
  				(Int32)(data->b));
  }
  else if ( f == BRIDGE_midi_stop ) 
  {
    pnobridge_retval=TwSmfStop((TwSmfHandle)arg2);
  }
  else if ( f == BRIDGE_midi_close ) 
  {
    pnobridge_retval=TwSmfClose((TwSmfHandle)arg2);
  }
  else if ( f == BRIDGE_midi_playing ) 
  {
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;  	
  	pnobridge_retval=TwSmfIsPlaying((TwSmfHandle)(data->a),
  									(Boolean*)(data->b));
  }
  else if ( f == BRIDGE_midi_volume ) 
  {
  	pnobridge_retval=TwMidiSetMasterVolume((Int32)arg2);
  }
  else if ( f == BRIDGE_midi_open ) 
  {
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;  	
  	pnobridge_retval=TwSmfOpen(	(TwSmfHandle*)(data->a),
  				(UInt8*)(data->b),
  				(UInt32*)(data->c)	);
  }
  else if ( f == BRIDGE_midi_play ) 
  {
  	hostcall_t *data;
  	data=(hostcall_t*)arg2;  	
  	pnobridge_retval=TwSmfPlay(	(TwSmfHandle)(data->a),
  				(SndSmfOptionsType*)(data->b),
  				(SndSmfChanRangeType*)(data->c),
  				(SndCallbackInfoType*)(data->d)	);
  }

  return ( pnobridge_retval );
}

UInt8 is_clie ( void ) {
  UInt32 val;

  if ( ! FtrGet ( sysFtrCreator, sysFtrNumOEMCompanyID, &val ) ) {

    if (val == 'sony' /*sonyHwrOEMCompanyID_Sony*/) {
      /* device might be CLIE */
      return ( 1 );
    } else {
      /* device might not be CLIE */
    }
  } else {
    /* something wrong ... */
  }

  return ( 0 ); /* not clie */
}
