torsdag 31 maj 2012

Problems upgrading WiFi + BlueTooth on HP laptop

My mission: Upgrade the Broadcom 54mbps WiFi in my old HP 530 laptop to something faster, "Intel Centrino Advanced-N 6230" (300mbit N-card with Bluetooth). It was not as easy as I first thought :(

First problem: Full-length vs half-length PCI Express Mini. The newer card was (like most other cards) half-length, to fit that in the older computer I needed an adapter which was about €1 on eBay.

Second problem: "104-Unsupported wireless network device detected". The BIOS of most HP/Compaq laptops whitelist only a few specific wifi cards and will not boot if they detect any other card. This is f*cked up and this alone makes me never buy an HP laptop again (or a Lenovo, which appearantly does the same). I bought the laptop, let me do what I want with it!
Fortunatelly, some very skilled people have found ways to disable the lock-out in the BIOS and have published these hacked BIOSes. See links below.

Just make sure you don't accidentally downgrade your BIOS. And of course, do this at your own risk, etc :)

Third problem: No Bluetooth device detected by Windows. The wifi device was found in device manager and worked fine after I downloaded the appropriate drivers. However, no Bluetooth devices were found or listed in the device manager - like the Bluetooth didn't even exist. Unfortunatelly, after reading a bit about the PCI Express Mini standard, I realize that it has two interfaces: PCI-e and USB. I think that the Bluetooth portion of the card works over the USB interface, while the wifi use the PCI-e interface, and that none of my two computers implement the USB interface, only the PCI-e interface. Either that or only the BT component of my card is broken, but I think that is less likely. So... Pity, I'll have to get a Bluetooth USB dongle I guess. But at least the wireless is a lot faster now :)

Please let me know if this helped you! Also please share any additional findings about this if you can!

Links I learned stuff from:

http://forums.mydigitallife.info/threads/7681-This-is-no-request-thread!-HP-COMPAQ-bioses-how-to-modify-the-bios/page111?p=333358#post333358

http://www.pugetsystems.com/parts/Networking/Intel-WiFi-Bluetooth-6230-300-Mbps-Mini-PCIe-Card-W-Desktop-Adapter-8591

http://www.allpinouts.org/index.php/PCI_Express_Card_and_PCI_Express_Mini_Card

http://en.wikipedia.org/wiki/PCI_Express

tisdag 8 maj 2012

Backup savegames from Indiana Jones on Steam (and probably other games)

I needed to copy the savegames for the Steam/LucasArts/SCUMM game "Indiana Jones and the Last Crusade" from one Windows 7 PC to another. The files were not that easy to find...

The files are located here:
"C:\Program Files (x86)\Steam\steamapps\common\indiana jones and the last crusade\INDY3\savegame.___"
and
"C:\Users\<your username>\AppData\roaming\LucasArts\Indiana Jones and the Last Crusade\*.*"

You need to copy the both the "savegame.___ " file and all files in the other folder and copy them to the corresponding location on the other computer.


I would guess this applies to other Steam/LucasArts classics as well.

Also note that using the Steam function "Verify integrity of game cache" can actually overwrite your Indiana save games! This is because Steam thinks the "savegame.___" file is a game data file and thus overwrites it with some file one they have on their servers! Because they don't change the other files, they will mismatch and wont be possible to load. That happened to me, but I was fortunate enough to recover my savegames by using system restore (or whatever it is called) - right-click on the file, Properties, Previous versions. Copy the old version.

Based on the fact that one of the savegame folders are for all users, and one which is specific for the current computer user, I think trying to run the game using different Windows accounts on the same computer would probably not work and might corrupt savegames!

I would be happy to post this info to Steam's support and the Steam forums instead, but because they for some moronic reason require separate accounts, I write about it here instead.

By the way, I wouldn't recommend anyone to buy the LucasArts classics from Steam. Even though non-steam of the games are made for DOS/Amiga/etc, you can use ScummVM to play the games on virtually any operating system and hardware.

Hope this was usefull to anyone!

söndag 5 februari 2012

PAL vs NTSC - what to play?

Some things you should know:

Japan/America and Europe use different TV systems (NTSC and PAL respectivelly). This matters, because video games must be adjusted for the different for the different formats. Because NTSC is a bigger market, games are usually adjusted for NTSC, and only a cheap PAL conversion is made, running in wrong speed (slower than it should) and with lower resolution (picture is letterboxed and "squeezed"). See comparison between NTSC and PAL here:

http://www.youtube.com/watch?v=ZmMXA7FpR_U

This was an issue all up until the PlayStation 2/GameCube/Xbox generation! For example, Final Fantasy X has a horrible PAL port (notice how the lipsynch is always good at the beginning of lines, but gets progressivelly worse the longer the conversation is...)

It is also an issue when playing Virtual Console/PSN games, see for example:

http://www.youtube.com/watch?v=T4gKOD4K088

So - which games should you play to get the best experience?

Portable consoles
Play anything, no difference in performance!

NES
Get an NTSC console and NTSC games. Most PAL games (with some exceptions) are horrible ports. A PAL console can easily be modified to be region free, but games will still run in the slower speed!

SNES

Get an NTSC console and NTSC games. Most PAL games (with some exceptions) are horrible ports. A converter can let you play most NTSC games on your PAL console - but the games will still run in the slower speed! If you're handy with a soldering iron, you could do this: http://www.gamesx.com/importmod/snes5060.htm - but remember that many games are "semi-ported" (for example, speed of music has been corrected but nothing more). Also, while the speed may be corrected for PAL games, you will still get a letterboxed and squashed video.

Nintendo GameCube
Sony PlayStation
Sony PlayStation 2
Get NTSC games, and any machine that can play NTSC games, if they run they will run properly (not including disc swap mods etc!) Many PAL games are bad ports.
Note that some NTSC PS2 games can even do 480p (as opposed to 480i)! This option is almost always removed in the PAL port.

Nintendo Wii
PAL ports of Wii games are fine. On Virtual Console, the "import" games are fine (including Final Fantasy VI and Super Mario RPG), they run in proper NTSC speed and resolution. Avoid all other games that can be purchased in the European VC store as they are the same shitty PAL ports as when they were originally released. Try to get games from a store in an NTSC region instead. TurboGraphx games found in the VC store are always fine, that console were built so that games did not have to be adjusted for NTSC/PAL!


Sony PlayStation 3
For physical PS1 and PS2 games, see above (get NTSC games). NTSC/PAL is no longer something to care about on PS3 games, and PS3 games are region free (all PS3 games works on all PS3 consoles). The PS1 games found in the european PlayStation Stores are bad ports. From any console you can, however, access any store, just lie about which country you live in, but NTSC PS1 games MAY not play on a PAL machine or vice versa (when launching it, you may get an "invalid video mode" message).

Notes:
- For consoles not listed, I don't know.
- There are no one NTSC region - Japanese NTSC consoles wont run north american NTSC games.
- Regardless of console, viewing NTSC signal may may require certain cables. Component and RGB has a higher probability of working with most TVs than the common composite and RF cables.

måndag 14 september 2009

Some tips for working with URLs in the SharePoint Object Model

Ok, so concistency is not one of the strenghts of the SharePoint OM.

Here's a couple of tips that might just save you from some headache...

1. SPListItem.Url does not make any sense

A typical value is "Lists/MyList/31_.000" where 31 is the list ID, and 000 somehow represents the version number. Of course, if you prepend the web URL and open this in a web browser, you get a 404. Great. If you want to send the user to the item display form, you need to get the name of the display form from the content type, and the item ID and build the URL manually.

2. Don't trust the documentation

The documentation has this to say about SPWeb.GetList(string):

public SPList GetList(string strUrl);
// Summary:
// Returns the list with the specified site-relative URL.
//
// Parameters:
// strUrl:
// A string that contains the site-relative URL for a list, for example, /Lists/Announcements.
//
// Returns:
// A Microsoft.SharePoint.SPList object representing the list.

Which is great, except it's completely wrong. The URL must be server relative or absolute - not site relative.

3. Be extremely careful not to mix up Absolute, Server, Site and Web Relative URLs

For a subweb of a site which is in the root web of a server, a site relative and a server relative URL are equal, which makes it easy to confuse them. If they are confused, the code will fail as soon as it tries to open a web under any site collection which is not in the root path of the server.

(Similar things can happen if a Site/Web relative or Server/Web relative URL is confused as well.)

Here's an example how not to do it, right out of one of the Microsoft assemblies using Reflector.

In one of the content database tables (regarding alerts), they've named two columns "siteUrl" and "webUrl". These names are confusing, most of all because siteUrl is not the siteUrl at all; the column contains only server URLs! Also, the values in "webUrl" are server relative.

Then, the developer of Microsoft.Office.Server.Search.Query.SearchAlertHandler.OnNotification in assembly Microsoft.Office.Server.Search, assumed that the "siteUrl" was the URL of the site (false), and that webUrl was a site relative URL (also false). S/he wrote these lines:

using (SPSite site = new SPSite(alertHandlerParams.siteUrl)){
SPWeb web = site.AllWebs[alertHandlerParams.webUrl];
// most of the code is here
}

(They forget to dispose that web, so the code is leaking memory, but that's not the main issue here.)

The SPWebCollection, most commonly returned by SPSite.AllWebs[] and SPWeb.GetSubwebsForCurrentUser(), has an indexer which accepts a site relative string. That makes sense, so ok.

But with webUrl actually being a server relative URL, that line will fail and throw an exception for any web whose parent site is not located in that the root of the server. It wont fail if the site is in the root of the server, because then a site relative and server relative web URL are the same.

Result?

Search-based alerts are completely broken for any web not being a subweb of the root site collection. They will inevitably fail with a "There is no web named ..." in the ULS log and no alerts will ever be sent. This bug exists in at least both SP1 and SP2 of MOSS 2007.

The lesson is of course that it is extremely important to always ensure if you are passing an absolute or a server, site or web relative URL, and make sure that matches what is expected!

By the way, Microsoft are aware of this issue, and they where already aware of it when I contacted them about it a couple of months ago. Appearantly, having all features in working order is not a high priority. :-(

PS. I mixed up site and server quite a few times myself just when writing this entry. I hope I got it right now though... :-)

4. URLs can change, so use other identifiers if possible

Web URLs are not static. For example, they can be changed by administrators. If possible, try not to handle any URL as something constant! That is, avoid specifying URLs in permanent configuration files, web part properties, etc. Whenever possible, use GUIDs or other static identifiers.

If you have the option to chose between for example a SiteRelative or a WebRelative url, use the one which is most general for your purpose. For specifying a list in the same web, for example, the web relative URL would be best, site relative URL second best, and so on. (Again, concider using other identifiers before resorting to URLs.)

Even worse of course is to use "Title" or "DisplayName" as identifiers, as they are even more likely to be changed in the future than the URL. Also, unlike any other identifier, they are never guaranteed to be unique!

5. Use SPUtility, SPUrlUtility, HttpUtility if you can

Don't re-invent the wheel! SPUtility, SPUrlUtility and HttpUtility contains several methods for common operations with URLs, such as concatenating and splitting a URL string. Feel free to check them out in Reflector to see what they do if it's a least bit unclear.

torsdag 3 september 2009

A random WSS 3.0 SP2 issue

I found this by accident:

http://support.microsoft.com/?id=909455

"Document library event handlers that use object model code without explicit impersonation fail with the "Cannot complete this action" error message after Windows SharePoint Services Service Pack 2 is installed"

"All document library event handlers must perform explicit impersonation to use Windows SharePoint Services object model calls."

"This behavior is by design."

I'll just leave it at that...

torsdag 27 augusti 2009

A little bit about SPListItemCollection...

Don't:
SPList list = SPContext.Current.Web.Lists["MyList"];
SPListItem item = list.Items.GetItemById(7);
Do:
SPList list = SPContext.Current.Web.Lists["MyList"];
SPListItem item = list.GetItemById(7);

Why?
Using the "Items" field of an SPList will always create an SPListItemCollection and populate it with all items from the database, which can take a long time if the list contains many items.
Calling GetItemById() directly on the SPList does not require this and can finish in a fraction of the time, even for a list with thousands of items.
To go further into this...
If performance is important (or if you are working with lists with many items), you should (or even must) avoid the "Items" field of SPList completely. Instead use SPQuery and SPList.GetItems(SPQuery) to create your own SPListItemCollection, and limit its size by setting these fields on the SPQuery:
- "ViewFields" - specify only the fields you need.
- Row Limit - set the maximum number of items you need
- Query - of course, to make the collection only contain items which you need.

For example,

Don't:
SPListItem item = list.Items.Add(...);
item.Update();
Do:
SPListItem item = list.GetItems(new SPQuery { RowLimit = 0 }).Add(...);
item.Update();
Another example,

Don't:
itemCount = list.Items.Count;
Do:
itemCount = list.GetItems(new SPQquery { ViewFields = "" }).Count;

Much of this is usually not required of course, but for lists which contains hundreds of items the difference will likely be noticable.

By the way, many of the OM methods use SPQuerys "behind the curtain". For example, SPList.GetItemById() creates an SPQuery with RowLimit = 1 and a "where eq" query searching for the specified ID, and the constructor of SPListItemCollection (which for some reason is marked internal) simply just takes an SPList and an SPQuery as parameters.

Hope this is of use to anyone!

onsdag 3 december 2008

Firefox, Safari, SharePoint and modal windows

Ok, I've been taking a closer look at the problem with SharePoint, modal windows, Firefox and Safari.

Turns out the problem is NOT Firefox/Safari, rather, it is an issue with the setModalDialogObjectReturnValue() function in core.js. Basically, because of differences between Firefox/Safari and Internet Explorer, the result of the 'if' clause in this method is different. For Firefox/Safari, this has the result that the wrong method is used to set the return value of the window.

Here is a very quick and dirty workaround that works in FF3, Safari 3 and IE7 (and WSS 3.0 SP1/MOSS 2007 SP1).

Add the bold line to ...\12\TEMPLATE\LAYOUTS\1033\CORE.JS:

function setModalDialogReturnValue(wnd, returnValue)
{
  if (wnd.opener !=null &&
    typeof(returnValue)=='string' &&
    wnd.opener.document.getElementById('__spPickerHasReturnValue') !=null &&
    wnd.opener.document.getElementById('__spPickerReturnValueHolder') !=null)
  {
    wnd.opener.document.getElementById('__spPickerHasReturnValue').value='1';
    wnd.opener.document.getElementById('__spPickerReturnValueHolder').value=returnValue;
    wnd.returnValue=returnValue;
  }
  else
  {
    setModalDialogObjectReturnValue(wnd, returnValue);
  }
}

I put this here only to illustrate the problem and the solution. I have not tested this with older browsers - this code will probably break functionality with older browsers! Preferably, one should modify the 'if' clauses in this method. Also, mind that changes to this file is not supported by Microsoft. It might be overwritten by future Service Packs or upgrades, so you better hope that this bug is fixed in the next Service Pack, or somehow put this fix in some other file.


So who is to blaim? Who should fix it?

What Mozilla changed to make this problem arise in Firefox 3 was simply to add support for the IE specific method showModalDialog(). They didn't have to - they already had another way to do the exact same thing.

For Firefox 3/Safari 3, the JavaScripts in core.js now choose the "IE" method to open the window, the "Firefox" method to set the return value to the window, and then again the "IE" method to read the return value from the window. Hence, the return value will always be undefined or null. The JavaScript functions must be modified in some way so that they are concistent.

No one is to "blaim" - Firefox and Safari supports everything IE supports, and Microsoft made an effort to support Firefox in SharePoint, but even though SharePoint worked in all browsers available during its release, it now fails to properly detect modern browsers.

While it's possible to work around the problem, and it should be quite easy to make the fix as a custom SharePoint solution, I recommend anyone being troubled by this issue to open a support case with Microsoft.