Category Archives: Nerd Notes

My technical notes

Concatenating SRT subtitles

Ever get a movie which is split into two parts? I usually use AviDemux to join the parts back together but what if the movie has srt subtitles – Here’s how to join two srt files together and adjust the timestamps using srttool in Ubuntu:

First install the tool:

sudo apt-get install subtitleripper

Then use ffmpeg to see how long the first part of the movie is:

ffmpeg -i movie.part1.avi

Look for the line which tells you the length of the movie. It will be something like 00:45:15.56. Whip out your calculator and work out the length in seconds, in this case it will be 2715 seconds.

Finally use srttool to displace the timing in the second subtitle file and append it to the first one:

srttool -d 2715 < movie.part2.srt >> movie.part1.srt

movie.part1.srt will now contain complete subtitles for your movie.

Python function is not callable

Here’s a Python gotcha that got me. Here is my function to print out a range of sinusoidal values:

import math

def cycle(centre, range):
        theta = 4.71
        speed = 0.1
        for i in range(0,80):
                theta = theta + speed
                value = centre + (range * math.sin(theta))
                print value

I got the following error which confused the hell out of me:

Traceback (most recent call last):
  File "cycle2.py", line 11, in 
    cycle(0.0,10.0)
  File "cycle2.py", line 6, in cycle
    for i in range(0,80):
TypeError: 'float' object is not callable

Can you see it? It took me a while. I’d assigned a variable called range and then tried to call the range() function. I’d overloaded a built-in function. Duh!

I just had to rename my variable and it was good.

Parallel port control in Python

Controlling the parallel port has always been a pain in Windows 2000, XP and later. In DOS or older versions of Windows you could just write a byte directly to port 0×378 and that was it.

Now you can get the same level of simplicity using inpout32.dll and Python. Go here to download the DLL and you can access it from Python just as easily as it used to be under DOS. The following example writes the number 5 to the parallel port:

import ctypes

ctypes.windll.inpout32.Out32(0x378, 5)


UPDATE: I have made a simple demo app using this technique. You can download it from my commercial website at http://siliconsparrow.com/parallel-port-tester-in-python/.

Australian Income Tax Spreadsheet Formula

Just a quick note for my future reference. I’m setting up my budget spreadsheet for the new financial year and I have converted the Australian 2010 income tax rates into a spreadsheet formula. I use OpenOffice, it should work fine in Excel too.

=if(A1<=6000;0;if(a1<=35000;.15*(a1-6000);if(a1<=80000;4350+(.3*(a1-35000));if(a1<=180000;17850+(.38*(a1-80000));55850+(.45*(a1-180000))))))

Creating a Debian Kernel Package for v2.6.26

There are so many guides out there on how to make a Linux kernel and so many of them are out of date, I thought I should write down a simple step-by-step of the current way to do it as of early 2009.

My goal here was to compile a new kernel for a Debian 4.0 (Etch) system. You can download pre-built kernels but I wanted to modify some drivers before building it.

Anyway, you will firstly need the source code. Go to the Debian Backports Repository and grab the latest linux-source package. Before installing it, you will need to install some tools:

sudo apt-get install kernel-package fakeroot libncurses5-dev

Now we can install the source:

sudo dpkg -i linux-image-2.6.26_dvc.1.2_i386.deb

cd /usr/src

tar jxvf linux-source-2.6.26.tar.bz2

ln -s linux-source-2.6.26 linux

cd linux

Next you need to configure the kernel. A good way is to simply copy the current kernel configuration:

cp /boot/config-2.6.18-6-686 ./.config

Finally, launch the make-kpkg utility. This will configure, compile and package the kernel in a DEB package.

fakeroot make-kpkg --revision=mycustomkernel-1.0 --config menuconfig --initrd kernel_image

This will launch the kernel configuration menu first. You can make any configuration changes here but usually the defaults are fine. When it is all done you will have the completed package file in /usr/src.

Reading a single keystroke with C++ on Linux

Just say you want to input a single key from your user such as asking “Would you like to continue [y/n] ?” without requiring the user to press ENTER. You’d think you could do it like this:

char c;
cin >> c;
cout << "You pressed " << c << endl;

But it doesn't work! The user has to press ENTER before the cin function will complete.

I read all sorts of crazy solutions on the web to fix this, most of which involve using NCURSES but I think that is total overkill. I have found a simpler way.

Now it's not the fault of std::cin or even C++. It's the operating system which buffers the keyboard input, only releasing it to your app when the user whacks ENTER. So what you need to do is tell the OS not to buffer keystrokes. You can do this with the termios functions in Linux. Here is an example:

// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam@doctort.org>
// This code is freeware. You are free to copy and modify it any way you like.

#include <iostream>
#include <termios.h>

using namespace std;
main()
{
// Black magic to prevent Linux from buffering keystrokes.
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &t);

// Once the buffering is turned off, the rest is simple.
    cout << "Enter a character: ";
    char c = cin.get();
    cout << "Your character was " << c << endl;

    return 0;
}

Networked Warcraft II under DOSBox

This is a guest post contributed by Richard Geoffrion. Thanks for sending this Richard, I hope others will find it useful!


First off, thank you so much, Adam, for the primer on getting Warcraft II working under DOSBOX. The “-t cdrom” option was the piece I was missing to get my game to recognize the CD and work.

After I installed my game, I wound up copying my entire Warcraft II CD to my C:\DOSGAMES\WAR2 directory, then I added “mount d c:\dosgames\war2 -t cdrom” to the [autoexec] section. By copying the CD to the same path as the installed game, I don’t have to duplicate the space to hold the files from the CDROM.

As for playing multiplayer Warcraft II in DOSBOX, it could not be made any easier. There is NOTHING that the user has to configure in Microsoft Windows (or Linux…or OSX) to get IPX gaming working under DOSBOX. The DOSBOX team has built an IPX wrapper right into DOSBOX. Once the Warcraft II game is operational on two or more computers on your network you are ready to setup networking in DOSBOX.

Instructions:
1) Identify the IP addresses or names of each computer that will be participating in the gaming session. (Windows users: To display the computer’s IP address click START, click RUN, type in “cmd” and click the OK button. At the prompt, type in the command ipconfig and press enter. Write down or remember the number on the IP ADDRESS line. If you want to know the name of the computer, you can type in the command ”hostname” and press enter to see the name.) (Linux/OSX users: run ifconfig from a terminal (you may have to sudo the command or su to root)

2) Once you have identified all of the IP addresses (or names) of the computers on your network that will be playing the game, pick one to designate as your IPX SERVER.

3) *OPTIONAL STEP* Sometimes the Microsoft Windows firewall is turned on and it could interfere with proper communications between the client and the server. If you want to run a test to make sure that everyone can connect to your server, then go to each computer that will be connecting to your designated server and start a windows command prompt. Once the prompt is open, use the ping command along with the IP address of the server -OR- the server computer’s name to make sure that the server can respond to the clients. [Example: " ping 192.168.1.100 " -or- " ping HP-PAV6330 " ]

4) Start DOSBOX on your designated server. Run the DOSBOX command:

ipxnet startserver

That is IT!! That is ALL YOU NEED TO DO on the server! It is THAT SIMPLE!

–we’re almost done!–

5) Now start DOSBOX on each client computer that will be joining in the multiplayer fun. Once DOSBOX is running we will be using the DOSBOX command ‘IPXNET CONNECT’ but we’ll be adding something to it. We will either add the IP address of the server or the name. If we were to use the IP address or name from the examples in the optional step 3, our DOSBOX command might look something like this:

C:\> IPXNET CONNECT 192.168.1.100

-OR-

C:\> IPXNET CONNECT HP-PAV6330

At this point, DOSBOX will handle wrapping the IPX packets in TCP/IP.

6) Start WAR2 on the server, Select Multiplayer, select the IPX Network connection method and
click CONNECT then CREATE GAME.

7) Start War2 on each client, Select Multiplayer, select the IPX Network connection method and click CONNECT then JOIN GAME.

8) Begin your game and race your peons out to the unclaimed gold mines to put walls around them to protect them from any players..especially computer players. Oh..wait….that doesn’t belong in this set of instructions! Now who let that slip by quality control?!!?

NOTE 1: It *IS* possible to play WARCRAFT II with a friend across the internet. The variety of the additional steps needed are a bit beyond anyone’s ability to document in a single document but I can briefly outline the requirements below.

A) The gamer who will be the server ( the server user) will have to know their real-world public IP address. If you don’t know your public IP address, you can visit a site that displays your public IP address. A google search on finding your public IP will reveal many. http://www.whatismyip.com is one. [#]

B) If the server user is behind a router/firewall, then the server user will also need to..

*) know their private IP address. This is the IP address that was discovered in the ‘ipconfig’ command from step 1 above.

*) configure their router/firewall to forward the UDP port 213 –DOSBOX IPX WRAPPER traffic– from their external interface to UDP port 213 on the private IP Address of the computer that is the DOSBOX IPX server.

Note 2: The DOSBOX command ” IPXNET help ” will display a list of available networking commands and a small bit of documentation — like the fact that the DEFAULT port for the IPX wrapper in DOSBOX is UDP port 213

Note 3: These same networking steps should work for any IPX DOS game that runs in DOSBOX. These steps have been successfully tested with “One Must Fall”. [Google omf21cd.zip to download this free game.]

[#] Please avoid http://moanmyip.com if you are ..oh I don’t know… at work setting up for a Christmas LAN party! Of course using that link as a secondary browser-start-up-home-page can be fun.

Happy Retro-Gaming!

UDEV swapped my drives!

After doing a dist-upgrade on a Debian Etch system, it would no longer boot! It loads the kernel and then stops displaying the following message:

Waiting for root filesystem

I’ve just spent a few torturous hours trying to get it back up again. It took me a while to figure out what was happening but it seems that the updated package for UDEV changes the GRUB configuration so it tries to mount hdb1 instead of hda1 as the root file system. Of course hdb1 does not exist on this single-drive machine so it just sits there like a moron.

Turns out it is not frozen. If you wait about 3 minutes, it will eventually come up with the following prompt:

(initfs)

I found that I can kind of get the system running by typing the following commands. These are for a single-partition system on an EXT3 file system on an IDE hard drive. If your system is different, you will need to modify them a bit:

mkdir /mnt

mount /dev/hda1 -t ext3 /mnt

chroot /mnt

login

Then log in. The next thing to do is to correct the GRUB configuration:

nano -w /boot/grub/menu.lst

Change the root=/dev/sdb1 entry to root=/dev/sda1. Once again, this is for a single IDE drive, you may need to change it if you are booting from SATA or some other kind of device.

Now regenerate the initramfs image:

dpkg-reconfigure initramfs-tools

At last we can reboot. The system came up fine for me after this.

reboot

Adaptec 1430SA on Debian Linux “Etch”

Well folks, I just got saddled with this Adaptec/Marvel piece of poo and now I have to make it work on a Debian server. The server belongs to my employer and is running Debian “Etch”.

The Etch release of Debian does not have a driver for this card built-in and even though Adaptec claim to support Linux, their drivers simply do not work unless you are running some specific outdated versions of Red Hat or SUSE. That’s not what I call Linux support!

I’m not the only one discovering this, Brent Norris wrote a wonderful article titled “Adaptec 1420SA is JUNK!” on his blog which describes pretty much the exact situation I find myself in which Adaptec just doesn’t want to know about Linux.

When are these guys (by whom I mean most major hardware manufacturers) going to realize that Linux is here to stay and is getting real popular, especially in the server room.

Anyway, enough ranting. After a couple of hours Googling around, I see that there is an open source driver available for this card and it is built into Linux kernel version 2.6.22. Debian Etch uses 2.6.18 so all I need to do is upgrade the kernel.

The easiest way to install the upgraded kernel is to get a DEB package from Debian Backports. Go to this page:

http://packages.debian.org/etch-backports/admin/

and grab a kernel, there are usually a couple of different versions available there.

Install it and reboot. Works great so far.

PS. I notice that the driver for this card was released into the Linux kernel by Red Hat corporation. So it seems even they are fed up with Adaptec’s poor support for Linux!