+static int GGtobin(char c)
+{
+ static char lets[16]={'A','P','Z','L','G','I','T','Y','E','O','X','U','K','S','V','N'};
+ int x;
+
+ for(x=0;x<16;x++)
+ if(lets[x] == toupper(c)) return(x);
+ return(0);
+}
+
+/* Returns 1 on success, 0 on failure. Sets *a,*v,*c. */
+int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c)
+{
+ uint16 A;
+ uint8 V,C;
+ uint8 t;
+ int s;
+
+ A=0x8000;
+ V=0;
+ C=0;
+
+ s=strlen(str);
+ if(s!=6 && s!=8) return(0);
+
+ t=GGtobin(*str++);
+ V|=(t&0x07);
+ V|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ V|=(t&0x07)<<4;
+ A|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<4;
+ //if(t&0x08) return(0); /* 8-character code?! */
+
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<12;
+ A|=(t&0x08);
+
+ t=GGtobin(*str++);
+ A|=(t&0x07);
+ A|=(t&0x08)<<8;
+
+ if(s==6)
+ {
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<8;
+ V|=(t&0x08);
+
+ *a=A;
+ *v=V;
+ *c=-1;
+ return(1);
+ }
+ else
+ {
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<8;
+ C|=(t&0x08);
+
+ t=GGtobin(*str++);
+ C|=(t&0x07);
+ C|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ C|=(t&0x07)<<4;
+ V|=(t&0x08);
+ *a=A;
+ *v=V;
+ *c=C;
+ return(1);
+ }
+ return(0);
+}
+
+int FCEUI_DecodePAR(const char *str, uint16 *a, uint8 *v, int *c, int *type)
+{
+ int boo[4];
+ if(strlen(str)!=8) return(0);
+
+ sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
+
+ *c=-1;
+
+ if(1)
+ {
+ *a=(boo[3]<<8)|(boo[2]+0x7F);
+ *v=0;
+ }
+ else
+ {
+ *v=boo[3];
+ *a=boo[2]|(boo[1]<<8);
+ }
+ /* Zero-page addressing modes don't go through the normal read/write handlers in FCEU, so
+ we must do the old hacky method of RAM cheats.
+ */
+ if(*a<0x0100)
+ *type=0;
+ else
+ *type=1;
+ return(1);
+}
+