V9938 Video Data Processor
Officially called the MSX-Video Data Processor V9938, this video chip is one of the main advantages of the Geneve 9640. The name already suggests that this VDP is typically used in MSX computer systems.
The V9938 was built with downward compatibility in mind; the first 8 video registers are used in the same way as those in the TMS9928. It fully implements the TMS9928 modes and some more in addition.
The Text 2 mode is a 80 char/line mode which allows for marking positions as "blinking" with a selectable blink rate, including 0. In that case, the locations are highlighted. You can set a foreground and background color for all of the marked positions on the screen, thus allowing for 2 foreground and 2 background colors.
Graphic 7 mode is the only mode without palette colors. In this mode, pixels are shown in a color composed of GGGRRRBB, that is, with the first three bits representing the green component, the next three bits standing for red, and the right two ones for blue.
|Mode||Description||Positions||Sprite mode||Colors||Corresponding TMS9928 mode|
|Text 1||Text-only mode||40x24||-||2 of 512||Text|
|Text 2||Text-only mode with blinking||80x25||-||4 of 512||-|
|Multicolor||4x4 block color graphics||64x48||1||16 of 512||Multicolor|
|Graphic 1||Character-oriented graphics||32x24||1||16 of 512||Graphics|
|Graphic 2||Character-oriented graphics, full screen||32x24||1||16 of 512||Bitmap|
|Graphic 3||Character-oriented graphics, full screen||32x24||2||16 of 512||-|
|Graphic 4||Pixel-oriented bitmap mode, 16 colors||256x192 (212)||2||16 of 512||-|
|Graphic 5||Pixel-oriented bitmap mode, 4 colors||512x192 (212)||2||4 of 512||-|
|Graphic 6||Pixel-oriented bitmap mode, 16 colors||512x192 (212)||2||16 of 512||-|
|Graphic 7||Pixel-oriented bitmap mode, 256 colors||256x192 (212)||2||256||-|
Mouse and Lightpen support
I wrote a couple of benchmark programs that run in native mode and use the clock chip for measuring the command execution times. The commands are repeated many thousand times so that in the end, an execution time in the range of several seconds up to minutes is measured; dividing by the iteration count and considering setup times, we get a good estimation of the single execution time.
This information is particularly important when using the VDP commands in time-critical situations, for instance, in games.
The times for the line operation vary, depending on the angle. Horizontal and vertical lines are fastest, while 45° diagonal lines are slowest. (This is a bit surprising, since on a raster screen, a line always consists of max(dx,dy) pixels.)
Tests showed that painting a rectangle is faster when there are fewer lines: 30 pixels wide, 60 pixels high is slower than 60 wide and 30 high (about 166 µs).
Graphic 7 mode
|Command||Description||Specifics||Setup [µs]||µs per pixel||Pixels per sec|
|HMMC||Write bytes into rectangle||Fast||133||39||25640|
|LMMC||Write bytes into rectangle||Logical||133||39||25640|
|HMMV||Fill rectangle with one color||Fast||37||2.9||344828|
|LMMV||Fill rectangle with one color||Logical||37||6.1||163934|
|HMMM||Copy rectangle content||Fast||100||5.875||170213|
|YMMM||Copy rectangle content, Y only||Very fast||100||5.125||195122|
|LMMM||Copy rectangle content||Logical||100||8.375||119403|
The setup time is a fixed time, independent of the amount of modified pixels on the screen. Maybe it is caused by internal calculations of the VDP, or by some trailing delay. You have to add some more time for your program to set the video registers; this is typically another 100 µs.
Graphic 6 mode
The high-speed operations like HMMV perform at double speed. The reason is that two pixels are processed in a single command invocation. Logical operations only operate on single pixels and thus run at the same speed as in graphic 7.
The following calculations all refer to graphic 7 mode, and we leave away all setup times. Thus, the required times are lower bounds; it will take longer to perform the action. Also, we assume 192 lines; the V9938 is able to expand this to 212 lines.
- We'd like to paint the whole screen: There are 192 rows and 256 columns, which means 49152 pixels. Using the HMMV command, we see that this takes t = 2.9 µs * 49152 = 142541 µs = 0.14 secs. Doing that repeatedly, we will achieve less than 8 frames per second.
- Instead of filling a rectangle, we can draw lines in subsequent rows. If we want to fill the screen, we have 192 lines with a length of 256 pixels. Each line takes about 1587 µs, hence, it takes 0.3 secs to fill the screen. (Exactly 0.343 secs, as a sample program proved.)
- Suppose we want to shift the upper half of the screen down by one row. The upper half takes up 24576 pixels; moving the contents with the fastest YMMM command takes 125952 µs = 0.126 secs, again, just 8 frames per second.
- We'd like to print a text on the graphics screen. Each character consists of 8x8 = 64 pixels. Using the HMMC command, printing a single character takes about 2500 µs, so we get 400 characters/second. Since 768 characters fit on the screen, it takes almost 2 seconds to fill the screen with characters.
- Alternatively, we could store the glyphs of the characters in a non-visible screen area, again, as 8x8 pixels rectangles and then just copy the glyph to the desired screen position. This can be done with the HMMM command. One character takes 376 µs, this means 2660 characters per second.
If we think about serious game programming, 8 frames per second is pretty disappointing. The line command is certainly useful, and also painting into the rectangles, but mass transfer should be avoided.