Pages

Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

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.


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, 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