1 /*
2  *  This file is part of x48, an emulator of the HP-48sx Calculator.
3  *  Copyright (C) 1994  Eddie C. Dost  (ecd@dressler.de)
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 /* $Log: rpl.c,v $
21  * Revision 1.3  1995/01/11  18:20:01  ecd
22  * major update to support HP48 G/GX
23  *
24  * Revision 1.2  1994/12/07  20:20:50  ecd
25  * lots of more functions
26  *
27  * Revision 1.2  1994/12/07  20:20:50  ecd
28  * lots of more functions
29  *
30  * Revision 1.1  1994/12/07  10:15:47  ecd
31  * Initial revision
32  *
33  *
34  * $Id: rpl.c,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $
35  */
36 
37 #include "global.h"
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <string.h>
43 
44 #include "hp48.h"
45 #include "hp48_emu.h"
46 #include "rpl.h"
47 #include "debugger.h"
48 #include "append.h"
49 #include "disasm.h"
50 #include "romio.h"
51 #define DEFINE_TRANS_TABLE 1
52 #include "hp48char.h"
53 #undef DEFINE_TRANS_TABLE
54 
55 struct objfunc {
56   char    *name;
57   short    length;
58   word_20  prolog;
59   char	  *(*func) __ProtoType__((word_20 *addr, char *string));
60 } objects[] = {
61   { "System Binary",	0,	DOBINT,		dec_bin_int },
62   { "Real",		0,	DOREAL,		dec_real },
63   { "Long Real",	0,	DOEREL,		dec_long_real },
64   { "Complex",		0,	DOCMP,		dec_complex },
65   { "Long Complex",	0,	DOECMP,		dec_long_complex },
66   { "Character",	0,	DOCHAR,		dec_char },
67   { "Array",		0,	DOARRY,		dec_array },
68   { "Linked Array",	0,	DOLNKARRY,	dec_lnk_array },
69   { "String",		2,	DOCSTR,		dec_string },
70   { "Hex String",	1,	DOHSTR,		dec_hex_string },
71   { "List",		0,	DOLIST,		dec_list },
72   { "Directory",	0,	DORRP,		skip_ob },
73   { "Symbolic",		0,	DOSYMB,		dec_symb },
74   { "Unit",		0,	DOEXT,		dec_unit },
75   { "Tagged",		0,	DOTAG,		skip_ob },
76   { "Graphic",		0,	DOGROB,		skip_ob },
77   { "Library",		0,	DOLIB,		dec_library },
78   { "Backup",		0,	DOBAK,		skip_ob },
79   { "Library Data",	0,	DOEXT0,		dec_library_data },
80   { "ACPTR",		0,	DOACPTR,	dec_acptr },
81   { "External 2",	0,	DOEXT2,		skip_ob },
82   { "External 3",	0,	DOEXT3,		skip_ob },
83   { "External 4",	0,	DOEXT4,		skip_ob },
84   { "Program",		0,	DOCOL,		dec_prog },
85   { "Code",		1,	DOCODE,		dec_code },
86   { "Global Ident",	0,	DOIDNT,		dec_global_ident },
87   { "Local Ident",	0,	DOLAM,		dec_local_ident },
88   { "XLib Name",	0,	DOROMP,		dec_xlib_name },
89   { "*",		0,	UM_MUL,		dec_unit_op },
90   { "/",		0,	UM_DIV,		dec_unit_op },
91   { "^",		0,	UM_POW,		dec_unit_op },
92   { " ",		0,	UM_PRE,		dec_unit_op },
93   { "_",		0,	UM_END,		dec_unit_op },
94   { 0, 0, 0 }
95 };
96 
97 char *
98 #ifdef __FunctionProto__
skip_ob(word_20 * addr,char * string)99 skip_ob(word_20 *addr, char *string)
100 #else
101 skip_ob(addr, string)
102 word_20 *addr;
103 char    *string;
104 #endif
105 {
106   word_20         size, type;
107   char           *p = string;
108   struct objfunc *op;
109 
110   type = read_nibbles(*addr - 5, 5);
111   for (op = objects; op->prolog != 0; op++)
112     {
113       if (op->prolog == type)
114         break;
115     }
116 
117   if (op->prolog)
118     {
119       sprintf(p, "%s", op->name);
120       p += strlen(p);
121     }
122 
123   size = read_nibbles(*addr, 5);
124   *addr += size;
125 
126   *p = '\0';
127   return p;
128 }
129 
130 long
131 #ifdef __FunctionProto__
hxs2real(long hxs)132 hxs2real(long hxs)
133 #else
134 hxs2real(hxs)
135 long hxs;
136 #endif
137 {
138   int n = 0, c = 1;
139 
140   while (hxs)
141     {
142       n += (hxs & 0xf) * c;
143       c *= 10;
144       hxs >>= 4;
145     }
146   return n;
147 }
148 
149 char *
150 #ifdef __FunctionProto__
dec_bin_int(word_20 * addr,char * string)151 dec_bin_int(word_20 *addr, char *string)
152 #else
153 dec_bin_int(addr, string)
154 word_20 *addr;
155 char    *string;
156 #endif
157 {
158   char    *p = string;
159   word_20  n = 0;
160 
161   n = read_nibbles(*addr, 5);
162   *addr += 5;
163   sprintf(p, "<%lXh>", (long)n);
164   p += strlen(p);
165   return p;
166 }
167 
168 char *
169 #ifdef __FunctionProto__
real_number(word_20 * addr,char * string,int ml,int xl)170 real_number(word_20 *addr, char *string, int ml, int xl)
171 #else
172 real_number(addr, string, ml, xl)
173 word_20 *addr;
174 char    *string;
175 int      ml;
176 int      xl;
177 #endif
178 {
179   hp_real r;
180   long    re, xs;
181   int     i;
182   char    fmt[20];
183   char    m[16];
184   char   *p = string;
185 
186   /*
187    * Read the number
188    */
189   r.x = read_nibbles(*addr, xl);
190   *addr += xl;
191   r.ml = read_nibbles(*addr, ml - 8);
192   *addr += ml - 8;
193   r.mh = read_nibbles(*addr, 8);
194   *addr += 8;
195   r.m = read_nibbles(*addr, 1);
196   (*addr)++;
197   r.s = read_nibbles(*addr, 1);
198   (*addr)++;
199 
200   /*
201    * Figure out the exponent
202    */
203   xs = 5;
204   while (--xl) xs *= 10;
205   re = hxs2real(r.x);
206   if (re >= xs)
207     re = re - 2 * xs;
208 
209 
210   if ((re >= 0) && (re < ml + 1))
211     {
212       if (r.s >= 5)
213         *p++ = '-';
214 
215       sprintf(fmt, "%%.1X%%.8lX%%.%dlX", ml - 8);
216       sprintf(m, fmt, r.m, r.mh, r.ml);
217 
218       for (i = 0; i <= re; i++)
219         *p++ = m[i];
220       *p++ = '.';
221       for ( ; i < ml + 1; i++)
222         *p++ = m[i];
223       p--;
224       while(*p == '0') p--;
225       if (*p == '.') p--;
226       *++p = '\0';
227 
228       return p;
229     }
230 
231   if ((re < 0) && (re >= -ml - 1))
232     {
233       sprintf(fmt, "%%.1X%%.8lX%%.%dlX", ml - 8);
234       sprintf(m, fmt, r.m, r.mh, r.ml);
235 
236       for (i = ml; m[i] == '0'; i--) ;
237 
238       if (-re <= ml - i + 1)
239         {
240           if (r.s >= 5)
241             *p++ = '-';
242 
243           *p++ = '.';
244 
245           for (i = 1; i < -re; i++)
246             *p++ = '0';
247 
248           for (i = 0; i < ml + 1; i++)
249             *p++ = m[i];
250           p--;
251           while(*p == '0') p--;
252           *++p = '\0';
253 
254           return p;
255         }
256     }
257 
258   sprintf(fmt, "%%s%%X.%%.8lX%%.%dlX", ml - 8);
259   sprintf(p, fmt, (r.s >= 5) ? "-" : "", r.m, r.mh, r.ml);
260 
261   p += strlen(p) - 1;
262 
263   while(*p == '0') p--;
264   *++p = '\0';
265 
266   if (re)
267     {
268       sprintf(p, "E%ld", re);
269       p += strlen(p);
270       *p = '\0';
271     }
272 
273   return p;
274 }
275 
276 char *
277 #ifdef __FunctionProto__
dec_real(word_20 * addr,char * string)278 dec_real(word_20 *addr, char *string)
279 #else
280 dec_real(addr, string)
281 word_20 *addr;
282 char    *string;
283 #endif
284 {
285   return real_number(addr, string, 11, 3);
286 }
287 
288 char *
289 #ifdef __FunctionProto__
dec_long_real(word_20 * addr,char * string)290 dec_long_real(word_20 *addr, char *string)
291 #else
292 dec_long_real(addr, string)
293 word_20 *addr;
294 char    *string;
295 #endif
296 {
297   return real_number(addr, string, 14, 5);
298 }
299 
300 char *
301 #ifdef __FunctionProto__
dec_complex(word_20 * addr,char * string)302 dec_complex(word_20 *addr, char *string)
303 #else
304 dec_complex(addr, string)
305 word_20 *addr;
306 char    *string;
307 #endif
308 {
309   char *p = string;
310 
311   *p++ = '(';
312   p = real_number(addr, p, 11, 3);
313   *p++ = ',';
314   p = real_number(addr, p, 11, 3);
315   *p++ = ')';
316   *p = '\0';
317   return p;
318 }
319 
320 char *
321 #ifdef __FunctionProto__
dec_long_complex(word_20 * addr,char * string)322 dec_long_complex(word_20 *addr, char *string)
323 #else
324 dec_long_complex(addr, string)
325 word_20 *addr;
326 char    *string;
327 #endif
328 {
329   char *p = string;
330 
331   *p++ = '(';
332   p = real_number(addr, p, 14, 5);
333   *p++ = ',';
334   p = real_number(addr, p, 14, 5);
335   *p++ = ')';
336   *p = '\0';
337   return p;
338 }
339 
340 char *
341 #ifdef __FunctionProto__
dec_string(word_20 * addr,char * string)342 dec_string(word_20 *addr, char *string)
343 #else
344 dec_string(addr, string)
345 word_20 *addr;
346 char    *string;
347 #endif
348 {
349   word_20        len;
350   unsigned char  c;
351   char          *p = string;
352   int            i, n;
353 
354   len = read_nibbles(*addr, 5);
355   *addr += 5;
356   len -= 5;
357   len /= 2;
358 
359   n = len;
360   if (len > 1000)
361     n = 1000;
362 
363   *p++ = '\"';
364   for (i = 0; i < n; i++)
365     {
366       c = read_nibbles(*addr, 2);
367       *addr += 2;
368       if (hp48_trans_tbl[c].trans)
369         {
370           sprintf(p, hp48_trans_tbl[c].trans);
371           p += strlen(p);
372         }
373       else
374         *p++ = c;
375     }
376 
377   if (n != len)
378     {
379       *p++ = '.';
380       *p++ = '.';
381       *p++ = '.';
382     }
383 
384   *p++ = '\"';
385   *p = '\0';
386   return p;
387 }
388 
389 char *
390 #ifdef __FunctionProto__
dec_hex_string(word_20 * addr,char * string)391 dec_hex_string(word_20 *addr, char *string)
392 #else
393 dec_hex_string(addr, string)
394 word_20 *addr;
395 char    *string;
396 #endif
397 {
398   int   len, lead, i, n;
399   static char hex[] = "0123456789ABCDEF";
400   char *p = string;
401 
402   len = read_nibbles(*addr, 5);
403   *addr += 5;
404   len -= 5;
405 
406   if (len <= 16)
407     {
408       *p++ = '#';
409       *p++ = ' ';
410       lead = 1;
411       for (i = len - 1; i >= 0; i--)
412         {
413           *p = hex[read_nibble(*addr + i)];
414           if (lead)
415             if ((i != 0) && (*p == '0'))
416               p--;
417             else
418               lead = 0;
419           p++;
420         }
421 
422       *p++ = 'h';
423     }
424   else
425     {
426       *p++ = 'C';
427       *p++ = '#';
428       *p++ = ' ';
429 
430       sprintf(p, "%d", len);
431       p += strlen(p);
432 
433       *p++ = ' ';
434 
435       n = len;
436       if (len > 1000)
437         n = 1000;
438 
439       for (i = 0; i < n; i++)
440         *p++ = hex[read_nibble(*addr + i)];
441 
442       if (n != len)
443         {
444           *p++ = '.';
445           *p++ = '.';
446           *p++ = '.';
447         }
448     }
449 
450   *addr += len;
451 
452   *p = '\0';
453   return p;
454 }
455 
456 char *
457 #ifdef __FunctionProto__
dec_list(word_20 * addr,char * string)458 dec_list(word_20 *addr, char *string)
459 #else
460 dec_list(addr, string)
461 word_20 *addr;
462 char    *string;
463 #endif
464 {
465   word_20  semi;
466   char    *p = string;
467 
468   *p++ = '{';
469   *p++ = ' ';
470   semi = read_nibbles(*addr, 5);
471   while (semi != SEMI)
472     {
473       p = dec_rpl_obj(addr, p);
474       semi = read_nibbles(*addr, 5);
475       if (semi != SEMI)
476         {
477           *p++ = ' ';
478           *p = '\0';
479         }
480     }
481   *p++ = ' ';
482   *p++ = '}';
483   *p = '\0';
484 
485   *addr += 5;
486   return p;
487 }
488 
489 char *
490 #ifdef __FunctionProto__
dec_symb(word_20 * addr,char * string)491 dec_symb(word_20 *addr, char *string)
492 #else
493 dec_symb(addr, string)
494 word_20 *addr;
495 char    *string;
496 #endif
497 {
498   word_20  semi;
499   char    *p = string;
500 
501   semi = read_nibbles(*addr, 5);
502   *p++ = '\'';
503   while (semi != SEMI)
504     {
505       p = dec_rpl_obj(addr, p);
506       semi = read_nibbles(*addr, 5);
507       if (semi != SEMI)
508         {
509           *p++ = ' ';
510           *p = '\0';
511         }
512     }
513   *addr += 5;
514 
515   *p++ = '\'';
516   *p = '\0';
517   return p;
518 }
519 
520 char *
521 #ifdef __FunctionProto__
dec_unit(word_20 * addr,char * string)522 dec_unit(word_20 *addr, char *string)
523 #else
524 dec_unit(addr, string)
525 word_20 *addr;
526 char    *string;
527 #endif
528 {
529   word_20  semi;
530   char    *p = string;
531 
532   semi = read_nibbles(*addr, 5);
533   while (semi != SEMI)
534     {
535       p = dec_rpl_obj(addr, p);
536       semi = read_nibbles(*addr, 5);
537       if (semi != SEMI)
538         {
539           *p++ = ' ';
540           *p = '\0';
541         }
542     }
543   *addr += 5;
544   return p;
545 }
546 
547 char *
548 #ifdef __FunctionProto__
dec_unit_op(word_20 * addr,char * string)549 dec_unit_op(word_20 *addr, char *string)
550 #else
551 dec_unit_op(addr, string)
552 word_20 *addr;
553 char    *string;
554 #endif
555 {
556   word_20 op;
557   char *p = string;
558 
559   op = read_nibbles(*addr - 5, 5);
560   switch (op)
561   {
562     case UM_MUL:
563       *p++ = '*';
564       break;
565     case UM_DIV:
566       *p++ = '/';
567       break;
568     case UM_POW:
569       *p++ = '^';
570       break;
571     case UM_END:
572       *p++ = '_';
573       break;
574     case UM_PRE:
575       p--;
576       break;
577     default:
578       break;
579   }
580   *p = '\0';
581   return p;
582 }
583 
584 char *
585 #ifdef __FunctionProto__
dec_library(word_20 * addr,char * string)586 dec_library(word_20 *addr, char *string)
587 #else
588 dec_library(addr, string)
589 word_20 *addr;
590 char    *string;
591 #endif
592 {
593   word_20        libsize, libidsize;
594 /*
595   word_20        hashoff, mesgoff, linkoff, cfgoff;
596   word_20        mesgloc, cfgloc;
597 */
598   int            i, libnum;
599   unsigned char  c;
600   char          *p = string;
601 
602   libsize = read_nibbles(*addr, 5);
603   libidsize = read_nibbles(*addr + 5, 2);
604   libnum = read_nibbles(*addr + 2 * libidsize + 9, 3);
605 
606   sprintf(p, "Library %d:  ", libnum);
607   p += strlen(p);
608 
609   for (i = 0; i < libidsize; i++)
610     {
611       c = read_nibbles(*addr + 2 * i + 7, 2);
612       if (hp48_trans_tbl[c].trans)
613         {
614           sprintf(p, hp48_trans_tbl[c].trans);
615           p += strlen(p);
616         }
617       else
618         *p++ = c;
619     }
620 
621   *addr += libsize;
622 
623   *p = '\0';
624   return p;
625 }
626 
627 char *
628 #ifdef __FunctionProto__
dec_library_data(word_20 * addr,char * string)629 dec_library_data(word_20 *addr, char *string)
630 #else
631 dec_library_data(addr, string)
632 word_20 *addr;
633 char    *string;
634 #endif
635 {
636   word_20  size;
637   char    *p = string;
638 
639   size = read_nibbles(*addr, 5);
640 
641   sprintf(p, "Library Data");
642   p += strlen(p);
643 
644   *addr += size;
645 
646   *p = '\0';
647   return p;
648 }
649 
650 char *
651 #ifdef __FunctionProto__
dec_acptr(word_20 * addr,char * string)652 dec_acptr(word_20 *addr, char *string)
653 #else
654 dec_acptr(addr, string)
655 word_20 *addr;
656 char    *string;
657 #endif
658 {
659   word_20  size;
660   char    *p = string;
661   int      i;
662   static char hex[] = "0123456789ABCDEF";
663 
664   if (opt_gx)
665     {
666       size = 10;
667       sprintf(p, "ACPTR ");
668       p += strlen(p);
669       for (i = 0; i < 5; i++)
670         *p++ = hex[read_nibble(*addr + i)];
671       *p++ = ' ';
672       for (i = 5; i < 10; i++)
673         *p++ = hex[read_nibble(*addr + i)];
674     }
675   else
676     {
677       size = read_nibbles(*addr, 5);
678       sprintf(p, "Ext 1");
679       p += strlen(p);
680     }
681 
682   *addr += size;
683 
684   *p = '\0';
685   return p;
686 }
687 
688 char *
689 #ifdef __FunctionProto__
dec_prog(word_20 * addr,char * string)690 dec_prog(word_20 *addr, char *string)
691 #else
692 dec_prog(addr, string)
693 word_20 *addr;
694 char    *string;
695 #endif
696 {
697   word_20  semi;
698   char    *p = string;
699 
700   semi = read_nibbles(*addr, 5);
701   while (semi != SEMI)
702     {
703       p = dec_rpl_obj(addr, p);
704       semi = read_nibbles(*addr, 5);
705       if (semi != SEMI)
706         {
707           *p++ = ' ';
708           *p = '\0';
709         }
710     }
711   *addr += 5;
712   return p;
713 }
714 
715 char *
716 #ifdef __FunctionProto__
dec_code(word_20 * addr,char * string)717 dec_code(word_20 *addr, char *string)
718 #else
719 dec_code(addr, string)
720 word_20 *addr;
721 char    *string;
722 #endif
723 {
724   char    *p = string;
725   word_20  n, len;
726 
727   len = read_nibbles(*addr, 5);
728   sprintf(p, "Code");
729   p += strlen(p);
730 
731   n = 0;
732   while (n < len)
733     {
734 /*
735       *addr = disassemble(*addr, p);
736 */
737       n += len;
738     }
739 
740   *addr += len;
741   return p;
742 }
743 
744 char *
745 #ifdef __FunctionProto__
dec_local_ident(word_20 * addr,char * string)746 dec_local_ident(word_20 *addr, char *string)
747 #else
748 dec_local_ident(addr, string)
749 word_20 *addr;
750 char    *string;
751 #endif
752 {
753   int           len, i, n;
754   char         *p = string;
755   unsigned char c;
756 
757   len = read_nibbles(*addr, 2);
758   *addr += 2;
759 
760   n = len;
761   if (len > 1000)
762     n = 1000;
763 
764   for (i = 0; i < n; i++)
765     {
766       c = read_nibbles(*addr, 2);
767       *addr += 2;
768       if (hp48_trans_tbl[c].trans)
769         {
770           sprintf(p, hp48_trans_tbl[c].trans);
771           p += strlen(p);
772         }
773       else
774         *p++ = c;
775     }
776 
777   if (n != len)
778     {
779       *p++ = '.';
780       *p++ = '.';
781       *p++ = '.';
782     }
783 
784   *p = '\0';
785   return p;
786 }
787 
788 char *
789 #ifdef __FunctionProto__
dec_global_ident(word_20 * addr,char * string)790 dec_global_ident(word_20 *addr, char *string)
791 #else
792 dec_global_ident(addr, string)
793 word_20 *addr;
794 char    *string;
795 #endif
796 {
797   int           len, i, n;
798   char         *p = string;
799   unsigned char c;
800 
801   len = read_nibbles(*addr, 2);
802   *addr += 2;
803 
804   n = len;
805   if (len > 1000)
806     n = 1000;
807 
808   for (i = 0; i < n; i++)
809     {
810       c = read_nibbles(*addr, 2);
811       *addr += 2;
812       if (hp48_trans_tbl[c].trans)
813         {
814           sprintf(p, hp48_trans_tbl[c].trans);
815           p += strlen(p);
816         }
817       else
818         *p++ = c;
819     }
820 
821   if (n != len)
822     {
823       *p++ = '.';
824       *p++ = '.';
825       *p++ = '.';
826     }
827 
828   *p = '\0';
829   return p;
830 }
831 
832 char *
833 #ifdef __FunctionProto__
xlib_name(int lib,int command,char * string)834 xlib_name(int lib, int command, char *string)
835 #else
836 xlib_name(lib, command, string)
837 int   lib;
838 int   command;
839 char *string;
840 #endif
841 {
842   int           n, len;
843   int		i, lib_n = 0;
844   unsigned char c;
845   word_20	romptab, acptr;
846   word_20	offset, hash_end;
847   word_20	lib_addr, name_addr;
848   word_20	type, ram_base, ram_mask;
849   short		present = 0;
850   char         *p = string;
851 
852   /*
853    * Configure RAM to address 0x70000
854    */
855   ram_base = saturn.mem_cntl[1].config[0];
856   ram_mask = saturn.mem_cntl[1].config[1];
857   if (opt_gx)
858     {
859       saturn.mem_cntl[1].config[0] = 0x80000;
860       saturn.mem_cntl[1].config[1] = 0xc0000;
861       romptab = ROMPTAB_GX;
862     }
863   else
864     {
865       saturn.mem_cntl[1].config[0] = 0x70000;
866       saturn.mem_cntl[1].config[1] = 0xf0000;
867       romptab = ROMPTAB_SX;
868     }
869 
870   /*
871    * look up number of installed libs in romptab
872    */
873   n = read_nibbles(romptab, 3);
874   romptab += 3;
875 
876   if (n > 0)
877     {
878       /*
879        * look up lib number in romptab
880        */
881       while (n--)
882         {
883           lib_n = read_nibbles(romptab, 3);
884           romptab += 3;
885           if (lib_n == lib)
886             break;
887           romptab += 5;
888           if (opt_gx)
889             romptab += 8;
890         }
891       if (lib_n == lib)
892         {
893           /*
894            * look at hash table pointer
895            */
896           lib_addr = read_nibbles(romptab, 5);
897           if (opt_gx)
898             {
899               romptab += 5;
900               acptr = read_nibbles(romptab, 5);
901               if (acptr != 0x00000)
902                 {
903                   saturn.mem_cntl[1].config[0] = ram_base;
904                   saturn.mem_cntl[1].config[1] = ram_mask;
905                   sprintf(p, "XLIB %d %d", lib, command);
906                   p += strlen(p);
907                   return p;
908                 }
909             }
910           lib_addr += 3;
911           offset = read_nibbles(lib_addr, 5);
912           if (offset > 0)
913             {
914               /*
915                * look at the hash table
916                */
917               lib_addr += offset;
918 
919 	      /*
920 	       * check if library is in ROM
921                */
922               if (!opt_gx)
923                 if (lib_addr < 0x70000)
924                   saturn.mem_cntl[1].config[0] = 0xf0000;
925 
926 	      /*
927 	       * check pointer type
928                */
929               type = read_nibbles(lib_addr, 5);
930               if (type == DOBINT)
931                 {
932 		  /*
933 		   * follow pointer to real address
934                    */
935                   lib_addr += 5;
936                   lib_addr = read_nibbles(lib_addr, 5);
937                 }
938               else if (type == DOACPTR)
939                 {
940 		  /*
941 		   * follow pointer to real address
942                    */
943                   lib_addr += 5;
944                   acptr = lib_addr + 5;
945                   lib_addr = read_nibbles(lib_addr, 5);
946                   acptr = read_nibbles(acptr, 5);
947                   if (acptr != 0x00000)
948                     {
949                       saturn.mem_cntl[1].config[0] = ram_base;
950                       saturn.mem_cntl[1].config[1] = ram_mask;
951                       sprintf(p, "XLIB %d %d", lib, command);
952                       p += strlen(p);
953                       return p;
954                     }
955                 }
956 
957               /*
958                * get length of hash table
959                */
960               lib_addr += 5;
961               hash_end = read_nibbles(lib_addr, 5);
962               hash_end += lib_addr;
963 
964 	      /*
965 	       * go into real name table
966                */
967               lib_addr += 85;
968               offset = read_nibbles(lib_addr, 5);
969               lib_addr += offset;
970 
971               /*
972                * look at library name number 'command'
973                */
974               offset = 5 * command;
975               lib_addr += offset;
976               if (lib_addr < hash_end)
977                 {
978                   offset = read_nibbles(lib_addr, 5);
979                   if (offset > 0)
980                     {
981                       name_addr = lib_addr - offset;
982                       len = read_nibbles(name_addr, 2);
983                       name_addr += 2;
984                       present = 1;
985                       for (i = 0; i < len; i++)
986                         {
987                           c = read_nibbles(name_addr, 2);
988                           name_addr += 2;
989                           if (hp48_trans_tbl[c].trans)
990                             {
991                               sprintf(p, hp48_trans_tbl[c].trans);
992                               p += strlen(p);
993                             }
994                           else
995                             *p++ = c;
996                         }
997                       *p = '\0';
998                     }
999                 }
1000             }
1001         }
1002     }
1003 
1004   /*
1005    * Reconfigure RAM
1006    */
1007   saturn.mem_cntl[1].config[0] = ram_base;
1008   saturn.mem_cntl[1].config[1] = ram_mask;
1009 
1010   if (!present)
1011     {
1012       sprintf(p, "XLIB %d %d", lib, command);
1013       p += strlen(p);
1014     }
1015   return p;
1016 }
1017 
1018 char *
1019 #ifdef __FunctionProto__
dec_xlib_name(word_20 * addr,char * string)1020 dec_xlib_name(word_20 *addr, char *string)
1021 #else
1022 dec_xlib_name(addr, string)
1023 word_20 *addr;
1024 char    *string;
1025 #endif
1026 {
1027   int           lib, command;
1028 
1029   lib = read_nibbles(*addr, 3);
1030   *addr += 3;
1031   command = read_nibbles(*addr, 3);
1032   *addr += 3;
1033 
1034   return xlib_name(lib, command, string);
1035 }
1036 
1037 char *
1038 #ifdef __FunctionProto__
any_array(word_20 * addr,char * string,short lnk_flag)1039 any_array(word_20 *addr, char *string, short lnk_flag)
1040 #else
1041 any_array(addr, string, lnk_flag)
1042 word_20 *addr;
1043 char    *string;
1044 short    lnk_flag;
1045 #endif
1046 {
1047   word_20  len, type, dim;
1048   word_20 *dim_lens, *dims;
1049   word_20  array_addr, elem_addr;
1050   long	   elems;
1051   int      d, i;
1052   char    *p = string;
1053   struct objfunc *op;
1054 
1055   array_addr = *addr;
1056   len = read_nibbles(*addr, 5);
1057   *addr += 5;
1058   type = read_nibbles(*addr, 5);
1059   *addr += 5;
1060   dim = read_nibbles(*addr, 5);
1061   *addr += 5;
1062 
1063   for (op = objects; op->prolog != 0; op++)
1064     {
1065       if (op->prolog == type)
1066         break;
1067     }
1068 
1069   dim_lens = (word_20 *)malloc(dim * sizeof(word_20));
1070   dims = (word_20 *)malloc(dim * sizeof(word_20));
1071   elems = 1;
1072   for (i = 0; i < dim; i++)
1073     {
1074       dim_lens[i] = read_nibbles(*addr, 5);
1075       dims[i] = dim_lens[i];
1076       elems *= dim_lens[i];
1077       *addr += 5;
1078     }
1079 
1080   if (op->prolog == 0)
1081     {
1082       sprintf(p, "of Type %.5lX, Dim %ld, Size ", type, (long)dim);
1083       p += strlen(p);
1084       for (i = 0; i < dim; i++)
1085         {
1086           sprintf(p, "%ld", (long)dim_lens[i]);
1087           p += strlen(p);
1088           if (i < dim - 1)
1089             {
1090               sprintf(p, " x ");
1091               p += strlen(p);
1092             }
1093         }
1094       *p = '\0';
1095       *addr = array_addr + len;
1096       free(dim_lens);
1097       free(dims);
1098       return p;
1099     }
1100 
1101   d = -1;
1102   while (elems--)
1103     {
1104       if (d < dim - 1)
1105         {
1106           for ( ; d < dim - 1; d++)
1107             {
1108               *p++ = '[';
1109             }
1110           d = dim - 1;
1111         }
1112       if (lnk_flag)
1113         {
1114           elem_addr = read_nibbles(*addr, 5);
1115           elem_addr += *addr;
1116           *addr += 5;
1117           p = (*op->func)(&elem_addr, p);
1118         }
1119       else
1120         p = (*op->func)(addr, p);
1121       *p = '\0';
1122       dims[d]--;
1123       if (dims[d])
1124         *p++ = ' ';
1125       while (dims[d] == 0)
1126         {
1127           dims[d] = dim_lens[d];
1128           d--;
1129           dims[d]--;
1130           *p++ = ']';
1131         }
1132     }
1133 
1134   free(dim_lens);
1135   free(dims);
1136   *addr = array_addr + len;
1137 
1138   *p = '\0';
1139   return p;
1140 }
1141 
1142 char *
1143 #ifdef __FunctionProto__
dec_array(word_20 * addr,char * string)1144 dec_array(word_20 *addr, char *string)
1145 #else
1146 dec_array(addr, string)
1147 word_20 *addr;
1148 char    *string;
1149 #endif
1150 {
1151   return any_array(addr, string, 0);
1152 }
1153 
1154 char *
1155 #ifdef __FunctionProto__
dec_lnk_array(word_20 * addr,char * string)1156 dec_lnk_array(word_20 *addr, char *string)
1157 #else
1158 dec_lnk_array(addr, string)
1159 word_20 *addr;
1160 char    *string;
1161 #endif
1162 {
1163   return any_array(addr, string, 1);
1164 }
1165 
1166 char *
1167 #ifdef __FunctionProto__
dec_char(word_20 * addr,char * string)1168 dec_char(word_20 *addr, char *string)
1169 #else
1170 dec_char(addr, string)
1171 word_20 *addr;
1172 char    *string;
1173 #endif
1174 {
1175   char *p = string;
1176   unsigned char c;
1177 
1178   c = read_nibbles(*addr, 2);
1179   *addr += 2;
1180 
1181   *p++ = '\'';
1182   if (hp48_trans_tbl[c].trans)
1183     {
1184       sprintf(p, hp48_trans_tbl[c].trans);
1185       p += strlen(p);
1186     }
1187   else
1188     *p++ = c;
1189   *p++ = '\'';
1190 
1191   *p = 0;
1192   return p;
1193 }
1194 
1195 short
1196 #ifdef __FunctionProto__
check_xlib(word_20 addr,char * string)1197 check_xlib(word_20 addr, char *string)
1198 #else
1199 check_xlib(addr, string)
1200 word_20  addr;
1201 char    *string;
1202 #endif
1203 {
1204   int           n, lib, command;
1205   word_20	romptab;
1206   word_20	offset, link_end;
1207   word_20	acptr;
1208   word_20	lib_addr;
1209   word_20	type, ram_base, ram_mask;
1210   char         *p = string;
1211 
1212   /*
1213    * Configure RAM to address 0x70000
1214    */
1215   ram_base = saturn.mem_cntl[1].config[0];
1216   ram_mask = saturn.mem_cntl[1].config[1];
1217   if (opt_gx)
1218     {
1219       saturn.mem_cntl[1].config[0] = 0x80000;
1220       saturn.mem_cntl[1].config[1] = 0xc0000;
1221       romptab = ROMPTAB_GX;
1222     }
1223   else
1224     {
1225       saturn.mem_cntl[1].config[0] = 0x70000;
1226       saturn.mem_cntl[1].config[1] = 0xf0000;
1227       romptab = ROMPTAB_SX;
1228     }
1229 
1230   /*
1231    * look up number of installed libs in romptab
1232    */
1233   n = read_nibbles(romptab, 3);
1234   romptab += 3;
1235 
1236 /*
1237 fprintf(stderr, "Number of Libraries = %d\n", n);
1238 fflush(stderr);
1239 */
1240 
1241   if (n > 0)
1242     {
1243       /*
1244        * look up lib number in romptab
1245        */
1246       while (n--)
1247         {
1248           lib = read_nibbles(romptab, 3);
1249           romptab += 3;
1250 /*
1251 fprintf(stderr, "Library num = %d\n", lib);
1252 fflush(stderr);
1253 */
1254           /*
1255            * look at link table pointer
1256            */
1257           lib_addr = read_nibbles(romptab, 5);
1258 /*
1259 fprintf(stderr, "Library addr = %.5lx\n", lib_addr);
1260 fflush(stderr);
1261 */
1262           romptab += 5;
1263 
1264           if (opt_gx)
1265             {
1266               acptr = read_nibbles(romptab, 5);
1267               romptab += 8;
1268               if (acptr != 0x00000)
1269                 continue;
1270             }
1271 
1272           lib_addr += 13;
1273           offset = read_nibbles(lib_addr, 5);
1274           if (offset > 0)
1275             {
1276               /*
1277                * look at the link table
1278                */
1279               lib_addr += offset;
1280 /*
1281 fprintf(stderr, "Link table addr = %.5lx\n", lib_addr);
1282 fflush(stderr);
1283 */
1284 	      /*
1285 	       * check if library is in ROM
1286                */
1287               if (!opt_gx)
1288                 if (lib_addr < 0x70000)
1289                   saturn.mem_cntl[1].config[0] = 0xf0000;
1290 
1291 	      /*
1292 	       * check pointer type
1293                */
1294               type = read_nibbles(lib_addr, 5);
1295               if (type == DOBINT)
1296                 {
1297 		  /*
1298 		   * follow pointer to real address
1299                    */
1300                   lib_addr += 5;
1301                   lib_addr = read_nibbles(lib_addr, 5);
1302                 }
1303 /*
1304 fprintf(stderr, "Link table addr (2) = %.5lx\n", lib_addr);
1305 fflush(stderr);
1306 */
1307               /*
1308                * get length of link table
1309                */
1310               lib_addr += 5;
1311               link_end = read_nibbles(lib_addr, 5);
1312               link_end += lib_addr;
1313 /*
1314 fprintf(stderr, "Link table end = %.5lx\n", link_end);
1315 fflush(stderr);
1316 */
1317               /*
1318                * look at library commands
1319                */
1320               lib_addr += 5;
1321               command = 0;
1322               while (lib_addr < link_end)
1323                 {
1324                   offset = read_nibbles(lib_addr, 5);
1325                   if (offset > 0)
1326                     {
1327                       if (addr == ((lib_addr + offset) & 0xfffff))
1328                         {
1329                           p = xlib_name(lib, command, p);
1330                           saturn.mem_cntl[1].config[0] = ram_base;
1331                           saturn.mem_cntl[1].config[1] = ram_mask;
1332                           return 1;
1333                         }
1334                     }
1335                   lib_addr += 5;
1336                   command++;
1337                 }
1338               if (opt_gx)
1339                 saturn.mem_cntl[1].config[0] = 0x80000;
1340               else
1341                 saturn.mem_cntl[1].config[0] = 0x70000;
1342             }
1343         }
1344     }
1345 
1346   /*
1347    * Reconfigure RAM
1348    */
1349   saturn.mem_cntl[1].config[0] = ram_base;
1350   saturn.mem_cntl[1].config[1] = ram_mask;
1351 
1352   return 0;
1353 }
1354 
1355 
1356 char *
1357 #ifdef __FunctionProto__
dec_rpl_obj(word_20 * addr,char * string)1358 dec_rpl_obj(word_20 *addr, char *string)
1359 #else
1360 dec_rpl_obj(addr, string)
1361 word_20 *addr;
1362 char    *string;
1363 #endif
1364 {
1365   word_20	  prolog = 0;
1366   word_20	  prolog_2;
1367   char           *p = string;
1368   char		  tmp_str[80];
1369   struct objfunc *op;
1370 
1371   prolog = read_nibbles(*addr, 5);
1372 
1373   for (op = objects; op->prolog != 0; op++)
1374     {
1375       if (op->prolog == prolog)
1376         break;
1377     }
1378 
1379   if (op->prolog == 0)
1380     {
1381       if (check_xlib(prolog, tmp_str))
1382         {
1383           p = append_str(p, tmp_str);
1384         }
1385       else
1386         {
1387           prolog_2 = read_nibbles(prolog, 5);
1388           for (op = objects; op->prolog != 0; op++)
1389             {
1390               if (op->prolog == prolog_2)
1391                 break;
1392             }
1393           if (op->prolog)
1394             p = dec_rpl_obj(&prolog, p);
1395           else
1396             p = append_str(p, "External");
1397         }
1398       *addr += 5;
1399       return p;
1400     }
1401 
1402   *addr += 5;
1403   p = (*op->func)(addr, p);
1404 
1405   return p;
1406 }
1407 
1408 void
1409 #ifdef __FunctionProto__
decode_rpl_obj_2(word_20 addr,char * typ,char * dat)1410 decode_rpl_obj_2(word_20 addr, char *typ, char *dat)
1411 #else
1412 decode_rpl_obj_2(addr, typ, dat)
1413 word_20  addr;
1414 char    *typ;
1415 char    *dat;
1416 #endif
1417 {
1418   word_20	  prolog = 0;
1419   int             len;
1420   char		  tmp_str[80];
1421   struct objfunc *op;
1422 
1423   typ[0] = '\0';
1424   dat[0] = '\0';
1425 
1426   prolog = read_nibbles(addr, 5);
1427 
1428   for (op = objects; op->prolog != 0; op++)
1429     {
1430       if (op->prolog == prolog)
1431         break;
1432     }
1433 
1434   if (op->prolog == 0)
1435     {
1436       if (addr == SEMI)
1437         {
1438           append_str(typ, "Primitive Code");
1439           append_str(dat, "SEMI");
1440         }
1441       else if (addr + 5 == prolog)
1442         {
1443           append_str(typ, "Primitive Code");
1444           sprintf(dat, "at %.5lX", prolog);
1445         }
1446       else
1447         {
1448           append_str(typ, "PTR");
1449           sprintf(dat, "%.5lX", prolog);
1450         }
1451       return;
1452     }
1453 
1454   if (op->prolog == DOCOL)
1455     {
1456       if (check_xlib(addr, tmp_str))
1457         {
1458           append_str(typ, "XLib Call");
1459           append_str(dat, tmp_str);
1460 	  return;
1461         }
1462     }
1463 
1464   if (op->length)
1465     {
1466       len = (read_nibbles(addr + 5, 5) - 5) / op->length;
1467       sprintf(typ, "%s %d", op->name, len);
1468     }
1469   else
1470     {
1471   append_str(typ, op->name);
1472     }
1473 
1474   addr += 5;
1475   (*op->func)(&addr, dat);
1476 
1477   return;
1478 }
1479 
1480 char *
1481 #ifdef __FunctionProto__
decode_rpl_obj(word_20 addr,char * buf)1482 decode_rpl_obj(word_20 addr, char *buf)
1483 #else
1484 decode_rpl_obj(addr, buf)
1485 word_20  addr;
1486 char    *buf;
1487 #endif
1488 {
1489   word_20	  prolog = 0;
1490   int             len;
1491   char           *p = buf;
1492   char		  tmp_str[80];
1493   struct objfunc *op;
1494 
1495   prolog = read_nibbles(addr, 5);
1496 
1497   for (op = objects; op->prolog != 0; op++)
1498     {
1499       if (op->prolog == prolog)
1500         break;
1501     }
1502 
1503   if (op->prolog == 0)
1504     {
1505       if (addr == SEMI)
1506         {
1507           p = append_str(buf, "Primitive Code");
1508           p = append_tab_16(buf);
1509           p = append_str(p, "SEMI");
1510         }
1511       else if (addr + 5 == prolog)
1512         {
1513           p = append_str(buf, "Primitive Code");
1514           p = append_tab_16(buf);
1515           sprintf(p, "at %.5lX", prolog);
1516           p += strlen(p);
1517           *p = '\0';
1518         }
1519       else
1520         {
1521           p = append_str(buf, "PTR");
1522           p = append_tab_16(buf);
1523           sprintf(p, "%.5lX", prolog);
1524           p += strlen(p);
1525           *p = '\0';
1526         }
1527       return p;
1528     }
1529 
1530   if (op->prolog == DOCOL)
1531     {
1532       if (check_xlib(addr, tmp_str))
1533         {
1534           p = append_str(buf, "XLib Call");
1535           p = append_tab_16(buf);
1536           p = append_str(p, tmp_str);
1537 	  return p;
1538         }
1539     }
1540 
1541   p = append_str(buf, op->name);
1542 
1543   if (op->length)
1544     {
1545       len = (read_nibbles(addr + 5, 5) - 5) / op->length;
1546       sprintf(p, " %d", len);
1547       p += strlen(p);
1548     }
1549 
1550   p = append_tab_16(buf);
1551   addr += 5;
1552   p = (*op->func)(&addr, p);
1553 
1554   return p;
1555 }
1556 
1557