Saturday, November 30, 2013

Nintendo Journal #15


Pull up exercise



Pull up bar, or chin up bar. I've always wanted one, but too cheap to buy one. Until I run into this on a Thrift store. Five bucks. Sold. I've been using it everytime I pass this hallway. Only about three pull ups everytime. I'm doing it not by repetition, but by duration. So, I'd better loading up on protein, because apparently, I'm not as good as I was before.

3 weeks into it, and I notice my upper body shape is solid! So it does work. No miracles, but for five bucks, I'm not complaining!

Friday, November 29, 2013

Petit Computer Journal #27

Boolean Operator Division

Have you ever wondered just how difficult it is to do division using nothing but NOT,AND,OR,XOR? Well, so do I. It turns out I also need ADD,SUB, and CMP. Also, Shift command. Still, these are easily within the domain of any assembly language programming.


  1. CLS
  2. A=RND(255):B=RND(15)
  3. ?A,B
  4. C=0:D=128:E=B*D
  5. FOR I=1 TO 8
  6. IF A-E>=0 THEN A=A-E:C=C+D
  7. ?A,B,C,D,E
  8. D=D/2:E=E/2
  9. NEXT I
  10. ?C,A
  11. FOR I=0 TO 8
  12. VSYNC 1:I=BTRIG():NEXT
  13. GOTO @DIV2


A contains the number to be divided. B contains the number that divides. This computes C=A/B and A=A%B. A pretty nifty code that fits single screen challenge. Notice, that you can also do it this way (untested) on line 6:


  1. A=A-E:IF A<0 THEN A=A+E ELSE C=C+D

This way, due to the calculation in Assembly language where the register holds the resulting value of the calculation.



Thursday, November 28, 2013

Book Review #12


Book #12 Simply Tai chi
Graham Bryant and Lorraine James

This is such a simple book that I got from a package. I believe it comes with DVD, although apparently I misplaced it. The good point is that it is clear, touches all the relevant points, and has good illustrations. The bad point is that the information presented is incomplete.

Half the book is dedicated for warming up and preparation. This is good. Most Tai Chi books just skipped between history and the forms. The activities here definitely helps in relaxation, necessary to do Tai Chi properly. The second half is dedicated to the forms, and here it fails. Not only there are only a pitiful few forms presented, but there is no sense of coherence. As this is personal, but I want to see feet weight distribution diagram to make it complete. There is no feet weight distribution diagram, nor there is some kind of directional marker. With the photograph shot at different angles, this can be confusing.

The book certainly simplifies Tai Chi so that it is accessible for everybody, and it certainly looks like fun. But I have to consider this to be an introduction to Tai Chi, as opposed to full formed Tai Chi.

Tuesday, November 26, 2013

Raspberry Pi Journal 38


Sync 


A little quickie here. One fine day, the Foundation Website features a tip of the day that says "sudo sync".

Well, that's strange. sync command does not require sudo, does it? And it does not. In fact, if you run it as sudo, not only the OS will login as super user before executing the command, it will also write to a log file after executing the command, hence, invalidating the write buffer. So, when you use a sync command, just type sync. Don't use sudo in front of it.

Another thing to worry about is whether or not it's safe to pull the card immediately after you issue the sync command. Turns out, it used to be not. An old version was set up as asynchronous, which is a fancy way to say that it runs as a background task. Therefore, you get the shell prompt immediately even though it hasn't finished executing. So that's bad.

The good news is that sync command cannot be doubled up. So, if you execute two sync command in a row, the second one must wait for the first one to finish. The solution is simple: run it twice!


  • sync; sync


And you should be fine.

One more thing. When you shutdown the device, do you need to use sync? Common sense says no. However, I always do. Better to be overly safe too many times, than a mishap happens once. Do you need to run it twice? No, you don't. The shutdown/halt command issues its own sync command, so you only need to do it once.


  • sync; sudo halt


And that should do it.

Monday, November 25, 2013

Cooking Journal #14


Baked Potato

It's always a hassle to skin a potato. That's why I never bothered. Sometimes, though, you want a good mash potato. My solution to that is to microwave the potato.



First, I make some cuts for ventilation. Exploding potato in microwave is very bad.



Then hit Baked Potatoes selection in the microwave. Let stand after baking.



The nice baked potato makes skin peeling easy. Just squish the potato. The skin will fall right off!

And that's it. Serve with butter and enjoy!



Saturday, November 23, 2013

Nintendo Journal #14


Digital Picture Frame



On one of my trip to Thrift store, I found this picture frame for cheap. Just a small one. I was hoping to be able to score the display for Raspberry Pi use. No such luck. The whole thing was integrated very well. I couldn't tell what kind of display that is, and the interface. In the end, it is a good digital picture frame. So, I use it as such.

Unfortunately, I don't have a good picture album to display. In the end, I simply download Nintendo 3DS data to a flash card, and stick it into the device. It shows mostly Animal Crossing New Leaf. This here is when I was visiting Morpheel's town. Monocot is the name of the town, but it was only once, a long time ago, and heavy thunderstorm. I remember the storm and Gulliver sleeping on the beach.

Friday, November 22, 2013

Petit Computer Journal #26

A Simple Interactive Story Reader

I am currently busy with Nanowrimo, and in the story, there is a program that lets student write their own interactive stories. Even knowing how little it takes to do it, I'm rather surprised at the economy of it. Here is the program in its entirety:


  1. REM INIT
  2. CLEAR:TITLE$=""
  3. DIM TEXT$[10]
  4. DIM PAGE$[4]
  5. DIM MENU$[4]
  6. CH=0:P$="INTRO"

  7. @SHOWPAGE
  8. RESTORE P$
  9. READ TITLE$
  10. READ TEXT$[0]:READ TEXT$[1]
  11. READ TEXT$[2]:READ TEXT$[3]
  12. READ TEXT$[4]:READ TEXT$[5]
  13. READ TEXT$[6]:READ TEXT$[7]
  14. READ TEXT$[8]:READ TEXT$[9]
  15. READ PAGE$[0]:READ MENU$[0]
  16. READ PAGE$[1]:READ MENU$[1]
  17. READ PAGE$[2]:READ MENU$[2]
  18. READ PAGE$[3]:READ MENU$[3]

  19. REM DISPLAY
  20. CLS:?TITLE$:?
  21. ?TEXT$[0]:?TEXT$[1]
  22. ?TEXT$[2]:?TEXT$[3]
  23. ?TEXT$[4]:?TEXT$[5]
  24. ?TEXT$[6]:?TEXT$[7]
  25. ?TEXT$[8]:?TEXT$[9]
  26. ?"1",MENU$[0]
  27. ?"1",MENU$[1]
  28. ?"1",MENU$[2]
  29. ?"1",MENU$[3]

  30. REM INPUT
  31. INPUT CH:CH=CH-1
  32. P$=PAGE$[CH]
  33. GOTO @SHOWPAGE




If the structure isn't clear to you, you need to add LABEL and DATA statements. Here's a sampling that I have. Notice, the DATA segments do go on, although each having the same structure.

  1. REM WINDELL

  2. @INTRO
  3. DATA "THE STORY OF WINDELL"
  4. DATA "ONCE UPON A TIME THERE WAS A"
  5. DATA "LITTLE RAT BY THE NAME OF"
  6. DATA "WINDELL."
  7. DATA " "
  8. DATA "SHE WAS HUNGRY AND IN SEARCH"
  9. DATA "OF CHEESE. WHERE DO YOU THINK"
  10. DATA "SHE SHOULD GO?"
  11. DATA " "
  12. DATA " "
  13. DATA " "
  14. DATA "KITCH","TO THE KITCHEN"
  15. DATA "BEDRO","TO THE BEDROOM"
  16. DATA "BADEND","STAY HOME"
  17. DATA "INTRO"," "

The DATA segments consist of a LABEL, 1 line TITLE, 10 lines TEXT, and 4 lines LABEL/CHOICE combo. Obviously there's also @KITCH, @BEDRO, and @BADEND DATA segments. There's also @GOODEND data segment, too!

The beauty of it is that the story can be long and involved. The size of the program stays the same regardless. This is a good introduction for computer programming, those of you who are just beginning. Obviously, it can be refined further. How about full screen text on top, and 8 or more choices on the bottom? Simple enough to enhance and experiment with.




Thursday, November 21, 2013

Book Review #11


Python Pocket Reference
Mark Lulz
11/21/13

I have Learning Python book and Programming Python book. They're good books. However, as tutorials go, they are too much. I don't blame Mark Lulz, the author, but those 3000 pages are too much for use as reference. There is another book: Python Pocket Reference. Unfortunately, I do not find much use for it. First of all, you need to have read Learning Python book in order to understand the terminology. Also, Python is surprisingly a thin language for something so complex. So, the pocket reference book did little to help me.

Bottom line? Get the excellent Learning Python book, and write your own Pocket reference book!

Tuesday, November 19, 2013

Raspberry Pi Journal #37


Trying Out Operating System


So, I was trying out different operating system. The two I want to check are Arch Linux and Raspbmc. So, here is my impression of them:

Arch Linux


This distro has been touted as "light" OS because of the minimal packages installed on it. I can certainly vouch for its minimalism. There's hardly anything there! Supposedly it has an excellent package manager "pacman" that lets you install the most current, desirable packages. Sadly, it's a whole new OS, and packages. That means, I have to learn everything from scratch. I did check out the package list, and although there are some overlap with Raspbian, some of the packages are custom version specific to Arch Linux. In the end, I decided that if I want a slim OS, I'd sooner clean up Raspbian out of unnecessary packages, rather than starting a whole new OS from scratch.

Raspbmc




I have heard that this distro is painless and fun. So, with great anticipation, I installed it. It's a simple matter to run NOOBS on it, and overwrite the SD card with this system. After some booting, the picture ended up skewed on the monitor. Uh-oh. Bad sign. Turns out it's not a problem at all. After a couple reboots, the system went up. It's just as they said: painlessly simple. I went around the menus, and admiring the user interface. There's no TV show, though. Hmmmm. I went to the option menu and installed some Internet TV connection. There's no connection.

Well, duh, obviously I need to connect it to the Internet. I completely forgot about that. The problem is, there's absolutely to option to scan Internet connection! None whatsoever. In the end, I have to look up my SSID, and typed it in exactly. Lo and behold! It worked!

The distro then went into automatic OS upgrade cycle. Auto re-boot. And that's the last thing I saw from it. It went to blank screen from then on. Sigh.

Monday, November 18, 2013

Cooking Journal #13


Potato chips

For a time, Lays was selling Sriracha potato chips. It's somewhere between BBQ and SuperHot. I love it. I just bought multiple bags of them. Well, Lays stopped selling them. Unfortunately, now that I know just how good potato chips with sriracha sauce can be, there's no going back! BBQ is not good enough anymore! So I cook my own.



 Regarding potato chip, I can tell you that the thinner you can slice it, the better! It's helpful if you have a slicer, then you can just set it up to the thinnest section. Paper thin is just right!



Frying them is simplicity itself. Just deep fry them until they float. You may even wait until they go slightly brown for extra crispiness.



It's okay if some of the chip "bubbles". It just makes it that extra crunchy!

Make sure to drain the oil with paper towel. Salt to taste, although personally, I never bothered. Serve with sriracha sauce. Delicious!

Saturday, November 16, 2013

Nintendo Journal 13


Trucker's Mug



There's a Big Man restaurant in Amarillo Texas that serves 72 oz Steak. Somehow I kept thinking of this 64 oz Big Mug to go with it. No comment. A picture is worth a thousand words.

Friday, November 15, 2013

Petit Computer Journal #25


Background Maker

A while back, I did a BGMaker program. That's a program that takes in graphic screen (GRP0) and turn it into background (SCU0) and background tiles (BGU0, BGU1, BGU2,BGU3). I had suspected it that it fits into one screen, and it did. Here is my entry to the single screen programming challenge:


  1. 'BGMAKER BY HARRY HARDJONO
  2. CLS:CLEAR:DIM TL$[1024]:MT=-1
  3. OX=0:OY=0:RX=31:RY=23:P$="G2"
  4. ?"GRAPHIC?":INPUT P$
  5. LOAD "GRP0:"+P$,FALSE
  6. FOR Y=0 TO RY:FOR X=0 TO RX
  7. X1=X*8:X2=X1+7:Y1=Y*8:Y2=Y1+7
  8. G$="":FOR YY=Y1 TO Y2
  9. FOR XX=X1 TO X2
  10. G$=G$+HEX$(GSPOIT(XX,YY)%16)
  11. NEXT:NEXT
  12. CT=-1:FOR I=MT TO 0 STEP -1
  13. IF G$==TL$[I] THEN CT=I
  14. NEXT
  15. IF CT==-1 THEN GOSUB @SETCHR
  16. BGPUT 0,OX+X,OY+Y,CT,0,0,0
  17. NEXT:NEXT:SAVE "SCU0:T0"
  18. FOR I=0 TO FLOOR(MT/256)
  19. B$="BGU"+STR$(I)
  20. SAVE B$+":B"+STR$(I):NEXT:END
  21. @SETCHR
  22. MT=MT+1:TL$[MT]=G$:CT=MT
  23. BU$="BGU"+STR$(FLOOR(MT/256))
  24. CHRSET BU$,MT%256,G$:RETURN


I also did a version with no memory. I'm not going to show it here because it's not only complicated, but also very, very slow. In fact, at one point, I actually put in an array to do it. That's when I decided to do a version with arrays instead.

Anyway, if you look at the code above, you'll see that it only works on single graphic screen. That's not what I want to have. I want to have the full 64 by 64 background tile generator. As you can see, from the variables OX, OY, P$, even though they do nothing in this version, the original design does take the full background field into account.

Here is the updated BGMAKER program that includes all available background screen. You'll need six graphic screens. They're all loaded into GRP0, but the build is done on different parts of BG screen.

'BGMAKER BY HARRY HARDJONO
CLS:CLEAR:DIM TL$[1024]:MT=-1
@PICFILE
DATA "G1","G2","G3","G6","G5","G4"
RESTORE @PICFILE

All this does is some initialization. I put the file names into DATA statements because I'm too lazy to modify the code. So I simply replaced all INPUT P$ into READ P$.


  1. 'LOAD GRPS
  2. OX=0:OY=0:RX=31:RY=23:READ P$
  3. LOAD "GRP0:"+P$,FALSE
  4. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER


Okay, you can see the pattern here. OX, OY are relative shifting or original X,Y coordinate. RX,RY are the size or width and height of the screen. I mentioned changing INPUT P$ into READ P$. Once I loaded the graphic into screen 0, I shifted the background to the appropriate place and call the @TILER subroutine. Since OX,OY are zeros, I guess I don't need to shift the background (using BGOFS), but I'm doing it here for consistency.


  1. OX=32:OY=0:RX=31:RY=23:READ P$
  2. LOAD "GRP0:"+P$,FALSE
  3. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER

  4. OX=0:OY=24:RX=31:RY=23:READ P$
  5. LOAD "GRP0:"+P$,FALSE
  6. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER

  7. OX=32:OY=24:RX=31:RY=23:READ P$
  8. LOAD "GRP0:"+P$,FALSE
  9. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER

  10. OX=0:OY=48:RX=31:RY=15:READ P$
  11. LOAD "GRP0:"+P$,FALSE
  12. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER

  13. OX=32:OY=48:RX=31:RY=15:READ P$
  14. LOAD "GRP0:"+P$,FALSE
  15. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER


As you can see, only the first line is being changed. I could have just put the whole thing into a subroutine. However, I'm not doing it because of the possibility that I don't have the whole 6 graphics to play with. If I only have four graphic screens, for example, it's easy for me to just comment out the necessary lines. This is judgement call, so you can certainly do it different. Whatever works.


  1. @SAVEBG
  2. SAVE "SCU0:T0"
  3. FOR I=0 TO FLOOR(MT/256)
  4. B$="BGU"+STR$(I)
  5. SAVE B$+":B"+STR$(I)
  6. NEXT 
  7. WAIT 300


Even though this is labelled as a subroutine. This is just a piece of code. It's not being called by GOSUB. I simply put the label there because I don't need to use comment. I could have, but simply decided not to.


  1. FOR I=0 TO 99
  2. X=RND(512):Y=RND(512)
  3. BGOFS 0,X,Y,60:WAIT 60
  4. NEXT
  5. WAIT 300


This is simply the scrolling of the background. You see 60 at the end of BGOFS call. This is equivalent of one second. So, I scroll for one second, while waiting for one second. What happens if I don't wait? Then the scroll will be reset immediately.


  1. BGCLR
  2. CHRINIT "BGU0"
  3. CHRINIT "BGU1"
  4. CHRINIT "BGU2"
  5. CHRINIT "BGU3"
  6. GCLS

  7. END


This code is necessary to reset the states to the original state. Otherwise, you will see that your screen is overlaid with your background. Of course, during debugging, that's quite problematic for me, since oftentimes the program does not run to completion, so I end up doing these commands by hand.


  1. @TILER
  2. FOR Y=0 TO RY:FOR X=0 TO RX
  3. X1=X*8:X2=X1+7:Y1=Y*8:Y2=Y1+7
  4. GOSUB @TILESTR
  5. CT=-1:FOR I=MT TO 0 STEP -1
  6. IF G$==TL$[I] THEN CT=I
  7. NEXT
  8. IF CT==-1 THEN GOSUB @SETCHR
  9. BGPUT 0,OX+X,OY+Y,CT,0,0,0
  10. NEXT:NEXT
  11. RETURN


There's some confusion here. I should have put the X1,X2,Y1,Y2 line into @TILESTR as it serves no purpose here. TL$[I] is the 64 hexadecimal string that contains the tile info. What the program does is simply set CT (Current Tile) to -1. Whenever the tile is found, CT is set to I. If the tile is not found, then CT will contain the value of -1. Then we know to store the current string (G$) into the tile array. After that, it's trivial to just set CT into the background.

Notice that I'm not doing mirror comparison. The documentation mentioned X,Y rotation. I'm ignoring that here. Actually, those aren't X,Y rotation. Those are mirror flip. If you want to you may want to modify the code to include that check. It's easy enough to do.


  1. @TILESTR
  2. G$=""
  3. FOR YY=Y1 TO Y2
  4. FOR XX=X1 TO X2
  5. G$=G$+HEX$(GSPOIT(XX,YY)%16)
  6. NEXT:NEXT
  7. RETURN


I have to make a decision here. Graphic screens can handle 256 colors. BG tiles can only handle 16 colors. What do I do? Well, if you notice, BG colors can actually have 240 colors. 256 colors-16 transparent colors. You can differentiate the different palettes, but I simply decided not to.

If you want to differentiate the palettes, then you want to store FLOOR(GSPOIT(XX,YY)/16) value and enter it into G$ so that it doesn't match equivalent pattern but different palette.

Another factor to consider is the X,Y mirror. Now you see why there's X1,X2,Y1,Y2. This is done for ease of mirroring. Normal: Y1-Y2/X1-X2. X Mirror: Y1-Y2/X2-X1. Y Mirror: Y2-Y1/X1-X2. XY Mirror: Y2-Y1/X2-X1. Note that I haven't done so, so the above is not guaranteed to work. Making it work is left as homework for the readers. ;)


  1. @SETCHR
  2. MT=MT+1:IF MT>1023 THEN MT=1023
  3. TL$[MT]=G$:CT=MT
  4. BU$="BGU"+STR$(FLOOR(MT/256))
  5. CHRSET BU$,MT%256,G$
  6. RETURN


Nothing to it. This simply increment the MT (MaxTile) counter and set the character to the appropriate BGUX bank.

And there you go. A very easy to do Background Maker. Here is the whole completed source code for your convenience. I suppose I should do the QR. Well, maybe sometimes in the future, or maybe not. Easy enough for you to do it by hand.



  1. 'BGMAKER BY HARRY HARDJONO
  2. CLS:CLEAR:DIM TL$[1024]:MT=-1
  3. @PICFILE
  4. DATA "G1","G2","G3","G6","G5","G4"
  5. RESTORE @PICFILE

  6. 'LOAD GRPS
  7. OX=0:OY=0:RX=31:RY=23:READ P$
  8. LOAD "GRP0:"+P$,FALSE
  9. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER
  10. OX=32:OY=0:RX=31:RY=23:READ P$
  11. LOAD "GRP0:"+P$,FALSE
  12. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER
  13. OX=0:OY=24:RX=31:RY=23:READ P$
  14. LOAD "GRP0:"+P$,FALSE
  15. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER
  16. OX=32:OY=24:RX=31:RY=23:READ P$
  17. LOAD "GRP0:"+P$,FALSE
  18. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER
  19. OX=0:OY=48:RX=31:RY=15:READ P$
  20. LOAD "GRP0:"+P$,FALSE
  21. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER
  22. OX=32:OY=48:RX=31:RY=15:READ P$
  23. LOAD "GRP0:"+P$,FALSE
  24. BGOFS 0,OX*8,OY*8,60:GOSUB @TILER

  25. @SAVEBG
  26. SAVE "SCU0:T0"
  27. FOR I=0 TO FLOOR(MT/256)
  28. B$="BGU"+STR$(I)
  29. SAVE B$+":B"+STR$(I)
  30. NEXT 
  31. WAIT 300

  32. FOR I=0 TO 99
  33. X=RND(512):Y=RND(512)
  34. BGOFS 0,X,Y,60:WAIT 60
  35. NEXT
  36. WAIT 300

  37. BGCLR
  38. CHRINIT "BGU0"
  39. CHRINIT "BGU1"
  40. CHRINIT "BGU2"
  41. CHRINIT "BGU3"
  42. GCLS

  43. END

  44. @TILER
  45. FOR Y=0 TO RY:FOR X=0 TO RX
  46. X1=X*8:X2=X1+7:Y1=Y*8:Y2=Y1+7
  47. GOSUB @TILESTR
  48. CT=-1:FOR I=MT TO 0 STEP -1
  49. IF G$==TL$[I] THEN CT=I
  50. NEXT
  51. IF CT==-1 THEN GOSUB @SETCHR
  52. BGPUT 0,OX+X,OY+Y,CT,0,0,0
  53. NEXT:NEXT
  54. RETURN

  55. @TILESTR
  56. G$=""
  57. FOR YY=Y1 TO Y2
  58. FOR XX=X1 TO X2
  59. G$=G$+HEX$(GSPOIT(XX,YY)%16)
  60. NEXT:NEXT
  61. RETURN

  62. @SETCHR
  63. MT=MT+1:IF MT>1023 THEN MT=1023
  64. TL$[MT]=G$:CT=MT
  65. BU$="BGU"+STR$(FLOOR(MT/256))
  66. CHRSET BU$,MT%256,G$
  67. RETURN



Thursday, November 14, 2013

Book Review #10


Programming Python
Mark Lulz

Programming Python is the more practical of the Learning Python-Programming Python pair. In all, I like this book better. I'm more of a practical programmer than theoretical one. As a Perl fan, I hate to see the oft-repeated attitude that Python is a "better Perl". Other than that, I have no problem. I am somewhat disappointed to discover that the thick 1500 pages tome does not cover PyGame. It does get a mention, but come on. Don't you think that if you don't have a space to cover that, at least reference some good books on it? I'm rather disappointed. Granted, the main purpose of the book is to write a clean, portable python programs, and in that mission, it succeeds admirably. But the lack of other resources cited remains a rather curious omission that would have made the book even more complete.

I also think that as good as it is, the book fails to convey Python's strength. Take this example from the clock (Ch 11, p748):


  1. def point (tick, range, radius):
  2.     angle = tick * (360.0 / range)
  3.     radiansPerDegree = math.pi / 180
  4.     pointX = int( round( radius * math.sin(angle * radiansPerDegree) ))
  5.     pointY = int( round( radius * math.cos(angle * radiansPerDegree) ))
  6.     return (pointX, pointY)


Reading the code makes it obvious that this is just a way to return a point, given angle and distance. In other words, polar coordinates. There are several marks, that I want to address.

  1. Why the parenthesis in (360.0 / range)? Precision should be no problem. The only reason that I can think of is variable types. I mark this as a drawback of strongly typed languages. The parenthesis should be optional.
  2. radiansPerDegree? Some languages provides that as a function. Why do you have to built your own?
  3. int( round( ? Come on. In any other language, it's either int() or round(). Definitely not both!
  4. math.sin(), math.cos(). Do you seriously prefer this to sin(), cos()?


And that's just the language. I suppose, if I'm feeling mischievious, I can point out that radiansPerDegree is completely internalized, and thus unnecessary complication. Just because the function takes radians, does not mean you have to convert degrees to radians. Like so:


  1. angle = math.pi * 2 * tick / range


You may put any necessary parenthesis where you want. If simple is better than complex, then the text code doesn't show. What's the matter? Can't think in radians? Don't you think that as a professional programmer, you should learn it? No computer language is so good that you can be sloppy!

And if I really nitpick, I guess I can complain about associating X with sin, and Y with cos, instead of the "proper" way X with cos, Y with sin. But I won't. ;)

And here's another thing, later in the book (p. 761):


  1. class PPClockBig(PhotoClockConfig):
  2.     picture, bg, fg = gifdir + 'ora-pp.gif', 'navy', 'green'

  3. class LP4EClock(GilliganClock):
  4.     size = 700
  5.     picture = gifdir + 'ora-lp4e.gif'
  6.     bg = 'navy'


and so on...

I counted 9 such classes. People have pointed out to me that Python is so powerful that it can take such flexible class arrangements. I agree that the language is powerful in order to take that. However, I'd rather see it in tabular form. A straight array will be simpler, cleaner, and clearer. Plus the advantage of loading it from file, so that you don't have to change the code just because you want a new background color. BTW, Perl can trivially do it via HereString, while retaining simplicity and clarity.

The book ends with a bad joke:

"But how will I know why Python is better than Perl?"

"You will know. When your code you try to read six months from now."

I think that joke is in poor taste. You're trying too hard to position "Python as the better Perl". My response?

"I get it. Your brain is spaghetti. However, instead of straightening your brain and learn how to code properly, you simply blame your tool. What kind of a workman, are you?"

I can still recommend the book, but it's not as good as Learning Python. Little distractionary things pepper the book, and I do not enjoy it as much.

Tuesday, November 12, 2013

Raspberry Pi Journal #36


Updating Raspberry Pi


This should be clear to everybody, but knowing that there are noobs out there, I thought I should mention this. Then again, noobs probably won't be able to find this page, so ... what can I say?

Anyway, when you try to install packages via apt-get, it is advisable to update the database. Those packages are indexed and you should refresh the index as to what packages are available and from where. It does take some time, but you really should update at least weekly. If a certain package you're trying to update is not available, then you should at least refresh the index and see if the list is outdated.


  • sudo apt-get update


Another thing that you can do is to upgrade all your installed packages to the newest current version. I don't usually do this, believing that if it ain't broke, don't fix it. But sometimes there is a feature that is new, and you want it. And if you're upgrading one, may as well upgrade the other. This kind of upgrade will not delete any packages. I would always do double backup before doing this, however.


  • sudo apt-get upgrade


Another kind of upgrade will actually remove obsolete packages. Presumably, this will keep your system current, and clean. I don't see this being done anywhere, however. Besides, if I really want to have a clean, current system, I'd rather rebuild than doing a simple upgrade.


  • sudo apt-get dist-upgrade


If you want to upgrade only one package, you can install it again. This will update only the package you want. I would use this most of all. Furthermore, you can install old package if you want. Check out the man page for details.


  • sudo apt-get install packagename


Any old, obsolete package should be removed. There are two kinds: remove and purge. The difference between them is that remove retains the configuration files in anticipation of future installation. Purge will remove not only the package, but also the configuration files, as well. Practically speaking, though, "remove" is the command you use if you want to lighten up your distro, but unsure whether or not purging of a package will break it. So you remove it, and see if everything still works fine. Then you purge it out of the system.

Speaking of different packages, you're probably wondering how you can tell what packages are installed on your system. Use dpkg command. You can get a list of the different packages that are installed on your system with this command:


  • dpkg --get-selections


You should see the list of installed packages, with the status "install" alongside it. As always, check the man page for details.

Monday, November 11, 2013

Cooking Journal #12


Home Fries

If you did the french fries last time, then you know how thick the cutting should be. Well, it's time for the next step in the potato frying: Home fries.



Which is exactly like hashbrown, except it's cut squares instead of string. And well, that's it.

Saturday, November 9, 2013

Nintendo Journal #12


Rubber band exercise



I really miss the old TotalGym. However, trucking life isn't really compatible with it. I tried having this thing with me, and I suppose it's better than nothing, but I don't thing there's enough resistance in it for it to be worthwhile. In the end, I just use body weight as exercise weight.

However, it does fit the niche for out-of-shape people who wants to gently ease into exercise routines. Me? I prefer old-fashioned dumbells.

Friday, November 8, 2013

Petit Computer Journal #24


Transferring Data from Petit Computer to PC

It's no secret that you can save the graphic screen to your SD card. What is the problem is that the data isn't stored flat. It actually is saved in character format, with block-sized groupings at that.

Discostew (of PTC MegaMan 2) wrote an article on the subject and Randomous reposted it here:

http://petitcomputer.wikia.com/wiki/GRP_File_Format_(External)

Well, that's fine and dandy if you want to use a separate program on the PC. What if you don't want to use a separate program on PC? Can you do the conversion right on Petit Computer? Of course. The question is: how difficult is it?

This is just an extremely simple problem. All I have to do is reverse the process, and I'd be done. Except, for some reason, I couldn't get it right. After four tries, and a whole day has gone, this is what I came up with:



  1. ACLS

  2. FN$="G0":'GRAPHIC FILENAME
  3. LOAD "GRP1:"+FN$,FALSE
  4. PNLTYPE "OFF"
  5. WAIT 180

  6. CX=0:CY=0
  7. FOR J=0 TO 2:FOR I=0 TO 3
  8. FOR Y=0 TO 7:FOR X=0 TO 7
  9. FOR YY=0 TO 7:FOR XX=0 TO 7

  10. GPAGE 0,2,2
  11. GPSET (I*64+X*8+XX),(J*64+Y*8+YY),CX
  12. GPAGE 1,3,3
  13. GPSET (I*64+X*8+XX),(J*64+Y*8+YY),CY
  14. CX=(CX+1)%256
  15. IF CX==0 THEN CY=CY+1

  16. NEXT:NEXT
  17. NEXT:NEXT
  18. NEXT:NEXT

  19. WAIT 60

  20. FOR J=0 TO 191:FOR I=0 TO 255
  21. GPAGE 1,2,1
  22. X=GSPOIT(I,J)
  23. GPAGE 1,3,1
  24. Y=GSPOIT(I,J)
  25. GPAGE 1,1,1
  26. C=GSPOIT(I,J)
  27. GPAGE 0,0,0
  28. GPSET X,Y,C
  29. GPAGE 1,1,1
  30. 'GPSET X,Y,0
  31. NEXT:NEXT

  32. WAIT 600


That's a two-step process. First, I load the graphic on the bottom screen, and encode the coordinates on GRP2 for x-coordinates, and GRP3 for y-coordinates. Then I use such coordinates to re-arrange the points on the top screen. You see such convoluted GPAGE commands because I'm switching back and forth among the different pages.

It works, but hardly elegant. The problem is that for some reason, my brain just can't wrap around the problem. Intellectually, I know the problem is a simple referencing problem. A pointer problem, for those of you doing in C programming language. And yet, the answer eludes me.

It's not until I'm at McDonald, getting my StreetPasses, warm and fed, that my brain functions again. Of course, after so many tries to the problem, my brain did start to warm up to the problem.

It was so trivial. I sketched the solution on the back of the receipt, and five minutes later, I was done! Here is what I came up with:


  1. LOAD "GRP1:FILENAME",FALSE
  2. PNLTYPE "OFF"
  3. GOSUB @SCAN
  4. 'SAVE GRP0 here...
  5. END

  6. @SCAN
  7. CX=0:CY=0
  8. FOR J=0 TO 2:FOR I=0 TO 3
  9. FOR Y=0 TO 7:FOR X=0 TO 7
  10. FOR YY=0 TO 7:FOR XX=0 TO 7

  11. GPAGE 1
  12. C=GSPOIT(CX,CY)
  13. GPSET CX,CY,0
  14. GPAGE 0
  15. GPSET (I*64+X*8+XX),(J*64+Y*8+YY),C
  16. CX=(CX+1)%256
  17. IF CX==0 THEN CY=CY+1

  18. NEXT:NEXT
  19. NEXT:NEXT
  20. NEXT:NEXT

  21. RETURN


Quite a big difference, wouldn't you say? I had all the pieces all along, and when I compared the solution on the receipt with my code, I realized that the code had it backwards. All I have to do then is to just switched the direction the coordinates was transfered! That's it.

Well, except it doesn't work, and Discostew pointed out that my latest code did double encoding, and the original "erroneous" code was right to begin with! Oh, well. So read in linear, and output blocks!

That's a reference, or pointer, problem. And guess what? As a programmer, you have to understand the concept of "reference". Like finger pointing to the moon. You look at the moon, instead of the finger. Simple, isn't it? Yet, so many people are confused.

So much so, that people are leaving C programming language for something easier to program. By that, they mean a programming language that does not use pointer. Guess what? The concept of reference is so universal in programming, it exists even in a pointer-less language such as BASIC.

Therefore, I say, you must learn the concept of pointers. If you don't, you just limit yourself to the problems you can solve.

Oh, and about this? I don't know why I was having such troubles. But I did solve it, and that's the important thing. The next time such a problem come up again, I'll be ready.

Thursday, November 7, 2013

Book Review #9


Learning Python
Mark Lulz

I'm trying to learn Python as part of my Raspberry Pi experience. O'Reilly has been a great source of learning in the past, and I do not see any reason to stop. I bought, sight unseen, three books: Learning Python, Programming Python, and Python Pocket Reference. All by Mark Lulz.

The content of Learning Python is comprehensive, informative, and extremely thorough. Worthy of any O'Reilly book. Unfortunately, I find the later section to be boring, and I was nodding my head off. The author, to his credit, understand this and wrote that the latter section is part of the advance section that only the most dedicated users will want to touch. He also helpfully highlights parts of the language that, at first sight, looks niche, but actually are used rather often. So, that is very helpful when you want to prioritize in learning the language.

The book is a tutorial book. The author provides plenty of explanations of how things work. Sometimes, I feel like there's too much information, but unlike fluffy padded books, I can't remove materials without sacrificing information. Therefore, I can say that the book is worth the number of pages it contained. There's only one complain. The book is 1500 pages long!

Don't you think that, maybe, it's better to split this tome into 3 books, instead? ^_^;

Another gripe, is that I think that the author is trying hard to position Python as "the better Perl". In that, it has all the Perl advantages, without the disadvantages. I'm afraid that's a common opinion, although I do not share it. One of the complain was that it's easier to write Perl from scratch than to read it. I take it as Perl is so easy to write, rather than Perl is hard to read. Another thing is that, taken in full context, Python is full of special cases that differs by little, each to its particular purpose. I keep thinking, "you mean you prefer this to Perl?"

Of course, it should be obvious by now, that I do not think much of Python. In fact, all of Perl's criticism can be easily levied to Python just as well. I never did find reading Python script easier than any other language. It's the programmer, not the language. In fact, at the end of the book, where the advanced section lies, the author warned the readers to use the knowledge judiciously, knowing that if the features are misused, it can lead away from Python's philosophy. You know what? Apply the same advice to Perl, and you'll get the same result!

So, now that I learned Python, I'm afraid to say that I am not a convert. However, as far as learning Python goes, this is the gold standard. I have yet to see any treatment that is more sophisticated, comprehensive, accessible than this tome. Just, please, split it into 3 books. My hands got cramped just holding it up. ;)
Highly recommended.

Tuesday, November 5, 2013

Raspberry Pi Journal #35


Cron Macro


Cron and the accompanying crontab is a scheduler. That is, you set the schedule for the programs you want to run at certain times. The instruction is clear enough, except, there is absolutely no instruction about the macro. By that I mean @hourly and others. I really can't find any instruction at all! I know @hourly is present because it is mentioned there. How about other macros? @daily, @weekly seem obvious. How about @minutely? Is that valid? I have no idea.

Here's something else: @reboot.

Yeah, I read that in some instruction pages somewhere, except I don't know how that person know that there is such instruction! It's not mentioned anywhere that I checked! Well, there's only one thing to do, then, isn't it? Try it out and see if the program really runs at booting time.

Strange that the macro is named @reboot. One would think that @boot would be more appropriate. No, I don't know if @boot macro exists. Like I said, there's no documentation that I can find anywhere.

Monday, November 4, 2013

Cooking Journal #11


French Fries


Last time, it was hashbrown. What do you do different if you want to cook some french fries?



The cutting. And the frying. The cutting is simple. Just cut them long. Instead of doing the second cut vertically, though, I did the second cut horizontally. If you want to keep the skin like I do, make sure to wash it really clean. I know from my trucking days, that they don't wash these potatoes. From the field to truck to processing plant and/or bagging. So clean those potatoes very, very well!



So just fry them. A little note. The first time you fry them, you may not know how hot the oil should be, or how thick you slice them. I always use medium heat, so for me, the heat is fixed. About the only thing I can change is the size of the slice. The outside will be crispy while the inside will be soft. There is a gradual change from crispy to soft. The trick, then, is to find out at what thickness the softness is desired. I find that cutting it to McDonald size yields the best crisp/soft ratio.



The color won't be as good as McDonald's version, but then again, they use beef extract to spruce up presentation.

Saturday, November 2, 2013

Nintendo Journal #11


Halloween Pumpkin Candy Bucket



There's a segment in Jimmy Kimmel where he asked parents to tell their kids that they ate all their Halloween candies. Such a mean trick! The kids are spoiled, too, by the look of it.

As for me, I really did eat all the Halloween candies all by myself. I had bought the whole thing one month early when they first go on sale. Then I eat a package or two or three, every day.

Come Halloween, I had to go out and buy another 2 bags of candies just to fill it up. I also put some protein bar in there, knowing I'll be taking some stuff from it everyday.

Friday, November 1, 2013

Petit Computer Journal #23


6. Loop with Player input + multi-thread


This time, we're going to do something that is common in complex games: multi-threading.

Multi-threading is a rather sophisticated and complex way to have multiple process going on at the same time. It is also extremely difficult to get right, especially if different processes depends on other processes. What I'm going to do is to simplify the problem, so that there is no dependency to the process.

We're going to set up and do multiple timers. Except, we're not going to do it the simple way using sprites. We're going to do it the hard way using internal timers: MAINCNTL.

MAINCNTL is the counting of frames since the program launched. Since there is a limit in the numerical accuracy, it is only able to count up to 145 minutes at a time. After that, it rolls over. So, our program must be able to handle that scenario.

The standard way to handle it, is to check MAINCNTH. However, in order to simplify the program, I'm not going to do that. What I'm going to do, is to store the MAINCNTL value for each thread, and compare it to the current MAINCNTL value. Then increase the timer for the difference. Surely, that method will lose a few frames over time, but I'm not worried. When the timer has minute resolution, a few frames missing isn't going to be a big deal.



  1. CLS:CLEAR
  2. DIM N(20)
  3. DIM M(20)
  4. DIM C(20)
  5. DIM L(20)
  6. DIM A(20)
  7. DIM T$(20)


  8. @TMRDATA
  9. DATA 0,99,"MAXTIMER"
  10. DATA 1,1,"QUICK TIMER"
  11. DATA 2,2,"SLOW TIMER"
  12. DATA 3,3,"EGG TIMER"
  13. DATA 4,4,"SNOOZER"
  14. DATA -1,-1,"DONE"

  15. @INIT
  16. CLS
  17. LOCATE 0,22:?"A START  ","B PAUSE  ","X RESET"
  18. P=1:RESTORE @TMRDATA
  19. FOR I=0 TO 19
  20. A[I]=FALSE
  21. IF P THEN READ N[I]:'TIMER NUMBER
  22. IF P THEN READ M[I]:M[I]=M[I]*3600:'TIMER MINUTES
  23. IF P THEN READ T$[I]:'TIMER LABEL
  24. IF N[I]<0 THEN P=0:TC=I-1
  25. NEXT
  26. CS=0:'CURSOR
  27. TH=0:'THREAD


Timers will have these operations on them: (A)START, (B)PAUSE, (X)RESET. It will have these data on them: (N)Timer Number,(M)Max Tick,(C)Current Tick,(L)Last MAINCNTL,(A)Active Status,(T$)Timer Label. We will also have something to process (TC)Timer Count up to 20.



  1. @LOOP
  2. 'PROCESS INPUT
  3. VSYNC 1:B=BTRIG()
  4. IF (B AND 1) THEN CS=CS-1:IF CS<0 THEN CS=TC
  5. IF (B AND 2) THEN CS=CS+1:IF CS>TC THEN CS=0
  6. IF (B AND 16) THEN A[CS]=TRUE
  7. IF (B AND 32) THEN A[CS]=FALSE
  8. IF (B AND 64) THEN GOSUB @TRESET

  9. 'PROCESS THREAD
  10. TH=TH+1:IF TH>TC THEN TH=0
  11. IF A[TH]==FALSE GOTO @SHOW
  12. IF MAINCNTL>L[TH] THEN C[TH]=C[TH]+(MAINCNTL-L[TH])
  13. IF C[TH]>M[TH] THEN GOSUB @ALARM

  14. @SHOW
  15. IF C[TH]==M[TH] THEN COLOR 13 ELSE COLOR 0
  16. TM=FLOOR((M[TH]-C[TH])/3600)
  17. TS=FLOOR(((M[TH]-C[TH])%3600)/60)
  18. TM$=RIGHT$(("00"+STR$(TM)),2)
  19. TS$=RIGHT$(("00"+STR$(TS)),2)
  20. LOCATE 0,TH:?" "*31
  21. IF CS==TH THEN LOCATE 0,TH:?">";
  22. LOCATE 3,TH:?N[TH];
  23. LOCATE 6,TH:TM$;":";TS$,T$[I]
  24. L[TH]=MAINCNTL
  25. GOTO @LOOP

  26. @TRESET
  27. A[CS]=FALSE
  28. C[CS]=0
  29. BGMSTOP
  30. RETURN

  31. @ALARM
  32. BGMPLAY 6
  33. A[TH]=FALSE
  34. C[TH]=M[TH]
  35. RETURN