minow@thundr.dec.com (Martin Minow THUNDR::MINOW ML3-5/U26 223-9922) (08/30/88)
Several months ago, I asked the collected wisdom of the net (also several other people) for information on extracting the Map latitude and longitude for use in an astronomy program I was messing around with. (Map is a Cdev in the 6.0 system release.) With the significant assistance of Mike Carleton, here is a simple program that extracts and formats the information. (If you need the city name, you'll have to poke around in the Map database yourself -- I can't help you there.) The program should be reasonably easy to follow. It is, of course, not guaranteed to work in future systems, is not blessed by Apple, and does not express the position of my employer. It is in the public domain. Martin Minow minow%thundr.dec@decwrl.dec.com ...!decwrldec-rhea!dec-thundr!minow ----- #include <stdio.h> #include <math.h> #include <pascal.h> #define _ReadXPRam 0xA051 #define _WriteXPRam 0xA052 /* * This structure defines the location currently set by the Map Cdev. * * Latitude and longitude are signed long integers giving the * fraction of the circle. I.e., * 1 degree East == 0x000308B9 * 1 degree West == 0xFFFCF747 * All values are possible for longitude, while latitude is constrained * to +/- 90 degrees. * * Only the low-order three bytes of timezone are used. The value is * the number of seconds East of UTC. */ typedef struct { long latitude; /* fractional latitude (North +) */ long longitude; /* fractional longitude (East +) */ long timezone; /* high byte zero, seconds in low 3 */ } MapDatum; typedef struct { Byte valid; Byte aTalkA; Byte aTalkB; Byte config; int portA; int portB; long alarm; int font; int kbdPrint; int volClik; int misc; Byte fill[76]; /* 0x14 */ char name[20]; /* 0x60 */ Byte fill2[112]; /* 0x74 */ MapDatum map; /* 0xE4 */ Byte XPram[16]; /* 0xF0 */ } XParmType; XParmType Rbuff; int WpRam(struct pRAM *, int, int); int WpRam(add, st, cnt) struct pRAM *add; /* Address of buffer */ int st; /* Starting address in PRam */ int cnt; /* Count of bytes to write */ { asm { move.w cnt,D0 /* Put count of bytes in DO. */ swap D0 /* Move it to the high word. */ move.w st,D0 /* Start at this Pram address. */ movea.l add,A0 /* Pointer to the data buffer. */ dc.w _WriteXPRam /* Trap to ROM */ return /* OK = 0, error = -87 */ } } int RpRam(struct pRAM *, int, int); int RpRam(add, st, cnt) struct pRAM *add; /* Address of buffer */ int st; /* Starting address in PRam */ int cnt; /* Count of bytes to write */ { asm { move.w cnt,D0 /* Put count of bytes in DO. */ swap D0 /* Move it to the high word. */ move.w st,D0 /* Start at this Pram address. */ movea.l add,A0 /* Pointer to the data buffer. */ dc.w _ReadXPRam /* Trap to ROM */ return /* OK = 0, error = -87 */ } } void main(void); void printf(char *, ...); void fputc(int, FILE *); int fgetc(FILE *); void print_map(MapDatum *); void main() { int status; XParmType *sys; /* * Rbuff.valid is never valid on my system! -- it's only * valid in the GetSysPPtr buffer, but I can't find the * map info in that buffer. */ do { status = RpRam((struct pRAM *) &Rbuff, 0, sizeof(XParmType)); sys = (XParmType *) GetSysPPtr(); print_map(&Rbuff.map); } while (getchar() != 'q'); } void dms(long, char *, char *); void hms(long, char *); void print_map(map) register MapDatum *map; { dms(map->longitude, "Longitude", "EW"); dms(map->latitude, "Latitude", "NS"); hms(map->timezone, "Zone"); } void dms(raw_value, what, zone) long raw_value; char *what; char *zone; { register long value; register long degree, minute, second; int west; static long one_degree = (0x80000000 / 180L); static long one_minute = (0x80000000 / (180L * 60L)); static long one_second = (0x80000000 / (180L * 60L * 60L)); value = raw_value; degree = value / one_degree; value -= (degree * one_degree); minute = value / one_minute; value -= (minute * one_minute); second = value / one_second; if ((west = (raw_value < 0))) { degree = (-degree); minute = (-minute); second = (-second); } printf("(%08lx): %3ld.%02ld.%02ld %c %s\n", raw_value, degree, minute, second, zone[west], what); } void hms(timezone, what) long timezone; char *what; { register long value; register long hour, minute, second; int west; static long one_hour = (60L * 60L); static long one_minute = (60L); if (timezone & 0xFF000000) { printf("High byte set in timezone: %02x\n", (timezone >> 12) & 0xFF); timezone &= 0x00FFFFFF; } if ((timezone & 0x00800000) != 0) timezone |= 0xFF000000; /* Sign-extend zone */ value = timezone; hour = value / one_hour; value -= (hour * one_hour); minute = value / one_minute; value -= (minute * one_minute); second = value; if ((west = (timezone < 0))) { hour = (-hour); minute = (-minute); second = (-second); } printf("(%08lx): %3ld.%02ld.%02ld %c %s\n", timezone, hour, minute, seconds, "EW"[west], what); } ---- end ----