Archive

Archive for the ‘PALib’ Category

Woopsi 0.39 Released

October 24th, 2009 Ant No comments

A new release! Download it at the SourceForge page as soon as SourceForge decide to update the front page. In the meantime, here’s a direct link:

Woopsi Source 0.39

Excitingly, in upgrading to the new layout, SourceForge appear to have lost all of the release notes I painstakingly appended to each Woopsi release.

Anyway, here’s a quick recap of the features in this latest version.

New Features

The TextBox and MultiLineTextBox now listen for the d-pad and respond to left/right presses by moving the cursor in the corresponding direction. This only happens if the gadget in question has focus.

The source distribution includes a new “tests” folder. Now that Woopsi is maturing it’s about time that I tested it properly. Each gadget in the system will eventually have a comprehensive test application in this folder; for the moment, just the CycleButton and RadioButtonGroup have test programs here.

As mentioned in the last post, Woopsi can now load and save 24-bit BMP files. It has two new classes in the “bonus” folder – BinaryFile and BitmapIO – to handle this. There is a new “BitmapLoader” example in the “examples” folder.

Bugfixes

As you’d expect, now that there’s a test harness for them, there are a number of bugfixes to both the CycleButton and RadioButtonGroup gadgets. There are few bugfixes to the base Gadget class that were similarly highlighted by the new tests. The Bitmap class also has had some fixes implemented to solve problems that arose when writing the BMP loader. Other bugfixes are listed in the changelog.

There are two important fixes that haven’t been mentioned on the blog before. Firstly, the problem detailed on the 11th in which overlapping gadgets were drawn incorrectly is now fixed.

The second bug arose from a similar situation. If a gadget is disabled and overlaps another gadget, any attempts to click the uppermost, disabled gadget fell through to the lower gadget. This is clearly incorrect behaviour and has been rectified. Disabled gadgets previously neglected to capture clicks; they now capture the clicks but do not react to them.

If you have implemented your own classes, or subclassed existing classes and overridden the “click()” method, you will probably need to change your code. The previous click() template looked like this:

bool MyGadget::click(s16 x, s16 y) {
	if (Gadget::click(x, y)) {
		redraw();
		return true;
	}
 
	return false;
}

It should now look like this:

bool MyGadget::click(s16 x, s16 y) {
	if (Gadget::click(x, y)) {
 
		if (isEnabled()) {
			redraw();
		}
 
		return true;
	}
 
	return false;
}

Note the extra “isEnabled()’ check.

Known Issues

Just a small one. The RadioButtonGroup does not re-raise any events raised by its child RadioButtons. This means that it is impossible to listen for click/release/drag/etc events from a RadioButtonGroup. This is a minor problem, however, as these events are not particularly useful for this gadget. The useful event is “value changed”, which is raised.

Forthcoming Changes – The Fate of PALib Support

I mentioned back in January that I was no longer checking PALib compatibility. I think it is about time that I removed PALib support from Woopsi. It doesn’t make any sense to leave it in, as I’m not using it for anything, but it does clutter up the code and require an extra makefile. The next release of Woopsi will be PALib-free.

Categories: PALib, Woopsi Tags: , , ,

PALib Download – A Public Service Announcement

March 19th, 2008 Ant 1 comment

As the PALib site is still down, here’s the latest (official, not community) release of the library:

PALib 070323 (EDIT: The download manager plugin I was using has deleted all of the files I’d uploaded with it, but since this version of PALib is now out of date, there’s not much point in restoring it.)

Might prove useful until the main site comes back.

Categories: PALib Tags:

Scrolling Panels

December 19th, 2007 Ant 15 comments

The ScrollingPanel gadget now works. It can scroll its content in any direction using the DMA hardware.

Scrolling vertically was easy to implement, and it works in the same way as the TextViewer class:

  • Work out how far we want to scroll in pixels.
  • Copy all visible rows up or down that number of pixels.
  • Fill the region that has scrolled into view by calling the draw(Rect) routine.

The major difference between the ScrollingPanel and the TextViewer is that the ScrollingPanel scrolls individual visible regions. It’s got clipping built-in, whereas the TextViewer still doesn’t have clipping because the iteratively-developed code is a godawful mess.

Scrolling horizontally was more complicated. Back when I was playing with solid-window dragging, I decided that the only way to perform horizontal scrolling using the DMA hardware was to:

  • Work out how far we want to scroll in pixels.
  • Loop through all visible rows.
  • Copy chunks of data the width of the scroll distance left or right along the row.
  • Fill the new regions by calling draw(Rect).

You can’t just copy 10 pixels from (x = 1) to (x = 5) because they’re copied as individual u16s. By the time you’ve copied half of the pixels and reached (x = 10), you’ve overwritten the second-half of the data you wanted to copy.

I implemented the above routine and ran into a problem. If we try to scroll an area of 10x10 pixels by one pixel, we have to copy the whole area pixel by pixel. This results in 100 copy operations. I was aware of the issue before I started, but decided it was worth a go anyway. It wasn’t too bad - it was certainly fast enough under emulation.

However, the obvious solution finally presented itself. If the routine creates an off-screen array of u16s with a length equal to the width of a row, I can just copy the whole row to the array and then copy it back to its new horizontal position. One extra copy routine and a memory allocation is a lot faster than 100 copy operations and associated calculations. It would probably even be feasible to have solid window dragging using that technique.

I’m not certain at this stage how well the ScrollingPanel will function as a gadget container. It currently has a method to adjust the positions of any child gadgets when the panel is scrolled, but it does not redraw its children. The problem is that we only want a small portion of a gadget to redraw, but the existing Gadget::draw(rect) function assumes that the rectangle parameter represents a valid, visible region, and will draw it without any further checks. I’d need to either:

  • Implement a new draw routine that will accept a clipping rectangle, but clip that rectangle to the gadget’s internal region cache before drawing, or;
  • Just call draw() on all children and allow them to completely redraw themselves.

The first option is trickier than you might expect, to the point that it really isn’t justified. The second option is easy, but will result in flickering child gadgets as the panel scrolls.

On the positive side, I think I should be able to modify the MultiLineTextBox so that inherits from the ScrollingPanel and thus immediately equip it with omni-directional scrolling functionality.

In order for scrollbars to work, the ScrollingPanel needs to keep a note of the lowest pixel drawn within it (so that we know how tall the draw space is). Must remember to do that. Or possibly some other mechanism that achieves a similar result.

Categories: Algorithms, DS Coding, PALib, Woopsi Tags:

Compiling – Magic, More Magic

December 17th, 2007 Ant No comments

Note to self - when swapping Woopsi’s makefiles from libnds to PALib or vice-versa, remember to “make clean” instead of “make”. If you don’t do that, strange things happen, nothing works properly, and you spend five minutes frantically disabling things to work out what the hell you did to break it all.

Categories: DS Coding, PALib, Woopsi Tags:

PALib-Be-Back

December 14th, 2007 Ant 4 comments

I’ve modified Steven’s code so PALib is now optional. There are two steps to enabling PALib. First, uncomment the line in “defines.h” that reads:

//#define USING_PALIB

Second, rename “Makefile.palib” to “Makefile” (replacing the current makefile).

That’s it - PALib is back in action.

Once I’ve worked out why the stylus release doesn’t work properly, I’ll switch this around so that PALib is enabled by default - I think that PALib users are more likely to want a solution that works without tinkering, whilst the libnds guys will be happier to fiddle with options.

I’ve also fixed the spelling errors in the code. “Woopsie” is now “Woopsi” again.

Categories: PALib, Woopsi Tags:

PALib-Be-Gone

December 14th, 2007 Ant 9 comments

I’ve applied Steven’s patch to the codebase. It needs a little tinkering to make it follow the rest of Woopsi’s coding style, but it’s a fantastic bit of code. Woopsi is now completely independent of PALib.

The question now, of course, is how I publicise it. Posting on the PALib forum is an easy way to get into the news pages of all the major DS homebrew sites. It’s not really appropriate to post it there any more…

Latest sources in SVN; looks like the patch has shaved 60K off the .nds binary file.

Categories: PALib, Woopsi Tags:

Filled Polygons

December 4th, 2007 Ant 17 comments

I became distracted by a question on the PALib forum this evening, so haven’t fixed any of the Woopsi bugs I’d intended to. Interesting problem - is it possible to draw a 100x100 rectangle rotating through 360 degrees, using nothing but PALib’s line routines and a floodfill algorithm, at 60fps?

Short answer: No. Long answer: Well, I couldn’t get it working fast enough.

This was an interesting query for a few reasons. I’m thinking of writing a vector-based game in a Woopsi window when that’s finished. Also, Woopsi may (or may not) get a floodfill routine at some point, so it was good to see how that should work.

I tried two floodfill algorithms, both from this page:

http://student.kuleuven.be/~m0216922/CG/floodfill.html

The first one I tried was the 4-way recursive routine which, as the site suggests, is a bit useless - it overflowed the stack. The second one I tried was the scanline-with-stack routine, which did the job. I optimised it by replacing its single pixel plotting method with a DMA accelerated line routine (which meant switching it from scanning through columns of pixels to rows) and switching to bitshifts where possible. There’s a “QuickFill” method on the internets somewhere that would probably do it a bit faster.

The (bog-standard C) code below includes useful functions such as stack management routines, polygon rotation and drawing routines, and the accelerated line drawing routine. This might turn out to be useful for Woopsi - I’ve been meaning to write this for ages, and it does produce a speed increase over the current routine. Instead of plotting each pixel in the line one by one, it plots the first 8th of the pixels required, then copies those to the location of the next 8th. It then copies all of the pixels drawn so far to the location of the next quarter, and so on (you can see the pattern emerging - each copy is double the size of the last). A 16-pixel wide line will thus take 5 draw operations (2 plots and 3 copies) instead of 16. Any pixels left to be drawn after the copies have completed are plotted using the standard method.

Rotating Rectangle DS Code

Categories: Algorithms, DS Coding, PALib Tags:

PALib Palette Rotation

November 19th, 2007 Ant No comments

As PALib doesn’t include any functions for rotating a palette, here’s a function that will rotate the background palette on a given screen between two palette indexes. It will rotate in either clockwise or anti-clockwise order.

void RotatePalette(u8 screen, u8 start, u8 end, u8 direction) {
	if (direction == 0) {
 
		// Remember first colour
		u16 firstColour = BG_PALETTE[start + ((screen) << 9)];
 
		// Shuffle palette towards front
		for (u8 i = start; i < end; i++) {
			BG_PALETTE[i + ((screen) << 9)] = BG_PALETTE[i + 1 + ((screen) << 9)];
		}
 
		// Wrap end colour
		BG_PALETTE[end + ((screen) << 9)] = firstColour;
	} else {
 
		// Remember last colour
		u16 lastColour = BG_PALETTE[end + ((screen) << 9)];
 
		// Shuffle palette towards end
		for (u8 i = end; i > start; i--) {
			BG_PALETTE[i + ((screen) << 9)] = BG_PALETTE[i - 1 + ((screen) << 9)];
		}
 
		// Wrap start colour
		BG_PALETTE[start + ((screen) << 9)] = lastColour;
	}
}

To rotate the colours from indexes 10 to 20, for example, on screen 1 in clockwise order, use this:

while (1) {
    PaletteRotate(1, 10, 20, 1);
    PA_WaitForVBL();
}

To do the same thing in anti-clockwise order:

while (1) {
    PaletteRotate(1, 10, 20, 0);
    PA_WaitForVBL();
}

BG_PALETTE is an array that stores the colours for each 8-bit screen. In fact, it’s probably just a pointer to the palette memory. Anyway, the first 256 indexes are screen 0’s background palette. Indexes 1024 to 1279 are screen 1’s background palette.

Looking through the PALib code, it seems that the indexes between 256 and 511 are the sprite palette for the lower screen, and the same is true of the 256 indexes from 1280 for the upper screen. However, this system may have been removed at some point, as there appear to be two different implementations of sprite palettes, with this simpler method commented out.

Categories: Algorithms, Code Snippets, DS Coding, PALib Tags:

XCode PALib Template

October 19th, 2007 Ant No comments

Following on from the previous post about getting PALib and devkitARM set up in OSX, here’s some instructions for creating a PALib template project:

  • Download the PALib XCode Template
  • Unzip the archive
  • Drag the resultant folder to “/Library/Application Support/Apple/Developer Tools/Project Templates”

All done!

To create a project using the template:

  • Fire up XCode
  • Choose “File/New Project” from the top menu
  • Select “PAlib” from the template list
  • Click “Next”
  • Choose a project name and a location for the project
  • Click “Finish”

You’ve now created a basic PALib project that will compile (ROMs are put in the “release” folder) and run in an emulator.

Categories: DS Coding, OSX, PALib Tags:

OSX PALib

October 19th, 2007 Ant 9 comments

Quick guide to setting up PALib in OSX.

  • Download the correct version of devkitARM for your CPU architecture
  • Mount the DMG
  • Run the package and install to the default location
  • Download the latest stable version of PALib (make sure you get the zipped version)
  • Unzip the archive
  • Rename the resultant folder to “PAlib”
  • Open a Finder window and browse to /opt/local
  • Drag the “PAlib” folder into the Finder window - you will receive a prompt to authenticate yourself (click “Authenticate”), so type in your OSX password

That’s all of the files downloaded and installed. Next we need to start mucking about in the command line in order to replace devkitPro’s version of libnds with the version that ships with PALib.

  • Open a Terminal window
  • Type:cd /opt/local/devkitPro
  • Type:sudo mv libnds libnds_old
  • Enter your OSX password (the Terminal should prompt you with “Password:”)
  • Open a Finder window and browse to /opt/local/PAlib
  • Click on the “libnds” folder and press Command-C to copy it
  • Click on the desktop and press Command-V to paste a copy of the “libnds” folder
  • In the Finder, browse to /opt/local/devkitPro
  • Drag the copy of the “libnds” folder from the desktop to the Finder window (authenticate when prompted by entering your OSX password)

That’s all of the files set up. Now we need to add the PALib environment variable to OSX.

  • Load the file “~/.profile” into a text editor - if you have Smultron installed (and if not, you should do - it’s great) you can type this in the Terminal: /Applications/Smultron.app/Contents/MacOS/Smultron ~/.profile
  • Add the following line to the end of the file (you will have to type your OSX password in when saving):export PAPATH="/opt/local/PAlib/PAlib"

Nearly done now. The last thing we need to do is comment out a couple of bugs in the DS Motion card code - you probably don’t need to do this if you’re working in C, and you definitely shouldn’t do this if you need to use the motion functionality (you’ll need to wait for a proper fix in that case):

  • Open the file “/opt/local/PAlib/PAlib/include/nds/arm9/PA_Motion.h”
  • Comment out line 23
  • Change line 29 to:return 0;

That, I think, should be everything. Note that this is correct at the time of writing, using devkitPro r20 and PALib 070717.

Categories: DS Coding, OSX, PALib Tags: