osViGetStatus.3p
11.5 KB
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
.TH osVi 3P local "Silicon Graphics, Inc."
.SH NAME
.upperok
osViGetStatus, osViGetCurrentMode, osViGetCurrentLine, osViGetCurrentField,
osViGetCurrentFramebuffer, osViGetNextFramebuffer, osViSetMode, osViSetEvent,
osViSetSpecialFeatures, osViSetXScale, osViSetYScale, osViSwapBuffer,
osViBlack, osViFade, osViRepeatLine,
osCreateViManager \- management functions for the video interface (VI)
.SH SYNOPSIS
.nf
\f3
.Op c
#include <ultra64.h>
.sp .8v
u32 osViGetStatus(void);
.sp .8v
u32 osViGetCurrentMode(void);
.sp .8v
u32 osViGetCurrentLine(void);
.sp .8v
u32 osViGetCurrentField(void);
.sp .8v
void *osViGetCurrentFramebuffer(void);
.sp .8v
void *osViGetNextFramebuffer(void);
.sp .8v
void osViSetMode(OSViMode *mode);
.sp .8v
void osViSetEvent(OSMesgQueue \(**mq, OSMesg msg, u32 retraceCount);
.sp .8v
void osViSetSpecialFeatures(u32 func);
.sp .8v
void osViSetXScale(f32 xscale);
.sp .8v
void osViSetYScale(f32 yscale);
.sp .8v
void osViSwapBuffer(void \(**vaddr);
.sp .8v
void osViBlack(u8 active);
.sp .8v
void osViFade(u8 active, u16 factor);
.sp .8v
void osViRepeatLine(u8 active);
.sp .8v
void osCreateViManager(OSPri pri);
.Op
\f1
.fi
.SH DESCRIPTION
The video interface (VI) is responsible for displaying the RDP-rendered image
in different video modes. Currently, VI supports 42 video display modes: 14 for
NTSC, 14 for PAL, and 14 for MPAL. Each mode contains different
settings to handle attributes such as interlaced and non-interlaced, 16-bit and
32-bit color pixel, and low and high resolution. Furthermore, a mode can be
configured to rescale the image to sacrifice resolution for rendering speed.
.PP
These modes supported can be represented by 5 switches: high/low
resolution, 16-/32- bit color pixel, antialiased/point-sampled, filtered/not
filtered, and NTSC/PAL/MPAL format. There are symbolic names defined for these
modes in <os.h>. For example, OS_VI_NTSC_LPN1 represents a NTSC mode supports
low resolution, point sampled, non-interlaced, and 16-bit color pixel.
Similarly, OS_VI_PAL_LPN1 refers to the same mode but in PAL format. The last
four characters (i.e. LPN1) in the symbol name is constructed using the
following codes for each character position:
.PP
.nf
.ta 6 20
1st position = high resolution (H) / low resolution (L)
2nd position = antialiasing (A) / point-sampled (P)
3rd position = for low res: non-interlace (N) /
interlace (F)
for high res: normal-interlace (N) /
deflickered interlace (F)
4th position = 16-bit pixel size (1) / 32-bit pixel size (2)
.fi
.PP
With the above codes, the following 14 modes are supported for NTSC as well
as for PAL and MPAL: LPN1, LPF1, LAN1, LAF1, LPN2, LPF2, LAN2, LAF2, HPN1,
HPF1, HAN1, HAF1, HPN2, and HPF2.
.PP
In low resolution (320 pixels by 240 lines), there is a choice between
non-interlaced and interlaced mode.
Non-interlaced mode repeats the same frame each field.
Interlaced mode interpolates between adjacent lines,
weighted 75% of the line above plus 25% of the line below in the first field,
then weighted 25% of the line above plus 75% of the line below in the
second field. Note that there will be no flicker, since there are no
high spatial frequencies.
.PP
In high resolution (640 pixels by 480 lines), there is a choice between normal
interlace and deflickered interlace. Normal interlace uses just the
data rendered in one field to display that field. This mode can use
one high resolution frame buffer without additional double buffering, since one
field can be displayed while the next is being rendered without
stepping on each other. However, any single pixel with high detail will
flicker, since it will only be displayed in one field. Deflickered
interlace averages adjacent lines to filter out the high frequency
vertical detail, but at the cost of requiring double buffering of the
entire high resolution frame, since both rendered fields are used to display
each field.
.PP
Currently, there exists a global VI mode table
.I osViModeTable
that contains register settings for these 42 modes.
.I osViSetMode
is used to register one of these modes with VI to be used at the next vertical
retrace. This function simply overwrites all the VI registers with data from
.I mode,
a pointer into
.I osViModeTable.
All previous settings (such as XY scaling and gamma correction) are
reset. To register the NTSC, low resolution, antialiased, non-interlaced,
16-bit mode with VI, one can issue
.PP
.nf
.ta 5 30
osViSetMode(&osViModeTable[OS_VI_NTSC_LAN1]);
.fi
.PP
Furthermore, for storage efficiency, the global VI mode table is divided
into 42 separate mode structures, where each structure is globally defined in
a separate source file. These structures are externally declared in <os.h>.
To access the equivalent mode mentioned above, one can call
.PP
.nf
.ta 5 30
osViSetMode(&osViModeNtscLan1);
.fi
.PP
.I osViGetCurrentMode
can be called to return the current VI mode that is being used.
.PP
After setting the display mode, application should call
.I osViSetEvent
to register a message queue
.I mq
and a message
.I m
with the VI manager. This allows the program to receive notification message
.I m
at the message queue
.I mq
from VI manager when a vertical retrace occurs.
Setting
.I retraceCount
to a value higher than 1 (i.e. 2) decreases the frequency that the
application receives the vertical retrace notification, allowing it to run at a
slower speed such as 30 Hz instead of 60 Hz.
.PP
The VI manager is a system thread that must be invoked at the beginning of
the application by calling
.I osCreateViManager
with priority
.I pri
at which it will run. Usually, this priority should be at OS_PRIORITY_VIMGR
which is defined in <os.h>. The VI manager is designed to service both the
VI interrupt (OS_EVENT_VI) and CPU counter interrupt (OS_EVENT_COUNTER)
in the most efficient manner. The counter interrupt is used by the timer
manager.
.PP
Once the display mode and message queue have been registered with the VI
manager, application needs to call
.I osViSwapBuffer
to register the frame buffer
.I frameBufPtr
to be displayed at the next vertical retrace interrupt.
.PP
When the Nintendo64 powers on, the boot code sets the timing to NTSC, PAL, or
MPAL and blanks the video. The call to osCreateViManager() initializes the
video to LAN1 (in either NTSC, PAL, or MPAL mode) and also blanks the video.
The first time video is enabled is when osViSetMode() is called. To keep the
screen blank until after the first osViSwapBuffer(), call osViBlack(TRUE)
immediately after the osViSetMode(). Then call osViBlack(FALSE) right before
the first call to osViSwapBuffer().
.PP
.I osViSetXScale
allows scaling the image up horizontally (in the X direction) to the required
display format from a reduced number of rendered pixels per line.
.I value
specifies the scaling factor and can range from 0.25 to 1.0. Similarly,
.I osViSetYScale
allows scaling the image up vertically (in the Y direction) to the required
display format from a reduced number of rendered lines per frame. Y-scaling
is recommended to be used only in low resolution and non-interlaced modes such
as LAN1, LAN2, LPN1, and LPN2.
.I value
specifies the scaling factor and can range from 0.05 to 1.0.
.PP
.I osViSetSpecialFeatures
allows the caller to enable/disable various VI special features such as
GAMMA, GAMMA_DITHER, DIVOT, and DITHER_FILTER. There are symbolic
.I func
names defined in <os.h> including OS_VI_GAMMA_ON, OS_VI_GAMMA_OFF,
OS_VI_GAMMA_DITHER_ON, OS_VI_GAMMA_DITHER_OFF, OS_VI_DIVOT_ON, OS_VI_DIVOT_OFF,
OS_VI_DITHER_FILTER_ON, and OS_VI_DITHER_FILTER_OFF. These names can
be ORed together to enable or disable specific features.
Note that some
of these settings only make sense in certain video modes. For example
Gamma Dithering will only happen if Gamma Correction is enabled, and
Divot Removal will only occur in an anti-aliased video mode. Divot is a special
operation that can be (optionally) performed on the antialiased pixels to
filter out the "divots" (one pixel notches) artifacts when multiple
silhouettes overlap on a pixel. Note that this filter is not used in regions
of full coverage, so high spatial frequency textures within a surface will
not be disturbed.
.PP
.I osViGetStatus
simply returns the value of the video interface status/control register.
The unsigned 32-bit returned value contains various bit patterns that are
defined in <rcp.h>. Some of these patterns include
.PP
.nf
.ta 5 30
VI_CTRL_TYPE_16 - 16-bit pixel size
VI_CTRL_TYPE_32 - 32-bit pixel size
VI_CTRL_GAMMA_DITHER_ON - gamma_dither mode is enabled
VI_CTRL_GAMMA_ON - gamma correction is enabled
VI_CTRL_DIVOT_ON - divot mode is enabled
VI_CTRL_SERRATE_ON - serrate mode is enabled
VI_CTRL_DITHER_FILTER_ON - dither filter mode is enabled
.fi
.PP
These bit patterns can be masked (ANDed) against the returned value to interpret
the video interface status. Serrate mode mentioned above is a special feature
of true NTSC that provides a twice line frequency narrow sync pulse during
vertical sync. This feature helps ancient analog amplifiers to stabilize
vertical retrace phase lock loop. Apparently, there are some very high-end TVs
that can differentiate between true interlaced and low resolution
non-interlaced mode by the presence or absence of these serration pulses.
The global VI mode table is initialized to have serrate mode enabled
in all interlaced modes and disabled in all low resolution non-interlaced
modes.
.PP
.I osViGetCurrentLine
returns the current half line, sampled once per line. The least significant bit
(lsb) of this value is constant within a field in non-interlaced modes but
toggles to give the field number (0 or 1) in interlaced modes.
.PP
.I osViGetCurrentField
returns the field number (either 0 or 1) currently being accessed by VI.
.PP
.I osViGetCurrentFramebuffer
simply returns an opaque pointer to the currently displayed framebuffer.
.I osViGetNextFramebuffer
returns an opaque pointer to the next framebuffer to be displayed.
.PP
Based on the
.I active
flag setting, which can be TRUE (enabled, screen black) or FALSE (disabled),
.I osViBlack
can black out the screen and still generates vertical retrace signals.
.I osViBlack
can only be used when the YScale factor for the video mode is 1.0.
Using the feature for YScale factors which are not 1.0 will create the
potential for the video interface to malfunction and enter a state which
cannot be exited without reseting the system.
In low-resolution, point-sampled, and non-interlaced modes (such as LPN1 and
LPN2), one can use the 10-bit fractional interpolation
.I factor
in
.I osViFade
to fade between the first 2 scan lines of the frame buffer.
In addition,
.I osViRepeatLine
can be used to repeat the first scan line of the frame buffer for the entire
frame.
.SH NOTES
The VI manager must be started at the beginning of the program so that vertical
retrace interrupt can be serviced as quickly as possible. Note that
.I osViSetMode
resets all current settings such X-Y scaling and special features (i.e.
gamma) to the default values defined in the global mode table.
.PP
The video back-end filter can only execute an antialiasing filter or a dither
filter, but not both simultaneously. This is especially visible on "billboard"
cutouts in texture edge mode during magnification in the region of the
cutout where alpha goes from 1 to 0. In this region, the dither pattern is
visible since the back-end filter executes an antialias filter (due to
partial coverage) and turns off the dither filter.
.PP
This problem also occurs on antialiased silhouette edges of polygons, but
is not obvious due to the small width of the partially covered region.
.SH "SEE ALSO"
.IR osSetEvent (3P),
.IR osGetTime (3P)