How to Make Sausage

Illustration

Here is recipe that I use for making sausages. These sausages can be made with pure pork, but I like to also add some beef meat.

First step is to grind meat in meat grinder. Pieces should be small, but not in paste-like form. If you don’t have meat grinder just ask your butcher to grind meat for you. Or buy minced meat. Just don’t use food processor because it will completely destroy meat texture.

Spread salt, pepper and paprika (both sweet and hot) over minced meat. In another bowl add garlic into boiling hot water and leave it to rest for fifteen minutes. Filter garlic out and pour hot water over minced meat with spices. Mix thoroughly.

After all spices are distributed evenly take a taste of meat. This step is quite necessary since hot paprika can vary from batch to batch. If it is not hot enough, just add hot paprika. During smoking sausage will loose quite a lot of water and hot paprika will surface so don’t go too wild.

Once you are satisfied with taste, fill casings (I usually use salted pig casings). You will need sausage stuffer for this step since consistency needs to be quite dense.

This sausage mix is intended for smoking and I would not recommend frying it. However, if you wish instant results, you can cook it with water on medium fire for fifteen minutes.

Ingredients:

  • 7.5 kg Minced pork
  • 2.5 kg Minced beef
  • 200 g Salt
  • 20 g Black pepper
  • 25 g Hot paprika (ground)
  • 250 g Sweet paprika (ground)
  • 250 g Garlic

Structure Alignment

Let’s begin with example:

struct Test {
    Int16 A;
    Int32 B;
}

Since Int16 has length of two bytes and Int32 has length of 4 bytes one would expect total length of 6 bytes. However, upon check (with Marshal.SizeOf) we will discover that total length is 8 bytes. This difference is expected and allocated length is due to alignment of data structures.

When 32-bit processor reads data, it will do that in chunks of 4 bytes. If we want whole value to be read in one pass, it needs to be placed on alignment boundaries. If we want to read 4 bytes, we need those bytes to be at offset 0, 4, 8… or any other multiple of 4. This also explains length of first structure. First two bytes belong to variable A, then there are two padding bytes and final four bytes are variable B. Only function of those two bytes of padding is to ensure proper offset for variable B. Exact values of padding bytes are not of interest to us.

Alignment is almost always done on natural boundary of data type. 8-bit data types (e.g. Byte) will be aligned on 1-byte boundary, 16-bit data types (e.g. Int16) will be aligned on 2-byte boundary, 32-bit data types (e.g. Int32, Single, Boolean) will be aligned on 4-byte boundary and 64-bit data (e.g. Int64, Double) will be aligned on 8-byte boundary. All data types larger than that will be also aligned on 8-byte boundary.

To show it with example:

struct Test {
    Int16 A;
    Int16 B;
    Int16 C;
}

Length of this structure will be 6. This is because every variable is on natural boundary and there is no padding needed. If we decide that B needs to be Int32, length will jump to 12. This is because byte boundary needs to be aligned on 4-byte values and we will have padding after both A and C. This also shows how important careful ordering can be. If we make C Int32, total length will be 8 - no padding.

Calculating everything by hand can be sometimes quite annoying. This is why I made this function:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
static void DebugStructureAlignment(object structure) {
    var t = structure.GetType();
    if (t.IsValueType) {
        Debug.WriteLine("Offset  Length  Field");
        int realTotal = 0;
        foreach (var iField in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
            Debug.Write(Marshal.OffsetOf(t, iField.Name).ToString().PadLeft(6));
            Debug.Write("  ");
            int size = Marshal.SizeOf(iField.GetValue(structure));
            realTotal += size;
            Debug.Write(size.ToString().PadLeft(6));
            Debug.Write("  ");
            Debug.WriteLine(iField.Name);
        }
        Debug.WriteLine("        " + Marshal.SizeOf(structure).ToString().PadLeft(6) + " bytes total");
        Debug.WriteLine("        " + realTotal.ToString().PadLeft(6) + " bytes total (data without padding)");
    }
}

Just give it instance of structure as parameter and you will get offsets and lengths of all fields inside of it. While this function is not perfect and I would not be surprised that there are some errors inside, mostly it will just work. In case you are playing with Windows API a lot, chances are that you have something like this already written.

Installing Windows 7 From USB Drive - XP Version

Illustration

I already wrote about creating USB installation media for Windows 7. However, that procedure worked only on Windows Vista and above. I stumbled upon problems when I tried to apply same procedure on Windows XP.

In this walk-through I will have USB drive on letter W: and Windows 7 installation CD (either real one or just mounted iso) on drive F:.

For this to work, we need to first format USB as NTFS drive:

FORMAT W: /FS:ntfs /Q
 Insert new disk for drive W:
 and press ENTER when ready...
 The type of the file system is FAT32.
 The new file system is FAT32.
 QuickFormatting 7647M
 Initializing the File Allocation Table (FAT)...
 ...

CONVERT W: /fs:ntfs
 The type of the file system is FAT32.
 Volume Serial Number is 8CD3-E43F
 Windows is verifying files and folders...
 ...
 Converting file system
 Conversion complete

One thing that is problematic on XP is making USB bootable in first place. There is DISKPART tool available, but only for internal disks. External USB memory will just not be recognized there. In order to go around this, you will need MBRWizzard. That tool gives you DISKPART-like commands and it works on Windows XP.

First we need to see what do we have:

MBRWIZ /list
 MBRWiz - Version 2.0 **beta** for Windows XP/2K3/PE         April 30, 2006
   Copyright (c) 2002-2006 Roger Layton                    http://mbr.bigr.net
 Disk: 0   Size: 153G CHS: 19457 255 63
 Pos MBRndx Type/Name  Size Active Hide Start Sector   Sectors    DL Vol Label
 --- ------ ---------- ---- ------ ---- ------------ ------------ -- ----------
  0    0    07-NTFS    152G   No    No            63  312,576,642 C: <None>
 Disk: 1   Size: 153G CHS: 19457 255 63
 Pos MBRndx Type/Name  Size Active Hide Start Sector   Sectors    DL Vol Label
 --- ------ ---------- ---- ------ ---- ------------ ------------ -- ----------
  0    0    07-NTFS    152G   No    No            63  312,576,642 D: <None>
 Disk: 2   Size: 7.6G CHS: 974 255 63
 Pos MBRndx Type/Name  Size Active Hide Start Sector   Sectors    DL Vol Label
 --- ------ ---------- ---- ------ ---- ------------ ------------ -- ----------
  0    0    07-NTFS    7.6G    No   No         2,048   15,661,056 W: <None>

As you can see, USB is recognized as drive 2. Do remember this. In order to make first partition bootable, we need to activate it.

Command parameters are easy. Disk takes number of disk (2 in this case), part is partition number (always zero - Windows have problems with multiple partitions on USB drive). Active works as simple boolean operation: 1 to make partition active and 0 to deactivate it.

MBRWIZ /disk=2 /part=0 /active=1
 MBRWiz - Version 2.0 **beta** for Windows XP/2K3/PE         April 30, 2006``
   Copyright (c) 2002-2006 Roger Layton                    http://mbr.bigr.net``
 Are you sure you want to set the partition(s) Active? (Y/N): y``
 Partition successfully set to Active``

Once partition layout is done, copy operation can commence. Just copy everything from Windows 7 CD to your USB drive.

XCOPY F:\*.* /s /e /f W:\

After everything is copied, we just need to update boot code on USB drive. We can do this with BOOTSECT program located on your Windows 7 installation CD in boot folder.

F:
CD boot
BOOTSECT /nt60 W:
 Target volumes will be updated with BOOTMGR compatible bootcode.
 W: (\\?\Volume{2f3c3a5d-1913-11de-a3ee-003005c321bd})
    Successfully updated NTFS filesystem bootcode.
 Bootcode was successfully updated on all targeted volumes.

Now your installation is ready to go!

Unlike Windows 7 procedure, here we need NTFS formatted media. I tried to do same with FAT32 formatted media, but my laptop would not recognize it. Since Windows 7 do work from such media, there is probably just small adjustment needed but I decided not to bother with it.

BeBook Mini

Illustration

Ever since I saw Sony’s PRS-600, I was searching for my e-book reader to call my own. I wanted something cheaper and similar in size. I did like other Sony devices - PRS-505 and PRS-300, but they had one big flow - they weren’t available in Croatia.

Looking for alternatives, I came upon quite a few devices and my choice was divided between Jinke Hanlin v3 and v5. While v3 had little bit bigger screen (6 inches), I decided upon newer v5. It has smaller screen (5 inches) but it also features faster processor and newer display controller.

Jinke also offers re-branding of Hanlin eReader V5 so same device can also be found under name of BeBook mini, Astak 5" EZ Reader Pocket PRO and lbook V5.

Since there is BeBook mini available in Croatia (Sveznadar bookstore), I decided upon it. It will definitely make my life easier in case of warranty.

Device is fairly light (160 g) and it fits hand quite comfortably. There are three separate sets of next/previous buttons so there is no problem finding comfortable position - even if you are left-handed.

Screen has great resolution (600x800 at 200 dpi) and it is quite confortable to read. If you have light pointed right at it, there is some reflection, but it is quite manageable. As with all eInk devices, there is black flash upon page change but I got quite used to it after a while. Epson controller and fast processor (400 MHz ARM) are doing quite nice job at minimizing time between page turns.

I was quite surprised that my device came with last firmware update already installed. While procedure for installing firmware is not too hard, this is quite a nice gesture from manufacturer. Great thing to note here is that boot loaded is in separated area of flash and there is almost no possibility of bricking your device with bad update. If something goes wrong, just repeat update.

I will not list all supported formats here since list is quite extensive. I will only note that there is no support for newest docx (Microsoft Office 2007) file format. Older doc files are supported so conversion is not too hard. Some formats are supported by Adobe’s engine (ePub and PDF) and others are displayed by CoolReader so there are some inconsistencies in user interface. Nice touch is selection among quite a few fonts already integrated within system or uploading custom one.

Bookshelf interface supports folders as main sorting mechanism and I like this quite a lot. Only issue I found with it is displaying system folders - fonts, Digital Editions and Restore_PC folders are always shown and there is no way of hiding it. Since one entry is already used for Recent files, only four entries will be visible on first page. This means lot of “next page” movement - especially if you happen to have Work folder that happens to be on far end of alphabet.

I find this device quite comfortable to use. It may not be easy to use for non-technical person, but it is getting better and better with each firmware update. If it continues this rate of development, we will have a treat in a year. For those with little bit more free time and courage, there is also SDK available. Customization may commence.

[2010-09-13: Unfortunately my device got broken - all analysis point to screen glass damage. I am open for advice regarding which device to choose next.]

[2010-11-26: I opted for Kindle 2 as my next device. So far I like everything except it’s size - it could lose keyboard.]

Visual Studio 2008 and Team Foundation Server 2010

Illustration

Team Foundation Server 2010 works great when combined with Visual Studio 2010. However, if you wish to combine it with Visual Studio 2008, some additional setup is required.

First thing that you need to install is Team Explorer 2008. If you already used source control, you may have it. Easiest way to check is to go into Tools > Options and select Source Control. If there is “Visual Studio Team Foundation Server” in plug-in list, you can skip this download.

Another thing I installed was Visual Studio Team System 2008 Service Pack 1 Forward Compatibility Update for Team Foundation Server 2010. I do not think that this long-named update is really “must” but I decided to install it anyhow - just in case.

Once you install everything, you can try adding Team Foundation Server 2010 as destination, but you will be greeted with error “TF31002: Unable to connect to this Team Foundation Server …”. Reason behind this is that old Team Explorer 2008 does not know anything about collections.

Solution would be to add it as full path (e.g “http://server:8080/tfs/collection”). I could not do it because every time I entered full path, I also got error “TF30335: The server name cannot contain characters ‘/’ or ‘:’ …”. Since official way would not work it was time to come up with alternative.

In order to add TFS 2010 server, you will need to exit Visual Studio 2008 and go into Registry editor. Find key “HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\TeamFoundation\Servers” and at this location just add string value. Name of this value will be what Team Explorer 2008 will use for display. It’s value is full address of your server. It should be something like “http://server:8080/tfs/collection”.

Now you can go into Visual Studio 2008 and Team Explorer will have new entry. As you work with it, you will notice that not everything is “bump-free” (e.g. tasks). However, source control it self will work perfectly and that was enough for me.