Pages

Saturday, July 30, 2011

Ethernet with r8101 module and RealTek 8101E in Linux with a HP 2000 219dx

HP has at least two laptop models that use the RealTek 8101E Fast Ethernet for their ports. One is the "g4 1117dx," and another is the "2000 219dx." 

On a Dell mini 9 running Ubuntu 11.04 (2.6.38-10-generic), the r8169 module works out-of-the-box when an ethernet cable is plugged in. This is not the case with either HP laptop, even though r8169.c mentions the 8101 model. 

It has been discussed elsewhere that ethernet devices using the r8169 module may be disabled in Windows after a reboot. Enabling "Wake on LAN," removing the battery and power supply, and waiting for some time allows the hardware to work in Linux. While I did not try the suggested solution with the former HP model, it did not work with the latter. 

As for wireless, it would have likely been easier to set up. While neither HP laptop works out-of-the-box with wireless in Ubuntu 11.04, using an external adapter and running software update enables the internal wireless on both machines.

With the LFS LiveCD, it's a toss-up: wireless or wired? I wanted to save the adapter for another day, so ethernet it is.

I used a HOWTO on the Debian forums leading me to this driver, and copied the tarball to an external flash drive. Mount the drive from LFS LiveCD and copy it to a convenient location like $LFS/opt.

Make sure you have partition(s) on the hard drive set up before mounting the external. You'll be producing files during extraction and compilation, so you'll need a place to put them. The CD-R has already been written with the LiveCD OS; it can't be written to twice. 

Here's the order of commands I used:

$ mkdir -v /mnt/usb
$ mount -v -t ext3 /dev/sdb1 /mnt/usb
$ cp -v /mnt/usb/r8101-driver.tar.gz $LFS/usr/src && cd $LFS/opt
$ tar xjf r8101-driver.tar.gz
$ cd r8101-driver.tar.gz/

The LFS LiveCD uses kernel 2.6.22.5, while the current kernel version is something like 3.0. Between 2.6.22.5 and 2.6.38, the symbol DMA_32BIT_MASK changed to DMA_BIT_MASK. You'll need to change all references to DMA_BIT_MASK(xx) to DMA_32BIT_MASK in ./src/r8101_n.c, about seven in all. Otherwise, while compilation succeeds, modprobe results in a "Undefined symbol" error. 

Now you're ready to run the included shell script:

$ ./autorun.sh

The script will remove the r8169 module that was detected earlier, rename it as a backup file, and load r8101. If you're successful, the ethernet port will glow white. :) Use lsmod to confirm that r8101 is loaded, and lsmod | grep r8169 to make sure the old one is not. 

Ping still won't detect a host, so 

$ ifconfig eth0 up
$ dhcpcd 

And you should be in business - that is, downloading the programs for LFS 6.8.


Thursday, March 24, 2011

Miniatures grid with PHP and MySQL

After reading "PHP & MySQL for Dummies," I created a miniatures grid for use via the browser:



This article covers general patterns and suggestions for further improvement. The code is certainly refactorable.

The strongest feature of PHP and MySQL is that it combines a server-side scripting language with a persistent data store. You can imagine the database as a global variable - and it might as well be, since it's as easily accessible as one. When to query the database is up to the programmer and his discipline.

Here is a general flowchart of a typical user case through the PHP files:



The two biggest parts of the grid project involve user interaction: logging in, and doing actions with the grid. Squares can be blackened to represent walls, and miniatures can be added or removed. The primary view is an HTML table that dispgrid.php spits out. Only minor adjustments are needed to accommodate adding or removing miniatures, and for editing squares:



Thanks to the database, I only have to worry about a small number of variables. That lets me collect and transfer data in two ways: through forms, and via session variables. I store database queries with an associative array, which is very useful in PHP: utterly convenient, as the code will show.

I control access to individual PHP files by testing whether a username session variable has been set. It is only set at the beginning with a successful login. In any other circumstance, kick the user back to the login page.


Session variable 'loggedin' is only set here if password matches the one from the database.

Every PHP file checks for this session variable at the beginning, and boots the user out if it is not set.

With PHP, I can generate dynamic content; in this case, an HTML table that populates relevant cells with information from the database. The foreach lets me iterate through the rows returned from a database query




With forms, session variables and a persistent store, "pseudo" multi-user interfaces like this grid can be simulated. Every refresh of the view is a new hit on the database, pulling in the most recent data. This works because the grid depends on the turn-based mechanic of these kinds of games.

Hopefully this code helps get you started on the path to web apps, or to clear some assumptions. The best thing to do is to jump in! :)



Go forth... and conquer.

Further Investigation
AJAX for automatic refresh
SVG and <canvas>
jQuery drag-and-drop with pathfinding
Refined user interface
Colored squares
Randomized dungeons
Faster painting than checkboxes
Additional tables in the database
Zend, or object-oriented PHP
Security

Code
PHP files (grid.zip) [MediaFire]
MySQL Database file [MediaFire]
Update August 2011: Old links died; uploaded as a folder. [MediaFire]
Update October 2011: Old link died. SQL file included. [MediaFire]

Reference
"PHP & MySQL for Dummies" [Amazon Affiliate Link]

Monday, February 14, 2011

Tandem sprite movement in Allegro 5

My friends and I worked on a flixel game called "Deaf Bastard," which featured a composer who moved notes. The player controlled two sprites simultaneously. Pressing left made one note move left, and made the other note move right. The former was called the "direct note," and the latter was called the "inverse note." Our last build here.



We hit a technical challenge early on, because flixel as-is checked for collisions after positions were updated. Both of the notes' positions were incremented even if one note collided against a wall. So you could bang the direct note repeatedly against the ceiling, and the inverse note would "creep" down. Without preservation of note positions, the game mechanics were inconsistent.

Compounding this difficulty was the seeming complexity of determining which note would collide against a wall first. Each note was independently updated. The distance traversed in each frame was hard to predict, and therefore hard to undo.

I never could figure it out, but with Allegro 5 I tried again.


This implementation uses two features to avoid creep and to maintain consistent note movement: states to permit a note's position to be updated (that is, to be moved), and events triggered by released keys.

During each iteration of the game loop, we first determine the direction of the note. If the note is moving down, it is affected by a positive velocity along the y-axis. We predict the note's future position by adding the note's (current) y-position and its speed. There is a collision if the note passes the floor boundary, designated by the #define symbol HEIGHT.


All of my drawing functions assume the sprite's position is at its center. In order to calculate boundaries, I have to add or subtract SPRITE_HEIGHT/2 or SPRITE_WIDTH/2 as needed.

If there is an imminent collision, we do some bookkeeping: zero the note's speed, and reset its position to be flush with the floor. We set the note's vertical state to DO_NOT_UPDATE_V, which denies permission to update position, at least in this loop (explained next). We also prevent the player from moving the note with the left or right key. Since this is a floor collision, the player can't move left or right until he releases the up key (explained in last code snippet). 


This is the crux of the matter: one note collided, which means the other note should not move. We use a state variable to control permission. In our final code snippet, we look at reenabling the player's left-right input if he releases the up key. This by the design of the mechanic: the player should not be able to move notes further if they collide against any wall.



We need the zerospeed() function call because the next iteration of the game loop leads directly back to the notes updating their positions. The player releases the up key, fine; but in the next frame the note's y-speed remains non-zero, therefore yspd > 0, therefore predy > HEIGHT, therefore lockedkeys = true. Perpetually so, which means the player is never able to move the notes left or right. You can see this for yourself by commenting out zerospeed() above and re-compiling.

Files
deaf.c
deaf.h

Compilation
gcc deaf.c -o deaf.out -L/usr/local/lib -lallegro -lallegro_main -lallegro_primitives


(This is assuming your shared libraries are in /usr/local/lib/ directory.)


Further Investigations
  • Does it work when notes are placed in different initial positions?
  • Implement checkpath().
  • Go back and do it in flixel.
Reference
Game Programming All-in-One, 3e by Jonathan Harbour [Amazon Affiliate Link]

Credits
Original flixel version: All of the architecture, design and initial coding was done by Josh Helpert, with co-design and graphics by dcb.

Update. Added a link to the swf file.
Update August 2011. Added Reference section and an Amazon affiliate link.

Saturday, January 15, 2011

TrueType fonts in Allegro 5 and Mac OS X

I tried the font tutorial, but couldn't run it due to a failed assertion. Despite linking against liballegro_font.dylib and liballegro_ttf.dylib with the linker flags -lallegro_font and -lallegro_ttf, and subsequent success in compilation, the executable immediately quits with an "Abort trap": 





While the tutorial uses a straight font name, on Mac OS X the font path must be fully specified. So if you want to use Arial, the string should be "/Library/Fonts/Arial.ttf". 






A lot prettier fonts than the default in Allegro 4.x. :)

Friday, January 14, 2011

Compiling Allegro 5 with Mac OS X Snow Leopard (10.6.6)

This tutorial takes you through building Allegro 5.0.0rc4 and compiling your first Allegro program. You will need the following:

The steps of the tutorial are as follows: 
  1. Extract Allegro source files, and install CMake.
  2. Use the CMake GUI to specify the Clang compiler, and to generate the makefile.
  3. Run make and make install at the command-line.
  4. Write and run your first Allegro 5 program.
Extract Allegro source and install CMake

  1. Open Terminal.
  2. cd ~/Downloads/
  3. tar xvzf allegro-5.0.0rc4.tar.gz
  4. cd allegro-5.0.0rc4.tar.gz
  5. mkdir Build
  6. cd Build
  7. Double-click on the cmake .dmg file and install CMake.
The cd command, change directory, takes you inside the Downloads/ folder. The command tar with the x option specifies an extraction operation. (tar can also list, add or create compressed files.) The additional options v, z, f specify the following, respectively: 
  • Show me what you're extracting.
  • z because it's a gzip file. Notice the filename has a .gz extension.
  • f because I'll supply you with the filename.
The Allegro README recommends building in a separate build directory, so we make the directory with mkdir. If you mess up during the build process, you just have to delete one folder; it's cleaner. We then go into the Build/ directory so that everything is built in this location. 

Installing CMake from a .dmg file should be self-explanatory.

Specify Clang as our compiler and generate the Makefile
  1. Launch the CMake application from your Applications folder. 
  2. In the Source field, enter /Users/your-login-name/Downloads/allegro-5.0.0rc4
  3. In the Build field, enter /Users/your-login-name/Downloads/allegro-5.0.0rc4/Build
  4. Click Generate - and when you do, a dialog like this should appear: 

If this dialog does not appear, make sure your Build/ directory is empty. This dialog needs to appear in order for you to specify Clang ("cee-lang") as your compiler of choice. It has to do with gcc being the default compiler and Snow Leopard being a 64-bit OS.

When this dialog appears, be sure to select "Specify native compilers." Clang comes with Snow Leopard; we just need to tell CMake that we will use Clang as our C compiler instead of the GNU C compiler. Click Continue. 

In the next dialog, in the C text field, enter the path to the clang tool: /Developer/usr/bin/clang


Click Done, and CMake should create nine files in the build directory. You can use ls to list them.


Make and make install

  1. Still in the Build/ directory, type sudo cmake .
  2. sudo make
  3. sudo make install
Alright, now take a look at the /usr/local/lib directory. Note the pattern of each filename:
  • lib
  • allegro or allegro_something
  • .dylib
Write and run your first Allegro program
  1. Create a text file alleg5test.c and enter this code listing.
  2. gcc alleg5test.c -o alleg5test -L/usr/local/lib -lallegro -lallegro_main
  3. ./alleg5test

You should get a window with a black background to show up. If you did, congratulations!

Check out the pattern of the flags: a -l ("dash-el") followed by allegro_. I guess all of them are the .dylib files from /usr/local/lib. Hmm.

You might be able to adjust this tutorial to work with Xcode, and then to create an Allegro template. (Hint: See my previous tutorial on Flixel.)

I hope this saves you some time. Go through the tutorials, and go make some games!

References

Updates

  • 1/15/2011: Removed -lz option from the long gcc above. That would have told the linker to look for a library named "z." Lol.
  • 1/15/2011: Much shorter gcc invocation. Originally gcc alleg5test.c -o alleg5test -lallegro -lallegro_font -lallegro_main -lallegro_primitives -lallegro_image -framework AppKit -framework OpenGL /usr/lib/libIOKit.dylib -framework Cocoa, but not all of these are needed (at least for our small program). Compare with Allegro 4.4, where you did gcc helloworld.c `allegro-config --libs`. The output of allegro-config 4.4.1 was -L/usr/local/lib -framework Cocoa -lalleg-main -lalleg. Similar, no? 
  • 1/15/2011: I can't compile the bitmap tutorial at the Allegro wiki. My error message is, "Undefined symbols: _al_set_clear_to_color." Strange. Oops, typo. gg. There's a al_clear_to_color() function; I was just practicing my speed typing.
  • 1/15/2011: Added an extra step, sudo cmake ., because there's no Makefile after CMake creates its nine files.
  • 1/22/2011: Took out the "-framework Cocoa" switch in gcc. Don't need it.
Now, if only there was a allegro-config that could do for Allegro 5 what it did for Allegro 4.4. (If you're up to it, write a program allegro5-config that outputs the appropriate arguments to gcc, place it in /usr/local/bin, and then try gcc alleg5test.c `allegro5-config [--libs]`. It might not even have to be a program, but just a shell script.)

Saturday, October 30, 2010

Passing code as a text stream into a program

A text stream is a line of text terminated by the newline character, '\n'. The standard library function getchar() retrieves one character at a time from the text stream. 


In the first chapter of Kernighan and Ritchie's The C Programming Language 2e, this function is used in programs of increasing complexity, from a character counter to a rudimentary syntax checker. 


Testing these programs in Xcode's Debugger Console can only be very limited. As soon as the user presses Enter, the text stream is happily processed, and the program expects additional input. But what if you want to test input spanning multiple lines?




In K&R C section 1.6, the first example program counts the frequency of different characters, like digits and blanks. Sample output is from "the program on itself." Near the end of the chapter, Exercise 1-23 asks to "write a program to remove all comments from a C program." There has to be some way to pre-populate the text stream, so that your program processes it to an EOF. 


Using cat, we can pipe the output of a file, such as main.c, to our program. Since we're using Xcode, the path to our project directory can be pretty long to type every time. Instead, we'll write an AppleScript script to tell Xcode to build the project, and to tell Terminal to activate and execute the cat pipe:





The script uses some parts from my previous AppleScript tutorial. Fortunately, all paths are POSIX formatted rather than aliases formatted as HFS paths.  


The one new thing is the use of quoted form, which lets me pass a directory with spaces, like /Programming Exercises/, without escaping the blanks.


With this script, the same program now processes a text stream all the way to EOF:



And the output:




I'm not sure how much use this will be beyond the first chapter, but now that I can pass text streams to EOF in my programs, I feel better about going through these exercises. Instead of one-liner "tests," I can pass whole files as representative input.


References

Sunday, October 24, 2010

Scrambling text for NaNoWriMo using AppleScript, Pages 09 and TextEdit

During National Novel Writing Month, or NaNoWriMo, people try to write a 50,000-word novel in thirty days. You can upload a text file of your progress to get an official word count. Instructions are included on the web site for scrambling your work before submission, if there is any worry of "untrustworthy, word-counting goons." However, only the following methods are detailed.


  • Microsoft Word supports regular expressions, so a quick Save As to a .txt file, and a straightforward [a-zA-Z0-9] wildcard expression with Find and Replace, does the trick. However, you have to manually overwrite further scrambled text files. 
  • Open Office works similarly, but again - you must manually delete a text file full of strings of the character 'a'. 
  • Use Find and Replace twenty-five times. 


I have Pages '09, so in this article I discuss using AppleScript to generate a scrambled text file from that application.

Given a Pages '09 document, generate a scrambled .txt file to the Desktop for upload to NaNoWriMo. Any intermediate files should be deleted after use. 


How would I do this by hand? 
  1. Save my Pages document as a plain text file using Save As. 
  2. Run a couple command-line programs to process the text.
  3. Redirect the output to a "upload_me.txt" file. 
  4. Delete the text file that Pages made.
  5. (Upload to NaNoWriMo's word-counting thing.)
Let's translate this to AppleScript. I will introduce each section and then give some explanations. 


You can find the Pastebin source here, and the script file itself on MegaUpload. I encourage you to compile the script for yourself, or to just run it from the script editor.




First, we ask the user to choose a .pages document with choose file. The activate keyword shifts focus to the file chooser dialog. We get the name and path of the chosen Pages document, and we return if the user cancels out. Note that the directories are separated by colons, and the presence of the word alias. AppleScript formats paths in two ways, and this is one. The alias path is formatted as an HFS path.

The file chooser repeats until a valid Pages document is chosen. Fortunately, even if a document is simply named "test," internally the file is recognized as "test.pages."

After we harvest the file information, we tell Pages to save the document as a plain text file, and we run cat and sed to process the text proper.

I tried redirection > to a file after sed, but I received error message -10004, or that a "privilege violation" occurred. A Technical Note (referenced below) gives some advice on granting admin-level access, but I'm creating a text file. So I decided to use TextEdit. This is the power of scripting: chaining application abilities together into an automated process.

There are more types than just SLDocumentTypePlainText. There's also 
  • SLDocumentTypeMSWord,
  • SLDocumentTypePDF,
  • SLDocumentRichText, and 
  • SLDocumentRichTextBundle.
We name the new text file by using the ampersand operator to concatenate the file path and name to the ".txt" extension. The POSIX path specifier gives us the path with '/' as the directory separator. This is the second way paths are formatted in AppleScript. If you pass an HFS path to a Unix tool like cat, it will return the error "No such file or directory."


Pages doesn't receive the activate command, but doesn't need to because its job is to simply Save As and close a file. The open command not only opens a document, but returns the document's id. This is very useful; exploit this as much as possible. 


With the scrambled text after cat/sed stored in the scramble_text variable, we can now use TextEdit's features to generate a text file. 


Question: at runtime, can an AppleScript variable store a string consisting of 50,000 words? I used a Pages document with 101,233 words spanning 278 pages consisting of 431,954 characters (excluding spaces), and the script took about three seconds. 




Here we tell TextEdit to create a new document, to populate it with the scrambled text, and to save to Desktop. Now a user can visit NaNoWriMo and upload this text file. Successive uses of this script will overwrite the "upload_me.txt" file, so we no longer have to confirm a file overwrite as with Word or Open Office. Error number 0 indicates success.


And there you have it: a script to make your novel one long shout. Try experimenting with AppleScript, and consider signing up for NaNoWriMo! :)


References

Update 11/1/2010. Had to use quoted form for the directory when passing in to the shell script. My file was called "Chapter 1.pages," and the script wouldn't work. The links to MegaUpload and to Pastebin have been updated. See screenshot: