#include <limits.h>

#if !defined(__RC4_H__)
#define __RC4_H__
/* If the system can handle byte ops, we use those so we don't have to do a
   lot of masking.  Otherwise, we use machine-word-size ops which will be
   faster on RISC machines */

#if UINT_MAX > 0xFFFFL                /* System has 32-bit ints */
#define USE_LONG_RC4
typedef unsigned int rc4word;
#else
typedef unsigned char rc4word;
#endif /* UINT_MAX > 0xFFFFL */

/* The scheduled RC4 key */

typedef struct {
  rc4word state[256];
  rc4word x, y;
} RC4KEY ;

#ifdef POWERUP

extern "C" {
  extern void (*do_rc4ExpandKey)( RC4KEY *rc4, unsigned char const *key, int keylen );
  extern void (*do_rc4Crypt)( RC4KEY *rc4, unsigned char *data, int len );
}

inline void rc4ExpandKey( RC4KEY *rc4, unsigned char const *key, int keylen ) {
  do_rc4ExpandKey(rc4, key, keylen);
}

inline void rc4Crypt( RC4KEY *rc4, unsigned char *data, int len ) {
  do_rc4Crypt(rc4, data, len);
}

#else

extern void *decryptBase;

#define rc4ExpandKey(rc4, key, keylen) \
({                                                              \
   RC4KEY *_v1 = (rc4);                                         \
   unsigned char const *_v2 = (key);                            \
   int _v3 = (keylen);                                          \
   {                                                            \
      register void *const _bn __asm("a6") = decryptBase;       \
      register RC4KEY *_n1 __asm("a0") = _v1;                   \
      register unsigned char const *_n2 __asm("a1") = _v2;      \
      register int _n3 __asm("d0") = _v3;                       \
      __asm volatile ("jsr a6@(-30:W)"                          \
      : /* no output */                                         \
      : "r" (_bn), "r"(_n1), "r"(_n2), "r"(_n3)                 \
      : "d0", "d1", "a0", "a1", "fp0", "fp1", "cc", "memory");  \
   }                                                            \
})

#define rc4Crypt(rc4, key, keylen) \
({                                                              \
   RC4KEY *_v1 = (rc4);                                         \
   unsigned char *_v2 = (key);                                  \
   int _v3 = (keylen);                                          \
   {                                                            \
      register void *const _bn __asm("a6") = decryptBase;       \
      register RC4KEY *_n1 __asm("a0") = _v1;                   \
      register unsigned char *_n2 __asm("a1") = _v2;            \
      register int _n3 __asm("d0") = _v3;                       \
      __asm volatile ("jsr a6@(-36:W)"                          \
      : /* no output */                                         \
      : "r" (_bn), "r"(_n1), "r"(_n2), "r"(_n3)                 \
      : "d0", "d1", "a0", "a1", "fp0", "fp1", "cc", "memory");  \
   }                                                            \
})

#endif

bool decryptionEnabled();

#endif

