Graphics programming.
Normally, when you need a good and reliable graphics package, you go for SVGAlib. It's stable, fast and
reasonably universal. But, svgalib was written for and in C. And I kind of don't like C. To put it mildly.
I'm not saying that C is a bad programming language. It's just not my kind of language since it gives too much
freedom and almost no protection.
That's why I want to use Modula-2 in combination with the SVGAlib libraries. And Modula-2 offers a construct to do just that: the FOREIGN MODULE. There's an example of a foreign module in the IOport section.
Sources for the FOREIGN MODULEs.
Below are the source files that make up the current 'Vga MODULE'. The first part is in C, the second is the 'DEFINITION MODULE'.
#include <vga.h>
int Initialize (void)
{
if ( vga_init () == 0 )
return 1;
else
return 0;
}
void SetMode (int newmode)
{
vga_setmode (newmode);
}
int GetMode (void)
{
return vga_getcurrentmode ();
}
int MaxWidth (void)
{
return vga_getxdim ();
}
int MaxHeight (void)
{
return vga_getydim ();
}
void Clear (void)
{
vga_clear ();
}
void SetColour (int colour)
{
vga_setcolor (colour);
}
void SetEGAcolour (int colour)
{
vga_setegacolor (colour);
}
void SetRGB (int red, int green, int blue)
{
vga_setrgbcolor (red, green, blue);
}
void DrawLine (int x0, int y0, int dx, int dy)
{
vga_drawline (x0, y0, x0 + dx, y0 + dy);
}
void Plot (int x, int y)
{
vga_drawpixel (x, y);
}
int ThisColour (int x, int y)
{
return vga_getpixel (x, y);
}
void GetKey (char *ch)
{
*ch = vga_getkey ();
}
These functions are SMALL and all they do is make an interface for Modula-2 to hook itself on. We also get the
chance to rename the functions or even change the order and nature of the arguments. As you undoubtedly have
seen... :o)
What follows is the source of the 'DEFINITION MODULE', although it is now called a 'FOREIGN MODULE' to indicate that the 'IMPLEMENTATION' section is -not- in Modula-2.
FOREIGN MODULE Vga; TYPE EGAcolour = (black, blue, green, cyan, red, pink, brown, white, GREY, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE); PROCEDURE Initialize () : BOOLEAN; PROCEDURE MaxWidth () : CARDINAL; PROCEDURE MaxHeight () : CARDINAL; PROCEDURE Clear; PROCEDURE SetColour (colour : CARDINAL); PROCEDURE SetEGAcolour (colour : CARDINAL); PROCEDURE SetRGB (red, green, blue : CARDINAL); PROCEDURE DrawLine (x0, y0, dx, dy : CARDINAL); PROCEDURE Plot (x, y : CARDINAL); PROCEDURE ThisColour (x, y : CARDINAL) : CARDINAL; PROCEDURE SetMode (newmode : CARDINAL); PROCEDURE GetMode () : CARDINAL; PROCEDURE GetKey (VAR ch : CHAR); END Vga.
Changes to the Mocka compiler
Below, I list the changes to the respective scripts such that Mocka will incorporate the right modules in the linking phase. You need to change just two script files. Remember to do this as 'root' user, otherwise the scripts might not run anymore.
First locate the files 'MC' and '???/sys/link' using the 'locate' command. Switch to the directory that contains the 'MC' script. Then issue the command:
bash-2.05# cp MC GMC
Edit the file as described below. You only need to add ONE token to GMC.
File : /usr/local/bin/MC
Change the line reading
LINK=${MCLINK-$MOCKADIR/sys/link}
into
LINK=${MCLINK-$MOCKADIR/sys/glink}
Now that we have changed the Integrated Development Environment (IDE) such that another linker mechanism has
been chosen, we also need to appropriately instruct the linker. That's done in the file in 'sys/glink'.
But first you need to create that file. Locate the file using something similar to:
bash-2.05# locate /sys/link
/usr/local/mocka/sys/link
Now create the file 'glink' as follows:
bash-2.05# cp link glink
You only need to change the bottom line of that file to something similar to:
$LD -o $program -lvga $STAT $PRE $RTS $modules $LIB $POST
Rounding up
Well, that's it. If you want to write executables that use SVGAlib graphics in them, just start the Mocka compiler using 'GMC' and do your thing. Don't forget that SVGAlib programs must be SUID root before they can run since there are some special instructions in the Initialize section of SVGAlib. To do that, change to user root and do as follows:
bash-2.05# chown root:root [filename]
bash-2.05# chmod 4755 [filename]
This should do the trick.
The current contents of the VGA module is just for testing. If you have ideas for additions or omissions, don't hesitate to implement them. Please report your problems and progress on
A pleasant side effect.
While running some tests to try out graphic mode, I found a strange but pleasant side effect of using the SVGAlib library. Look at the following source and visualize what will happen:
MODULE ttt;
FROM InOut IMPORT Read, Write, WriteLn;
VAR ch : CHAR;
BEGIN
LOOP
Read (ch);
IF ch = 'X' THEN EXIT END
END;
Write (ch);
WriteLn;
END ttt.
Not too difficult, I think. The program enters an infinite loop and it gets out of it if the 'X' (capital 'x')
is pressed. But since Unix runs with buffered I/O, you can enter what you like, nothing will happen before you
have pressed the Enter key.
Enter the following source:
MODULE svg01;
FROM InOut IMPORT Read, Write, WriteBf, WriteString;
IMPORT Vga;
VAR OldMode, x, y : CARDINAL;
ch : CHAR;
BEGIN
IF Vga.Initialize () = FALSE THEN
WriteString ('Could not start SVGAlib libraries. Aborting...');
WriteBf;
HALT
END;
OldMode := Vga.GetMode ();
Vga.SetMode (4);
Vga.SetColour (14);
Vga.Clear ();
Vga.SetColour (10);
FOR y := 125 TO 175 DO
FOR x := 100 TO 500 DO
Vga.Plot (x, y)
END
END;
LOOP
Read (ch);
IF ch = 'X' THEN EXIT END
END;
Vga.SetMode (OldMode);
Write (ch);
WriteBf;
END svg01.
This program does a bit more. It initializes the SVGAlib functions and it paints a nice geometrical shape on
the screen. It was nice to see how fast it worked. And it proves the power of Mocka as a Modula-2 compiler.
The 'FOREIGN MODULES' are very powerful.
But now compile and run this program (with the GMC script). What do you think will happen after the shape is drawn on screen?
I'll tell you: the 'Read' function suddenly doesn't need an Enter key to access the keys you type! Apparently,
'Read' suddenly reads from an -unbuffered- inputstream!
Just try it. Run the program and touch some keys. Nothing happens, as usual. But as soon as you hit the
capital 'X', the program jumps out of its loop and resumes execution.
This opens up a lot of opportunities. Now we won't need the SVGA 'raw' keyboard functions anymore. Cooked will do just as well for us!
Page created 2004,
Page equipped with GoogleBuster technology