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 ----