Either I feasted too heavily or my jeans shrunk in the wash. Most likely both. I haven't eaten much today, so my pants are feeling better. Lemme tell ya, there was much feasting over the weekend. My parents woke me up at 9am every morning to feed me breakfast. Egg sandwiches, omelettes, and pancakes. A nice turkey dinner with yams, scalloped pineapples, cranberries, mashed potatoes, and hot rolls. I'm a little disappointed that I didn't get to have a turkey & mayo sandwich. I'm sure I could have had one if I made an effort, but I didn't. My parents used the leftover turkey to make turkey salad for sandwiches. The turkey salad resembled potato salad more than tuna salad, but it was edible.
***
Saturday, I was used to hang Christmas decorations at my parents church. I'm quite certain I'm the youngest attendee (when I'm there) and every else there Saturday are at least 30 years older than me. It was pretty fun though. They were all very thankful of my help; the church had been donated a 12' tree. They were lucky I was there for two reasons: I am comfortable on ladders, and I know how to read directions. It was a pre-lit tree, and the wiring was kinda crazy. The bottom section (A) plugs into section B above it. B has a plug that goes into a wall. C also plugs into a wall. D plugs into C. E plugs into D. Luckily, the angel on top doesn't light up. The angel was still a bit of a hassle because there were five little, old ladies trying to get me to align her properly. A little to the left. No, the other left. Now forward a bit. My forward. Yada yada yada.
My parents like to tell everyone I'm a computer guy. This does not mean I know how to (nor want to) fix a computer. This didn't stop the 70+ year old pastor from asking me to help with his computer. So of course I tried, but I didn't seem to get anywhere. It's not my fault Windows hates him.
***
There must be something wrong with my brain because I thought it'd be a good idea to drive to my parents with the top down. Now, it may have been 70 degrees outside, but with a slight wind and a speed of 80 mph, it was freakin cold! And far be it from me to pull over to put the top up. Screw that. The trip took longer than expected because I'm not the worse driver out there. There was a four car pile-up on I-4 in the middle lane. That was kinda near Disney, but there wasn't much traffic coming out of Disney at the time. So that averaged out with what I normally see on that stretch of highway. On I-75, however, there was a two mile crawl for some accident. By the time I passed, a minivan was being towed off. It looked like a little car took a nice chunk out of him.
Adding to my stupidity, I had a laundry basket in the back seat. I had tucked a shirt on top so nothing would fly out. Well ... I probably should have used a towel or jacket. Halfway through the trip, a rag flies from the back seat and hits me in the arm. I caught it instantly and tucked it into the laundry basket on the passenger seat. I double-checked the back seat (for what I could going 80mph at dusk) and resecured the shirt. About an hour later, a pair of underwear flies onto the dashboard. I turned around and saw a few shirts lying on the floor in back. This was a good thing and a bad thing. It was good that they didn't fly out of the car, but it was bad that they were flying around. I was scared that I was going to lose a shirt. (I'm foolishly in love with all my shirts.) Well ... I didn't notice any shirts flying out the back, and I think I still have all of them. But I don't really know if I'm missing one. Oh well.
***
I probably should have gone to bed earlier last night / this morning. I arrived at about 2:15am. Traffic was much better this time. Del came home at 2:30am, and we stayed up talking until 4:30am. I woke up around 10am to pick up Chill from the airport. He didn't get much sleep last night either.
I watched Se7en when I got home. Eh, it's not all that great. There's too much suspense at the end. Then I watched The Haunted Mansion. That too wasn't all that great, but I wasn't expecting much. It was quite different than what I had thought it was about. I thought they had inherited the mansion, but in fact, they are retailers trying to sell the mansion. That might not sound like much of a difference, but it is. I recommend avoiding both movies, but that's just my opinion.
I've been playing Final Fantasy Tactics Advance all weekend. I think it's good, but not great. The skills/abilities are a bit awkward. See, I avoid spending money (gil) as much as I can. But to learn new skills, my guys need new equipment. Generally for RPG games, I prefer using a strategy guide. I don't consider it cheating because I've got nothing to prove. I bought the game to have fun, right? That means I'll try to beat it in the funnest way possible. Which, for some games, does include using cheat codes. But those were mostly wrestling games. I cheated on Pokemon: Yellow after I had beaten the game. I didn't feel like beating the Elite Four eleventy billion more times, so I just used an infinite item cheat to get me rare candy. My Pikachu did get up to 100 naturally. Charizard: 79. Blastoise: 60. Venusaur: 54. Needless to say, Pikachu + Charizard = pwnage. But I've used strategy guides for Mario RPG, Yoshi's Island, and a few others. Oddly enough, I don't think I used a strategy guide for Fire Emblem. In my opinion, Fire Emblem is superior to Final Fantasy Tactics Advance. Especially since FFTA's storyline includes referencing the Final Fantasy videogame. *sigh* Oh well. Maybe I'll get far enough in the business to make a difference. But I was playing FFTA today. Overall, I do like it.
After my fun, I did my OpenGL work. I guess that could be considered fun too ... but I'm not that big a fan of Visual C++ 6.0. Remember, my laptop is still in the shop; I'm borrowing a friend's laptop. I had installed .NET, but it was a registered edition. So it wants me to buy a new license for this laptop. That's clearly too much work, money, and effort for me. Plus, I didn't bother installing the MSDN help files. I'd be happier with my work if you could actually tell that the fifth demonstration looked like it was in 3D. I mean, it is in 3D, but it's just a circle and a triangle. So you can barely tell. Plus, I don't really like OpenGL much at this point. It has its own main loop and I don't know how to break out of it, aside from just closing the window. And it doesn't refresh the screen on it's own, so I don't really know what good its main loop is doing. Jerks.
***
Boromir's rings.
***
Here's what I was working on for Machine Architecture (MAR). In bold are my comments. Good luck trying to read any of it without tabbing.
/*
Use bit map to track sprite allocation. The sprite data is
allocated in an array and tracked using a bit map. A one
on in the bit map shows that the sprite is in use. A zero
on indicates that the sprite data is free and not in use.
*/
#include
#include
#include
#define DEBUG 1
#define TRACE 1
static char const ident[] =
"$Id: msprite.c,v 1.1 2005/11/23 01:27:54 Owner Exp $";
#include "debug.h"
const int SHIFT_SIZE[17] =
{ 0, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7 };
// TODO:: explain macros
// ELEMENT_BITS: return the number of bits in an integer
// the default would be: 4 * 8 = 32
#define ELEMENT_BITS ((sizeof(int)*8))
// ELEMENT_MASK: returns the number of bits in an integer minus one
// this creates a mask for the lowest bits as predetermined in SHIFT_SIZE
// the default would be a mask for the lowest 5 digits
// 31 = 00000000 00000000 00000000 00011111
#define ELEMENT_MASK (ELEMENT_BITS - 1)
// ELEMENT_SHIFT: returns the predetermined "shift size" for the size of the integer
// this returns the number of low bits the mask uses
// the default size would be 4, so this would return 5
#define ELEMENT_SHIFT (SHIFT_SIZE[sizeof(int)])
// ALL_ELEMENTS_USED: returns an all bit mask
// the default for an integer would be: 11111111 11111111 11111111 11111111
#define ALL_ELEMENTS_USED (~0)
// TODO:: explain how all code that uses bit operators WORK
/*
sample line:
// increment variable. (WHAT not HOW)
fubar_variable = - (~fubar_variable);
comment: HOW and WHAT
increment the variable by complementing the bits which give you
the negative of the variable plus 1 and then making the number
positive by negating the variable.
*/
typedef enum
{ NO_ERROR = 0,
BAD_SPRITE_PTR = -1,
BAD_SPRITE_NO = -2,
BAD_SPRITE_IS_FREE = -3,
BAD_SPRITE_IS_USED = -4,
BAD_SPRITE_ALL_USED = -5,
BAD_ALL_SPRITES_FREE = -6
} sprite_error;
typedef struct _sprites_
{
int x; // Current Sprite location x,y
int y;
int rows, cols; // Size of Sprite Row x Col
char *elements; // Data to display (size is Row x Col)
int life_value; // Life force
int sprite_number; // Sprite number in set, zero based
} sprite;
typedef struct _allocation_data_
{
int number_of_elements; // number of possible sprites
int first_free; // first element with free bit
int shift_amt; // shift for entry index
int bit_mask; // mask to isolate bit number
int max_entry; // maximum entry in array of bits
int *bit_table; // bits for each possible sprite
int free_cnt; // number of free sprites
int used_cnt; // number of used sprites
} allocation_data;
typedef struct _sprite_tbl_
{
allocation_data salloc; // allocation data
sprite *sprites; // sprite data
} sprite_tbl;
/*
Allocate space to manage a group of "number_of_sprites"
using the defined structures. Allocate space, initalize
memory and return pointer. Return != NULL if no error otherwise
return NULL
Sample usage:
sprite_tbl tbl_ptr;
tbl_ptr = allocate_sprite_table( 1024 );
if ( tbl_ptr == NULL ) {
printf("Table allocation failed.\n");
exit( -1 );
}
*/
sprite_tbl *
allocate_sprite_table (int number_of_sprites)
{
static char my_fn[] = "allocate_sprite_table";
sprite_tbl sample, *tmp_s;
int i;
int last_element_no = number_of_sprites - 1;
enter (my_fn);
// Check size of int on this platform
if ((sizeof (int) + 1) > (sizeof (SHIFT_SIZE) / sizeof (int))) {
printf ("Shift table size exceeded, modify code for this machine.\n");
exit (-1);
}
// Check for number of sprites
if (number_of_sprites <= 0)
rtnval (NULL);
// Allocate space for for table area
tmp_s = (sprite_tbl *) malloc (sizeof (sprite_tbl));
if (tmp_s == NULL)
rtnval (NULL);
// Clear data area
memset (tmp_s, 0, sizeof (sprite_tbl));
// Allocate space for sprites
tmp_s->sprites = calloc (number_of_sprites, sizeof (sprite));
if (tmp_s->sprites == NULL) {
free (tmp_s);
rtnval (NULL);
}
// Initalize sprite numbers
for (i = 0; i < number_of_sprites; i++)
tmp_s->sprites[i].sprite_number = i;
// Set table initial values
tmp_s->salloc.number_of_elements = number_of_sprites;
tmp_s->salloc.shift_amt = ELEMENT_SHIFT; // Shift amount for each "int"
tmp_s->salloc.bit_mask = ELEMENT_MASK; // mask to clear unused bits
// Allocate bit table
//TODO::
// Allocates enough bits for the number of sprites passed in
// if the number of sprites is less than 33, it will only allocate 32 bits (1 int)
// in that way, it expands and contracts based on the number of sprites
// this also takes different integer sizes into consideration
tmp_s->salloc.bit_table = (int *) calloc (((number_of_sprites +
(ELEMENT_BITS -
1)) >> ELEMENT_SHIFT),
sizeof (int));
// Allocate the correct number of bits
if (tmp_s->salloc.bit_table == NULL) {
free (tmp_s);
rtnval (NULL);
}
// Set count of free sprites to number of sprites
tmp_s->salloc.free_cnt = number_of_sprites;
//TODO::
// Determines the maximum index in the bit table
// less than 33 sprites will only need 1 integer
// thus the maximum index will be 0: 32 >> 5 = 0
// 33-63 sprites will give 1 as the max: 33 >> 5 = 1, 63 >> 5 = 1
// this takes the size of the integer into consideration
tmp_s->salloc.max_entry = (last_element_no >> ELEMENT_SHIFT);
// Check bit usage in last element
//TODO::
// Checks if all the bits in the last entry index are being used
// 32 sprites will give 31 as the last element number, which will return false here
// if the number of sprites has unused bits in the bit table, this will return true
// the statement will turn on all the unused bits
if ((last_element_no & ELEMENT_MASK) != (ELEMENT_BITS - 1)) {
int tmp_bit = ((~0) << ((last_element_no & ELEMENT_MASK) + 1));
/*
last bit used (zero based) and add one to get next power of 2, shift
an all one value to the left to clear the number of bit positions and
then use that to set the last position in the table.
*/
// Fix last element for bits allocated after last element
tmp_s->salloc.bit_table[tmp_s->salloc.max_entry] = (tmp_bit);
}
rtnval (tmp_s);
}
/*
Return a pointer to a free sprite in the passed table. If no
free sprites are found return a NULL, otherwise mark the sprite
as "inuse" and return a pointer to the structure.
Sample usage:
sprite * sp_ptr;
sp_ptr = get_free_sprite( tbl_ptr, &err_flag );
if ( err_flag != NO_ERROR ) {
printf("Get free sprite failed with error %d\n", err_flag);
exit( -1 );
}
*/
sprite *
get_free_sprite (sprite_tbl * stbl, sprite_error * err)
{
static char my_fn[] = "get_free_sprite";
int i, *tmp, mask;
enter (my_fn);
if (stbl == NULL) { // bad ptr
*err = BAD_SPRITE_PTR;
rtnval (NULL);
}
if (stbl->salloc.free_cnt == 0) { // none free
*err = BAD_SPRITE_ALL_USED;
rtnval (NULL);
}
//TODO::
// Loops through the bit table to find an unused bit
// tmp is the integer for the first available bit table int
// thus, tmp will start at 0 to grab the first int in the bit table
tmp = stbl->salloc.bit_table + stbl->salloc.first_free; // point a first bit mask
for (i = stbl->salloc.first_free; i <= stbl->salloc.max_entry; i++, tmp++) { // loop through bit masks
if (*tmp != (~0)) { // All bits on, then all used, otherwise some free
//TODO::
// Determines the first sprite index in this bit table integer
// the 0th integer will have 0 as the first index
// whereas the 1st integer will have 32 as the first index
int bit_array_index = (i <<>salloc.shift_amt); // get bit number of first bit
int bit_offset; // count bits
int mask = 1; // mask for first bit
/*
Loop through all possible bit positions, count bits and shifting mask.
*/
for (bit_offset = 0; bit_offset < ELEMENT_BITS; // loop through bits
//TODO::
// Increments the loop variable: bit offset by one
// then shifts the mask over to grab only that bit
bit_offset++, mask = mask << 1) { // looking for 0 bits
if (((*tmp) & mask) == 0) { // bit off ??
bit_array_index += bit_offset; // get bit number
*tmp = (*tmp) mask; // mark bit used
stbl->salloc.used_cnt++; // one more used
stbl->salloc.free_cnt--; // one less free
*err = NO_ERROR;
rtnval (stbl->sprites + bit_array_index); // return pointer to bit data
}
}
*err = BAD_SPRITE_ALL_USED;
rtnval (NULL); // all used .... this means free count is fubar.
}
}
*err = BAD_SPRITE_ALL_USED;
rtnval (NULL); // all used .... this means free count is fubar.
}
/*
Mark a "inuse" sprite as free in the passed table. If the sprite
is not "inuse" or any other error return a nonzero value that
indicates the error.
Sample usage:
sprite_error sp_error;
sp_error = free_sprite( tbl_ptr, 5 );
if ( sp_error != NO_ERROR ) {
printf("Free of sprite failed with error %d\n", sp_error );
exit( -1 );
}
*/
sprite_error
free_sprite (sprite_tbl * stbl, int sprite_number)
{
static char my_fn[] = "free_sprite";
int bit_array_index; // get bit array index
int bit_mask; // get bit mask
enter (my_fn);
if (stbl == NULL) // bad ptr
rtnval (BAD_SPRITE_PTR);
if (stbl->salloc.used_cnt == 0) // none used
rtnval (BAD_ALL_SPRITES_FREE);
if ((sprite_number >= stbl->salloc.number_of_elements) // out of range
(sprite_number < 0)) // out of range
rtnval (BAD_SPRITE_NO);
// Get mask to isolate correct bit
//TODO::
// Determines the index in the bit table integer where the sprite index is
// it shifts the sprite number by the shift amount
// which would have the same effect as using modulas to get the remainder index
// such as: 33 % 32 will return 1, sprite index 33 is at index 1 in this integer
// Then it determines the bit mask for the given sprite index
bit_array_index = (sprite_number >> stbl->salloc.shift_amt);
bit_mask = (1 << (sprite_number & (stbl->salloc.bit_mask)));
// Check for bit on
//TODO::
// Checks for the sprite bit on by anding the integer with the mask
// the bit mask will return true if the sprite bit is on
// and false if that sprite bit is off
if ((stbl->salloc.bit_table[bit_array_index] & bit_mask) != 0) {
//TODO::
// Frees the sprite by turning the sprite bit off
// it is turned off by anding the integer with the opposite of the bit mask
// the opposite of the bit mask will have all the flags on except this sprite
// anding the integer with it will then preserve all the other bit states
// while turning off the bit for this sprite index
stbl->salloc.bit_table[bit_array_index] &= ~bit_mask; // turn bit off
stbl->salloc.used_cnt--; // one less used
stbl->salloc.free_cnt++; // one more free
if (bit_array_index <>salloc.first_free) // reset first free if needed
stbl->salloc.first_free = bit_array_index;
rtnval (NO_ERROR);
}
rtnval (BAD_SPRITE_IS_FREE);
}
/*
Get the pointer to an "inuse" sprite in the passed table. If the
sprite is not "inuse" or some other error return a NULL.
Sample usage:
sprite * sp_ptr;
sprite_error err_flag;
sp_ptr = get_used_sprite( tbl_ptr, 5, &err_flag );
if ( err_flag != NO_ERROR ) {
printf("Get pointer to used sprite failed with error %d\n", err_flag );
exit( -1 );
}
*/
sprite *
get_used_sprite (sprite_tbl * stbl, int sprite_number, sprite_error * err)
{
static char my_fn[] = "get_used_sprite";
int bit_array_index; // get bit array index
int bit_mask; // get bit mask
enter (my_fn);
if (stbl == NULL) { // bad ptr
*err = BAD_SPRITE_PTR;
rtnval (NULL);
}
if (stbl->salloc.used_cnt == 0) { // none used
*err = BAD_ALL_SPRITES_FREE;
rtnval (NULL);
}
if ((sprite_number >= stbl->salloc.number_of_elements) // out of range
(sprite_number < 0)) { // out of range
*err = BAD_SPRITE_NO;
rtnval (NULL);
}
// Get mask to isolate correct bit
//TODO::
// Determines the index in the bit table integer where the sprite index is
// it shifts the sprite number by the shift amount
// which would have the same effect as using modulas to get the remainder index
// such as: 33 % 32 will return 1, sprite index 33 is at index 1 in this integer
// Then it determines the bit mask for the given sprite index
bit_array_index = (sprite_number >> stbl->salloc.shift_amt);
bit_mask = (1 << (sprite_number & (stbl->salloc.bit_mask)));
// Check for bit on
//TODO::
// Checks for the sprite bit on by anding the integer with the mask
// the bit mask will return true if the sprite bit is on
// and false if that sprite bit is off
if ((stbl->salloc.bit_table[bit_array_index] & bit_mask) != 0) { // bit on ??
*err = NO_ERROR;
rtnval (stbl->sprites + sprite_number);
}
*err = BAD_SPRITE_IS_FREE;
rtnval (NULL);
}
int
main (int argc, char **argv)
{
static char my_fn[] = "msprite";
sprite_tbl *my_sprites;
sprite *tmp_s;
int i, number;
sprite_error err;
sprite_error *err_ptr = &err;
enter (my_fn);
set_debug ();
Log_debug ("This is the start of the program");
if (argc < 2) {
printf ("%s n\n", argv[0]);
printf (" n - count of sprites\n");
exit (-1);
}
number = atoi (argv[1]);
my_sprites = allocate_sprite_table (number);
if (my_sprites == NULL) {
printf ("Unable to allocate sprite table\n");
exit (-1);
}
for (i = 0; i < (my_sprites->salloc.number_of_elements + 2); i++) {
if ((tmp_s = get_free_sprite (my_sprites, err_ptr)) == NULL)
printf ("Get free failed on try %d with error %d\n", i, err);
}
printf ("After get_free, used = %d, free = %d\n",
my_sprites->salloc.used_cnt, my_sprites->salloc.free_cnt);
for (i = 0; i < (my_sprites->salloc.number_of_elements + 2); i++) {
if ((tmp_s = get_used_sprite (my_sprites, i, err_ptr)) == NULL)
printf ("Get used failed on try %d with error %d\n", i, err);
}
printf ("After get_used, used = %d, free = %d\n",
my_sprites->salloc.used_cnt, my_sprites->salloc.free_cnt);
for (i = 2; i < (my_sprites->salloc.number_of_elements); i++) {
if ((err = free_sprite (my_sprites, i)) != 0)
printf ("Free for sprite %d failed with error %d\n", i, err);
}
printf ("After free_sprite, used = %d, free = %d\n",
my_sprites->salloc.used_cnt, my_sprites->salloc.free_cnt);
for (i = 0; i < 2; i++) {
if ((tmp_s = get_used_sprite (my_sprites, i, err_ptr)) == NULL)
printf ("Get used failed on try %d with error %d\n", i, err);
}
printf ("After 2nd get_free, used = %d, free = %d\n",
my_sprites->salloc.used_cnt, my_sprites->salloc.free_cnt);
rtnval (0);
}
4 Comments:
Going for longest post ever on a blog? Glad to hear you had a nice Thanksgiving--hope you still have all your shirts!
Eh, not my fault Matt wanted to see my homework. I'm pretty sure I've had longer posts, but I don't pay all that much attention. I mostly just skipped reading this assignment in my post.
I looked a bit at the code, even copied it into a file and ran 'cb' on it to get the indentation back. But then I got bored. Anyway, using the two's-complement of the one's complement to do an increment is cute, but I'm not convinced it's more efficient. I suppose it depends greatly on the specific machine architecture.
Also, it's not so much that the 'default' size of an int is four bytes/32 bits, but rather that it's the most typical size these days. Again, it's machine specific.
[ cb == C beautifier. It's not all that great with C++ though. ]
I'm confused as to why you're saying that "using the two's complement of the one's complement to do an increment is cut, but I'm not convinced it's more efficient." Are you referring to their code or my comments? Because two's complement wasn't intended to merely increment one's complement. I don't know what it was intended to do.
Post a Comment
<< Home