-
Notifications
You must be signed in to change notification settings - Fork 1
/
portnote.txt
1116 lines (916 loc) · 53 KB
/
portnote.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Notes on porting TADS
=====================
Following are notes on changes made to the OS layer in recent
versions, starting with the most recent changes. If you're updating
a TADS port, you should refer to the changes made since the last
working version on your system.
At the end of the file, you'll find more general information on how
the portability layer is designed and how to get TADS working on a
new operating system. If you're porting TADS to a new system for the
first time, you should look at the general notes at the end of this
file.
Quick Start Guide
-----------------
To port TADS to a new platform, you should start by looking at
osifc.h, which specifies the entire TADS Operating System Interface.
You must provide an implementation of this interface for your
platform.
If you're porting TADS to a machine that resembles another platform
where TADS already runs, you can probably use the OS Interface
implementation for that existing platform as a starting point; if
not, you should read the documentation in osifc.h to learn what each
function must do.
You'll also need to construct a makefile or equivalent for your
platform, to compile the C files that make up TADS and link the
results into executables for the TADS Interpreter, and optionally the
TADS Compiler and other tools. You should refer to an existing
makefile (such as the DOS or Unix makefile) as a starting point.
A Note on Newlines
------------------
Different operating systems have a tendency to disagree on the most
trivial details. One of these pointless variations that causes a lot
of trouble is "newline" conventions: each OS has its own way of
signaling the end of a line of text in files such as C source and
header files. In almost every case, the end of a line of text is
indicated by some combination of the special characters with ASCII
values 10 and 13, known respectively as "line feed" or "LF", and
"carriage return" or "CR". MS-DOS uses the sequence CR-LF; Unix uses
just LF; Macintosh uses just CR; and some system somewhere probably
uses LF-CR.
In many cases, systems are tolerant of "foreign" conventions, but
sometimes the wrong conventions will confuse compilers and other
tools. If you run into any mysterious compiler errors, or your text
editor or other tools have problems reading or displaying the TADS
source files, you might want to try converting the files to your
system's newline conventions. One of the easiest ways to do this is
usually to use your UNZIP tool's "auto-convert text files" option
when you unpack the TADS source archive - on command-line systems,
this is usually the "unzip -a" option.
Version 2.5.8 changes
---------------------
* New OS_ATTR_xxx codes:
In the past, the single text attribute was "highlighting," specified
with OS_ATTR_HILITE. Several new attributes have been added. First,
there are two new attributes with specific renderings: OS_ATTR_BOLD
and OS_ATTR_ITALIC. The former should use bold-face if available, the
latter an italic font. On most character-mode platforms, bold-face
can be approximated with a brighter color, and italics can be ignored.
Second, there are two new abstract attributes: OS_ATTR_EM and
OS_ATTR_STRONG. These correspond to the HTML <EM> and <STRONG>
attributes, so it's up to the platform to define the actual
appearance.
PORTS CAN IGNORE THE NEW ATTRIBUTES. These changes have been made in
such a way that everything will continue to work as it has all along
if a port ignores the changes. OS_ATTR_BOLD, OS_ATTR_HILITE, and
OS_ATTR_EM will all map to the same code, which is the same as the
original OS_ATTR_HILITE code. OS_ATTR_ITALIC will map to a new code,
but since existing ports don't know this code, it will do nothing.
OS_ATTR_STRONG maps to zero by default (i.e., no change to the codes
at all), so it will also do nothing. Thus, existing ports will work
the same as they always have with existing games.
Any port that's capable of displaying italics might want to add
recognition of italics. If you do this, it might be desirable to add
definitions to your OS-specific header to #define OS_ATTR_EM as
OS_ATTR_ITALIC and OS_ATTR_STRONG as OS_ATTR_BOLD, for consistency
with most HTML browser renderings. Your #defines for these symbols
will override the defaults, since the defaults will be defined only if
your OS header doesn't otherwise define the symbols.
* MORE banner style:
A new style flag has been added: OS_BANNER_STYLE_MOREMODE. This style
indicates that the banner should pause for a MORE prompt any time its
text overflows the vertical display area of the banner, to give the
user a chance to read a long passage and acknowledge that it's okay to
show more text. When this flag isn't set, the default is that long
passages are allowed to scroll off the screen (assuming the
auto-vscroll style is set), even if the user might not have had a
chance to read them. With this new style flag set, though, a banner
window should pause when text overflows the window, using the same
sort of prompt and user acknowledgment used for the MORE prompt in the
main game window. Note that there's no sysinfo flag to opt out of
implementing this style; it's important enough that platforms
supporting the banner API at all must support this style.
Platforms based on osgen3.c won't need to do anything to support this
new style, as it's fully handled in osgen3.c. Other platforms will
have to implement this style in their banner code.
* Parent Windows in the os_banner API:
The new concept of a "parent" window has been introduced into the
banner API. When a banner window is created, the caller can now
optionally designate a parent banner, which is an existing banner
window from which the new banner's display area will be taken. In
past versions, there was no explicit parent window, and each new
banner's display area was taken out of the main game window's
rectangle. When the caller does not specify a parent banner, this
traditional behavior applies; however, when the caller specifies a
parent, the display area is taken from the parent rather than from the
main game window.
For implementations based on osgen.c or osgen3.c, no changes are
needed to any system-specific code. All of the necessary changes are
handled entirely in osgen.c and osgen3.c.
Implementations that do not implement the banner API must merely to
change the definition of their dummy os_banner_create() function to
match the new prototype.
Systems that implement the banner API and which DO NOT use osgen.c or
osgen3.c must implement the new parent window mechanism. This will
require several changes. First, os_banner_create() must be changed to
use the new prototype, which includes an argument for the parent
banner handle. Second, os_banner_create() must remember the parent
window handle with the internal data structure it uses to represent
the new window. Third, the system-specific code that calculates the
banner layout must take the parent structure into account; see
os_banner.htm for details of the required new layout algorithm.
Fourth, if the implementation supports drawing banner window borders
(as specified through the style flags), it will have to take into
account the new rule that a border is drawn to the horizontal or
vertical extent (as appropriate) of the *union* of the banner and all
of its child windows. Fifth, os_banner_delete() might need to hide or
set to zero size any children of the banner being deleted, since once
a parent is deleted, its children become invisible, although they
remain valid as abstract objects until explicitly deleted.
* os_nonstop_mode():
This new function lets the portable code tell the OS layer that it
wants to run in "non-stop" mode, which means that MORE prompting (or
any local equivalent) should be disabled. By default, non-stop mode
is turned off; this function lets the portable code turn it on and
off. Character-mode platforms based on osgen.c/osgen3.c don't have to
worry about this. Platforms where MORE prompting doesn't exist or is
provided by the portable console layer can simply provide a dummy
implementation. Platforms where the OS layer handles MORE prompting
should provide a real implementation of this function.
Version 2.5.7 changes
---------------------
IMPORTANT - if you're using a platform based on osgen.c, you can skip
#1 through #5, because these changes are handled by the portable osgen.c
implementation. Skip to #6 if you're using osgen.c
1. The function os_hilite() has been DELETED. You should remove any
implementation of this function you provide.
2. The new function os_set_text_attr() replaces os_hilite(). This
new function is used to set text attributes in the main window. If
you had an implementation of os_hilite() that simply returned zero,
your os_set_text_attr() need do nothing at all. If your os_hilite()
implementation did anything else, it can be implemented with something
like this:
void os_set_text_attr(unsigned int attr)
{
os_printf("%c", (attr & OS_ATTR_HILITE) != 0 ? ON : OFF);
}
where ON is to be replaced by the character code that os_hilite(1)
returned in your old implementation, and OFF is to be replaced by the
character code that os_hilite(2) returned. If possible, you should
optimize this by doing nothing when the current hilite mode is not
being changed. The purpose of this change is to generally improve the
osifc design, and to make it more extensible by providing a structured
way to add new attributes to be added in the future.
The meanings of colors in os_set_text_color() and os_set_screen_color()
have changed. The values are now encoded RGB values; some macros are
provided in osifc.h for manipulating these color values. Platforms
based on osgen.c will NOT have to do anything for this change, since
osgen.c defines the osifc-level color routines.
3. The os_printf() and os_vprintf() routines have been DELETED. These
have been replaced by os_printz() and os_print() (see #4).
4. The new routines os_printz() and os_print() have been ADDED. These
routines do essentially what os_printf() and os_vprintf() formerly did,
but with a greatly simplified interface. These functions are notably
different from the former os_printf() and os_vprintf() in some important
ways:
4a. These routines do NOT take a printf-style format string, but
simply take a string to display directly. There is no need to perform
any parameter substitutions on the string.
4b. os_printz() takes a NULL-TERMINATED string, while os_print() takes
a COUNTED-LENGTH string (the byte length is given as a separate argument),
and thus CANNOT assume that the string is null-terminated. os_printz()
for (PRINT-Zero-terminated) can be implemented as a simple call to
os_print, with the string's length computed with strlen().
4c. These routines NO LONGER have to worry about the "highlight" escape
code sequences. Highlighting is handled with the new text attributes
settings (see #2 above), so strings presented to os_print will no longer
have any embedded escape codes. The only special characters that these
routines are now expected to recognize are '\n' and '\r'.
5. Several new SYSINFO_xxx codes have been added to osifc.h. Your
os_get_sysinfo() implementation should be updated for the new codes.
6. [Begin osgen.c changes]
All platforms based on the semi-portable osgen.c implementation must
make some small adjustments to their ossxxx routines. THE FOLLOWING
NOTES APPLY *ONLY* TO OSGEN.C PLATFORMS - if you're not linking with
osgen.c, ignore the following. Note that these aren't changes you
have to make to osgen.c itself - these are changes you have to make
to your system-specific code that osgen.c relies upon.
There are now two different "osgen" implementations. First, there's
the traditional osgen.c - this is the one you'll get by default if
you do nothing, since it's the one your makefile (or equivalent)
already uses. This version of osgen.c has been reworked a little,
but it's substantially the same as in past versions. Second, there's
a new version called osgen3.c - if you like, you can switch to this
one. osgen3.c is a REPLACEMENT for osgen.c - you use EITHER osgen.c
or osgen3.c, but not both. If you switch, simply substitute osgen3.c
for osgen.c wherever it appears in your makefile.
Okay, so should you switch to osgen3.c, or stick with osgen.c? In
the long run, the answer is that you should switch; but when you do
so is up to you. What you get with osgen3.c is a full implementation
of the new TADS 3 "banner API," which lets TADS 3 programs control
the screen layout much more precisely than TADS 2 programs could. If
you are building the TADS 3 interpreter, you should definitely switch
to osgen3.c, to give TADS 3 programs the full capabilities of the new
banner API. If you're building only a TADS 2 interpreter, there's
less immediate benefit in switching, because TADS 2 programs don't
have any way to access the banner API. The main reason not to switch
if you don't have to is that osgen3.c is a substantial rewrite that
hasn't been around nearly as long as osgen.c and thus hasn't had
nearly as much practical testing; sticking with osgen.c is less
likely to introduce new bugs. On the other hand, it should be
practically no work to switch to osgen3.c - the only change should be
replacing osgen.c with osgen3.c in your makefile. If you do plan to
port the TADS 3 interpreter at some point, switching to osgen3.c now
would have the advantage that you'll feel safer using osgen3.c when
the time comes for the TADS 3 port, because you will have been using
osgen3.c between now and then.
You'll have change your osxxx code as described in the sub-topics
below, regardless of whether you stick with osgen.c or switch to
osgen3.c.
6a. Several global variables have been eliminated. You can delete
these from your osxxx.h headers and remove calcaulations from your
osxxx.c source files. (It's not vital that you do this, but it's
encouraged in the interests of general clean-up. If you're still
using any of these variables for your own purposes, of course, you are
free to keep them - just be aware that osgen.c no longer needs them.)
The following variables are no longer used in osgen.c:
ldesc_color
ldesc_column
ldesc_curline
ldesc_line
max_column
max_line
score_column
sdesc_column
sdesc_line
text_column
text_lastcol
text_normal_color
text_bold_color
Note that you might not want to delete the xxx_color variables, since
you might want to use these same values in your ossgetcolor()
implementation (see "fifth..." below). However, osgen.c no longer
uses these variables, since it now instead calls your ossgetcolor()
routine to determine what color values to use.
If you switch to osgen3.c, the following globals are also eliminated
(or, rather, can be eliminated, as osgen3.c doesn't require them):
sdesc_color
text_color
6b. Your osxxx.c code MUST NOT set or modify G_os_pagelength or
G_os_linewidth. In the past, the osxxx.c code was responsible for
setting these, and was aware of the status line location and so forth.
Don't set these variables any more. Instead, set the new global
variables G_oss_screen_width and G_oss_screen_height to the height and
width of the screen, in characters - DO NOT make any adjustments for
status lines or anything else, as osgen.c will take care of that. Be
sure to set these variables in your os_scrini() routine, so that
they're available during osgen.c's initialization.
6c. If the screen size can ever change dynamically after
initialization, you MUST call the new function
osssb_on_resize_screen() immediately after updating the global
variables G_oss_screen_width and G_oss_screen_height. This will
ensure that osgen.c has a chance to refigure its internal layout
parameters according to the new screen size.
6d. You should #include "osgen.h" in your osxxx.c file(s).
6e. You must implement the new routines oss_get_sysinfo() and
ossgetcolor(). (These actually were added just before the 2.5.6
release, so if you've sync'ed up lately, you probably have implemented
these already - they haven't changed in this version.) Refer to
osgen.h for details on how these are supposed to work. These new
routines provide text color support, so that games can explicitly set
the colors of the text they display; color support is optional, but if
you don't support color, you must must still provide minimal
implementations of these routines to return the same color scheme
you've used in the past.
In the past, several global variables (text_normal_color,
sdesc_color, etc) had the "oss color codes" to use for different
types of text - these color codes were passed to ossdsp(), ossclr(),
and so on for rendering by your osxxx.c code. osgen.c no longer uses
most of these; it only uses sdesc_color and text_color. If you're
switching to osgen3.c, even those hold-outs are gone. Instead, the
osgen layer calls your ossgetcolor() routine to get the color code to
use for each case. If you don't want to support any more color than
you did in the past, you can simply implement ossgetcolor() so that
it looks for the various abstract color codes (OS_COLOR_TEXT,
OS_COLOR_STATUSLINE, etc), and returns the corresponding global
variable value. The advantage of the new scheme is that it allows
the game code to set *specific* colors (e.g., red, blue, cyan) for
individual bits of text, as long as your osxxx.c code (and your
display hardware, of course) can support specific colors.
6f. The macro OSGEN_ATTR_BOLD has been renamed to OS_ATTR_HILITE. If
you ported the 2.5.6 release, you might have a reference to this
macro; the meaning is the same, so all you have to do is change the
name. For convenience, OSGEN_ATTR_BOLD is now defined as equivalent
to OS_ATTR_HILITE, but the new name should be used as soon as
possible.
6g. The OS_COLOR_xxx symbols have been renamed to OSGEN_COLOR_xxx.
The meanings are the same as they were; the name change reflects the
change in the osifc-level color scheme.
6h. Eight new OSGEN_COLOR_xxx values have been introduced, to allow
for somewhat better granularity in setting colors at the system level.
With the new colors, the OSGEN_COLOR_xxx values can specify a total of
16 colors, which correspond to the eight ANSI colors at "low
intensity" and "high intensity"; the low-intensity set is essentially
the high-intensity set at half brightness. On most systems based on
osgen.c, if this full range of colors is available, the brighter half
of the range will be used to show high-intensity text, so in fact only
eight colors will really be available; on such systems, ossgetcolor()
should simply collapse the 16 colors down to the 8 ANSI colors, by
treating the low-intensity and high-intensity version of a given color
the same, and then pick from the low- or high-intensity version
according to the boldness attribute. Even for systems that collapse
the colors in the this manner, though, there is still value in having
the broader range, in that the full range of 16 colors can be selected
for backgrounds, which do not have a boldness attribute and thus are
free to offer the full range of 16 colors to clients.
6i. You must implement the new routine oss_raw_key_to_cmd(). This
routine's purpose is to map "raw" keystroke codes to command-editing
CMD_xxx codes, essentially mapping results from the style that
os_getc_raw() uses to the style os_getc() uses. This routine was
created to give the OS implementation more specific control over the
mapping of raw keystrokes to command-editing functions. For most
systems, you can probably just copy the MS-DOS implementation, in the
source file msdos/osdos.c, making any desired changes to the control
key or other mappings.
[End osgen.c changes]
Version 2.5.6 changes
---------------------
Several new SYSINFO_xxx codes have been added - osifc.h has the full
list. The system-specific code that provides system information
should be updated to handle the new codes.
A new file-open function, osfoprwt(), has been added. This function
is the text-mode equivalent of osfoprwb(): it opens a text file for
both read and write access, keeping intact any existing contents. I
have attempted to provide a suitable implementation in the source
code for each ported version of which I have a copy in my source
tree, but a platform expert on each target system might want to check
my work to make sure it's correct for their system.
A second new file-open function, osfoprwtt(), has been added. This
function is the text-mode equivalent of osfoprwtb(): it opens a text
file for both read and write access, truncating any existing file.
I've attempted to provide a suitable definition for each platform for
this function as well.
The new function os_update_display() has been added. This function's
purpose is to process any pending redraw events immediately, if
applicable to the system. This function only needs to be implemented
on event-driven operating systems where the display is drawn in
response to redraw events generated by window region invalidations.
(If that doesn't mean anything to you, you're almost certainly not on
such a platform - the Windows and Macintosh GUI's both use this kind
of drawing scheme, but text-mode versions would certainly not.) The
purpose of this routine is to update the display prior to a long
computation, to avoid the appearance that the program is frozen
during the computation delay.
The new functions os_set_text_color() and os_set_screen_color() can
optionally provide the game with control over display colors. These
are described in osifc.h. These functions are optional; if they're
not suitable for a given platform, simply provide empty
implementations.
The new functions os_gets_timeout() and os_gets_cancel() provides an
event-oriented interface for reading a command line from the keyboard.
This function is similar to the regular os_gets(), but has a timeout
feature that allows the keyboard read to be interrupted after a
specified interval has elapsed, and then possibly resumed later.
Timed keyboard input is optional; if it can't be implemented on a
platform, simply provide an implementation for os_gets_timeout() that
returns OS_EVT_NOTIMEOUT when a timeout is provided, and an empty
implementation for os_gets_cancel().. Note that even if timed input
is not allowed, os_gets_timeout() should minimally call the plain
os_gets() when the caller does not specify a timeout, and only return
the OS_EVT_NOTIMEOUT error when a timeout is actually requested by the
caller.
A new interface for managing "banner" windows in the process of being
added. This is a work in progress, and you should just ignore it for
now, providing only stub implementations. The new interface consists
of a set of functions (about a dozen) whose names are of the form
os_banner_xxx(); I'm still in the process of working out the final
details, so the set may change in the future. These new functions,
when they're completed, will provide functionality similar to the HTML
TADS <BANNER> tag, but without the limitations that arise from using a
single output stream to control all aspects of the display. In the
future, this interface will allow for for implementation of
banner-like behavior in text-only platforms, allowing more flexibility
for games in their use of text-mode displays. The banner interface
will always be entirely optional; if it is not feasible or desirable
to implement the interface, a platform will be able to provide
do-nothing implementations for these routines.
Version 2.5.2 changes
---------------------
In preparation for TADS 3, I've been tightening up the interfaces
between the OS layer and the portable code. My goal is to ensure
that the a common OS layer can be shared by TADS 2 and TADS 3, which
will dramatically simplify the porting of TADS 3 by eliminating the
need to write a new set of OS routines. Porting TADS 3 will simply
be a matter of compiling and linking the TADS 3 portable code with
the existing TADS 2 OS code for your platform; the only coding you
should have to do is to create the makefile.
I've been working on this OS interface improvement for some time.
This process started with the creation of osifc.h, which provides us
with a comprehensive definition of the entire interface that the
portable code uses to call the OS code. I've also been expanding and
improving the OS interfaces slightly over the past few releases, but
I've been trying to minimize these changes to minimize the resulting
porting work created.
With this release, I've addressed a new area, which is references
from the OS code to the portable code. In general, the OS code
should never call the portable code or use any global variables
defined in the portable code; doing so ties the OS code to a
particular portable system, which makes it difficult to re-use the OS
code in a new system (such as TADS 3).
The OS code should NOT henceforth refer to ANY function or global
variable defined in the portable code. If your OS code refers to
anything in the portable code, your OS code will not work with TADS
3, because those portable symbols will probably not be defined at all
in TADS 3.
I've tried to remove all of the references I could find from the OS
code into the portable code. However, until TADS 3 is ported to the
existing platforms, where the linker can root out the missing
symbols, it is difficult to know for sure that all of the references
are gone.
* OS code should no longer call runstat(). Most os_gets()
implementations started by calling runstat() to update the status
line prior to reading input. The OS code is no longer responsible
for this. You should simply remove any runstat() calls from your
OS code. If you have runstat() calls that are needed in places
other than at the start of os_gets(), contact me ([email protected])
if you would like advice on how to remove the dependency and I'll
try to help figure out what to do.
* The global variables "pagelength" and "linewidth" have been renamed
to G_os_pagelength and G_os_linewidth. This formally moves these
variables into the OS layer rather than leaving them in the portable
formatter.
* The global variable "moremode" has been renamed to G_os_moremode,
moving it into the OS layer.
* OS routines should no longer call tio_is_html_mode() (or any other
tio routines).
* OS routines should no longer call qasclose(). Most of the
os_term() implementations in the OS code were calling this routine;
this should instead be handled in the portable code, so the OS code
should not use this method at all.
* OS code should no longer call outformat() or getstring(). The
text-only implementations of os_askfile() and os_input_dialog()
called these routines, because they implemented their dialogs using
formatted text. To address this, I've moved these text
implementations to the portable layer; there is no longer a text-only
version of os_askfile() or os_input_dialog(). Refer to askf_tx.c,
askf_os.c, indlg_tx.c, and indlg_os.c for details on the new
portable-layer implementations.
MAKEFILE CHANGES: You must include one of askf_tx.c or askf_os.c in
each executable you build. You must include one of indlg_tx.c or
indlg_os.c in each executable. Refer to these files to determine
which one to choose. In general, the _tx versions are text-only
implementations -- these do not invoke os_xxx routines; the _os
versions simply pass through the operation to the corresponding
os_xxx routines. You should choose the _os version if you have a
corresponding os_xxx implementation that you want to use; you should
choose the _tx version if you want to use the plain text version.
If your os_xxx routine was calling outformat() or getstring(), you
should simply delete your os_xxx routine entirely and use the _tx
version; otherwise, keep your os_xxx routine and use the _os version.
OTHER CHANGES:
* added os_is_special_file()
* added os_uninit()
* added OS_CHARMAP_FILECONTENTS identifier
Version 2.5.1 changes
---------------------
* I added a new command code for os_getc(): CMD_EOF. This new code
indicates that "end of file" has been reached on the console input;
this usually means that the player has terminated the application
through some means such as closing its main window, or disconnected
the terminal, or something like that. os_getc() should return this
new code when it detects this type of condition so that code that
calls os_getc() can finish up whatever it's doing and terminate the
application gracefully.
* There's a new function called os_getc_raw(). This is conceptually
a lower-level version of os_getc(). The difference is that os_getc()
returns "translated" keystroke CMD_xxx codes, whereas os_getc_raw()
returns "raw" CMD_xxx codes. The translated codes are higher-level
functional codes; for example, on Unix, when the user types Ctrl-E,
os_getc() would return CMD_END, because Ctrl-E is bound to the
end-of-line command. In contrast, os_getc_raw() would simply return
ASCII 5. Similarly, on DOS, if the user presses the Escape key,
os_getc() would return CMD_KILL, but os_getc_raw() returns ASCII 27.
Note that some keys return different CMD_xxx codes for os_getc() and
os_getc_raw(); for example, on DOS, if the user presses F1, os_getc()
returns CMD_SCR (to toggle scrollback mode), but os_getc_raw() returns
CMD_F1.
The purpose of os_getc_raw() is to allow lower-level access to keystroke
information, particularly for the inputkey() TADS function, while still
preserving the port-specific functional mapping that os_getc() affords.
Refer to osifc.h for documentation of the new function. Note that the
CMD_xxx codes defined in osifc.h are now commented to indicate which
command codes are "translated" and which are "raw"; when a particular
key maps to one of each type, os_getc() should return the translated
CMD_xxx code and os_getc_raw() should return the raw code.
* The osfoprwb() function has traditionally been implemented
incorrectly. On most platforms, this has been implemented as a call
to fopen() with the mode "r+b" (or simply "r+" on platforms with no
text/binary mode distinction), following the example of the DOS code.
In fact, the intended function, which was not adequately documented
in the osifc.h comments, was to open an existing file or create a new
file if it didn't already exist. The C fopen() "r+" mode fails if the
file doesn't exist. The intended behavior has now been correctly
documented in osifc.h, and the DOS, Windows, Unix, and Mac versions
have been changed to use the correct behavior.
Version 2.4.1 changes
---------------------
* New OS function: os_input_dialog(). A default character-mode
implementation in osgen.c should suffice for most ports, but GUI
ports should show a dialog box if possible. The character-mode
implementation in osgen.c is selected at compile time with #define
symbol USE_STDIO_INPDLG, which osgen.c defines implicitly if
USE_STDIO is defined.
* New OS function: os_get_str_rsc(). Most platforms should be able
to use the default implementation in ostadrsc.c (in the generic
code directory). Where possible, though, this function should be
implemented using native OS string resources; this will make it
easier for translators to localize the TADS executables.
* TADSVER.TXT has been changed to TADSVER.HTM, and DOSVER.TXT is
now DOSVER.HTM.
* The interface to the os_askfile() function has changed very
slightly, in that the result code values are now more precisely
specified. In the past, this function simply returns zero for
success and non-zero to indicate failure of some kind. The result
codes can now indicate the type of failure; in particular, the
function can distinguish actual errors from the case where the user
simply chooses to cancel the dialog. Refer to osifc.h for details.
I've attempted to change all of the OS sources that I have in my
source tree; experts on the code for the individual platforms are
encouraged to double-check my changes.
Version 2.4.0 changes
---------------------
* os.h has been reorganized to make it cleaner and more consistent.
All of the DOS code has been removed from os.h and moved to new
DOS-specific headers; this leaves os.h as a very simple "switchboard"
file whose only function is to select the appropriate set of headers
to #include based on the system macro settings. All of the non-DOS
headers already worked this way, so this change should be transparent
to other ports.
* osifc.h now has (as far as I can tell) complete documentation of
the entire TADS Operating System Interface. In particular, all of
the file-related functions (osfoprb, osfrb, etc) are now specified
and documented in osifc.h, as are the former "library" functions
(osmalloc, osfree). This change should not affect any existing code;
the additions are mostly comments.
* The os_find_first_file() and os_find_next_file() interfaces have
changed. Two new parameters, outpathbuf and outpathbufsiz, have been
added; the new buffer is to receive the full path of the current
file, so that the caller doesn't have to attempt to construct the
path name from its components using possibly non-portable
assumptions. This should have minimal impact, since the only ports
that appear to implement these functions currently are DOS, Windows,
OS/2, and Macintosh. Refer to osifc.h for documentation.
* The os_progress() interface has changed slightly. This function no
longer takes a (struct linfdef *) argument, which tied the function
to the particulars of an internal structure in the TADS 2 compiler;
instead, the function now takes a filename string and a line number.
This change should have minimal impact, since only the Macintosh port
currently provides a non-trivial implementation of this function.
Version 2.3.0 changes
---------------------
* ATTENTION UNIX USERS - If you run into weird display problems in
the interpreter, especially with spurious extra spaces at the
beginning of each line, try these definitions in your makefile:
LIBS= -lncurses
CFLAGS= -DHAVE_TPARM (plus whatever other CFLAGS you were already using)
* The existing os_term() function is now used more rigorously. In
the past, the generic code called exit() directly in a few places,
which prevented the OS layer from doing any clean-up at termination.
The generic code should now use os_term() exclusively to terminate
execution. This shouldn't require any new porting work, since
nothing about os_term() has changed -- the only change is that the
generic code is calling it more predictably now. However, a few
ports may accidentally have omitted an os_term() implementation from
some executables, since it wasn't always needed before; if you get a
link error for this symbol during building, adjust your makefile to
include an os_term() implementation.
* A new file, oem.c, defines some global strings for use in identifying
the version of TADS. You must fill in that file with a couple of
customized settings for your version. Please refer to oem.h and
oem.c for details on how to do this.
* A few new OS interface functions have been added. These functions
are described in comments in osifc.h. The new functions are:
os_get_sys_clock_ms()
os_sleep_ms()
os_get_event()
os_set_title()
osfdel_temp()
These functions should be reasonably simple to implement on most
systems. os_get_event() in particular can simply degrade to
os_getc() with some additional argument checks and changes in the
return value if it's hard to implement fully on your system; the
USE_STDIO version in osgen.c can be used as a default implementation.
Note also that a completely portable implementation of os_sleep_ms()
is in msdos/oswin.c. You can use this implementation if you wish,
but the function is included in the OS interface so that you can
replace it with something more suitable for your platform. The
implementation in msdos/oswin.c discards keystrokes and other events
that occur during the delay, which may be undesirable on your system.
This implementation has the desirable effect of processing UI events,
such as window sizing, during the delay.
Most platforms can provide an empty implementation of os_set_title();
this function merely notifies the OS layer that the game has set a
title string via the HTML <title> tag. If it's convenient, the OS
layer can use the title string as a window caption, or whatever else
makes sense. Most character-mode display code will simply ignore
this; osgen.c has a default implementation that does nothing.
osfdel_temp() is a new function to complement os_create_tempfile().
This function deletes a temporary file previously created with
os_create_tempfile(), after the temporary file has been closed;
callers previously used osfdel(), the generic file deletion function,
to delete these temporary files. The purpose of this new function is
to support systems that can be instructed to delete temporary files
automatically when closed; on such systems, a call to osfdel() is
redundant (and problematic), since the system will already have
automatically deleted the temporary file by the time the caller gets
around to invoking osfdel().
osnoui.c provides a simple implementation of osfdel_temp() that simply
calls osfdel(); this works with the implementation of os_create_tempfile()
in osnoui.c, so you won't need to make any changes if you're already
using this file. If you're using a customized os_create_tempfile(),
you may want to provide a correspondingly customized osfdel_temp().
In particular, if your os_create_tempfile() opens the file in such a
way that the underlying OS will automatically delete the file when
closed, your osfdel_temp() should simply do nothing.
* The os_askfile() interface (defined in osifc.h) has been changed to
provide more information about what kind of prompt to use. The extra
parameters indicate whether we're opening an existing file or saving
a new file, and what type of file we're interested in. Many GUI
systems use different dialogs for opening and saving files, and
filter files displayed in a file selector dialog according to the
type of file to be chosen. Systems that don't need the extra
information can ignore the new parameters; they're purely to make it
easier for the system code to determine what type of dialog to show.
I've updated my copies of the MSDOS, Win32, Mac, and Unix sources for
the new os_askfile interface, but I don't have a copy of every
port-specific version, so you may need to propagate this change into
your version.
* The #define's for the OSFTxxx codes (the file type codes) are now
in osifc.h. In the past, these were scattered among the different
system-specific headers for no good reason -- these are used by
portable code, so they are necessarily part of the OS interface, and
hence belong in osifc.h. If you encounter any errors with redundant
#define's for these symbols, you should simply remove the #define's
from your system-specific headers and use the ones in osifc.h.
* The #define's for the CMD_xxx codes (the os_getc() extended keystroke
codes) are now in osifc.h. In the past, as with the OSFTxxx codes,
these were scattered among the system-specific headers. It's desirable
to be able to use these key codes in the portable code, so these are
now part of the general OS interface. As with the OSFTxxx codes, if
you run into any compilation errors with redundant #define's for CMD_xxx
symbols, you should be able to remove the #define's from your system-
specific headers and use the new osifc.h definitions.
Version 2.2.6 changes
---------------------
In past versions, the release notes for generic changes and platform-
specific changes were combined into a single file, which had to be
maintained separately on each platform. For example, the DOS release
notes were in TADSVER.DOS. To create a comprehensive set of release
notes for another platform, someone porting TADS had to sift through
TADSVER.DOS to pick out the generic changes, then add any changes
specific to the ported version.
In order to remove this extra work, I've broken up the release notes
into two separate files. The new file TADSVER.TXT contains only the
generic changes. Since these changes will automatically be included
in any port (because such changes are always in the portable portion
of the code), the distribution for a port should always be able to
include TADSVER.TXT unchanged. The separate new file TADSVER.DOS
contains changes that apply only to the DOS version. Since such
changes are only in the DOS osxxx code, they should not affect any
other platforms, so only DOS users should need to look at this file.
When creating a ported version, you can now simply create your own
platform-specific release notes file where you can describe any changes
that you made that apply only to your platform.
Please let me know ([email protected]) the name of your port-specific
release notes file, and I'll add it to the table at the top of
TADSVER.TXT, which refers users to the appropriate file for each
platform. (You may want to add an entry to the table yourself for
your initial version, if you plan to include TADSVER.TXT with your
distribution.)
Version 2.2.4 changes
---------------------
I've changed the source distribution zip file's layout slightly to
make the TADS source tree more self-contained. In the previous
version, several files were in a separate LIB directory, which was at
the same level in the hierarchy as the TADS2 directory. This was an
undesirable layout for some people, since it meant that TADS had two
high-level directories. Since keeping the files in a separate
directory doesn't serve any real purpose currently (the separation is
historical), I've merged these files into the base TADS directory
(except that a few of the files are now in TADS/MSDOS, because
they're DOS-specific). Of course, you can still lay out your source
files however you want them, of course, but if you follow the layout
in the zip file, you'll need to adjust your makefile for the changed
location of these files.
If you change the default memory sizes in your osXXX.h file, you should
also define message strings that correspond to your new defaults for the
usage messages. To do this, look at errmsg.c, and notice the big list
of TxD_xxxSIZ_MSG definitions. For each value that you override in your
OS header, you should provide a corresponding TxD_xxxSIZ_MSG definition
that looks like the one in errmsg.c but uses your changed default value.
Version 2.2.3 changes
---------------------
The operating system interfaces have changed somewhat between version
2.2.2 and 2.2.3 (the HTML TADS release). The OS interfaces have been
stable for a long time, so most systems where TADS has been ported
should have OS-dependent implementations that conform to the 2.2.2
interfaces. Unfortunately, all of these ports will have to be reworked
slightly to accomodate the changes in 2.2.3.
The changes in 2.2.3 should be fairly minor, though, so it shouldn't
require a huge effort to upgrade port-specific code that worked with
the previous version. The main changes are that the OS interfaces
have been rearranged slightly in the header files (note in particular
the creation of osifc.h), and some of the functions that were in
osgen.c have been moved to the new file osnoui.c. A few functions
have had minor changes to their interfaces as well. It will probably
be necessary to make some small changes to your makefiles because of
the rearrangements.
One of the biggest changes may be the use of ANSI-style function
prototypes throughout the code. Depending on your compiler, you may
or may not have to change your OS function implementations to use ANSI
prototypes.
==============================================================================
General notes on porting TADS
-----------------------------
Code Organization
-----------------
The TADS code is divided into portable and system-specific sections.
In porting TADS to a new platform, only the system-specific portions
should need to be changed. If any changes are needed to the portable
code, we consider the portable code in error and will try to correct
it so that it is the same on all platforms. We want the portable
portion to have a single set of sources, without port-dependent
ifdefs, across all platforms.
For the most part, the system-specific sections are isolated in
files with the prefix "os", and system-specific functions and macros
all begin with "os" or "OS".
Historical note: At one point we started to group some code that High
Energy was internally sharing between multiple products into a code
library, all of whose files start with "L". The file los.h formerly
many system-specific macros and definitions; these have been moved
into the OS files along with everything else.
oem.h
-----
This file defines information about the person who built a particular
version ("OEM" for "Original Equipment Manufacturer"). Refer to oem.h
for details about how to set up the definitions there.
osxxx.h, os.h, and osifc.h
--------------------------
The first thing to do when starting a new port is to create a new
system-specific header file for your platform. You should choose a
name for the header based on your platform name; for example, on DOS,
the file is osdos.h, and on Unix it's osunix.h.
Next, you must define a C preprocessor macro that will identify your
platform. This macro will be used to select the appropriate code to
include in your version of TADS, using #ifdef preprocessor directives
in the TADS code. Many compilers automatically pre-define a symbol
for this purpose, in which case you should use this symbol;
otherwise, make up a symbol of your own and define it on the C
compiler command line or equivalent when you compile the TADS C files.
Edit the file os.h. This is a "switchboard" file that selects an
appropriate system-specific header to include. The TADS portable C
files #include os.h, and os.h must in turn #include your header file.
You should add a few lines to os.h to #include your header; follow
the example of DOS, Unix, and the other platforms:
#ifdef FROBNIX_OS
/* Frobnix operating system definitions are in osfrob.h */
#include "osfrob.h"
#endif
You shouldn't add anything else to os.h - the rest of your code should
go in your own "osfrob.h" file.
Now you must write the code in your OS-specific header ("osfrob.h" in
the example above). To do this, refer to osifc.h, which defines the
TADS Operating System Interface, which is what you must implement for
your machine.
The purpose of your osxxx.h is to isolate certain platform-specific
definitions to a well-defined location in the code. The rest of the
TADS C code is written so that it uses the definitions in osxxx.h;
this way, the other code doesn't have to be changed when moving TADS
to a new platform.
The file osifc.h contains the specification and documentation of the
TADS Operating System Interface, which contains the portable
interface definitions for functions, types, and macros that must be
tailored to each platform. osifc.h contains a portable interface to
code that varies by platform; because the interface is portable, the
rest of the TADS code doesn't have to know anything about different
platforms, since it can expect the exact same functions to be
available on every machine. osifc.h contains only portable code, so
you shouldn't make any changes in this file.
You can probably take one of the existing osxxx.h implementations as
a starting point, depending on your hardware and operating system.
For example, for a 68000 or 68000-like processor, you might want to
start with the Macintosh header (osmac.h), since the alignment and
byte ordering macros will be appropriate. For an 8086-like
processor, start with the DOS headers (os.h and los.h). Other
platforms may need additional work.
IMPORTANT NOTE: Do not make changes in osifc.h - this file should never
contain any #ifdef's for different platforms, because it defines a
portable interface that is the same everywhere, even though the
implementation of the interface varies by platform. In particular,
the #define constants (OS_EVT_xxx, SYSINFO_xxx, and so on) MUST be the
same on all platforms, because some of these values can be used
programmatically by TADS games; a game can be compiled on one platform
and run on any other machine, so these constant values must be the same
everywhere for games to work properly.
Datatype configuration
----------------------
TADS makes relatively few assumptions about datatype sizes. TADS
expects that shorts are at least 16 bits, ints are at least 16 bits,
and longs are at least 32 bits.
System-specific function implementation
---------------------------------------
Depending on your platform, you may be able to re-use some code that
was originally written for the DOS platform, but works with some
minor changes on other types of machines as well.
The files osdos.c, osgen.c, and osnoui.c provide an implementation of
the system routines for DOS. osgen.c and osnoui.c should be usable
on any system with DOS-like display characteristics. Note osgen.c
and osdos.c check to see if several USE_xxx preprocessor symbols are