Programming The Nintendo Game Boy Advance: The Unofficial Guide
Programming The Nintendo Game Boy Advance: The Unoffic...
88 downloads
497 Views
12MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Programming The Nintendo Game Boy Advance: The Unofficial Guide
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Programming The Nintendo Game Boy Advance: The Unofficial Guide
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
! "
$
! ! #
" %
&
! '* ,
!
"
&
'((" " " ) +
'
., + *
/ !4
0 !-
5
7
0
!
(
!9
!
+
: ;;! 8
#!
(
!6
12! +
" !7
8! 7
0 7
!3
"!7
! +
( !7
+
+
:
5
(
" % "
<
"
4 "
!
! !
$
! =
4 4 0 ' >&?@ /
&
& @&1 5
2 ? 1 A0
> @BA1?2
" "
>
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/
!
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" 4
" "
C
! " D6
+ " !7 0 "
E
4
,
*
H I
4
!* F 9 ! ,
! !4
!"
C
" '
" C
" "
) LM! #
G
! G
I % J % ,
%
N: K4- 7 M! / !" "
%
4
! 4 7
"
&
"
!
" G4
!% ) " ! "#$ "
-
!
7
N " " !+ <
) "
% "
+
% "
!
* "
! " "
"
!:
"
" N:
7
., +
#
%
!
/ &
G & G
! & & 4
/
!
!
!
" / !
"
G
7
"
"
-
4
) #
4 7
!
4
' G
G7
"
!
J
% K" " " -
!"
4 )
F 0
!
!
"
%
"
! N
"
4"
!
=
! !
" !
=
-
! "
& & #
& -0
"
! O4N ,
J "
"
"
"
!
* 7C
!
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!% !
LO %
! /
#
47 *
!% %
& "
" -0 %
"
! "
4
< )
"
)
%
" !
"
! "
!
! " 2 PK , # !
!
4 )
" =
!
!
!
M *
N" %
! +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
., + )
!
%
0
4:
0
% 7
/
!
!9 7 9
4
0 4
!9
" !
>@@A " !
" !
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! +
" : ;;! !
!9 0
+ B
-6 & B1 "
*% : ! 4
!
"
!
"
: ;;!
!
)
:! 0 6
%
! !
"
%
>? : ;;! 6
! ! !
: J
"
4
! " : 6
# > % %
9
-
:
6
L
-
%
:
:
7
9
-
0 + : %
>1&0
* J
7
:
6 %
Q
4 5
H
4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0
J -
&
:
&0
0
',
J :
:
:
R
: -
<
0
-
4
0 -
0 ! >@B@
-
0
/
-
0
:
-
0
-
0
7
! >@@1 ! >@@B !
> /!
"
+ 4
6
= +
*#
6
= +
:
+ -
=I + +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
7
-
+ 9
+
/
+
I ) %
:
+
/
%"
4
: /5 = %
%
&0
+
KS TM
+ +
>
+ 0
&0
+
K S T?M
+ +
2
+
?
%
:
: -
R
0 0
<
7
% 7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
7
=+ A
*
'%
C
=
5
*
6
/
9
7
+ 7C 4
+
+ %
Q 6
9
4
+ *
7
%
4
+
4
9
+
:
9 -
0
-
0
=
:
/
* H
5
+
5
J
R
2 6 0
+
/
:
%
7
+ 6
=
*
-0 : ,
<
% -
0 0
/
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
Q
:
*
6
+
J
4 %
:
" / )
6
-
/
:
"
:
-
% 7
Q
/
-
/
*
/# 6
7
"/#
:
7
%
7
6
J
/
"/#
"/#
: /
/
*
J /
:
J
% 0 6
/
0
% 0
%
0 /
%
+
%
J
*
/
:
=
/
J
7
:
/ %
% 7
: /
/
* -0
: ,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
: :
R
<
$
!! %
&
: 0
? &0
9
4
'
+
0 %
4
"
9 7
0
< 6 7
7
6
+
"
0
9
7
"
/#
7
"
,
7
"
:
7
"
J
"
+
=
0 #
0 :
B&0
:
0
7
"
:
0
>?&0 4
-
0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4 0
J
6
6
+
7
2
6
7
"
/#
7
"
0
/
" % 5 6 7
6
+
"
/#
% /
/ ?
+
?
% # I % %
J
%
&: 7
J
"% # /
: :
: %
R
<
1 &0
4
9
+
% %
&0
9
+
0 0 % %
%
7
%
+
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
:
0 :
%
J
0
%
6
7+
+
:
: =
0
:
%
:
%
=
% %
4 +
+
:
: :
R
: =
<
A 5
, N+
'/ 4
6
:
% : :
-
J % %
5 ,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
, 7
%
,
" :
%
%
:
: 6 %
7
%
7 Q
0
:
%
J
%
+
=
<
J %
0
* 4
0 0
% %
%
J
%
%
J
= %
=
/
%
=
J
%
=
J
: :
R
<
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!!! (
%
: 5 5
B 4 4 %
5
%
4
%
/
%
4
%
J
%
4
%
J
% %
%
%
%
/
%
%
%
%
%
%
J
:
/
%
J
%
J
: :
: %
R
<
@
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4
%
/
-0
" J+ 5
7
7
/
+ # /
7
J
/
7
%
%
/
:
%
%
%
%
J
%
%
J
/
/
% %
J
/ /
C
J %
%
/
J
%
/
J
: :
R
<
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
: 4 %
> 6
%
0
0
7
0
4 J
%
0
0
/
+
0
:
9
4
7
0
0
-
O
%
:
:
O
I 0
4
0 + %
7
0
0
/
0
:
: :
:
R
<
>> =+ A
,
4
/
% : :
J :
&, % :
:
:
, 0
J
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
:
/ J
% %
:
:
,
: ,
0 J
%
: K9
:
J ,
,
M0
:
0
=+ A
J
, /
%
J
/
:
J +
%
%
7
J
J
:
:
"/#
:
:
%
*#
/
: :
R
<
!) (
*
*
' +
# :44 : #0 =
0
6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
=
0
=
6
#: -
0
"
=
+ 0
9
% 0
0 9 7+ 4 +
=
%
" :
#7 % %
:
R
<<
>
: : :
2
:
?
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
:
1
:
A
:
B
:
@
:
>
:
>>
5
#* % : 7 &=I +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
J
" J 5
>
!
-
0 !
"
-
0 ! "
"
" !
< ) 0
"
)
N
"
"! N
*
N
7
! *
H
"
" &
N "M
-
)
: '!
0 " "
" N
#
"
0
N 6
/
/: "
=I + M 4 N
! 6
!" )
K
#
N "
0
" !
" & ! "
! -
K 0
N
$ 6
"
Q %
L
= -
7 '((" " "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
N
"
4 %
-
0
!"
&
! >1& -
+ >
!
!
!
0
!"
"
" 0
"
! !"
-
"
>2 !
!
% "
!
4 0
"
K K
M! -
"
0
!2
!
"
!
0
L
-
"
6 : 7 &=I + I
7 97
-
! -
0 !
"
K
-
0
0
0
! "
1
0
! -
M >2
!
J
"
-
0
:
M
!
"
-
-
" 0
0
"
! K>B& 2M
Game Boy Development 5
!
" % #
$ # #
' "
" " & !
" %
G
"
!
N
"
/: !
N $
"
!
0
" !
" !
!
$ -
M %
" Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# K
!
! M! "
0
!
K $
! $
&
K 7 M % "
4
"
"
!
I
" R !
K " "
" $
M!
"
/:
"
!
#
!"
"
/:
*# "
!
%
/: $
* !
!
!
" +
! 0
M
"
K !
So You Want To Be A Console Programmer? %
" %
) -
0
K
"
7
" : /5
=+ A : /5 M
!
!/ 0
' 9: = ! 7 97 /: ! - / 4
K
! %9 ! ! " =+ : /5 !
7
!+ /
!7 , 7
!
7
7
: /5
-
0
M
%
" !
=+ : %
"
"
$
" " "
"
M
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
K%
0
=+ !
0 "
7
Software Development Kits H
"
'
" -
"
K
%
" K -
" !
" ,
* 4
/
"
,
#M %
N
!
0
*
-
47 * !
!% ! 9 0 =I +
& +
" 0
, "
#
" ! 6
& "
,
-
#!
" 0
Q6 "
! "
#! 4 + "
'((" " " " ) , #
" %
"
0 ,
" +
#
=I + ,
" !
#
" 6
" !
" =I +
J
" !
%
# /: N
% !"
& H
!
+ + :( 7
"
"
"
"
0 !% !
+
N6
"!" -
!
%
, 6
! " !
!
# %
L !
0
M
K -
-
0
0
4 K47 *M "
6
-
Q%
M
"
%
0
"
0 "
! 5 0 +
(" J I
!:
"
!
-
0
)
" I -
$ 0
! !
$ &
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" 6 !
!
" " N
$
!
4
! !
&
"
-
0
0
!
"
9 "
+
" " :
"
+ !
-
H
0
2! O
6
I !
!
%
% !O
0
& "
6
"
-
"
0
!
'((" " "
&
Is This Book For You? +
"
)
-
0
!
! %
4
N"
)
"
%
) "
"
/:
%
"
"
" 6
4
!
/:
/: " K"
L4 " :
7
8
"
!
" !
"
-
" :
"
% !
+
: H
9
0 J
(
/:
M :
:!
"
! 8
N !
:/5 !
" N
6
!
(
#
"
J 8 !7
7
# < !" + &7 I
L
/: !
/: " !
"
!
!
%
H = 4
N
" #
! C
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# !
!
! N
$
4:
!" "
4
$) ! "
"
'
0
:
! !
:
"&
4
N
"
: ;; & ! "
#
N"
-
"
N
!
0
+
0
K
$
#
-
J
0 "
L4N
!
4
-
* $ ++
0
4
"
: ;;
!
!
"
:;;
"
" ! ! 4N
K" M
!
M
: $ ++
, !% " -
+
$++
.
: ;;
System Requirements %
$ $
! >
/ "
"
" "
0
) "
!
!
U U U U U
-
7
" 6 8
" &
/: * K
" M
/: ' 6 " @?! %! / 44 + < > B +0 +0 B +0
Book Summary %
' !
"
#
%
" -
0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4
"
!
-
0
+
" 9
!! $
%
!
" M
0 &
+ 7C K
'
%
# # ! !<
! !!! (
9
-
0
K "
&
"
! &
!
M!
!
!
%
%
"
-
0
!
! !
!) % 6
(
*
*
!
' + !
! -
"&
0
" : 7 &=I +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
: 44 !
"
! $ << !
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
) ! #
$ %
$ %
"
&
'
()
'
+
'
,
'
.
* *
'
)
)
* *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" #
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
) !
"
# !"$
"
!"
# %&
'(
)
*
$
*
+
* , *
*
*
*
* *
* -
. • • •
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
*
/
0
1
2
33 *4 #
$
+
5+
*
*
1
* ,
6
+
-
*
*
4 #
"/
$
4
4,
,
Getting into the Nintendo Thing /
6 & "
7
7 8
39:3 &
*
<
8 ;
*
*
"
*
7
< 7 *
!
=& 6 * " 4
&
8
<
7
!"
*
) *
* !" 7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
)
!"* *
#$ *
*
$* +
6
(.%
%
&
#% '( ) '
**
*
?) &
* > ) /; * $
*
6
"
!"* #4
)
*
Console Contemplation 4
/)
*
*
2
*
@ *
* .
* )
*
*
A 7
>
(: 7
4 /) *
.
* *
/) , :
* /)
*
*
") 44
6
*
*
3
) 3
* *
" *
) .4
%:(
#
7
*
$
Definition of a Video Game B
*
* * 5 C4
, *
C
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/) C
! C
"
"
50
*
/)
" * 2 /
,
.7
)
/
"
*
14 *
2
+ "
7
* /)
1
@ "
6 D
>
A Brief History of Nintendo 4
*
3::9
39E3* 7
)
*
<
2
@
7
*
7
-
4 39E3 7 -
*
)
/
)
39F= @
)
C 39GF *
C
, B
< 06
7 39GE
'
06
4 39G: * * . *
, 4 39GG* 3E *
B 7
*
/ *
6
+
3F 39G:* 39:F =*FFF
, #
$*
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
* 6
# 8
*
*
='FF
*
Shigeru Miyamoto *-
@
#
*
!
* 7
"
*
# @
*7
,
7 @
#
7
*
7
* *
*
*
&
#
&
8
8 *
$ !
'
/
) -
2 334 5
467
#
2
$
Home Consoles 4 39:% / 0 *
:6
!"
1
<
* *
;
! ' "
/
*!
*
'
# $
* + <
,
2
, !" > ; " *
; " ; " 2
*
2
)
39:E 9F
#4
*
$
&
!"* < :6
'EF=
*
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
* 2 3*G9F
* #3 G9
!
7 - 1$ 7
.
*
*
*
*
* 9 '
)
) !
)
39:9
(+
* ,
@ H +
)
)
4 $ ! ' 6 )
*
2
! :
$ $
.
( ) ' 2 '2
0
/
8 ) )
)
2
39:F
) 2 9 ' 9 ' $
#
) *
*
*
'(
* $
#8
: 2 *
>
* #8 $ 4 8 8
: *
>
The 16-Bit Era 4 3993
3'6
*
"
!"
*
8
*
" >
*
> 4 3993 "
, 4
.
*
*
3'6
* *
* *
# ?
*
$
* ,
*
*
* ,
*
>
Success and Failure 2
*
399F *
:6 6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
3'6 "
!"
"
%=
+
%=6
*
0 D D 399F *
#
$
A Detailed Comparison 33
* !
( (
=F
'
$
/
%
'
1985
Nintendo
NES
8-bit
1989
Atari
Lynx
8-bit
1989
Nintendo
Game Boy
8-bit
1990
Sega
Genesis
16-bit
1990
NEC
TurboGrafix 16
16-bit
1991
Nintendo
SNES
16-bit
1991
Sega
Game Gear
8-bit
1993
Atari
Jaguar
64-bit
1993
Sega
32X
32-bit
1994
Sega
Saturn
32-bit
1994
Nintendo
Virtual Boy
32-bit
1995
Sony
PlayStation
32-bit
1996
Nintendo
Game Boy Pocket
8-bit
1996
Nintendo
Nintendo 64
64-bit
1998
Nintendo
Game Boy Color
16-bit
1999
Sega
Dreamcast
128-bit
2000
Sony
PlayStation 2
128-bit
2001
Nintendo
Game Boy Advance
32-bit
2001
Nintendo
GameCube
128-bit
2001
Microsoft
Xbox
128-bit
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
* :6 $
4 '(6
* 3'6
* *
3=:6 *
%=6
#
4 &
*
*
*
,
What Happened to the Atari Jaguar? < '(
/
<
" 47 #
$ * ,
$ ,
) <
4
+
* 5
*
6 <
*
* * 8
&
<
" :!
6 . <
399%*
#
<
7
*
,
*
1
!
*
5 *
"
* * " !"
" *
* <
The Importance of Goals &
* 5+
*
4 %
&
;
% '
1
*
@ 6 *
6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Use Your Imagination ;
& *
,
+ C
*
C
4
* 1& >
*
* #7
*
@
* $@
, 1!
*
4
*
Build a Franchise 4 ,
" /
*+
+
/
<
* )
*< * I 6
! 7
"
6 & <
/) 14
*4 *
*
A <
*
#
:!
!
*
A *,
/) "
A
)
6 8
5) 7
$
C
C
Genre- and Character-Based Franchises )
*
*
5) 7
6 !
' &
/
*!
'
/
0 *
* * C7
7
* !
* ...
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
* "
5# *
$
8
C *
:!
@ *
D *
* *
> 2
*
, *+
*
*+
* C7
C
6
* 5
* )
*
#$
4 "
*&
7 0
*
* 4
)
*
* , *
"
>
>
*
4
46
* *
%&
46
* %&
4,
#
#
6
$*
$
Strike a Balance: Level Count vs. Difficulty -
7 *
46
5J
*4 !"
" 7 =F
! #
# '
/
5&
# $*
$* #
,
$ *
7
7
7 *
* +
* $ &
* 4 *
$
6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5#
!" *
Surprise the Critics +
5 &
* #
*
$
*
&
* 5
*
>
# $ &
+
4
*
,
1
* *
4 <*
*
&
* >
-
. ( 4
*
+ 0 @
*
, 2
*
4
Summary * *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
*
*
Chapter Quiz > >
3F
6
> &* C
)
3 +
J
C 5
" ) & " = +
!"
5
< , ) &
:
% -
%:(
5
(: 3' ) %= & '( ( +
! ) @ " & "
E +
'
/
5
@ @ 7
* 3::9* " 7 2 @ ) @ & @
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5
' +
C C? C ) C+ & C-
6
6 C*
8
*
C C C *
C
G +
!
"
<
5
!" 7 ) 2 & "
7 ) 2
: +
, & " ) 7 & )
5
8 4 B
9 +
5 " ) @ " & < A
@ 7
3F +
5 3'6 %=6 ) '(6 & 3=:6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
"# $
% %
&
%
% '
& ' %
%
%
%
% (
)
* • •
$
•
,
• •
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
'
Game Boy Handheld Systems %
-./. 0
1 2 2 3 '
%
4-
Table 2.1 Game Boy Specifications Model
CPU
Memory
Display
Colors
Game Boy
8-bit Z80 4.17 MHz
64 Kbits
160 x 144
4
Game Boy Pocket
8-bit Z80 4.17 MHz
64 Kbits
160 x 144
4
Game Boy Color
8-bit Z80 8.0 MHz
384 Kbits
160 x 144
56
Game Boy Advance
32-bit ARM7 16.7 MHz
3,072 Kbits
240 x 160
32,768
Game Boy Advance SP
32-bit ARM7 16.7 MHz
3,072 Kbits
240 x 160
32,768
Game Boy, 1989 1 1 62
! "
5 2
4 -#
-./.
7 !
1 62# 8 8/9 -./9 ( 8/9 ; "
& : ; '; " (,
;
< -= , ) >
< == , ) > 1 ?< @
)
-?9 & 0 A 9 - 4
' B
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
-<<
0
5 40
2 7
9
%
'
4?99 )
40 %
1 *
-?
/
#
-?9
!
/
-4/
-<< D
& D /
/
/
! C =?9 #
-?
<9
Game Boy Pocket, 1996 %
!
5
4 4#
0 %
&
!B
?# >
%
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
'
Game Boy Color, 1998 ;
!
5
4 B# ; " ;
&
;
C? B4 ;
7 %
% ;
1 *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0
!
;
#
7 0& , ! ,-
" #
$
; ()
%& '
*'
+"
#.
Game Boy Advance, 2001 !
5
4 <# -9
; ;
>
0
E(2; ; " !
# (
8/9 ; " ; (
% 1
; %
-
, /
E, = %
8/9 ; "
-./.:
( -./.: F1
!
;
00
%
7
# 2
(
( 2
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
5
4C
0
36$
3;$
%
1 %& " - & "
2
& # 5 3 %02
,(
%
" 2 3 &
3
!
: ! !
, /
% %
GB9# +HH
%0
0
# (
(
Game Boy Advance SP, 2003 2 !
5 0
(
4 ?# ! 2
!
# !
%
# 7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
#
(
&
4 , /
00
Direct Hardware Access ; 0
!E , #
#
! !$ 2 # ; ! (7 2#
H
; !
# , >
% % 6 ,
7
;
% 7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
!
&
-
"
#
% (
5
' : %
A 3 '
%
%
Memory Architecture I E ,
;
I '
%
%
!
%
E ,#
%
%
3%
%& &
; /0
! # % E(2; ,
!D
;
E,
D# /
-?
B4
5
" & "
"" &
& & 6 & "( " & 2 ( & %& " $ " " %& ( " " 67 8, ! : 33 /
98, ! & / 07 ; &
" 44
<7 8, ! " 7 "=
& -
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
3 " (
"
"
( & &
/ & " & 5 "3 (
" " " & " -
"
"
( " -
Memory Type
Access Widths
Comments
IWRAM
8, 16, 32
32 KB "internal" working RAM. Typically used for fast scratchpad RAM and for time-critical code.
EWRAM
8, 16
256 KB "external" working RAM. Typically used for main data storage and multiboot code.
VRAM
8, 16
96 KB video RAM. Stores all graphics data. Can only write 16 bits at a time.
ROM
8, 16
ROMs can be read in either slow (4/2) or fast (3/1) mode. See chapter text for more details.
Game Save RAM
8, 16
The game save RAM is part of the cartridge. See chapter text for more details.
Internal Working RAM (
%
E , !( E , # ; "
B40 ; " E , !
7 8, ! # ( E ,
B4 % E,
'
," ( " & , 8! " 3 " -& & (3 " 3 "
"
4C? @
External Working RAM 7
% )
; "'
-?0
'
% 6 E ,
% E , !6 E , # (' $ 4 9 @ ( E , I
JE ,
I
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
E ,
"" " " 4 3 "
%&
(
& 3
E7 ,
& E7 ,
-
(
>
""
"" 3 " %& 0
Cartridge Memory ' E7 ,
"
; $ 0E7 ,
"" "
-
41 1 4; -
%&
"
!
@
( "
4 0
000 "
:
( ? $ 0 @
? @ 0
"3
( -
& (
3
?@
0
1A4
;
E ,
2
2
J %
%
:
" "
"
%
4
; %& " & " 3 A4 3
3 "" 3 " "
% % #
!
%
;
Game ROM 3% 6 E , E7 ,
E7 ,
-?0 2 0
E7 ,
BH-
E7 ,
&
&
&
E7 , E7 ,
2
%
% (
&
!
%
#
&
E7 , E7 ,
( %
&
& -
E7 ,
6
E7 , ! E7 ,
# 0
7
E7 , &
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
6 E , 0
6 E ,
&
"
E,
! >
; '
,
%
E, %
4 #
, &
?<0
/
3
3
,$ C > B40 B4 ?<
'
(
% > '
K
-?0
> /0
( (, /9/? ,
(,
-./9
;
E,
( ,
!
?/999 -?
/?#
/0
8/9
2; (( 3 3 B-
-?0 %
%
(
-
/ -?
;
/9?
B4
E, + E,
5
(
, & (-
B4 ?<0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
;
/ -?0
E, % (
B4
Game Save Memory 2
! + &
0
J
%
#
E , !2E , # 5 2 J 2E ,
% 66 E7 , 6
E7 , 5
E7 , !
66 E7 , #
Graphics Memory +
*
!7 ,
#
Video Memory J >
JE , 0
% ( E , ( E , ) JE ,
-?0 7 -?
B4
#
E ,
(
! 4 &
;
%
%
JE , ! # 5
JE ,
; "
Palette Memory ,
' 4C?0 6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
% -? ;
-? 9
%
!J
%# '
!
<#
Object Attribute Memory 7 *
!7 , # JE , '
> J
7 , 7 , %
The Central Processor E, = $ , (
B40 :
0 (
%
%
0
*
•
$ (2 1 9049-0=B=-.0E,
E(2; & E,
%
2
0
, 8! , 8! %
•
2 (2 1 .049-0?=C-.0? % E, , 8! , 8!
% 5
0 % 5
Two Instruction Sets E,
E(2; ! E(2;
#
E(2;
%
; " ( (
:
E(2;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" : ;(2; !
#
% ( 3
-- D E, =
'
%
% D( 0 @
;
E,
: :
% &
%
; "
E,
E,
6
-? -?0
B4 -?0
(
'
% E,
CPU Registers E,
-? D E-C
% %
D
7 %
B4
E-B
E-< !
%
%
#
% %
E, >
;
2 # I
!
;2# ;
' '
;2
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! ;
'
4B
!
%$&
"
#
$
R0–R3 '
%
R4–R10
E -9
.
% '
R11
R12
%
R13
% %
%
5
D
D
!
% #
% %
R14
% %
R15
I *
The Graphics System 0 (
0
(
' & %
! C. =B
% > !) >#
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4/9 /.? #
L?9 5 2
?9 5 2 ,
'
%
(
Tile-Based Modes (0–2) 0
D
D
/
% %
/
7
(
>
Mode 0 (
% D
D
(
%
%
;
9MB
%
%
Mode 1 9 % %
:9 H
4
4 %
%
9
-
%
Mode 2 3%
9
-
4 %
H
%
(
%
4
B
Bitmap-Based Modes (3–5) 0 ; (
>
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
I (
Mode 3 -?0 =? /99
9?999999
! 2
# 4<9
-?9
9 "
! :
#
%
7
%E ,
JE ,
Mode 4 /0 9 9?999999
! # 9 9?99 999 <
2 0
4<9 -?9 < E6 N$ (2 ; 1 ' 9 C999999
&
4C? -?0
Mode 5 -?0
-?9
-4/
0 %
4 0 B
<
&
E6 N$ (2 ; 1 9 ?99 999
>
C 9
9?999999
The Sound System 5, % -?0 %
0
%
0 ;
D
D "
3
(
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
;
. D
2
& 2
" D
Summary , 0
4$
B$
0 *
:
Chapter Quiz & > & >
-9
0
& $ D
;
O
-
>>
499BF 2 2 ; 2 $
4
;
F
?/94 /9/? ; 8/9 $ ?/999 B )
F /@ ?< @ ; -4/ @ $ B/< @
<
" -/=. -./B ; -./. $ -..-
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
F
D
C
F /9B/? $ P<0-99 E, = $ , ( ; ?/994 $ ?C9-
?
F 6 E , JE , ; ( E , $ ;E ,
= F -49 B9 ; /9 $ ?9 /
9 -
4
F
B <
C
F
0 ; 2 $
0 0 %
. 0 ; 2 $
0 0 %
-9 )
F 4 < ; ? $ /
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!"# $% &
'
(
• •
)
•
)
•
+
& * "# $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Game Boy Advance Development , -
(
.
/
01
, !
%
1
2 & 3
.
0)-
* *1 .
4# * *1
%
!)-
5 0%
6 !&
+7 * 1
+7 *
+7 *
Deconstructing The ARM7 CPU &
68
+* 9 +7 *
1
+7 *
"
+7 * +7 *
+7 *
+7 *
:
:
+7 * +7 * '
+7 * 7
+7 * +* 9
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
) : +* 9
' ,
<
: '
;
5 +7 * ?
;; ) = 4
!
% " +7 * +7 *
>
3
)
2 '
+7 *
@ 3#
# A#
/
0
Emulation: The Key to Reverse Engineering 2
-
+7 * 1 B
C
1 <3
B
'
C
0 " +7 * 8 <3 7
+7 * +7 * '
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
)-
Unfortunate Side Effects 8
!
+7 * ) * * 1 +7 * % 61
! # A +
.
-
+7 *
6/ A
2
%
& * &
A
"# $ !
% )
+7 * )
6 &
@
! % 01 '
)
$ )
'
, <
-
C 0)-
'
B
) # ! 3
" "
" <
"
"
% " -
" D>
2 -
-
1 "# $
"
" ! )
% 6
B
.
/ 07
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
1
What About Public Domain Development Tools? ) , & *
.
) ) 2
#
$
)
& *
& *
# 28
"# $ )
$
A
!
% A
& *
& * "# $
Visual HAM And The HAM SDK )
3
= +* 9 2 2 2
2
D>
"
3
) <8 !
)* <
<3
% 6,
+* 9
EFG
2 5
2
5
+* 9 !
-
%
& * "
A
& *
<
1
" !
A
% .
6 !@ 3 A
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
H : & *
"
" & * "# $
:%
)
33
#
$
!
%
What Is HAM All About? & *
! & *
33
+* 9 & *
3 ?3 II
!
28
% % +*
3 # +7 * (
•
& *
•
& *
•
A
•
<1 *
•
A
"# $ & * 1
& * 33 & * "
# & * "# $
A
1 ,
A <
"
& *
& * <1 * 1 )
& * "# $ 33 & *
!&
* &
HAM on the Web C A
& * !
& * ! (??
(??
% ?
& * =9
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
@ %
4; @
C 4= )
%
!""
# $ !"" &
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"&
%
The Visual HAM Environment A "
& * !
& * !1 % @
<
"
4 4% & *
6 !&
% C
&
"# $ ) & @
44
J
'
!
> K6%
$ & &
)
! %
) A %
& * "# $
&
& & * ! & *
) A
& *
' A
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6
!
6% )
A
& * @
4>
' $ &
Installing the Development Tools & *
'
& * & * A
1
& *
A
(??
B )
3 # +7 *
Installing HAM . .
& *
!
= 9G % 1
! .
3 # +7 * & *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
% L& * @
. # 4K
4=
( % )
:7 $: < "
) & *
)
& , )
' & *
-./ 0 /
1/ / . !2
& * @
4D
*
& * @
49
+ )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
Installing Visual HAM /
A
& *
C 3 # +7 *
'
(
(??
7 A
) ' & *
"
& * "# $ LA
& * & *
A 3 (LA
E
3 # +7 * / 3 # +7 * A & * & * "# $ A & * '
& *
& * & * C
-
E )
A
& *
. LA
& * 2 & * "# $
& * "# $ A
)# 1
3 (L& * ) 3 # +7 * 3 (L& * A 3 (L& * LA & * 7 "# $
& *
A& * 1M1 )
C & *
! ! !
.
% @
A
& *%
A C
"
2
"
4 F%
3 %
3 " A& * 1M1 +7 * !
3 A @
& * 4 H%
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
3#
4 $
@
5
4 ;G
6
.
2
) )# 1:
@
) $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4 ;;
7
:A
& *
/ 6J
A
& * J
A
& *
-
Configuring Visual HAM & * "# $ & * /
!
@M=
1M1
% & -
A
& *
C
"# $
C & * "# $ )
7 @
A
& *
+ '
A
& *
& *
4 ;=
# $
8 ) 8
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
-
A & * ) (L
&
& * @
& *
4 ;4
2
L )
) /
!
3 (L& * L%
= K= ! A ' A
%
& * "# $ & * @M=
C
A
/
C
/ &
2
) &
)
& * 2
A
& * !
'
C A
& * C 1 -
C A
& * -
7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+ % / A
& *
-@
Running Game Boy Programs & * "# $
A
& * )# 1 )-
) A @ A
" & * <
<
-
)
"
<
@
!
)-
L"
A & * 3 # +7 * L3
6% & * "# $ ,
4 )
' '
'
9 $
2 " @
!)
& )/
& * !
&
/ 70 : -
/
)
& $
/ $ ;
%
)1 )
&
<
' 4 ;>
A
& *
-
' '
) @ -
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
7
/
8
.
70 : -
<
/
)
& &
7 0
3 # +7 * < " & * C & *
) )
/
A
)
5
'
!A
<
L"
%
"
"
3#
' % A
2
@ 4 ;>
1 /
' 7 8 $
2 @
4 ;K "
< ' '
IA
A
!
( < 8 $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
& * "#
%$<
) A
" < 4 ;D &
@
0/
' 6
* 7
$
)
-
)
<
= )
&
) 6)*
6
Game Boy Emulation A
& * "# $
) A
A !
3
% A .
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
& * "# $
) A
C
!
(??
% ;>
A & * "# $
;G
, .
) B
A
& *
A A & *
-
C . A
'
2 )
3 (L
L
L
4=
Running Programs on Your GBA ) 6
-
-
5
C
'
) '
!
%
2
) 3 # +7 *
'
) A
)
)
) ' . 5 7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
)
)-
2
&
3 # +7 * N
C 0 8" +7 * !
-
"<
! "
*
<3
3
@
% &
% ?
'
C
6
C
0 ( B
Using A Multiboot Cable *
*
A
= !* A=%
C : +7 *
7 !
%
+7 *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
* A= +7 *
.
=KD $ ' % C =KD $
&
'
!
=KD $ -
0@ 0
-
'
Using a Flash Advance Linker B
5 %
C :
<+7 * ! :
?
1<+7 * !
7
<+7 *
% )
1<+7 * 8" !
<3 '
%
* A=
' ) +7 *
<3 ! @
%
) )
) @ !
% )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
O;KG
Summary A
& *
& * "# $
!
2
"# $ %
. 7
@
& *
Chapter Quiz . .
;G .
; C 0 & * A & * 3 & # # $ = C ' & * A & * 3 & # # $ Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0
4 C 0 & * A & * 3 & # # $ > C
* *1 * * 3 * # *
0 * * *
1 1 1 *
1
K &
& * "# $
A
& *
0
O=K OKG 3 O;GG # @ D C
& * "# $ <
0
"
1 3 & # "
" * *
9 C
A + & 3 < # 1
& *
0
" * " "
F C
0 #
$
3 A #
@
1
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
H C
8 +, (?? (?? (?? (??
3 #
& * "# $ C
;G C 0 * 3 3 # @
A @ @
= , ,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! "
# $ %&
$ %&
'
$ (&
$ )
*
+'
(
$ %&
'
%&
! $ ' $ $
,
•
%
•
.
•
.
•
/
•
.
•
0
&
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%&
The Basics Of A Game Boy Program +
*
#
$
1 ( 1
$
$
'
(2
$
1 3 $ %
1 %
&
$
&
$ +
1
$ 4
2
$
$
$ %&
/
$
+5
%&
%& 4*
%
%&
1
/
$
$
%&
$
'
$
$ )
% & ,+
!
$
What Makes It Tick? &
-* %&
$
%
&
$3
0) %& 1
$ &
%& 6 1
'
$
/
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ %&
$ 1
'
%&
7
%& $ $ %&
*
$
" &
8
$ 9
$
' $ # "
#
, 3
$
"
9 $
$
$
$
:
9
A Friendly Greeting ! !
3
1
' $
7
%&
%&
"
,
+
1 , '
$
+
%& '
+
"
1
$ ; ;
$ %& "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
'
: #
$
'
%&
!
1
$ !
#
"
1 $
4 9
! = (2
$
#
< $
(" :
1
%
Creating A New Project 1
!
$
$
+
<>< ? -@ /
@ AB
: '
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/
:
:
:
+ D? E <
'
/ (%
( $
?
$
AC , , )F
! $
$ %
$
$
" # %
! $
/
A5
$
&
! ' !
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
$
-
#include "mygba.h"
MULTIBOOT
int main(void) { ham_Init(); while(1) { }
return 0; }
/* END OF FILE */
1
" *
% "
%&
? %&
'
" ) %&
? GG
' 2 6 &) ) 8
$ "
Writing The Greeting Program Source Code )$
1
$
% $ /
8
' %
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#include "mygba.h"
MULTIBOOT
int main(void) { ham_Init();
//initialize the text system ham_InitText(0);
while(1) { //display a greeting message ham_DrawText(0, 0, "Greetings!"); ham_DrawText(0, 2, "Welcome to the world of"); ham_DrawText(0, 4, "Game Boy Advance programming!"); }
return 0; }
/* END OF FILE */
:
3 H. :
'
' H
$ H.
!
'
'
$ $
! %& 4
$
'
Compiling The Greeting Program :
1
$ $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/
AA
+
)
+
&
$
% (
!
' * (<00) 0( / $ )
$ +?
&
? . !0) "
Testing The Greeting Program In The Emulator 7 &
%
+?
& G &
+ A I"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/
$
/
!
AJ
) ( (
+ ,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
% !*
8 &
8
7
8
) 8
/ A'
B'
A K" !
1 "
! . /
Drawing Pixels :
4
1
$
%&
$ :
BLL
8
" 1
1
%& 9 4.
'
' & 0
$
* F
. $"
$ % "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
*
0
$ ?
9 *
' '
%&
: ? . !0) @,
@?
LA@";
&
3
4 '
%&
* .
+'
,
<'
!
"
'
'
.
!
$
1
?
1
&
$ * 1
'
:
' "
.
+'
"
Writing the DrawPixel Program Source Code 6
'
$
%&
4 1 %&
1
'
1 1 '
" $
)$
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 4: Starting With The Basics // DrawPixel Project // main.c source code file //////////////////////////////////////////////////
int main(void) { // create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
// switch to video mode 3 (240x160 16-bit) // by setting a memory register to a specific value *(unsigned long*)0x4000000 = (0x3 | 0x400);
// draw a white pixel (16 bits) directly to video memory // pixel location is centered on the screen (120,80) videoBuffer[80 * 240 + 120] = 0xFFFF;
// continuous loop while(1) { }
// end program return 0; }
.<
$ $ /
A=
1 2
#
32 4
+ '
& %&
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
3 $
? 1
%& .<
,. F
$ '
7
$
%&
/
-
*(unsigned long*)0x4000000 = (0x3 | 0x400);
L'5 $
5- CAL ' BJL BJ! )0
C
'
L'ALL M"
+ /
%&
$
$ '
!
-
videoBuffer[80 * 240 + 120] = 0xFFFF;
'
5
BJL
CAL '
BCL ' =L !
' 1>7
"
-
Memory Location = Y * Screen Width + X
& 9 L'//// A 8 L'//// BJ! ' 0 % '
L'////
'
L' LNO
' + &
"
'
N/
BJ
" 5
' 9
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
BJ! '
Compiling the DrawPixel Program :
1 "
/I
'
Testing the DrawPixel Program in the Emulator +
&
/K
$ /
G &
$ "
AO .
.
+'
'
3
5 2
#
!
# ,(
Filling The Screen :
'
1 '
4
1 +
$ $
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
1
$
$
3
Writing the FillScreen Program Source Code 7 1 " / ,
1 %&
1
3"
%& %&
' ? (% $
&
0
$
("
$ $ 0<% H. ,+?:
$
$
-
#define REG_DISPCNT *(unsigned long*)0x4000000
1
?
1 P *
?" 0<% H. ,+? :
'
$
Q
$
Q"L'ALLLLLL
4
%&
1
* %&
$ $
,
%&
*
1
,
* L'5 $
( 3
!
1 $ 1 &
1
'
$
9
%& ' #define MODE_3 0x3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
(
-
8
.
+' CAL ' BJL '
5 1
) .
BJ!
& 8
L'5
" '
-
#define BG2_ENABLE 0x400
. ) 01
L'5
+'
L'ALL
$
C
+
1
#define RGB(r,g,b) (unsigned short)(r + (g << 5) + (b << 10))
$
/
.
0% &
+' 5
BJ!
-
void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
'
5 .
+'
>7 :
-
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 4 - Starting With The Basics // FillScreen Project
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// main.c source code file //////////////////////////////////////////////////
//define register for changing the video mode #define REG_DISPCNT *(unsigned long*)0x4000000
//video mode 3 = 240x160 16-bit #define MODE_3 0x3
//use background 2 #define BG2_ENABLE 0x400
//macro to pack an RGB color into 16 bits #define RGB(r,g,b) (unsigned short)(r + (g << 5) + (b << 10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//draw a pixel on the mode 3 video buffer void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main(void) { int x, y;
//switch to video mode 3 (240x160 16-bit) REG_DISPCNT = (MODE_3 | BG2_ENABLE);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//fill the screen for (x = 0; x < 239; x++) { for (y = 0; y < 159; y++) { DrawPixel3(x, y, RGB(0,(255-y),x)); } }
// continuous loop while(1) { // do nothing }
// end program return 0; }
$
( .
+' 5
> >
(
7 7
7
Compiling the FillScreen Program :
/I 1
'
$
"
' 0 ?
> $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
8
'
Testing the FillScreen Program in the Emulator : $
$
'
$ &
$
$ G &
6 9
'&
/K %& !
*
% ??
)
%& $
%&
"
$ ;
2 $ % %&
/
A BL
7 8 ,( #
7
$
/ , %&
8 '
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
,
! "
&
/
4 9
R, 1
S )$
1 1
$
#
$
%& ' , J (
(
? 1 !
K (0
!
2 !
4:
!&
(
? $
'
&
& 1
%&
Detecting Button Presses & & ?
9
49
%& 1
BL (
*
&
(
'
$ 4
&
H.
'
'
('(" /H? 06 : +2 H2 +H+0<,,<. "
Writing the ButtonTest Program Source Code & " & $ /
8 : '
8
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
%& H H
' L" $
$
+
" H.
8 '
/
/
& : A BB ,
: D?E <
/ :
+
/ +
'
/ $
(& :
1
'
!
: '
(
" #
$ &
) $ T
1 1
" 8
8 ,. F
? . !0)
$ $ 9
$ $ &
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
-
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 4: Starting With The Basics // ButtonTest Project // main.c source code file //////////////////////////////////////////////////
// include the main ham library #include "mygba.h"
// enable multi-boot support MULTIBOOT
////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main() { // initialize hamlib ham_Init();
// initialize ham for text output ham_InitText(0);
// display the button names ham_DrawText(0,0,"BUTTON INPUT TEST"); ham_DrawText(3,2,"UP"); ham_DrawText(3,3,"DOWN"); ham_DrawText(3,4,"LEFT"); ham_DrawText(3,5,"RIGHT"); ham_DrawText(3,6,"A"); ham_DrawText(3,7,"B"); ham_DrawText(3,8,"L");
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
ham_DrawText(3,9,"R"); ham_DrawText(3,10,"START"); ham_DrawText(3,11,"SELECT");
// continuous loop while(1) { // check UP button if (F_CTRLINPUT_UP_PRESSED) ham_DrawText(0,2,"X"); else ham_DrawText(0,2," ");
// check DOWN button if (F_CTRLINPUT_DOWN_PRESSED) ham_DrawText(0,3,"X"); else ham_DrawText(0,3," ");
// check LEFT button if (F_CTRLINPUT_LEFT_PRESSED) ham_DrawText(0,4,"X"); else ham_DrawText(0,4," ");
// check RIGHT button if (F_CTRLINPUT_RIGHT_PRESSED) ham_DrawText(0,5,"X"); else ham_DrawText(0,5," ");
// check A button if (F_CTRLINPUT_A_PRESSED) ham_DrawText(0,6,"X");
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
else ham_DrawText(0,6," ");
// check B button if (F_CTRLINPUT_B_PRESSED) ham_DrawText(0,7,"X"); else ham_DrawText(0,7," ");
// check L button if (F_CTRLINPUT_L_PRESSED) ham_DrawText(0,8,"X"); else ham_DrawText(0,8," ");
// check R button if (F_CTRLINPUT_R_PRESSED) ham_DrawText(0,9,"X"); else ham_DrawText(0,9," ");
// check START button if (F_CTRLINPUT_START_PRESSED) ham_DrawText(0,10,"X"); else ham_DrawText(0,10," ");
// check SELECT button if (F_CTRLINPUT_SELECT_PRESSED) ham_DrawText(0,11,"X"); else ham_DrawText(0,11," "); }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// end program return 0; }
& $
$ /
A BC
( !
9 "
!
" "
Compiling the ButtonTest Program :
1
&
T /
/
1 +
1 &
A B5
:
$ $ $
.<
$
$ /
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
A BA :
$
& :
%(
% !
" !
$
Testing the ButtonTest Program in the Emulator )
1
$
& .<
1
%& + /K $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ &
G &
/
A BI
!
) (
!* ( !
* /
A BJ
+ ( " !
!
Running Programs Directly on the GBA % $
&
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%& 9 /
&
C
& C"
%& /
+?
6 $
"
,
1 "
$ & C
/
*
6 $
+?
1 $
?. !0) "
#
9 %& 9
#
The Multiboot Cable $ %& %&
* 9 & C
& $
;
8
C
& C"
$
%& 1 <' " ,
%& A BK
/
%
( " ,( !
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
& C
! !
& C
& C "
+?
%& 0 %& :
$ %&
%& $
$
/
A B= T
+
& C /I
& C %&
/= %&
& C
"
1 8
( "$ % (
/
A BO
& C
$
$
& C & C
$ & C$ -UU
$!
7
$
(
! $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ *
"
(
5 (
' %
! !
! ' '
The Flash Advance Linker /
6 $
/
A CL"
%&
%&
$
%& 0)
%&
$
7 !<
0 ' "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
/ BC= CIJ IBC
6 $ JA
B LCA
8 / 6 $
/
"
! 0 '
!< "
2
$
,(
A CB
! !
& C
%&
JA
$
/
6 $
$
#
+?
%&
!< !
0 ' ! "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! < ! !
/
A CC
Summary $
$ %& %&
Challenges ? . !0)
%
.
+'
'
' / , / ,
0% &
Chapter Quiz $
# 8
'.
B *
$
%
&
3
?GG & & ? ? . + C *
' &
H. H.
' '
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
3
? .
H+ H,
' '
5 *
%& & & % ? % & !< 2 . * %&
A
/
$
"3
<
-
$
& / I *
53 5CL ' CAL & CJL ' B=L ? BCL ' =L . CAL ' BJL
J *
$ ! & ? . .
"
$3
F !
K *
53 = & BJ ? CA . 5C
= *
3 0<% H? % ) . & 0<% H ) . ? 0<% H. ,+? : . 0<% H. LB
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
O *
8 & ? .
H, H6 H& H
' ' ' '
BL *
<' %& 3
& ? / .
& & 6
'
C
& C" & " 6 $ /6 " & 6&"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%&
3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! "
" # "
$
%
$
(
$
)*
"
"
& & +
' '
,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! "
#
' ( )
* •
+
•
,
-
!
•
,
-
"
•
,
-
#
•
.
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ %
&
Introduction to Bitmapped Graphics /
-
0
1
2.
+3 ,
0 4 . .5
1
.6 7
8
5
+ ,
9 ) <' 4 = ,
4 :
;
+
+ <' 4
6
> : =
3
: ?,
@
.
: -
,
6
!*
// // bg (38400 uncompressed bytes) // extern const unsigned char bg_Bitmap[38400] = { 0x4f, 0x3b, 0x23, 0x23, 0x2c, 0x1f, 0x22, 0x2d, 0x2f, 0x2f, 0x2f, 0x2f,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
0x31, 0x2f, 0x2d, 0x2f, 0x23, 0x1d, 0x2d, 0x4c, 0x37, 0x38, 0x2f, 0x2d, 0x22, 0x1f, 0x2f, 0x2d, 0x2d, 0x1d, 0x22, 0x2d, 0x23, 0x23, 0x33, 0x2f, 0x2f, 0x2d, 0x34, 0x2f, 0x2f, 0x2d, 0x2c, 0x23, 0x23, 0x2d, 0x2d, 0x2d, 0x22, 0x1f, 0x2f, 0x2b, 0x23, 0x2d, 0x2e, 0x2d, 0x1d, 0x23, 0x38, 0x2b, . . . 0xe1, 0xe4, 0xc7, 0xbf, 0xc3, 0xf2, 0xf2, 0xf6, 0xf6, 0xf7, 0xf8, 0xf9, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf8, 0xf8, 0xf8, 0xf8, 0xf2, 0xf8, 0xf8, 0xf8, 0xf2, 0xf6, 0xf6, 0xf2, 0xf2, 0xf2, 0xf2, 0xf6, 0xf2, 0xd9, 0xe1, 0xd6, 0xd9, 0xd9, 0xd9, 0xd9, 0xc9, 0xf6, 0xf6, 0xf2, 0xf6, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9 };
+
0 3
#%
&
, +
:
6
! "
!A "$$
<
(
%B
+ C
-
&"$
-
! +
-
3 #&"
)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
3
%B$ D !A "$$ ' 0 #&
%"& B"
B"
:
"#
/
@
= +:
6
E F<
F
# $
Selecting the Ideal Video Mode , #%
% - &
'
'
*
$
.
.
!
&"$
%B$
%#
5
"
&"$
%B$
A
8
#
%B$
%&A
%#
8
Hardware Double Buffer 4
"
#
0 -
4
! (
>
)
:
:
+ +, < 4
!& G
1, < 4 1, < 4
E# G @
1, < 4
B G
1 !& G +, < 4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! &$ G
"
:
!
+:
!
Horizontal and Vertical Retrace C
,
96 H
C -
,
6<
.6 @
I
: : :
Working with Mode 3 I
!
0 &"$
!& EBE
%B$
%#
,
: -
B
#
+
"
%#
!
: )
3
!H
1, < 4 :( +
# 0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
Drawing Basics 9 :
!
8
! 6
H
" )
.
3 @
)
5
Drawing Pixels +:
!
* videoBuffer[y * SCREENWIDTH + x] = color;
)
:
!*
void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = c; }
4 6
!.
! (
I
) 4
4
!.
* ///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode3Pixels Project // main.c source code file /////////////////////////////////////////////////////////////
//add support for the rand function #include <stdlib.h>
//declare the function prototype
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
""
:
void DrawPixel3(int, int, unsigned short);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//packs three values into a 15-bit color #define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x, y; unsigned short color;
SetMode(MODE_3 | BG2_ENABLE);
while(1) { //randomize the pixel x = rand() % 240; y = rand() % 160; color = RGB(rand()%31, rand()%31, rand()%31);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"$
DrawPixel3(x, y, color); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
4
!.
3
#!
% "
&
%'
( )$
Drawing Lines '
0 4
@H G
+
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
:
@
:
-
+:
+ ( H
- ; . !
( J@
J6
$#J4
4
!9
6H <' 4
!9
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode3Lines Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//add support for the rand function #include <stdlib.h>
//declare the function prototype void DrawPixel3(int, int, unsigned short); void DrawLine3(int, int, int, int, unsigned short);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//packs three values into a 15-bit color
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
#define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x1,y1,x2,y2; unsigned short color;
SetMode(MODE_3 | BG2_ENABLE);
while(1) { x1 = rand() % 240; y1 = rand() % 160; x2 = rand() % 240; y2 = rand() % 160; color = RGB(rand()%31, rand()%31, rand()%31);
DrawLine3(x1,y1,x2,y2,color); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 /////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
///////////////////////////////////////////////////////////// // Function: DrawLine3 // Bresenham's infamous line algorithm ///////////////////////////////////////////////////////////// void DrawLine3(int x1, int y1, int x2, int y2, unsigned short color) { int i, deltax, deltay, numpixels; int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2;
//calculate deltaX and deltaY deltax = abs(x2 - x1); deltay = abs(y2 - y1);
//initialize if(deltax >= deltay) { //If x is independent variable numpixels = deltax + 1; d = (2 * deltay) - deltax; dinc1 = deltay << 1; dinc2 = (deltay - deltax) << 1; xinc1 = 1; xinc2 = 1; yinc1 = 0; yinc2 = 1; } else
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
{ //if y is independent variable numpixels = deltay + 1; d = (2 * deltax) - deltay; dinc1 = deltax << 1; dinc2 = (deltax - deltay) << 1; xinc1 = 0; xinc2 = 1; yinc1 = 1; yinc2 = 1; }
//move the right direction if(x1 > x2) { xinc1 = -xinc1; xinc2 = -xinc2; } if(y1 > y2) { yinc1 = -yinc1; yinc2 = -yinc2; }
x = x1; y = y1;
//draw the pixels for(i = 1; i < numpixels; i++) { DrawPixel3(x, y, color);
if(d < 0) {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"!
d = d + dinc1; x = x + xinc1; y = y + yinc1; } else { d = d + dinc2; x = x + xinc2; y = y + yinc2; } } }
4
!9
3
#"
* "
&
%+
( )$
Making GBA Programs Multi-Bootable 4
!9
-
* #define MULTIBOOT int __gba_multiboot; MULTIBOOT
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$#
+ ( -
4
3 +
" "
"
'
+
,
-$
.
, -
4
I
& 4 I&
<' 4 -
*KK
<' 4 <' 4
.6 :
#define MULTIBOOT int __gba_multiboot;
LL
L ) 4
@H G
C
-
<' 4
4 I& )
(
M
:
-
< *
MULTIBOOT
+
-
*
int __gba_multiboot;
)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4 /9 + ''
$
4 /9 + '' G
/
<' 4 <
< 4 (
C
4 I&
-
)
B
< 4 =+ <' 4
(
4 /9 + ''
-
+ 4 I&
N!$ $$ 9-@ +
+
+ +
4 I& J4
6 H <' 4 -
5
0
4 I&
, 4 I&
J4 J4 J, +5 5 J@8@ 14 !&JH <+I1<@
&$$$
J, 5
4
171
7. 3 - +
L&GL7. 3
.6 5
9. %
!EA !E3 8 <
' 4
171 H 4 I&
6
.
, ,
;
OAK4 1
4 I& 5 6
.
@
<
6H
J4
6 H <' 4
6H multiboot Mode3Lines
3 * Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
mb -w 50 -s %1.gba
5 4 I&
+
<' 4 .6
/
J4
C @
F,
+
@ =3 :
+
6
E F<
@ =)
+
:
4 I& + -
C -
*
Parallel MBV2 cable found: hardware=v2.0, firmware=v4 EPP support found. Looking for multiboot-ready GBA... Sending data. Please wait... CRC Ok - Done.
+
ERROR - No hardware found on selected parallel port! Check parallel port number, make sure cable is connected to port and to GBA, & make sure GBA is turned on.
+
1 :
.
.
1.. (
+
-
.6 +
:
%$$
<
1.. : #$
.6 : +' @ 4 I&
+
.6
-
- +
4 I& , C =
+
N!$ $$ Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4 I& @
$"
-
3
9 -
1
4 I&
: I
) 4
. (
4 I& & 0
9 -
-
+ 4 I&
@
-
- + K
3 8
+ *KK
4 I& 3 P
'
K
F4 I&F
Drawing Circles = -
+ ,
4
!6 !
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode3Circles Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//add support for the rand function #include <stdlib.h>
//declare the function prototype void DrawPixel3(int, int, unsigned short); void DrawCircle3(int, int, int, int);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$$
K
#define MODE_3 0x3 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//packs three values into a 15-bit color #define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x, y, r; unsigned short color;
SetMode(MODE_3 | BG2_ENABLE);
while(1) { x = rand() % 240; y = rand() % 160; r = rand() % 50 + 10; color = RGB(rand()%31, rand()%31, rand()%31);
DrawCircle3(x, y, r, color); }
return 0;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
}
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
///////////////////////////////////////////////////////////// // Function: DrawCircle3 // Bresenham's infamous circle algorithm ///////////////////////////////////////////////////////////// void DrawCircle3(int xCenter, int yCenter, int radius, int color) { int x = 0; int y = radius; int p = 3 - 2 * radius; while (x <= y) { DrawPixel3(xCenter + x, yCenter + y, color); DrawPixel3(xCenter - x, yCenter + y, color); DrawPixel3(xCenter + x, yCenter - y, color); DrawPixel3(xCenter - x, yCenter - y, color); DrawPixel3(xCenter + y, yCenter + x, color); DrawPixel3(xCenter - y, yCenter + x, color); DrawPixel3(xCenter + y, yCenter - x, color); DrawPixel3(xCenter - y, yCenter - x, color);
if (p < 0) p += 4 * x++ + 6; else
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
p += 4 * (x++ - y--) + 10; } }
4
!6
3
##
"
&
%
( )$
Drawing Filled Boxes )
?+: = 4 ,
+
C !
: ,
( J@
J6
4 $#J4
!
6 H <' 4
!
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode3Boxes Project // main.c source code file /////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//add support for the rand function #include <stdlib.h>
//declare the function prototype void DrawPixel3(int, int, unsigned short); void DrawBox3(int, int, int, int, unsigned short);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//packs three values into a 15-bit color #define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x1, y1, x2, y2; unsigned short color;
SetMode(MODE_3 | BG2_ENABLE);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
while(1) { x1 = rand() % 240; y1 = rand() % 160; x2 = x1 + rand() % 60; y2 = y1 + rand() % 60; color = RGB(rand()%31, rand()%31, rand()%31);
DrawBox3(x1, y1, x2, y2, color); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
///////////////////////////////////////////////////////////// // Function: DrawBox3 // Draws a filled box ///////////////////////////////////////////////////////////// void DrawBox3(int left, int top, int right, int bottom, unsigned short color) { int x, y;
for(y = top; y < bottom; y++)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$!
for(x = left; x < right; x++)
DrawPixel3(x, y, color); }
4
!
3
#B
/ "
&
%)
( )$
Drawing Bitmaps 5 ,
: -
?
(
(
+: 6
E
+:
-
Converting 8-Bit Bitmaps to 15-Bit Images A %#
!
B #
& : (
%#
%B
###
A :
5 K
K<
< Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
A -
-
-
-
A
-
%B
Converting Bitmap Images to Game Boy Format :
: :
6
+
;
@ >
&
; :( -
& ) 4
J
J
J
!&
) 4 ) 4
-
@
<
F
F
2 'G
-
4@ H' @ 8 '
0 +
J@
J6
& $#J4 6 H <' 4
8 ( F +
!
F6 H J@ ' -
&
!
( C
* gfx2gba -fsrc -c32k filename.bmp
A
B 6
& !&A
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5
& C
C :
%# -
! -
# 3 + (
5 !
*
gfx2gba -fsrc -c32k mode3.bmp
! +
!
-
*
// // mode3 (76800 uncompressed bytes) // const unsigned short mode3_Bitmap[38400] = { 0x7717, 0x7293, 0x69cd, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x6e0f, 0x7293, 0x7717, 0x6e51, 0x6e0f, 0x7717, 0x6e51, 0x656a, 0x69cd, 0x61aa, 0x58c3, 0x6e51, 0x6e51, 0x7293, 0x7717, 0x7bbc, 0x7b5a, 0x6a2f, 0x6a2f, 0x6e51, 0x69cd, 0x656a, 0x6a2f, 0x6a2f, 0x6a2f, 0x6a2f, 0x6a2f, 0x6a2f, 0x6a2f, 0x7717, 0x7b9b, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7759, 0x7293, 0x6e51, 0x6a2e, 0x6a2f, 0x6a72, 0x7293, 0x6127, 0x58c3, 0x58c3, . . .
5
C %# !A "$$
EB A$$ ;
+ C
"
+
"
Drawing Converted Bitmaps 6 ;
-
)
:
* ///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode3Bitmap Project Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4
!
// main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//include files #include <stdlib.h> #include "mode3.raw.c"
//declare the function prototype void DrawPixel3(int, int, unsigned short);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x, y;
SetMode(MODE_3 | BG2_ENABLE);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
//display the bitmap for(y = 0; y < 160; y++) for(x = 0; x < 240; x++) DrawPixel3(x, y, mode3_Bitmap[y * 240 + x]);
//endless loop while(1) { }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
4
"
!
3
0
#E
1& $ .
"
1& $ 3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0
2 34
$
5 "
&
%)
( )$
Working with Mode 4 I
"
A
C -
&"$ %B %B
%B$
Dealing with Palettes 4
"
A
C
B -
"
&
) *
const unsigned short mode4_Palette[256] = { 0x0001, 0x0023, 0x0026, 0x0086, 0x002a, 0x008a, 0x00aa, 0x010a, 0x00a9, 0x00ad, 0x00ae, 0x014e, 0x3940, 0x190b, 0x44e0, 0x4522, 0x25c0, 0x1e20, 0x3181, 0x2dc1, 0x2a23, 0x15cb, 0x3604, 0x3629, 0x4183, 0x45a5, 0x41e5, 0x4206, 0x3e27, 0x4627, 0x4228, 0x420c, 0x5481, 0x58c3, 0x5525, 0x6127, 0x4d86, 0x4dc7, 0x5186, 0x5988, . . . 0x5fb5, 0x6357, 0x6396, 0x63b7, 0x639a, 0x6b36, 0x6b57, 0x6f37, 0x7357, 0x6f58, 0x7359, 0x7759, 0x7b5a, 0x6b78, 0x6f99, 0x6b99, 0x6fba, 0x739a, 0x7779, 0x7b9a, 0x6fdb, 0x73dc, 0x77bb, 0x7b9b, Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0x7bbc, 0x7bdc, 0x7bdd, 0x77fd, 0x7fde, 0x7bfe, 0x7ffe, 0x77bf, 0x7bdf, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
: 8
5 -
+ ) 4
I
,
" -
$ B
$
#$$$$$$ *
:
unsigned short* paletteMem = (unsigned short*)0x5000000;
@ B
4
3
*
for (n = 0; n < 256; n++) paletteMem[n] = RGB(31, 31, 31);
4
" 5 =
:
(
B
C 5 -
$
-
$
:
$$
< %B F<
/
@
F 3 ! %#
#A " A
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
;
6
E
2 2 !
Drawing Pixels +
"
!
#
"
:
A
%B 96 H
>
-
3
#O
6 &
* !/
+
%B 0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
(
;
-
3
-
:
-
+: 3
&*
unsigned short offset = (y * 240 + x) >> 1; pixel = videoBuffer[offset];
5
5H:
%*
if (x & 1)
3
+ A -
*
videoBuffer[offset] = (color << 8) + (pixel & 0x00FF);
+ -
*
videoBuffer[offset] = (pixel & 0xFF00) + color;
) , '-
:
"
{ unsigned short pixel; unsigned short offset = (y * 240 + x) >> 1;
pixel = videoBuffer[offset]; if (x & 1) videoBuffer[offset] = (color << 8) + (pixel & 0x00FF);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" !
void DrawPixel4(int x, int y, unsigned char color)
else
" H4 #
videoBuffer[offset] = (pixel & 0xFF00) + color; }
4
4 "
".
". H
.
"
+
)
-
"
+ 4
".
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode4Pixels Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//add support for the rand function #include <stdlib.h>
//declare the function prototype void DrawPixel4(int x, int y, unsigned char bColor);
//declare some defines for the video mode #define MODE_4 0x4 #define BG2_ENABLE 0x400 #define REG_DISPCNT *(unsigned int*)0x4000000 #define RGB(r,g,b) (unsigned short)((r)+((g)<<5)+((b)<<10))
//create a pointer to the video and palette buffers unsigned short* videoBuffer = (unsigned short*)0x6000000;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
unsigned short* paletteMem = (unsigned short*)0x5000000;
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x1,y1,n;
SetMode(MODE_4 | BG2_ENABLE);
for (n = 1; n < 256; n++) paletteMem[n] = RGB(rand() % 31, rand() % 31, rand() % 31);
while(1) { x1 = rand() % 240; y1 = rand() % 160;
DrawPixel4(x1, y1, rand() % 256); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel4 // Draws a pixel in mode 4 ///////////////////////////////////////////////////////////// void DrawPixel4(int x, int y, unsigned char color)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
{ unsigned short pixel; unsigned short offset = (y * 240 + x) >> 1;
pixel = videoBuffer[offset]; if (x & 1) videoBuffer[offset] = (color << 8) + (pixel & 0x00FF); else videoBuffer[offset] = (pixel & 0xFF00) + color; }
4
".
3
# %$
!7 "
&
*'
( )$
/
H
.
"
!
+ H
H
.
"
H
.
#
+
:
.
H H
.
"
.
! (
-
Drawing Bitmaps @
"
A
-
& !A "$$
" "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
: ! 3 -
!
-
EB A$$
C
9
!
+:
2 :A -
B (
6H <' 4 6
J@ *
J6
" &"$ %B$ & + $#J4 "
)
gfx2gba -fsrc -pmode4.pal mode4.bmp
&
* @
"
" "L.
+: "
(
2
4 (
I 3E
" ) 4
4
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode4Bitmap Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//include files #include <stdlib.h> #include <string.h> #include "mode4.raw.c" #include "mode4.pal.c"
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_4 0x4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
:
#define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video and palette buffers unsigned short* videoBuffer = (unsigned short*)0x6000000; unsigned short* paletteMem = (unsigned short*)0x5000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int n;
//set video mode 4 SetMode(MODE_4 | BG2_ENABLE);
//set up the palette colors for (n = 0; n < 256; n++) paletteMem[n] = mode4_Palette[n];
//display the bitmap memcpy(videoBuffer, mode4_Bitmap, 38400);
//endless loop while(1) { }
return 0; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
,
=
: - 4
!
,
:
H
.
"
? +: + 3
-
"=
# %%
5 @+ 6
-
+
6
) 4 @H G
5 @+ 6
=
!! "
&
*)
*
4 :
)
; "L %&$
%B$
:
+:
( 8
C
H4
Page Flipping and Double Buffering .
" 0
-
#
+
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+: -
$
-
-
+
; -
!
- + $ B$$$$$$ *
" -
$ B$$ $$$ )
unsigned short* FrontBuffer = (unsigned short*)0x6000000; unsigned short* BackBuffer = (unsigned short*)0x600A000;
/
-
*
#define BACKBUFFER 0x10
;
0
=
void FlipPage(void) { if(REG_DISPCNT & BACKBUFFER) { REG_DISPCNT &= ~BACKBUFFER; videoBuffer = BackBuffer; } else { REG_DISPCNT |= BACKBUFFER; videoBuffer = FrontBuffer; } }
)
4 6H <' 4
J@
"3 J6
8 $#J4 I
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"3 ) 4
(
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode4Flip Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
//add support for the rand function #include <stdlib.h> #include <string.h>
//declare the function prototype void DrawPixel4(int, int, unsigned char); void DrawBox4(int, int, int, int, unsigned char); void FlipPage(void); void WaitVBlank(void);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_4 0x4 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//packs three values into a 15-bit color #define RGB(r,g,b) (unsigned short)((r)+((g)<<5)+((b)<<10))
//video buffer defines Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define BACKBUFFER 0x10 unsigned short* FrontBuffer = (unsigned short*)0x6000000; unsigned short* BackBuffer = (unsigned short*)0x600A000; unsigned short* videoBuffer; unsigned short* paletteMem = (unsigned short*)0x5000000;
volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int n;
//set video mode and start page flipping SetMode(MODE_4 | BG2_ENABLE); FlipPage();
//set the first two palette entries paletteMem = RGB(0, 31, 0); paletteMem = RGB(31, 0, 0);
//draw the first random box DrawBox4(20, 20, 100, 140, 1);
//flip the page to the back buffer FlipPage();
//draw the second random box DrawBox4(140, 20, 220, 140, 2);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
while(1) { //wait for vertical blank WaitVBlank();
//flip the page FlipPage();
//slow it down--modify as needed n = 500000; while(n--); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel4 // Draws a pixel in mode 4 ///////////////////////////////////////////////////////////// void DrawPixel4(int x, int y, unsigned char color) { unsigned short pixel; unsigned short offset = (y * 240 + x) >> 1;
pixel = videoBuffer[offset]; if (x & 1) videoBuffer[offset] = (color << 8) + (pixel & 0x00FF); else videoBuffer[offset] = (pixel & 0xFF00) + color; }
/////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// Function: DrawBox4 // Draws a filled box ///////////////////////////////////////////////////////////// void DrawBox4(int left, int top, int right, int bottom, unsigned char color) { int x, y;
for(y = top; y < bottom; y++) for(x = left; x < right; x++) DrawPixel4(x, y, color); }
///////////////////////////////////////////////////////////// // Function: FlipPage // Switches between the front and back buffers ///////////////////////////////////////////////////////////// void FlipPage(void) { if(REG_DISPCNT & BACKBUFFER) { REG_DISPCNT &= ~BACKBUFFER; videoBuffer = BackBuffer; } else { REG_DISPCNT |= BACKBUFFER; videoBuffer = FrontBuffer; } } ///////////////////////////////////////////////////////////// // Function: WaitVBlank
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
// Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(*ScanlineCounter < 160); }
4
"3
3
# %&
"
&
!# *
Working with Mode 5 4
#
! )
%B$
%#
#
*
%&A=
&"$
%B$
:
%#
Drawing Pixels 4
# (
H
! !
.
:
0
#
*
void DrawPixel5(int x, int y, unsigned short c)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
{ videoBuffer[y * 160 + x] = c; }
Testing Mode 5 4 #. @ 4
! 4 ' H 1L# %B$
%&A
H
#
!
C # (
& !L
(
%B$ !
@
=)
+
4
#.
%&A #L *
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // Mode5Pixels Project // main.c source code file /////////////////////////////////////////////////////////////
//add support for the rand function #include <stdlib.h>
//declare the function prototype void DrawPixel5(int, int, unsigned short);
//declare some defines for the video mode #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_5 0x5 #define BG2_ENABLE 0x400
//changes the video mode #define SetMode(mode) REG_DISPCNT = (mode)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
C
//packs three values into a 15-bit color #define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main(void) { int x, y; unsigned short color;
SetMode(MODE_5 | BG2_ENABLE);
while(1) { //randomize the pixel x = rand() % 160; y = rand() % 128; color = RGB(rand()%31, rand()%31, rand()%31); DrawPixel5(x, y, color); }
return 0; }
///////////////////////////////////////////////////////////// // Function: DrawPixel5 // Draws a pixel in mode 5 ///////////////////////////////////////////////////////////// void DrawPixel5(int x, int y, unsigned short c)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
{ videoBuffer[y * 160 + x] = c; }
4
#.
3
# %!
!% "
&
'
( )$
.
@ +
:
0
+:
-
(
-
(
8 = )
-
6
( 5
+
" F@
F
-
>
C
: )
+ +
+
. H
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6
"
. void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color); pos += 8; } }
void DrawChar(int left, int top, char letter, unsigned short color) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { // grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; // if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); } }
The Hard-Coded Font 5
-
: >
+
( 8
+ -
%
' 6 H <' 4 +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
J@
J6 (
I
$#JH ) 4
+ H
#ifndef _FONT_H #define _FONT_H
#define W 1
unsigned short font[] = { // (space) 32 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // ! 33 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, // " 34 0,0,0,0,0,0,0,0, 0,W,W,0,W,W,0,0, 0,W,W,0,W,W,0,0, 0,0,W,0,0,W,0,0, Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
: (
0,0,W,0,0,W,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // # 35 0,0,0,0,0,0,0,0, 0,0,W,0,0,W,0,0, 0,W,W,W,W,W,W,0, 0,0,W,0,0,W,0,0, 0,0,W,0,0,W,0,0, 0,W,W,W,W,W,W,0, 0,0,W,0,0,W,0,0, 0,0,0,0,0,0,0,0, // $ 36 0,0,0,W,0,0,0,0, 0,0,W,W,W,W,0,0, 0,W,0,W,0,0,0,0, 0,0,W,W,W,0,0,0, 0,0,0,W,0,W,0,0, 0,W,W,W,W,0,0,0, 0,0,0,W,0,0,0,0, 0,0,0,0,0,0,0,0, // % 37 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,W,W,0,0,W,0,0, 0,W,W,0,W,0,0,0, 0,0,0,W,0,0,0,0, 0,0,W,0,W,W,0,0, 0,W,0,0,W,W,0,0, 0,0,0,0,0,0,0,0, // & 38 0,0,0,0,0,0,0,0, 0,0,W,W,W,0,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,W,0,0,0,W,0,0, 0,0,W,W,W,0,0,0, 0,W,0,W,0,0,0,0, 0,W,0,0,W,0,W,0, 0,0,W,W,W,W,0,0, 0,0,0,0,0,0,W,0, // ' 39 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,W,0,0,0, 0,0,0,0,W,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // ( 40 0,0,0,0,0,0,W,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,W,0,0, 0,0,0,0,0,0,W,0, // ) 41 0,W,0,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,0,W,0,0,0,0,0, 0,W,0,0,0,0,0,0, // * 42
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,0,0,0,0,0,0,0, 0,0,0,W,0,0,0,0, 0,W,0,W,0,W,0,0, 0,0,W,W,W,0,0,0, 0,0,W,W,W,0,0,0, 0,0,W,W,W,0,0,0, 0,W,0,0,0,W,0,0, 0,0,0,0,0,0,0,0, // + 43 0,0,0,0,0,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,0,0,0,0, // , 44 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,0,0,0,0,0, // - 45 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,0,0,0,0,0,0,0, // . 46 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,0,0,0,0,0, // / 47 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,W,0, 0,0,0,0,0,W,W,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,0,0,0,0,0,0, // 0 48 0,0,W,W,W,W,0,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,W,W,0, 0,W,W,0,W,0,W,0, 0,W,W,W,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // 1 49 0,0,0,0,W,0,0,0, 0,0,W,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,W,W,0,0, // 2 50 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,0,0,0,0,W,0, 0,0,0,0,0,W,W,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,W,W,W,W,0, // 3 51 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,0,0,0,0,W,0, 0,0,0,0,0,0,W,0, 0,0,0,W,W,W,0,0, 0,0,0,0,0,0,W,0, 0,W,0,0,0,0,W,0, 0,0,W,W,W,W,0,0, // 4 52 0,0,0,0,W,W,0,0, 0,0,0,W,W,W,0,0, 0,0,W,W,0,W,0,0, 0,W,W,0,0,W,0,0, 0,W,W,W,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, // 5 53 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
0,W,W,0,0,0,0,0, 0,0,W,W,W,W,0,0, 0,0,0,0,0,0,W,0, 0,W,0,0,0,0,W,0, 0,0,W,W,W,W,0,0, // 6 54 0,0,0,W,W,W,W,0, 0,0,W,W,W,W,W,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,W,0,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // 7 55 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,W,0,0,0,W,W,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, // 8 56 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,0,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // 9 57 0,0,W,W,W,W,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,W,0, 0,0,0,0,0,W,W,0, 0,0,0,0,0,W,W,0, 0,0,0,0,0,W,W,0, // : 58 0,0,0,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,0,0,0,0,0, // ; 59 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, // < 60 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,W,W,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// = 61 0,0,0,0,0,0,0,0, 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,0,0, 0,0,0,0,0,0,0,0, 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // > 62 0,W,W,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,0,0,0,0,0, // ? 63 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,0,0,0,W,W,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, // @ 64 0,0,0,0,0,0,0,0, 0,0,W,W,W,0,0,0, 0,W,0,0,0,W,0,0, 0,W,0,W,W,0,0,0, 0,W,0,W,W,0,0,0, 0,W,0,0,0,0,W,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
0,0,W,W,W,W,0,0, 0,0,0,0,0,0,0,0, // A 65 0,0,W,W,W,0,0,0, 0,W,W,W,W,W,0,0, 0,W,W,0,0,W,0,0, 0,W,W,0,0,W,0,0, 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,0,0, 0,W,W,0,0,W,0,0, 0,W,W,0,0,W,0,0, // B 66 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,W,W,0, 0,W,W,0,0,W,0,0, 0,W,W,W,W,W,0,0, 0,W,W,0,0,W,W,0, 0,W,W,0,0,W,W,0, 0,W,W,W,W,W,0,0, // C 67 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // D 68 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,W,W,W,0,0, // E 69 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,W,W,0, // F 70 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, // G 71 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,0,0, 0,W,W,0,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // H 72 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, // I 73 0,0,W,W,W,W,0,0, 0,0,W,W,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,W,W,0,0, // J 74 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,W,0,0,W,W,0,0, 0,W,W,W,W,W,0,0, 0,0,W,W,W,0,0,0, // K 75 0,W,W,0,0,0,W,0, 0,W,W,0,0,W,W,0, 0,W,W,0,W,W,0,0, 0,W,W,W,W,0,0,0, 0,W,W,W,W,0,0,0, 0,W,W,0,W,W,0,0, 0,W,W,0,0,W,W,0, 0,W,W,0,0,0,W,0, // L 76
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,W,W,0, // M 77 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,W,0,W,W,0, 0,W,W,W,W,W,W,0, 0,W,W,0,W,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, // N 78 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,W,0,0,W,0, 0,W,W,W,W,0,W,0, 0,W,W,0,W,W,W,0, 0,W,W,0,0,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, // O 79 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,0,W,W,W,W,0,0, // P 80 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,W,W,W,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, // Q 81 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,W,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,W, // R 82 0,W,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,W,0,0, 0,W,W,W,W,0,0,0, 0,W,W,0,W,W,0,0, 0,W,W,0,0,W,W,0, // S 83 0,0,W,W,W,W,0,0, 0,W,W,W,W,W,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,0,0, 0,0,W,W,W,W,0,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0,0,0,0,0,0,W,0, 0,W,0,0,0,0,W,0, 0,0,W,W,W,W,0,0, // T 84 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, // U 85 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, // V 86 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,0,W,0,0, 0,0,W,W,0,W,0,0, 0,0,W,W,0,W,0,0, 0,0,0,W,W,0,0,0, // W 87 0,W,W,0,0,0,0,W, 0,W,W,0,0,0,0,W, 0,W,W,0,0,0,0,W,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
0,W,W,0,0,0,0,W, 0,W,W,0,W,W,0,W, 0,0,W,W,0,0,W,0, 0,0,W,W,0,0,W,0, 0,0,W,W,0,0,W,0, // X 88 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,0,W,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,W,0,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, // Y 89 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,W,W,0,0,0,W,0, 0,0,W,W,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, // Z 90 0,W,W,W,W,W,W,0, 0,W,W,W,W,W,W,0, 0,0,0,0,0,W,W,0, 0,0,0,0,W,W,0,0, 0,0,0,W,W,0,0,0, 0,0,W,W,0,0,0,0, 0,W,W,0,0,0,0,0, 0,W,W,W,W,W,W,0, // [ 91 0,0,0,0,W,W,W,0,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!#
0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,W,0, // \ 92 0,W,W,0,0,0,0,0, 0,W,W,0,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,W,W,0,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,W,W,0,0,0, 0,0,0,0,W,W,0,0, 0,0,0,0,W,W,0,0, // ] 93 0,W,W,W,0,0,0,0, 0,W,W,W,0,0,0,0, 0,0,0,W,0,0,0,0, 0,0,0,W,0,0,0,0, 0,0,0,W,0,0,0,0, 0,0,0,W,0,0,0,0, 0,0,0,W,0,0,0,0, 0,W,W,W,0,0,0,0, }; #endif
The DrawText Program H
! 6
( (
H
3
H +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
-
"
#
!
H
6
H
.
"
H
.
#
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 5: Bitmap-Based Video Modes // DrawText Project // main.c source code file //////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "font.h"
//declare some function prototypes void DrawPixel3(int, int, unsigned short); void DrawChar(int, int, char, unsigned short); void Print(int, int, char *, unsigned short);
//create some color constants #define WHITE 0xFFFF #define RED 0x00FF #define BLUE 0xEE00 #define CYAN 0xFF00 #define GREEN 0x0EE0 #define MAGENTA 0xF00F #define BROWN 0x0D0D
//define some video mode values #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//create a pointer to the video buffer Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
unsigned short* videoBuffer = (unsigned short*)0x6000000;
////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main() { char *test = "TESTING...1...2...3..."; int pos = 0;
//switch to video mode 3 (240x160 16-bit) REG_DISPCNT = (MODE_3 | BG2_ENABLE);
Print(1, 1, "DRAWTEXT PROGRAM", RED); Print(1, 20, "()*+,-.0123456789:;<=>?@", GREEN); Print(1, 30, "ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]", BLUE); Print(1, 50, "BITMAP FONTS ARE A CINCH!", MAGENTA); Print(1, 60, "(JUST BE SURE TO USE CAPS)", CYAN);
//display each character in a different color while (*test) { DrawChar(1 + pos, 80, *test++, 0xBB + pos * 16); pos += 8; }
Print(1, 100, "THAT'S ALL, FOLKS =]", BROWN);
//continuous loop while(1) { }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!"
return 0; }
////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
////////////////////////////////////////////////// // Function: Print // Prints a string using the hard-coded font ////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color); pos += 8; } }
////////////////////////////////////////////////// // Function: DrawChar // Draws a character one pixel at a time ////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color) { int x, y; int draw;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!$
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { // grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; // if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); } }
H
3
# %"
!* "
1
"
( )$
Summary 0
( ! " A
! 9
# "
%# -
.
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
Challenges
-/ 4
$
# !
+ -
5
:
=,
# $
4
0/
! 4
1/ 5
$
C H
5
-
!
=
!
( +
(
.
@6 ++
Chapter Quiz 0 C 0 C 0 C
%$
0
% ,
-
? $ $ 6 $ H $
E$$B$$$ B$$$$$$ B$$#$$$ "O&A!$$
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
& ,
&"$ 4 4 6 4 H 4
!
%B$
?
" ! # & 3
*I
#
3 " ,
%B$ 4
B
4 6 4 H 4
" # !
# ,
$ $
B$$$$$$ E$$B$$$
6 $ H $
B$$#$$$ B$$ $$$
%&A?
"?
B ,
4
!9
?
1 6 ) H I
5
E ,
&"$ 4 4 6 4 H 4
%B$ %#
-
?
! & # "
A ,
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%#
!
#?
!
6 H
-
O ,
"? !& %B 6 B" H A
%$ ,
C
?
@1 + , 6 . H +
-
6 :
-
=
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! " !
# •
$
%
#
&
(
• •
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
'
"
Introduction to Tile-Based Video Modes !
) +
,$ .$&/
&$
* +
!
-
) .&+
0.&
-
!
.$&/ 0.&
*
1.
$
$ . & ,
6
.
$ . &
7
)&*
&
& ,
7
)& ,*
2
.&+ -
.&+
3 5
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
4 1.
.&+ 4
2
1& 8
! "
Backgrounds 5
4
4
)$
.* ) 2
1 &* )
* 9
4
4
.1
.1 ,&
,&
1/
3
(
+
+ : + ! )
$
0$$$$$$
&01
)& ,* ! .&+ . $&/ .1
* ( .1
.1 9
-
.1 +
1/
.1
* )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
.1 /
)
.1 .0
( *
! &
1& ,
$
.
$
0.&
0.&
6
.
0.&
0.&
6
&
.&+
. $&/
7
,
.&+
. $&/
7
Background Scrolling !
( ;
$
-
)
,9
)
* (
* )
* # 3
#
$
7 6 <( )
=
,9
* = 2
1,
Tiles and Sprites : ), /
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0*
>% # (
'
-
3
:
.&+
( : -
(
(
? 3
3
# $
$"
% $
!
$
$ $ " %
$ $
&
'
$
The Tile Data and Tile Map !
)
*
( .1
)$ )&
,*
.* +
!
!
)
* $ 1$$2222 A
! .1 @
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
>% # $ 1$$$$$$
" 2 !
"
%
,&
"
"
%
1/ )
*
,.
" $'$ $'$ $ " % () "
! $
Creating a Scrolling Background ! ! # (9 B 2
( $
2
3 10
( A
(
(3 (
2
1 1
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&01 $
&01
* $ + $ "
"
%
$ $
$
6 ! ( !
( ( 3
2
)
1 C*
, ! $ $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
Converting the Graphics 3
! &
' # ' #
D' #
' # )
5
%
4
4
%
*" \ham\startham.bat
!
' # 59 @ )
%#
* !
=
' # ' # @
)
&C 4' #
5 5
* 5 4 !
=
' # 9 =
9 %: # D5
D
$1D! # $
!
#
$ *
3
) "
gfx2gba -fsrc -m -ptest.pal -t8 test.bmp
&
)
4' #
4
(
*" \ham\tools\win32\gfx2gba -fsrc -m -ptest.pal -t8 test.bmp
!
+ -
+
+
)
-
( *
(
&
======================= gfx2gba Converter v0.14 ----------------------Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
(C) 2oo1-2oo2 [TRiNiTY] =======================
Reading: test.bmp
(256x256 pixel, 256 colors)
Number of tiles before optimization: 1024 Number of tiles after
optimization: 0906
Saving tiled bitmap data to: test.raw.c ... ok Saving map data to: test.map.c ... ok
Saving masterpalette to..: test.pal.c ... ok
Total files read & converted.:
1
Colors used before converting: 108 Colors used after converting.: 108 Colors saved.................:
0
( -
"
Number of tiles before optimization: 1024 Number of tiles after
optimization: 0906
9
,& . $&/
)
+
+
,& *
&01
&
!
,&
,&
(
4
- E
.1 1/ (
Fast Blitting with DMA :
( ?
9#
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
4
+ F$1 -
(
&01 E
E E =G
9#
) !
*
=G 9#
=G 6
3
! %9 % #
99%
=
9# )
* A
9# !
=G
9#
9# 9#
)
* H
9#
=G 7 2
%# C =G
)%(5 * # A .& 4:
) -
H
4* '
9#
E ( $
!
9# (
!
E
3 2
,3
9# 9# " 9 # J,&6 : A
)
! # $ 9 # J.16 : A ! % #*
2
! .1
,&
) .1
,& Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
)I $* . &
% #*
#define REG_DMA3SAD *(volatile unsigned int*)0x40000D4 #define REG_DMA3DAD *(volatile unsigned int*)0x40000D8 #define REG_DMA3CNT *(volatile unsigned int*)0x40000DC #define DMA_ENABLE 0x80000000 #define DMA_TIMING_IMMEDIATE 0x00000000 #define DMA_16 0x00000000 #define DMA_32 0x04000000 #define DMA_32NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_32) #define DMA_16NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_16)
(
9#
9# '
9# 2
"
void DMAFastCopy(void* source,void* dest,unsigned int count,unsigned int mode) { if (mode == DMA_16NOW || mode == DMA_32NOW) { REG_DMA3SAD = (unsigned int)source; REG_DMA3DAD = (unsigned int)dest; REG_DMA3CNT = count | mode; } }
6 ( ! 2
9#
=G
(
TileMode0 Source Code !
9# (
3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! K = )
9
(
L E
6
> 3
' # 9 %: #
7
8E 3
D5
L* :
D
! $1D! # (
# $ 7
$
9 %: # (
( 3
5 !
5
9# (
' " //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 6: Tile-Based Video Modes // TileMode0 Project // main.c source code file ////////////////////////////////////////////////////////////
MULTIBOOT
//include the sample tileset/map #include "test.pal.c" #include "test.raw.c" #include "test.map.c"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
(
-
#define MULTIBOOT int __gba_multiboot;
# -
!
#
$
//function prototype void DMAFastCopy(void*, void*, unsigned int, unsigned int);
//defines needed by DMAFastCopy #define REG_DMA3SAD *(volatile unsigned int*)0x40000D4 #define REG_DMA3DAD *(volatile unsigned int*)0x40000D8 #define REG_DMA3CNT *(volatile unsigned int*)0x40000DC #define DMA_ENABLE 0x80000000 #define DMA_TIMING_IMMEDIATE 0x00000000 #define DMA_16 0x00000000 #define DMA_32 0x04000000 #define DMA_32NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_32) #define DMA_16NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_16)
//scrolling registers for background 0 #define REG_BG0HOFS *(volatile unsigned short*)0x4000010 #define REG_BG0VOFS *(volatile unsigned short*)0x4000012
//background setup registers and data #define REG_BG0CNT *(volatile unsigned short*)0x4000008 #define REG_BG1CNT *(volatile unsigned short*)0x400000A #define REG_BG2CNT *(volatile unsigned short*)0x400000C #define REG_BG3CNT *(volatile unsigned short*)0x400000E #define BG_COLOR256 0x80 #define CHAR_SHIFT 2 #define SCREEN_SHIFT 8 #define WRAPAROUND 0x1
//background tile bitmap sizes #define TEXTBG_SIZE_256x256 0x0 #define TEXTBG_SIZE_256x512 0x8000 #define TEXTBG_SIZE_512x256 0x4000 #define TEXTBG_SIZE_512x512 0xC000
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//background memory offset macros #define CharBaseBlock(n) (((n)*0x4000)+0x6000000) #define ScreenBaseBlock(n) (((n)*0x800)+0x6000000)
//background mode identifiers #define BG0_ENABLE 0x100 #define BG1_ENABLE 0x200 #define BG2_ENABLE 0x400 #define BG3_ENABLE 0x800
//video identifiers #define REG_DISPCNT *(unsigned int*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000) #define SetMode(mode) REG_DISPCNT = (mode)
//vertical refresh register #define REG_DISPSTAT
*(volatile unsigned short*)0x4000004
//button identifiers #define BUTTON_RIGHT 16 #define BUTTON_LEFT
32
#define BUTTON_UP
64
#define BUTTON_DOWN
128
#define BUTTONS (*(volatile unsigned int*)0x04000130)
//wait for vertical refresh void WaitVBlank(void) { while((REG_DISPSTAT & 1)); }
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//////////////////////////////////////////////////////////// int main(void) { int x = 0, y = 0; int n;
//create a pointer to background 0 tilemap buffer unsigned short* bg0map =(unsigned short*)ScreenBaseBlock(31);
//set up background 0 REG_BG0CNT = BG_COLOR256 | TEXTBG_SIZE_256x256 | (31 << SCREEN_SHIFT) | WRAPAROUND;
//set video mode 0 with background 0 SetMode(0 | BG0_ENABLE);
//copy the palette into the background palette memory DMAFastCopy((void*)test_Palette, (void*)BGPaletteMem, 256, DMA_16NOW);
//copy the tile images into the tile memory DMAFastCopy((void*)test_Tiles, (void*)CharBaseBlock(0), 57984/4, DMA_32NOW);
//copy the tile map into background 0 DMAFastCopy((void*)test_Map, (void*)bg0map, 512, DMA_32NOW);
//main game loop while(1) { //wait for vertical refresh WaitVBlank();
//D-pad moves background
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
if(!(BUTTONS & BUTTON_LEFT)) x--; if(!(BUTTONS & BUTTON_RIGHT)) x++; if(!(BUTTONS & BUTTON_UP)) y--; if(!(BUTTONS & BUTTON_DOWN)) y++;
//use hardware background scrolling REG_BG0VOFS = y ; REG_BG0HOFS = x ;
//wait for vertical refresh WaitVBlank();
for(n = 0; n < 4000; n++); } return 0; }
//////////////////////////////////////////////////////////// // Function: DMAFastCopy // Fast memory copy function built into hardware //////////////////////////////////////////////////////////// void DMAFastCopy(void* source, void* dest, unsigned int count, unsigned int mode) { if (mode == DMA_16NOW || mode == DMA_32NOW) { REG_DMA3SAD = (unsigned int)source; REG_DMA3DAD = (unsigned int)dest; REG_DMA3CNT = count | mode; } }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Creating a Rotating Background %
)& $ .
,* &) )
, / *
(
% &
0*
#
&
, !
&
&E
& 3
>
' #
%
#
&
(
( !
2
, 2
%
#
&
1+
.
* $ $
& " %
$
Converting the Tile Image !
% 2
1 F
/ $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
.
* $
#
&
! &
"
\ham\tools\win32\gfx2gba -fsrc -m -t8 -rs -ptiles.pal tiles.bmp
!
) )
*
-
+
+ ) +*
M
*
Creating the Tile Map 2
% &
#
&
(
2 3
7
//16x16 tile map const unsigned char tiles_Map[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 4, 4, 3, 4, 4, 4, 3, 3, 4, 4, 4, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5 !
RotateMode2 Source Code !
%
#
&
!
" #define REG_BG2X
*(volatile unsigned int*)0x4000028
#define REG_BG2Y
*(volatile unsigned int*)0x400002C
#define REG_BG2PA
*(volatile unsigned short *)0x4000020
#define REG_BG2PB
*(volatile unsigned short *)0x4000022
#define REG_BG2PC
*(volatile unsigned short *)0x4000024
#define REG_BG2PD
*(volatile unsigned short *)0x4000026
! " #define ROTBG_SIZE_128x128
0x0
#define ROTBG_SIZE_256x256
0x4000
#define ROTBG_SIZE_512x512
0x8000
#define ROTBG_SIZE_1024x1024
0xC000
A
!
ROTBG_SIZE_128x128
% void RotateBackground(int ang, int cx, int cy, int zoom) { center_y = (cy * zoom) >> 8; center_x = (cx * zoom) >> 8;
DX = (x_scroll - center_y * SIN[ang] - center_x * COS[ang]); DY = (y_scroll - center_y * COS[ang] + center_x * SIN[ang]);
PA = (COS[ang] * zoom) >> 8; PB = (SIN[ang] * zoom) >> 8; PC = (-SIN[ang] * zoom) >> 8; PD = (COS[ang] * zoom) >> 8; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
G !
!
? ( ! ,1$
85 %
#
&
3
9 %: #
( 2
(
6 //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 6: Tile-Based Video Modes // RotateMode2 Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "rotation.h" #include "tiles.pal.c" #include "tiles.raw.c" #include "tilemap.h"
//prototypes void DMAFastCopy(void*, void*, unsigned int, unsigned int); void RotateBackground(int, int, int, int);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//defines needed by DMAFastCopy #define REG_DMA3SAD *(volatile unsigned int*)0x40000D4 #define REG_DMA3DAD *(volatile unsigned int*)0x40000D8 #define REG_DMA3CNT *(volatile unsigned int*)0x40000DC #define DMA_ENABLE 0x80000000 #define DMA_TIMING_IMMEDIATE 0x00000000 #define DMA_16 0x00000000 #define DMA_32 0x04000000 #define DMA_32NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_32) #define DMA_16NOW (DMA_ENABLE | DMA_TIMING_IMMEDIATE | DMA_16)
//background movement/rotation registers #define REG_BG2X
*(volatile unsigned int*)0x4000028
#define REG_BG2Y
*(volatile unsigned int*)0x400002C
#define REG_BG2PA
*(volatile unsigned short *)0x4000020
#define REG_BG2PB
*(volatile unsigned short *)0x4000022
#define REG_BG2PC
*(volatile unsigned short *)0x4000024
#define REG_BG2PD
*(volatile unsigned short *)0x4000026
//background 2 stuff #define REG_BG2CNT
*(volatile unsigned short *)0x400000C
#define BG2_ENABLE
0x400
#define BG_COLOR256
0x80
//background constants #define ROTBG_SIZE_128x128
0x0
#define ROTBG_SIZE_256x256
0x4000
#define ROTBG_SIZE_512x512
0x8000
#define ROTBG_SIZE_1024x1024
0xC000
#define CHAR_SHIFT
2
#define SCREEN_SHIFT
8
#define WRAPAROUND
0x1
#define BG_MOSAIC_ENABLE
0x40
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//video-related memory #define REG_DISPCNT
*(volatile unsigned int*)0x4000000
#define BGPaletteMem
((unsigned short *)0x5000000)
#define REG_DISPSTAT
*(volatile unsigned short *)0x4000004
#define BUTTON_A
1
#define BUTTON_B
2
#define BUTTON_RIGHT
16
#define BUTTON_LEFT
32
#define BUTTON_UP
64
#define BUTTON_DOWN
128
#define BUTTON_R
256
#define BUTTON_L
512
#define BUTTONS
(*(volatile unsigned int*)0x04000130)
#define CharBaseBlock(n)
(((n)*0x4000)+0x6000000)
#define ScreenBaseBlock(n)
(((n)*0x800)+0x6000000)
#define SetMode(mode) REG_DISPCNT = (mode)
//some variables needed to rotate the background int x_scroll=0,y_scroll=0; int DX=0,DY=0; int PA,PB,PC,PD; int zoom = 2; int angle = 0; int center_y,center_x;
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main(void) {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
int n; int charbase = 0; int screenbase = 31;
unsigned short * bg2map = (unsigned short *)ScreenBaseBlock(screenbase);
//set up background 0 REG_BG2CNT = BG_COLOR256 | ROTBG_SIZE_128x128 | (charbase << CHAR_SHIFT) | (screenbase << SCREEN_SHIFT);
//set video mode 0 with background 0 SetMode(2 | BG2_ENABLE);
//set the palette DMAFastCopy((void*)tiles_Palette, (void*)BGPaletteMem, 256, DMA_16NOW);
//set the tile images DMAFastCopy((void*)tiles_Tiles, (void*)CharBaseBlock(0), 256/4, DMA_32NOW);
//copy the tile map into background 0 DMAFastCopy((void*)tiles_Map, (void*)bg2map, 256/4, DMA_32NOW);
while(1) { while(!(REG_DISPSTAT & 1));
//use the hardware to scroll around some if(!(BUTTONS & BUTTON_LEFT)) x_scroll--; if(!(BUTTONS & BUTTON_RIGHT)) x_scroll++; if(!(BUTTONS & BUTTON_UP)) y_scroll--; if(!(BUTTONS & BUTTON_DOWN)) y_scroll++; if(!(BUTTONS & BUTTON_A)) zoom--; if(!(BUTTONS & BUTTON_B)) zoom++; if(!(BUTTONS & BUTTON_L)) angle--;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
if(!(BUTTONS & BUTTON_R)) angle++;
if(angle > 359) angle = 0; if(angle < 0) angle = 359;
//rotate the background RotateBackground(angle,64,64,zoom);
while((REG_DISPSTAT & 1));
//update the background REG_BG2X = DX; REG_BG2Y = DY; REG_BG2PA = PA; REG_BG2PB = PB; REG_BG2PC = PC; REG_BG2PD = PD;
while((REG_DISPSTAT & 1)); for(n = 0; n < 100000; n++);
} }
//////////////////////////////////////////////////////////// // Function: RotateBackground // Helper function to rotate a background //////////////////////////////////////////////////////////// void RotateBackground(int ang, int cx, int cy, int zoom) { center_y = (cy * zoom) >> 8; center_x = (cx * zoom) >> 8;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
DX = (x_scroll - center_y * SIN[ang] - center_x * COS[ang]); DY = (y_scroll - center_y * COS[ang] + center_x * SIN[ang]);
PA = (COS[ang] * zoom) >> 8; PB = (SIN[ang] * zoom) >> 8; PC = (-SIN[ang] * zoom) >> 8; PD = (COS[ang] * zoom) >> 8; }
//////////////////////////////////////////////////////////// // Function: DMAFastCopy // Fast memory copy function built into hardware //////////////////////////////////////////////////////////// void DMAFastCopy(void* source, void* dest, unsigned int count, unsigned int mode) { if (mode == DMA_16NOW || mode == DMA_32NOW) { REG_DMA3SAD = (unsigned int)source; REG_DMA3DAD = (unsigned int)dest; REG_DMA3CNT = count | mode; } }
Summary ! ' ?
3 3
3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
C
" 3
0
1
Challenges !
"!
!
#
$
&01
&01
# 0.&
"!
%
#
&
.&+
0.&
.&+
'
. $&/
. $&/
- 8
#
Chapter Quiz ! !
? ? ? -
.$
. A
?
$ .
!
&
<
!
9 = & '
< , & / 9 .
, A
< # #
/ $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# 9 #
C &
/ A
&< . . & / 0 9 &
& , 1 ,
0 A
< # #
$ &
# 9 #
, .
1 A
.< $ . . & & 9 , /
C A
& , , 0 .
<
, . & 9 $ + A %B J
" %B J
&=
%B J
&=
%B J
&=9 <
9 F '
? / &
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
9#
<
&=
, 9 . .$ !
M2 ! 2
"9
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
<
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
! "
#$
%
&
'
(
'
) * ) +
,
•
- %
•
.
• •
/
% ( !
!
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
- %
!0
1 2
#
, 3
,
4.
3 %
$
%
2 (
0/
5
/ 1 6 0
7 0/ 6 ,
2$ 8 3 -
1
$ 8 (
94:
;
94:
! 2
3
<
=> '
'
1 % <
> >
(
:
$
9=
(
< ?4
:
= 4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
8
6
1
6
,
% !
1. 2. 3. 4. 5.
/ 6 ;
<
$ 8 ";
. 6 0/ 7 $ 8
@
,
$ 8
/ ; >
:
:
: )
,
)
$
)
9
2
(
(
2
3
3 $ *
* ) 2
9=
4A=
3
< )
/ 1 % 4 4 Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
1 % ! 9=
4A=
4A=
94:
6
<
<
>
=
: ;
* ?4
9=(
9=
4A=(
/ 4
, 1
;
2
3
4 4
(:
4A=
<
:
( ?4
!
:
?2 9=
3
4A=
( B (
$
! & #' #$( !
*
"
#$ %
' $ ' $( * #'"
! $ 8
") !
$ 8 $ 8
2
3 $ 8
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
" 8
$ 8
7
% $ 8
- %
:
:
,
%
<
%
+
%
<
< 9=( 4A=( 9=(
4A=( C C=C9CCCC
%
=> C C=C9CC? 4A=(
4A=( 4A=( C
9
9=( 4
C C=C9CC>C)
9=( 4
4A=(
#"
4A=( A94
-
%
4.
B
9 C4> 2
A943
*
?4 D
"$ 8 2 .
;1 " 8 3
4.
E
";
. 6 0/7
REG.DISPCNT |= DC_SPRITESEQ;
%
*
?4
.8
'
"
' < '2
4 + 8 .D
' 0
+ 8 .
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
D
" $
< 3
(
$ E
4
. 7
% # B
F9
, 6 6
6% 6
/ ( ! G
&B G/
F4 CFG
E
,
+
,"# "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
,"' " * "
,
4 % * 1
* E /
( ;
)
4
4 / 0 5 $ 7
*' 0
1
1
*' !
2 ! 6 " " "7 -
;
344 8"
"
G
G/
1
"
!
CFG
4
4A=(
4 B
F?
+
,"
. *'
%
6
%
! /**********************************************\ * *
ship.h
*
by dovotos pcx->gba program
*
/**********************************************/ #define
ship_WIDTH
64
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
#define
ship_HEIGHT
64
const u16 shipData[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE9AD,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x1301, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xFB50,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
...
$ .
%
6
,
/ , /
,
! //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // SimpleSprite Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
typedef unsigned short u16;
#include "ship.h"
//macro to change the video mode #define SetMode(mode) REG_DISPCNT = (mode)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
@
+ 8
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000) #define REG_VCOUNT *(volatile unsigned short*)0x4000006 #define REG_DISPSTAT *(volatile unsigned short *)0x4000004
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//misc sprite constants #define OBJ_MAP_2D
0x0
#define OBJ_MAP_1D
0x40
#define OBJ_ENABLE
0x1000
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_16
0x0000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define ROTDATA(n)
((n) << 9)
#define HORIZONTAL_FLIP
0x1000
#define VERTICAL_FLIP
0x2000
#define SIZE_8
0x0
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//attribute2 stuff #define PRIORITY(n) #define PALETTE(n)
((n) << 10) ((n) << 12)
//sprite structs typedef struct tagSprite { unsigned short attribute0; unsigned short attribute1; unsigned short attribute2; unsigned short attribute3; }Sprite,*pSprite;
//create an array of 128 sprites equal to OAM Sprite sprites[128];
//function prototypes void WaitForVsync(void); void UpdateSpriteMemory(void);
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main(void) { signed short x = 10, y = 40;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
signed short xdir = 1, ydir = 1; int char_number = 0; int n;
//set the video mode--mode 2 with sprites SetMode(2 | OBJ_ENABLE | OBJ_MAP_1D);
//move all sprites offscreen to hide them for(n = 0; n < 128; n++) { sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; }
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = shipPalette[n];
//copy the sprite image into memory for(n = 0; n < 256*8; n++) { SpriteData[n] = shipData[n]; }
//setup the first sprite sprites[0].attribute0 = COLOR_256 | y; sprites[0].attribute1 = SIZE_64 | x; sprites[0].attribute2 = char_number;
while(1) { //update sprite x position x += xdir; if (x > 239 - ship_WIDTH) x = 0;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//update sprite y position y += ydir; if (y > 159 - ship_HEIGHT) { y = 159 - ship_HEIGHT; ydir = -1; } if (y < 1) { y = 1; ydir = 1; }
//update sprite attributes with new x,y position sprites[0].attribute0 = COLOR_256 | y; sprites[0].attribute1 = SIZE_64 | x;
//wait for vertical retrace WaitForVsync();
//display the sprite UpdateSpriteMemory(); } }
//////////////////////////////////////////////////////////// // Function: WaitForVsync // Waits for the vertical retrace //////////////////////////////////////////////////////////// void WaitForVsync(void) { while((REG_DISPSTAT & 1)); }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites;
for(n = 0; n < 128*4; n++) SpriteMem[n] = temp[n]; }
6
( (
/
2 <
3
+
7
%
6% 1 %
8
6 < $
6% 2
1
.
3
+
. # % +
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
!
int size; }SpriteHandler;
Actually using the struct involves creating an array of structs: SpriteHandler mysprites[128];
7 * 6
/ - %
# B
F>
+
,"
!
#9 ! "
6
1 6
*
9C , ,
/. ("$ 8 % 7
@
+ 8 G/
G
B
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
B
FA
CFG ,
6 B
7
7
B
+
," :
+
! * 1
/ +
'
'
0 , ,
+
B !
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // BounceSprite Project // main.h header file ////////////////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
typedef unsigned short u16;
#include <stdlib.h> #include "ball.h" #include "bg.raw.c"
//macro to change the video mode #define SetMode(mode) REG_DISPCNT = (mode)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000)
//declare scanline counter for vertical blank volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
//video modes 3-5, OAMData starts at 0x6010000 + 8192 unsigned short* SpriteData3 = SpriteData + 8192;
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//misc sprite constants #define OBJ_MAP_2D 0x0 #define OBJ_MAP_1D 0x40 #define OBJ_ENABLE 0x1000 #define BG2_ENABLE0x400
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff #define SIZE_8
0x0
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//an entry for object attribute memory (OAM) typedef struct tagSprite { unsigned short attribute0; unsigned short attribute1; unsigned short attribute2; unsigned short attribute3; }Sprite,*pSprite;
//create an array of 128 sprites equal to OAM Sprite sprites[128];
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry; int size;
}SpriteHandler;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
SpriteHandler mysprites[128];
#endif
8
B
7
"
#
$ % && '(
E
94: //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // BounceSprite Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
#define NUMBALLS 10
//////////////////////////////////////////////////////////// // Function: HideSprites // Moves all sprites off the screen //////////////////////////////////////////////////////////// void HideSprites() { int n; for (n = 0; n < 128; n++) {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; } }
//////////////////////////////////////////////////////////// // Function: MoveSprite // Changes sprite attributes for x,y positions //////////////////////////////////////////////////////////// void MoveSprite(int num) { //clear the old x value sprites[num].attribute1 = sprites[num].attribute1 & 0xFE00; sprites[num].attribute1 = sprites[num].attribute1 | mysprites[num].x;
//clear the old y value sprites[num].attribute0 = sprites[num].attribute0 & 0xFF00; sprites[num].attribute0 = sprites[num].attribute0 | mysprites[num].y; }
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites;
for(n = 0; n < 128 * 4; n++) SpriteMem[n] = temp[n]; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
///////////////////////////////////////////////////////////// // Function: InitSprite // Initializes a sprite within the sprite handler array ///////////////////////////////////////////////////////////// void InitSprite(int num, int x, int y, int size, int color, int tileIndex) { unsigned int sprite_size = 0;
mysprites[num].alive = 1; mysprites[num].size = size; mysprites[num].x = x; mysprites[num].y = y;
//in modes 3-5, tiles start at 512, modes 0-2 start at 0 sprites[num].attribute2 = tileIndex;
//initialize sprites[num].attribute0 = color | y;
switch (size) { case 8: sprite_size = SIZE_8; break; case 16: sprite_size = SIZE_16; break; case 32: sprite_size = SIZE_32; break; case 64: sprite_size = SIZE_64; break; }
sprites[num].attribute1 = sprite_size | x; }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period /////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
void WaitVBlank(void) { while(*ScanlineCounter < 160); }
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main() { int n;
//set the video mode--mode 3, bg 2, with sprite support SetMode(3 | OBJ_ENABLE | OBJ_MAP_1D | BG2_ENABLE);
//draw the background for(n=0; n < 38400; n++) videoBuffer[n] = bg_Bitmap[n];
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = ballPalette[n];
//load ball sprite for(n = 0; n < 512; n++) SpriteData3[n] = ballData[n];
//move all sprites off the screen HideSprites();
//initialize the balls--note all sprites use the same image (512) for (n = 0; n < NUMBALLS; n++) {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
InitSprite(n, rand() % 230, rand() % 150, ball_WIDTH, COLOR_256, 512); while (mysprites[n].dirx == 0) mysprites[n].dirx = rand() % 6 - 3; while (mysprites[n].diry == 0) mysprites[n].diry = rand() % 6 - 3; }
//main loop while(1) { //keep the screen civil WaitVBlank();
for (n = 0; n < NUMBALLS; n++) { //update sprite x position mysprites[n].x += mysprites[n].dirx; if (mysprites[n].x > 239 - mysprites[n].size) { mysprites[n].x = 239 - mysprites[n].size; mysprites[n].dirx *= -1; } if (mysprites[n].x < 1) { mysprites[n].x = 1; mysprites[n].dirx *= -1; }
//update sprite y position mysprites[n].y += mysprites[n].diry; if (mysprites[n].y > 159 - mysprites[n].size) { mysprites[n].y = 159 - mysprites[n].size;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
mysprites[n].diry *= -1; } if (mysprites[n].y < 1) { mysprites[n].y = 1; mysprites[n].diry *= -1; }
//update the sprite properties MoveSprite(n); } //copy all sprites into object attribute memory UpdateSpriteMemory(); } }
"
< < 4
2
3
6
B
* <
B
F =
6
% 4
7 8
--
94: - % 6%
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
,"$
; #$ * #$
! <
!
! !
*'
"
; <
(
)
%
2 )
*
3 *
& )
)
!
6 *
$ *
B
.
) *$&
%
//transparency registers #define REG_BLDMOD
*(unsigned short*)0x4000050
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+
) * + & ,!
#define REG_COLEV
*(unsigned short*)0x4000052
0
2
3
! //set transparency level REG_BLDMOD = (1 << 4) | (1 << 10); REG_COLEV = (8) + (8 << 8);
1 + ! #define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
1
#
,
2$ 8 3 $
C
23 6
5 #6
* 6
6
<
6 %
26
'
'
3 +
C
! sprites[num].attribute0 = COLOR_256 | MODE_TRANSPARENT | y;
6%
B
6% , / . ("$ 8 6
FF 2
6%
@
+ 8 7 G/
G 3
6
% B
F:
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
, CFG
6 4
@
< 2
6
3
1 +
,
#6% )
,
2
3
+
,",
! ! "
+
,"=
. 7 >?: . @ . 7 >? : 0 >: "
7 7
% 7
, 0 ,
7
6 @
+ 8
B
,
,
+
B
%
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
%
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // TransSprite Project // main.h header file ////////////////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
typedef unsigned short u16;
#include <stdlib.h> #include "ball.h" #include "bg.raw.c"
//macro to change the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000)
//declare scanline counter for vertical blank volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
//video modes 3-5, OAMData starts at 0x6010000 + 8192 unsigned short* SpriteData3 = SpriteData + 8192;
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//transparency stuff #define REG_BLDMOD
*(unsigned short*)0x4000050
#define REG_COLEV
*(unsigned short*)0x4000052
//misc sprite constants #define OBJ_MAP_2D
0x0
#define OBJ_MAP_1D
0x40
#define OBJ_ENABLE
0x1000
#define BG2_ENABLE
0x400
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff #define SIZE_8
0x0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//an entry for object attribute memory (OAM) typedef struct tagSprite { unsigned short attribute0; unsigned short attribute1; unsigned short attribute2; unsigned short attribute3; }Sprite,*pSprite;
//create an array of 128 sprites equal to OAM Sprite sprites[128];
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry; int size; int colormode; int trans;
}SpriteHandler;
SpriteHandler mysprites[128];
#endif
.
+ E ,
%
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6
% ,
#
B
* 7 //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // TransSprite Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
#define NUMBALLS 5
//////////////////////////////////////////////////////////// // Function: HideSprites // Moves all sprites off the screen //////////////////////////////////////////////////////////// void HideSprites() { int n; for (n = 0; n < 128; n++) { sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; } }
////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
// Function: MoveSprite // Changes sprite attributes for x,y positions //////////////////////////////////////////////////////////// void MoveSprite(int num) { //clear the old x value sprites[num].attribute1 = sprites[num].attribute1 & 0xFE00; sprites[num].attribute1 = sprites[num].attribute1 | mysprites[num].x;
//clear the old y value sprites[num].attribute0 = sprites[num].attribute0 & 0xFF00; sprites[num].attribute0 = sprites[num].attribute0 | mysprites[num].y; }
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites;
for(n = 0; n < 128 * 4; n++) SpriteMem[n] = temp[n]; }
6
23 6
///////////////////////////////////////////////////////////// // Function: InitSprite // Initializes a sprite within the sprite handler array ///////////////////////////////////////////////////////////// void InitSprite(int num, int x, int y, int size, int tileIndex)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
{ unsigned int sprite_size = 0;
mysprites[num].alive = 1; mysprites[num].size = size; mysprites[num].x = x; mysprites[num].y = y; mysprites[num].colormode = COLOR_256; mysprites[num].trans = MODE_TRANSPARENT;
//in modes 3-5, tiles start at 512, modes 0-2 start at 0 sprites[num].attribute2 = tileIndex;
//initialize sprites[num].attribute0 = COLOR_256 | MODE_TRANSPARENT | y;
switch (size) { case 8: sprite_size = SIZE_8; break; case 16: sprite_size = SIZE_16; break; case 32: sprite_size = SIZE_32; break; case 64: sprite_size = SIZE_64; break; }
sprites[num].attribute1 = sprite_size | x; }
///////////////////////////////////////////////////////////// // Function: SetTransparency // Changes the transparency of a sprite, // MODE_NORMAL or MODE_TRANSPARENT /////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
void SetTrans(int num, int trans) { mysprites[num].trans = trans; sprites[num].attribute0 = mysprites[num].colormode | mysprites[num].trans | mysprites[num].y; }
///////////////////////////////////////////////////////////// // Function: SetColorMode // Changes the color mode of the sprite // COLOR_16 or COLOR_256 ///////////////////////////////////////////////////////////// void SetColorMode(int num, int colormode) { mysprites[num].colormode = colormode; sprites[num].attribute0 = mysprites[num].colormode | mysprites[num].trans | mysprites[num].y; }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(*ScanlineCounter < 160); }
8 6
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//////////////////////////////////////////////////////////// int main() { int n; int counter = 0; int change = 0;
//set the video mode--mode 3, bg 2, with sprite support SetMode(3 | OBJ_ENABLE | OBJ_MAP_1D | BG2_ENABLE);
//draw the background for(n=0; n < 38400; n++) videoBuffer[n] = bg_Bitmap[n];
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = ballPalette[n];
//load ball sprite for(n = 0; n < ball_WIDTH * ball_HEIGHT / 2; n++) SpriteData3[n] = ballData[n];
//move all sprites off the screen HideSprites();
//initialize the balls--note all sprites use the same image (512) for (n = 0; n < NUMBALLS; n++) { InitSprite(n, rand() % 230, rand() % 150, ball_WIDTH, 512); while (mysprites[n].dirx == 0) mysprites[n].dirx = rand() % 6 - 3; while (mysprites[n].diry == 0) mysprites[n].diry = rand() % 6 - 3; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//set transparency level REG_BLDMOD = (1 << 4) | (1 << 10); REG_COLEV = (8) + (8 << 8);
//main loop while(1) { //keep the screen civil WaitVBlank();
//toggle transparency after an interval if (counter++ > 1000) { counter = 0; if (change) { change = 0; for (n = 0; n < NUMBALLS; n++) SetTrans(n, MODE_NORMAL); } else { change = 1; for (n = 0; n < NUMBALLS; n++) SetTrans(n, MODE_TRANSPARENT); } }
for (n = 0; n < NUMBALLS; n++) { //update sprite x position mysprites[n].x += mysprites[n].dirx; if (mysprites[n].x > 239 - mysprites[n].size)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
{ mysprites[n].x = 239 - mysprites[n].size; mysprites[n].dirx *= -1; } if (mysprites[n].x < 1) { mysprites[n].x = 1; mysprites[n].dirx *= -1; }
//update sprite y position mysprites[n].y += mysprites[n].diry; if (mysprites[n].y > 159 - mysprites[n].size) { mysprites[n].y = 159 - mysprites[n].size; mysprites[n].diry *= -1; } if (mysprites[n].y < 1) { mysprites[n].y = 1; mysprites[n].diry *= -1; }
//update the sprite properties MoveSprite(n); } //copy all sprites into object attribute memory UpdateSpriteMemory(); } }
1
%
6% )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
" 6 # %
%
(
( 67
/$
% , % 2
6%
3
+ %
(
,
6 $ 8
" .
$ 8
+
% typedef struct tagRotData { u16 filler1; u16 pa; u16 filler2; u16 pb;
u16 filler3;
u16 pc;
u16 filler4;
u16 pd; }RotData,*pRotData;
% 2
3
pRotData rotData = (pRotData)sprites;
6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
( (
2
3
/ ?=C
//math values needed for rotation #define PI 3.14159265 #define RADIAN(n) (((float)n) / (float)180 * PI)
+
67
/$
!
//precomputed sine and cosine arrays signed int SIN[360]; signed int COS[360];
67
/$
(
/0
6
for(n = 0; n < 360; n++) { SIN[n] = (signed int)(sin(RADIAN(n)) * 256); COS[n] = (signed int)(cos(RADIAN(n)) * 256); }
"
0
7
% 6
< 1
6
6 ,
B
FH
"
" , 1
6 %
0
.$ 1 7 5
, / . ("$ 8
"6 +
5 -
/
-;B
" @
+ 8 G
" CFG"
G/ @
3
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
E
, "
2
+
,"A
"
"
+
B
6 , //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // RotateSprite Project // main.h header file ////////////////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
typedef unsigned short u16;
#include <stdlib.h> #include <math.h> #include "spot.h" #include "bg.raw.c"
//macro to change the video mode Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
,
#define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000)
//declare scanline counter for vertical blank volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
//video modes 3-5, OAMData starts at 0x6010000 + 8192 unsigned short* SpriteData3 = SpriteData + 8192;
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//transparency stuff #define REG_BLDMOD
*(unsigned short*)0x4000050
#define REG_COLEV
*(unsigned short*)0x4000052
//misc sprite constants #define OBJ_MAP_2D
0x0
#define OBJ_MAP_1D
0x40
#define OBJ_ENABLE
0x1000
#define BG2_ENABLE
0x400
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_16
0x0000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff #define ROTDATA(n)
((n) << 9)
#define HORIZONTAL_FLIP
0x1000
#define VERTICAL_FLIP
0x2000
#define SIZE_8
0x0
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//Attribute2 stuff #define PRIORITY(n)
((n) << 10)
#define PALETTE(n)
((n) << 12)
//an entry for object attribute memory (OAM) typedef struct tagSprite { unsigned short attribute0; unsigned short attribute1; unsigned short attribute2; unsigned short attribute3;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
}Sprite,*pSprite;
typedef struct tagRotData { u16 filler1; u16 pa; u16 filler2; u16 pb; u16 filler3; u16 pc; u16 filler4; u16 pd; }RotData,*pRotData;
//create an array of 128 sprites equal to OAM Sprite sprites[128]; pRotData rotData = (pRotData)sprites;
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry; int size; int colormode; int trans; signed int rotate; signed int scale;
}SpriteHandler;
SpriteHandler mysprites[128];
//define the buttons
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define BUTTON_A 1 #define BUTTON_B 2 #define BUTTON_SELECT 4 #define BUTTON_START 8 #define BUTTON_RIGHT 16 #define BUTTON_LEFT 32 #define BUTTON_UP 64 #define BUTTON_DOWN 128 #define BUTTON_R 256 #define BUTTON_L 512
//create pointer to the button interface in memory volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130;
//keep track of the status of each button int buttons[10];
//math values needed for rotation #define PI 3.14159265 #define RADIAN(n) (((float)n)/(float)180 * PI)
//precomputed sine and cosine arrays signed int SIN[360]; signed int COS[360];
#endif
"
B
+
"
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // RotateSprite Project
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
//////////////////////////////////////////////////////////// // Function: HideSprites // Moves all sprites off the screen //////////////////////////////////////////////////////////// void HideSprites() { int n; for (n = 0; n < 128; n++) { sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; } }
//////////////////////////////////////////////////////////// // Function: MoveSprite // Changes sprite attributes for x,y positions //////////////////////////////////////////////////////////// void MoveSprite(int num) { //clear the old x value sprites[num].attribute1 = sprites[num].attribute1 & 0xFE00; sprites[num].attribute1 = sprites[num].attribute1 | mysprites[num].x;
//clear the old y value sprites[num].attribute0 = sprites[num].attribute0 & 0xFF00;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
sprites[num].attribute0 = sprites[num].attribute0 | mysprites[num].y; }
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites;
for(n = 0; n < 128 * 4; n++) SpriteMem[n] = temp[n]; }
6 6 ///////////////////////////////////////////////////////////// // Function: InitSprite // Initializes a sprite within the sprite handler array ///////////////////////////////////////////////////////////// void InitSprite(int num, int x, int y, int size, int tileIndex) { unsigned int sprite_size = 0;
mysprites[num].alive = 1; mysprites[num].size = size; mysprites[num].x = x; mysprites[num].y = y; mysprites[num].rotate = ROTATION_FLAG; mysprites[num].scale = 1 << 8; mysprites[num].angle = 0;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//in modes 3-5, tiles start at 512, modes 0-2 start at 0 sprites[num].attribute2 = tileIndex;
//initialize sprites[num].attribute0 = y | COLOR_256 | ROTATION_FLAG;
switch (size) { case 8: sprite_size = SIZE_8; break; case 16: sprite_size = SIZE_16; break; case 32: sprite_size = SIZE_32; break; case 64: sprite_size = SIZE_64; break; }
sprites[num].attribute1 = x | sprite_size | ROTDATA(tileIndex); }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(*ScanlineCounter < 160); }
+
/ !
///////////////////////////////////////////////////////////// // Function: CalcAngles Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// Pre-calculates the sine and cosine tables ///////////////////////////////////////////////////////////// void CalcAngles(void) { int n; for(n = 0; n < 360; n++) { SIN[n] = (signed int)(sin(RADIAN(n)) * 256); COS[n] = (signed int)(cos(RADIAN(n)) * 256); } }
6
%
" 67
/$
23 67
/$ :
:
23 (
H2
: 3
( . ///////////////////////////////////////////////////////////// // Function: RotateSprite // Rotates and scales a hardware sprite ///////////////////////////////////////////////////////////// void RotateSprite(int rotDataIndex, int angle, signed int xscale, signed int yscale) { signed int pa,pb,pc,pd;
//use the pre-calculated fixed-point arrays pa = ((xscale) * COS[angle])>>8;
pb = ((yscale) * SIN[angle])>>8;
pc = ((xscale) * -SIN[angle])>>8; pd = ((yscale) * COS[angle])>>8;
//update the rotation array entry rotData[rotDataIndex].pa = pa;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
rotData[rotDataIndex].pb = pb;
*
rotData[rotDataIndex].pc = pc; rotData[rotDataIndex].pd = pd; }
///////////////////////////////////////////////////////////// // Function: CheckButtons // Polls the status of all the buttons ///////////////////////////////////////////////////////////// void CheckButtons() { //store the status of the buttons in an array buttons[0] = !((*BUTTONS) & BUTTON_A); buttons = !((*BUTTONS) & BUTTON_B); buttons = !((*BUTTONS) & BUTTON_LEFT); buttons = !((*BUTTONS) & BUTTON_RIGHT); buttons = !((*BUTTONS) & BUTTON_UP); buttons[5] = !((*BUTTONS) & BUTTON_DOWN); buttons[6] = !((*BUTTONS) & BUTTON_START); buttons[7] = !((*BUTTONS) & BUTTON_SELECT); buttons[8] = !((*BUTTONS) & BUTTON_L); buttons[9] = !((*BUTTONS) & BUTTON_R); }
///////////////////////////////////////////////////////////// // Function: Pressed // Returns the status of a button ///////////////////////////////////////////////////////////// int Pressed(int button) { switch(button) { case BUTTON_A: return buttons[0]; case BUTTON_B: return buttons; case BUTTON_LEFT: return buttons;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
case BUTTON_RIGHT: return buttons; case BUTTON_UP: return buttons; case BUTTON_DOWN: return buttons[5]; case BUTTON_START: return buttons[6]; case BUTTON_SELECT: return buttons[7]; case BUTTON_L: return buttons[8]; case BUTTON_R: return buttons[9]; } return 0; }
" / $ 8
67 <
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main() { int n;
//pre-calculate the SIN and COS tables CalcAngles();
//set the video mode--mode 3, bg 2, with sprite support SetMode(2 | OBJ_ENABLE | OBJ_MAP_1D);
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = spotPalette[n];
//load ball sprite for(n = 0; n < spot_WIDTH * spot_HEIGHT / 2; n++) Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/$
SpriteData[n] = spotData[n];
//move all sprites off the screen HideSprites();
//initialize the sprite at the center of the screen InitSprite(0, 120-spot_WIDTH/2, 80-spot_HEIGHT/2, spot_WIDTH, 0);
//main loop while(1) { //comment out when running on real hardware for (n=0; n<1000; n++); //grab the button status CheckButtons();
//control sprite using buttons if (Pressed(BUTTON_LEFT)) if (--mysprites[0].x < 1) mysprites[0].x = 1;
if (Pressed(BUTTON_RIGHT)) if (++mysprites[0].x > 239-spot_WIDTH) mysprites[0].x = 239-spot_WIDTH;
if (Pressed(BUTTON_UP)) if (--mysprites[0].y < 1) mysprites[0].y = 1;
if (Pressed(BUTTON_DOWN)) if (++mysprites[0].y > 159-spot_HEIGHT) mysprites[0].y = 159-spot_HEIGHT;
//buttons A and B change the angle
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
if (Pressed(BUTTON_A)) if (--mysprites[0].angle < 0) mysprites[0].angle = 359;
if (Pressed(BUTTON_B)) if (++mysprites[0].angle > 359) mysprites[0].angle = 0;
//buttons L and R change the scale if (Pressed(BUTTON_L)) mysprites[0].scale--;
if (Pressed(BUTTON_R)) mysprites[0].scale++;
//update sprite position MoveSprite(0);
//rotate and scale the sprite RotateSprite(0, mysprites[0].angle, mysprites[0].scale, mysprites[0].scale);
//wait for vertical refresh before updating sprites WaitVBlank();
//copy all sprites into object attribute memory //this is only possible during vertical refresh UpdateSpriteMemory(); } }
2
3 8
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
B * *
$ 8
B
$ 8
,
0 2
B
F 9C3 ?.
+ + 6
%
,
,
+
,"#9
"
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// AnimSprite Project // main.h header file ////////////////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
typedef unsigned short u16;
#include <stdlib.h> #include "bg.raw.c" #include "ball2.h"
//macro to change the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000)
//declare scanline counter for vertical blank volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//video modes 3-5, OAMData starts at 0x6010000 + 8192 unsigned short* SpriteData3 = SpriteData + 8192;
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//misc sprite constants #define OBJ_MAP_2D
0x0
#define OBJ_MAP_1D
0x40
#define OBJ_ENABLE
0x1000
#define BG2_ENABLE
0x400
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff #define SIZE_8
0x0
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//an entry for object attribute memory (OAM) typedef struct tagSprite { unsigned short attribute0;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
unsigned short attribute1; unsigned short attribute2; unsigned short attribute3; }Sprite,*pSprite;
//create an array of 128 sprites equal to OAM Sprite sprites[128];
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry; int size;
}SpriteHandler;
SpriteHandler mysprites[128];
#endif
/ $ ,
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 7: Rounding Up Sprites // AnimSprite Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
MULTIBOOT
#include "main.h"
#define NUMBALLS 10
//////////////////////////////////////////////////////////// // Function: HideSprites // Moves all sprites off the screen //////////////////////////////////////////////////////////// void HideSprites() { int n; for (n = 0; n < 128; n++) { sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; } }
//////////////////////////////////////////////////////////// // Function: MoveSprite // Changes sprite attributes for x,y positions //////////////////////////////////////////////////////////// void MoveSprite(int num) { //clear the old x value sprites[num].attribute1 = sprites[num].attribute1 & 0xFE00; sprites[num].attribute1 = sprites[num].attribute1 | mysprites[num].x;
//clear the old y value sprites[num].attribute0 = sprites[num].attribute0 & 0xFF00; sprites[num].attribute0 = sprites[num].attribute0 | mysprites[num].y; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites;
for(n = 0; n < 128 * 4; n++) SpriteMem[n] = temp[n]; }
///////////////////////////////////////////////////////////// // Function: InitSprite // Initializes a sprite within the sprite handler array ///////////////////////////////////////////////////////////// void InitSprite(int num, int x, int y, int size, int color, int tileIndex) { unsigned int sprite_size = 0;
mysprites[num].alive = 1; mysprites[num].size = size; mysprites[num].x = x; mysprites[num].y = y;
//in modes 3-5, tiles start at 512, modes 0-2 start at 0 sprites[num].attribute2 = tileIndex;
//initialize sprites[num].attribute0 = color | y;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
switch (size) { case 8: sprite_size = SIZE_8; break; case 16: sprite_size = SIZE_16; break; case 32: sprite_size = SIZE_32; break; case 64: sprite_size = SIZE_64; break; }
sprites[num].attribute1 = sprite_size | x; }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(!(*ScanlineCounter)); while((*ScanlineCounter)); }
void UpdateBall(index) { u16 n;
//load ball sprite for(n = 0; n < 512; n++) SpriteData3[n] = ballData[(512*index)+n]; }
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
int main() { int n;
//set the video mode--mode 3, bg 2, with sprite support SetMode(3 | OBJ_ENABLE | OBJ_MAP_1D | BG2_ENABLE);
//draw the background for(n=0; n < 38400; n++) videoBuffer[n] = bg_Bitmap[n];
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = ballPalette[n];
//move all sprites off the screen HideSprites();
//initialize the balls--note all sprites use the same image for (n = 0; n < NUMBALLS; n++) { InitSprite(n, rand() % 230, rand() % 150, ball_WIDTH, COLOR_256, 512);
while (mysprites[n].dirx == 0) mysprites[n].dirx = rand() % 6 - 3; while (mysprites[n].diry == 0) mysprites[n].diry = rand() % 6 - 3; }
int ball_index=0;
//main loop while(1)
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
{ if(++ball_index > 31) ball_index=0; UpdateBall(ball_index);
for (n = 0; n < NUMBALLS; n++) { //update sprite x position mysprites[n].x += mysprites[n].dirx; if (mysprites[n].x > 239 - mysprites[n].size) { mysprites[n].x = 239 - mysprites[n].size; mysprites[n].dirx *= -1; } if (mysprites[n].x < 1) { mysprites[n].x = 1; mysprites[n].dirx *= -1; }
//update sprite y position mysprites[n].y += mysprites[n].diry; if (mysprites[n].y > 159 - mysprites[n].size) { mysprites[n].y = 159 - mysprites[n].size; mysprites[n].diry *= -1; } if (mysprites[n].y < 1) { mysprites[n].y = 1; mysprites[n].diry *= -1; }
//update the sprite properties MoveSprite(n);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
}
//keep the screen civil WaitVBlank();
//copy all sprites into object attribute memory UpdateSpriteMemory(); } }
1
&
% ( 2?IA3
(
2CI43
* "
E (
/
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
(
'8
"
( .=> =>3 7 8
?4
4
<
: 9=
--
/6%
2:
%
#1
&8 E $ 8
$ 8
/
J
<
* < * < * <
9C
(
* .
9 + # => 94: / 4A= . ?:> 4 1
<
#
9= 9= ?4 ?4 / => => . 94: 94: ? 1
# 8 8 / 8 .
4 ? >
> 1
# 8 $ . ;K " 7 0 ";7 8 $ . ;K -0+ -;7 . / 8 $ . ;K " 7 - / ;7 . 8 $ . ;K1 67 . $ 1 ;.
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
9= ?4 <
A 1
#
/ . =
LB
!.
"8 F
(
(
#
B
F 1
# " / .
: 1 C C / C . C
, # =CCCCCC FCCCCCC =C9CCCC >CCCCA4
2$ 8 3
H 1
/ # 4 / .
4 4 , 4
4 4 4
4
9C 1 #
/ .
C 9 4 ?
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
!"# $
!
%
&'
%
)(
%
+,
%
++ ! " # $ !
! *
(
* -
/
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
( .
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
! "
# !
" $
" %
&
'
(
) *)
! *%
+
+
)
! !
•
-
•
-
%$Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
,
!
Using Interrupts #
*% " . /'
(
0
#1
. /-
2
. /3
4555
6/ 7
" . /-
%2 7
0 2 %
3
/0 %
3
%* 2 +#
% 89 :%1 9
+ 89 :%1 9 ; 5"5
+3 <
$+
89 :%1 9 ; 5"= %
89 :%9
+
+ #1
> 0 #1 4 <
89 :# %7/7 %
89 :# %7/7 & 89 :%9
! ?
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
@4
89 :# 1 4. ? '
@ =(
(
& + " / 01 * *(!( 1
5
A &
=
)
4
A. &
B
A 9&
C
) 9&
D
A. 9 &
EF=D
A. 2 - ?
(
&
>
&
'5F=DG(
& 2 "/ 0 / 1
5
A &
=
)
4
A. &
B
5&
5
C
=&
=
D
4&
4
E
B&
B
H
.2 1 &
@
#1 5 & #1 5
G
#1 = & #1 =
=5
#1 4 & #1 4
==
#1 B & #1 B
=4 =B =CF=D
&
-
>
2? &
. 8 & I
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
89 :%9 " 89 :%9
?# #define INT_VBLANK 0x0001 #define INT_HBLANK 0x0002 #define INT_VCOUNT 0x0004 #define INT_TIMER0 0x0008 #define INT_TIMER1 0x0010 #define INT_TIMER2 0x0020 #define INT_TIMER3 0x0040 #define INT_COM
0x0080
#define INT_DMA0
0x0100
#define INT_DMA1
0x0200
#define INT_DMA2
0x0400
#define INT_DMA3
0x0800
#define INT_BUTTON 0x1000 #define INT_CART
0x2000
%
3 . /'
(
%78
%78
. /-
$
.
%78
%
( 3
%
,9 5"B55H00. 3 %78 ' + "
+
.
%78 89 :%0 ' 2
)
89 :%9 @4
89 :%0
J %
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
89 :%0( $7
%
7
. /-
5"B55H00. * 89 :%0 1
!
K
0
"
,
if ((REG_IF & INT_TIMER0) == INT_TIMER0) { //your timer code goes here }
%78
,
REG_IF |= INT_TIMER0
< 0 , #define REG_INTERRUPT *(unsigned int*)0x3007FFC
7
%78 ) ,
//first, turn off interrupts REG_IME = 0x00; //make ISR point to my own function REG_INTERRUPT = (unsigned int)MyHandler; //turn on vblank interrupt REG_IE |= INT_VBLANK; //tell dispstat about vblank interrupt REG_DISPSTAT |= 0x08; //lastly, turn interrupts back on REG_IME = BIT00;
? 1 )
7 % & (
"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
% %
% '
void MyHandler(void) { REG_IME = 0x00; Int_Flag = REG_IF; if((REG_IF & INT_HBLANK) == INT_HBLANK) { //horizontal refresh--do something quick! } REG_IF = Int_Flag; REG_IME = 0x01; }
The InterruptTest Program %
'
0
@ =( %
% B
"
%
> '
> ( #
"
&
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
&
!
""
" =E5
%$"
=E5 7 "
"
" "
%
%
The InterruptTest Header File //////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Interrupts, Timers, and DMA // InterruptTest Project // main.h header file ////////////////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
#include <stdlib.h>
//define some data type shortcuts typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32;
//packs three values into a 15-bit color #define RGB(r,g,b) ((r)+(g<<5)+(b<<10))
//define some display registers #define REG_DISPCNT *(u32*)0x4000000
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"#
#define BG2_ENABLE 0x400 #define SetMode(mode) REG_DISPCNT = (mode)
//define some interrupt registers #define REG_IME
*(u16*)0x4000208
#define REG_IE
*(u16*)0x4000200
#define REG_IF
*(u16*)0x4000202
#define REG_INTERRUPT
*(u32*)0x3007FFC
#define REG_DISPSTAT
*(u16*)0x4000004
//create prototype for custom interrupt handler void MyHandler(void);
//define some interrupt constants #define INT_VBLANK 0x0001 #define INT_HBLANK 0x0002 #define INT_VCOUNT 0x0004 #define INT_TIMER0 0x0008 #define INT_TIMER1 0x0010 #define INT_TIMER2 0x0020 #define INT_TIMER3 0x0040 #define INT_COM 0x0080 #define INT_DMA0 0x0100 #define INT_DMA1 0x0200 #define INT_DMA2 0x0400 #define INT_DMA3 0x0800 #define INT_BUTTON 0x1000 #define INT_CART 0x2000
//create pointer to video memory unsigned short* videoBuffer = (unsigned short*)0x6000000;
#endif
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
The InterruptTest Source File ?
% "
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Interrupts, Timers, and DMA // InterruptTest Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main(void) { //Set mode 3 and enable the bitmap background SetMode(3 | BG2_ENABLE);
//disable interrupts REG_IME = 0x00;
//point interrupt handler to custom function REG_INTERRUPT = (u32)MyHandler;
//enable hblank interrupt (bit 4) REG_IE |= INT_HBLANK;
//enable hblank status (bit 4) Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
REG_DISPSTAT |= 0x10;
//enable interrupts REG_IME = 0x01;
//endless loop while(1); return 0; }
//////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 //////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
//////////////////////////////////////////////////////////// // Function: MyHandler // Custom interrupt service callback function //////////////////////////////////////////////////////////// void MyHandler(void) { u16 Int_Flag; u16 x, y; u16 color;
//disable interrupts REG_IME = 0x00;
//backup the interrupt flags Int_Flag = REG_IF;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
//look for horizontal refresh if((REG_IF & INT_HBLANK) == INT_HBLANK) { //draw a random pixel x = rand() % 240; y = rand() % 160; color = RGB(rand()%31, rand()%31, rand()%31); DrawPixel3(x, y, color); }
//restore the interrupt flags REG_IF = Int_Flag;
//enable interrupts REG_IME = 0x01; }
Using Timers !
!
'
"
0 " 4@5 @GE . /-
( '
'
=E5
( "
(
&
'
(
+
+'
& "
>
(
'
(
44@
@B HHE >
= 55C =E& 5
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
ED DBD
"
@B
(
& 3(
4
5
6
4
5
1
5
=E H@ 1 ) >
9
DG DGD
=
EC
9
H E4@=
4
4DE
9
=D 4DE
B
= 54C
9
E= 54D ,
#define TIMER_FREQUENCY_SYSTEM
0x0
#define TIMER_FREQUENCY_64
0x1
#define TIMER_FREQUENCY_256
0x2
#define TIMER_FREQUENCY_1024
0x3
% %
%
0 , #define REG_TM0CNT *(volatile u16*)0x4000102 #define REG_TM1CNT *(volatile u16*)0x4000106 #define REG_TM2CNT *(volatile u16*)0x400010A #define REG_TM3CNT *(volatile u16*)0x400010E
? 89 : 1 "# , #define REG_TM0D
*(volatile u16*)0x4000100
#define REG_TM1D
*(volatile u16*)0x4000104
#define REG_TM2D
*(volatile u16*)0x4000108
#define REG_TM3D
*(volatile u16*)0x400010C
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
=E&
(
@C
& 7 " / 0( # 8% 9 ( 1
5F=
0
4
2
BFD E
2
H @F=D %1 98:089L - 9? . J:" , #define TIMER_OVERFLOW
0x4
#define TIMER_IRQ_ENABLE
0x40
#define TIMER_ENABLE
0x80
'
%
( ' 5
ED DBE "
( 2
!
,
timer = REG_TM0D; if (timer % 65536) { //overflow--time to deal with it }
The TimerTest Program 9 ! .
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
D + #
& "
$2 A !
1
+ .
"!
D
!
M7
M.
5@M &
!
% ? %
! % !
J
% !
> ?
0
! A
) 1
@4 3
% .
& ?
B +
#
+
! ! !
%
!
"
The TimerTest Header )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Using Interrupts and Timers // TimerTest Project // main.h header file //////////////////////////////////////////////////
#ifndef _MAIN_H #define _MAIN_H
#include <stdio.h> #include <string.h> #include "font.h"
//define some data type shortcuts typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32;
//declare some function prototypes void DrawPixel3(int, int, unsigned short); void DrawBox3(int, int, int, int, unsigned short) void DrawChar(int, int, char, unsigned short); void Print(int, int, char *, unsigned short);
//define the timer constants #define TIMER_FREQUENCY_SYSTEM 0x0 #define TIMER_FREQUENCY_64 0x1 #define TIMER_FREQUENCY_256 0x2 #define TIMER_FREQUENCY_1024 0x3 #define TIMER_OVERFLOW 0x4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
#define TIMER_ENABLE 0x80 #define TIMER_IRQ_ENABLE 0x40
//define the timer status addresses #define REG_TM0CNT
*(volatile u16*)0x4000102
#define REG_TM1CNT
*(volatile u16*)0x4000106
#define REG_TM2CNT
*(volatile u16*)0x400010A
#define REG_TM3CNT
*(volatile u16*)0x400010E
//define the timer data addresses #define REG_TM0D
*(volatile u16*)0x4000100
#define REG_TM1D
*(volatile u16*)0x4000104
#define REG_TM2D
*(volatile u16*)0x4000108
#define REG_TM3D
*(volatile u16*)0x400010C
//define some video mode values #define REG_DISPCNT *(unsigned long*)0x4000000 #define MODE_3 0x3 #define BG2_ENABLE 0x400
//declare scanline counter for vertical blank volatile unsigned short* ScanlineCounter = (volatile unsigned short*)0x4000006;
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
////////////////////////////////////////////////// // Function: Print // Prints a string using the hard-coded font ////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#"
while (*str) { DrawChar(left + pos, top, *str++, color); pos += 8; } }
////////////////////////////////////////////////// // Function: DrawChar // Draws a character one pixel at a time ////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { // grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; // if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); } }
////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
##
}
///////////////////////////////////////////////////////////// // Function: DrawBox3 // Draws a filled box ///////////////////////////////////////////////////////////// void DrawBox3(int left, int top, int right, int bottom, unsigned short color) { int x, y;
for(y = top; y < bottom; y++) for(x = left; x < right; x++) DrawPixel3(x, y, color); }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(!(*ScanlineCounter)); while((*ScanlineCounter)); }
#endif
The TimerTest Source Code "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Using Interrupts and Timers // TimerTest Project // main.c source code file //////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main() { char str[20]; int timers;
//switch to video mode 3 REG_DISPCNT = (3 | BG2_ENABLE);
//turn on timer0, set to 256 clocks REG_TM0CNT = TIMER_FREQUENCY_256 | TIMER_ENABLE;
//turn on timer1, grab overflow from timer0 REG_TM1CNT = TIMER_OVERFLOW | TIMER_ENABLE;
//turn on timer2, set to system clock REG_TM2CNT = TIMER_FREQUENCY_SYSTEM | TIMER_ENABLE;
//turn on timer3, grab overflow from timer2
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
REG_TM3CNT = TIMER_OVERFLOW | TIMER_ENABLE;
//print out labels Print(70, 30, "TIMER0:", 0x0FF0); Print(70, 40, "TIMER1:", 0xFE00); Print(70, 60, "TIMER2:", 0x00FA); Print(70, 70, "TIMER3:", 0x09B0);
//endless loop while(1) { WaitVBlank();
//erase the old timer values DrawBox3(140, 30, 180, 80, 0x0000);
//read the timer data timers[0] = REG_TM0D / (65536 / 1000); timers = REG_TM1D; timers = REG_TM2D / (65536 / 1000); timers = REG_TM3D;
//print out timer0 sprintf(str, "%i", timers[0]); Print(140, 30, str, 0x0FF0);
//print out timer1 sprintf(str, "%i", timers); Print(140, 40, str, 0xFE00);
//print out timer2 sprintf(str, "%i", timers); Print(140, 60, str, 0x00FA);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
//print out timer3 sprintf(str, "%i", timers); Print(140, 70, str, 0x09B0);
WaitVBlank(); }
return 0; }
The Framerate Program 0
% %
A E5 0/7 2
$ $ 0
@B 7
0 " " <
$
0
@B
! "# $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
0/7 '
' @ C( E5 ) > ? "
0
E5 0/7
3
A
'(
(
E5
" '
0
@ B(
% & '( )* +
,
. 7
+%
H +8
-
! % !
0
7 % %
!
! 7
M7
M.
!
. # &82 1 %
5@M0
The Framerate Header ?
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Using Interrupts and Timers // Framerate Project // main.h header file ////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
#ifndef _MAIN_H #define _MAIN_H
//define some data type shortcuts typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32;
#include <stdlib.h> #include <stdio.h> #include "bg.raw.c" #include "ball.h" #include "font.h"
//declare some function prototypes void DrawPixel3(int, int, unsigned short); void DrawChar(int, int, char, unsigned short); void Print(int, int, char *, unsigned short); void WaitVBlank(void);
//define the timer constants #define TIMER_FREQUENCY_SYSTEM 0x0 #define TIMER_FREQUENCY_64 0x1 #define TIMER_FREQUENCY_256 0x2 #define TIMER_FREQUENCY_1024 0x3 #define TIMER_OVERFLOW 0x4 #define TIMER_ENABLE 0x80 #define TIMER_IRQ_ENABLE 0x40
//define the timer status addresses
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#!
#define REG_TM0CNT
*(volatile u16*)0x4000102
#define REG_TM1CNT
*(volatile u16*)0x4000106
#define REG_TM2CNT
*(volatile u16*)0x400010A
#define REG_TM3CNT
*(volatile u16*)0x400010E
//define the timer data addresses #define REG_TM0D
*(volatile u16*)0x4000100
#define REG_TM1D
*(volatile u16*)0x4000104
#define REG_TM2D
*(volatile u16*)0x4000108
#define REG_TM3D
*(volatile u16*)0x400010C
//macro to change the video mode #define SetMode(mode) REG_DISPCNT = (mode)
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//define some video addresses #define REG_DISPCNT *(volatile unsigned short*)0x4000000 #define BGPaletteMem ((unsigned short*)0x5000000)
//declare scanline counter for vertical blank volatile u16* ScanlineCounter = (volatile u16*)0x4000006;
//define object attribute memory state address #define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address #define SpriteData ((unsigned short*)0x6010000)
//video modes 3-5, OAMData starts at 0x6010000 + 8192 unsigned short* SpriteData3 = SpriteData + 8192;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
//define object attribute memory palette address #define SpritePal ((unsigned short*)0x5000200)
//misc sprite constants #define OBJ_MAP_2D 0x0 #define OBJ_MAP_1D 0x40 #define OBJ_ENABLE 0x1000 #define BG2_ENABLE0x400
//attribute0 stuff #define ROTATION_FLAG
0x100
#define SIZE_DOUBLE
0x200
#define MODE_NORMAL
0x0
#define MODE_TRANSPARENT
0x400
#define MODE_WINDOWED
0x800
#define MOSAIC
0x1000
#define COLOR_256
0x2000
#define SQUARE
0x0
#define TALL
0x4000
#define WIDE
0x8000
//attribute1 stuff #define SIZE_8
0x0
#define SIZE_16
0x4000
#define SIZE_32
0x8000
#define SIZE_64
0xC000
//an entry for object attribute memory (OAM) typedef struct tagSprite { unsigned short attribute0; unsigned short attribute1; unsigned short attribute2; unsigned short attribute3;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
}Sprite,*pSprite;
//create an array of 128 sprites equal to OAM Sprite sprites[128];
typedef struct tagSpriteHandler { int alive; int x, y; int dirx, diry; int size;
}SpriteHandler;
SpriteHandler mysprites[128];
////////////////////////////////////////////////// // Function: Print // Prints a string using the hard-coded font ////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color); pos += 8; } }
////////////////////////////////////////////////// // Function: DrawChar // Draws a character one pixel at a time //////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
void DrawChar(int left, int top, char letter, unsigned short color) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { // grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; // if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); } }
////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; }
///////////////////////////////////////////////////////////// // Function: WaitVBlank // Checks the scanline counter for the vertical blank period ///////////////////////////////////////////////////////////// void WaitVBlank(void) { while(!(*ScanlineCounter)); while((*ScanlineCounter)); }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
#endif
The Framerate Source ?
0
J
1 !
3
A
//////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 8: Using Interrupts and Timers // Framerate Project // main.c source code file ////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "main.h"
#define NUMBALLS 10
//////////////////////////////////////////////////////////// // Function: HideSprites // Moves all sprites off the screen //////////////////////////////////////////////////////////// void HideSprites() { int n; for (n = 0; n < 128; n++) { sprites[n].attribute0 = 160; sprites[n].attribute1 = 240; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
}
//////////////////////////////////////////////////////////// // Function: MoveSprite // Changes sprite attributes for x,y positions //////////////////////////////////////////////////////////// void MoveSprite(int num) { //clear the old x value sprites[num].attribute1 = sprites[num].attribute1 & 0xFE00; sprites[num].attribute1 = sprites[num].attribute1 | mysprites[num].x;
//clear the old y value sprites[num].attribute0 = sprites[num].attribute0 & 0xFF00; sprites[num].attribute0 = sprites[num].attribute0 | mysprites[num].y; }
//////////////////////////////////////////////////////////// // Function: UpdateSpriteMemory // Copies the sprite array into OAM memory //////////////////////////////////////////////////////////// void UpdateSpriteMemory(void) { int n; unsigned short* temp; temp = (unsigned short*)sprites; for(n = 0; n < 128 * 4; n++) SpriteMem[n] = temp[n]; }
///////////////////////////////////////////////////////////// // Function: InitSprite // Initializes a sprite within the sprite handler array /////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
void InitSprite(int num, int x, int y, int size, int color, int tileIndex) { unsigned int sprite_size = 0;
mysprites[num].alive = 1; mysprites[num].size = size; mysprites[num].x = x; mysprites[num].y = y;
//in modes 3-5, tiles start at 512, modes 0-2 start at 0 sprites[num].attribute2 = tileIndex;
//initialize sprites[num].attribute0 = color | y;
switch (size) { case 8: sprite_size = SIZE_8; break; case 16: sprite_size = SIZE_16; break; case 32: sprite_size = SIZE_32; break; case 64: sprite_size = SIZE_64; break; }
sprites[num].attribute1 = sprite_size | x; }
//////////////////////////////////////////////////////////// // Function: UpdateBall // Copies current ball sprite frame into OAM //////////////////////////////////////////////////////////// void UpdateBall(index) { u16 n; //copy sprite frame into OAM
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
for(n = 0; n < 512; n++) SpriteData3[n] = ballData[(512*index)+n]; }
//////////////////////////////////////////////////////////// // Function: main() // Entry point for the program //////////////////////////////////////////////////////////// int main() { char str[10]; int n; int frames = 0; int timer = 0;
//set the video mode--mode 3, bg 2, with sprite support SetMode(3 | OBJ_ENABLE | OBJ_MAP_1D | BG2_ENABLE);
//draw the background for(n=0; n < 38400; n++) videoBuffer[n] = bg_Bitmap[n];
//set the sprite palette for(n = 0; n < 256; n++) SpritePal[n] = ballPalette[n];
//move all sprites off the screen HideSprites();
//initialize the balls--note all sprites use the same image (512) for (n = 0; n < NUMBALLS; n++) { InitSprite(n, rand() % 230, rand() % 150, ball_WIDTH, COLOR_256, 512);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
while (mysprites[n].dirx == 0) mysprites[n].dirx = rand() % 6 - 3; while (mysprites[n].diry == 0) mysprites[n].diry = rand() % 6 - 3; }
int ball_index=0;
//start the timer REG_TM3CNT = TIMER_FREQUENCY_256 | TIMER_ENABLE;
//main loop while(1) { //increment the ball animation frame if(++ball_index > 31)ball_index=0; UpdateBall(ball_index);
for (n = 0; n < NUMBALLS; n++) { //update sprite x position mysprites[n].x += mysprites[n].dirx; if (mysprites[n].x > 239 - mysprites[n].size) { mysprites[n].x = 239 - mysprites[n].size; mysprites[n].dirx *= -1; } if (mysprites[n].x < 1) { mysprites[n].x = 1; mysprites[n].dirx *= -1; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//update sprite y position mysprites[n].y += mysprites[n].diry; if (mysprites[n].y > 159 - mysprites[n].size) { mysprites[n].y = 159 - mysprites[n].size; mysprites[n].diry *= -1; } if (mysprites[n].y < 1) { mysprites[n].y = 1; mysprites[n].diry *= -1; }
//update the sprite properties MoveSprite(n); } //copy all sprites into object attribute memory WaitVBlank(); UpdateSpriteMemory();
timer = REG_TM3D / (65536 / 1000); frames++; if (timer > 999) { //erase top of screen for(n=0; n < 2400; n++) videoBuffer[n] = bg_Bitmap[n];
//display frame rate sprintf(str, "FPS %i", frames); Print(1, 1, str, 0xFFFF); frames = 0; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
} }
%
% %
>
%
) 8 3
A
$
. /-
" E5 0/7 ! >
> $ 3 !
Summary ?
"
% !
Challenges % 1
+,
%
2,
%
" " 1
%
3,
0 ?-1
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
<<7
E5 0/7 =5
"
E5
0/7
Chapter Quiz > >
=5
&
>
"
= 3
* 89 89 . 89 # 89
:%9 :%0 :%1 9 :# %7/7
4 )
* =C C . @ # =4
B 3
* 89 89 . 89 # 89
:%1 9 :# %7/7 :%? 988- / :.2 # 9
C
. /-
*
5"E555555 5"H55=555 . 5"C055C5= # 5"B55H00. D 3 * 89 89 . 89 # 89
:%0 :%9 :# %7/. ? :%1 9
E 3
=E5 %? :# 1 = %? :) < ? N
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
*
. %? : %1 98B # %? :A < ? N H
I0
,#
<.#
*
0 @ )
. /4@5 @GE C @BE GB@ 4B@ . =E5 # =E B@E
G )
*
* = 4 . B # C
=5 3
=E&
*
C 5GE =E B@C . ED DBE # = 5C@ DHE
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
"
#
$
• • •
% & &
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
'
&
( % %
'
)
# *
+, - . *
% , ,
' +&-/ .
*
0/ '
'
&-/
&
' -
0 1
0/ 1
+0/ .
% !
%
22 3
41 0/
) %
'
!
%
% 0/
5
%%
, -
&
6 &- 4
0 #
%
)
0/ 0
0/
+
7
,
'
,
.
&
0 1
! !
%
0/ 1
!
, -+ '
8
9::: +
- , ;< /
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
=
=-
8
9:::.
. ( )-
( -
)
-
% 0
'
>?
/ ! )
+
)
.
! "
&-
(
)
!
5<
&-
-, (
/
&
+ (
.
!
%
&-
!
&- @ +
. ,
% !
A &4
B
/
,
, '
/
,
'
'
/
, /
% 0
# /
!
!
C
C 1 Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
&% (
C
# /
C $DD
%
D
C
1 %
%
! ! F
C
&
E F
!
%
C %
!
&
,
F;
'
(
'
F
0
, 9:GE: 0
%)
%)
&
,
%
&
' '
' ) $ ,/ )
<
,/
1
,/
% 1
+
.
(
;8 H0%0< H
:!6:::: : ) '
* ?9I
+
?9*.
+0%0< . %
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
( ?
+
. '
9,
E, %
% 9,
E,
# 4
%)
)
54 @
? , $
,/
,/ 0%0<
;8 H'< 7 @ , H- @ H# >?
:!:6::::*9
:G?
-
?G6
9
,
'
E
,
'
*
8
,
'
>
8
,
'
?:
,
'
??
,
'
?9
8
,
'
?E
8
,
'
?6
,
'
?J
,
'
6GI
0%0<
0%0<
'
%) $
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define SND_ENABLED
0x00000080
#define SND_OUTPUT_RATIO_25
0x0000
#define SND_OUTPUT_RATIO_50
0x0001
#define SND_OUTPUT_RATIO_100
0x0002
#define DSA_OUTPUT_RATIO_50
0x0000
#define DSA_OUTPUT_RATIO_100
0x0004
#define DSA_OUTPUT_TO_RIGHT
0x0100
#define DSA_OUTPUT_TO_LEFT
0x0200
#define DSA_OUTPUT_TO_BOTH
0x0300
#define DSA_TIMER0
0x0000
#define DSA_TIMER1
0x0400
#define DSA_FIFO_RESET
0x0800
#define DSB_OUTPUT_RATIO_50
0x0000
#define DSB_OUTPUT_RATIO_100
0x0008
#define DSB_OUTPUT_TO_RIGHT
0x1000
#define DSB_OUTPUT_TO_LEFT
0x2000
#define DSB_OUTPUT_TO_BOTH
0x3000
#define DSB_TIMER0
0x0000
#define DSB_TIMER1
0x4000
#define DSB_FIFO_RESET
0x8000
1 + .
,
'
" (
K'
L%
(
-
+: 0%0<
?.
* F7
,
%
F%
'
, ; , - &7
?M I / # 2
- &7
?M III 9?M
N
! ! 0
?M III 9?M
!
66 ? # 2 )
E*: 66 -, 1 Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
-, 1
) ?M III 9?M D 66 ?:: O , E*: - &7 )
?M III 9?M D ?? :9J O ? J9? I6 ) 1 @ - &7
? J9? -&7 ) , MJ JEJ
?M ? M6 9JM
1
'
? J9?
? :96 -&7 ?? # 2
MJ JEJ MJ JEJ
1
? J9? O M6 :?6
'
&
'
! 1
%)
' 9:
-
'
0
>9
0
% 2
!
&- /
" -
8
% 9::: '
% +
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&- / .
# $
• • • • •
D
B
(
-/ ( , 3%D%/
, &-/
/
, &- /
(
&-/ ( %
;
3
% +
='
&- /
) 9
,
0
.
9 :>
=-
$DD
D
! - , ;< /
=
9
!9 (
9
!$
wav2gba
%
'
&
='
=:>=' - , ;< /
+' +
&
-, - , ;< / "
. ='
+ ;
.
='
<
&
!. '
$ wav2gba splash.wav splash.bin
7 !
(
!
+
%
. ' 9
!
,
0
!
$ bin2c
9 bin2c splash.bin splash.c
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
%
+
.$
const unsigned char splash[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00, 0x18,0x2D,0x00,0x00,0xFA,0x00,0xFD,0xFD,0x03,0x00,0xFD,0x03, 0xFD,0x03,0x00,0xFA,0xFD,0xFD,0xFA,0xFD,0x03,0x00,0x00,0x03, 0x03,0x0C,0x00,0x06,0x00,0x03,0x03,0x00,0x00,0xFD,0xFA,0xFD, . . . 0xFA,0xFD,0x00,0xFA,0x06,0x00,0xFD,0xFD,0xFD,0xF7,0x00,0xFD, 0xFD,0x03,0xFD,0xFA,0x03,0xFA,0x03,0x00,0xFD,0x03,0x09,0xFD, 0x00,0x00,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
'
%
% "
-
@
$ @echo off wav2gba %1.wav %1.bin if exist %1.bin bin2c %1.bin %1.c
@
+ 5. %
$
wav splash
9
9
-
'
5
% $ 'data' not found
$ 8 bit required
&- / 8
-
9:::
'
&-/
% ?M
*
9
*
?M % -
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
8
9:::
" 8
0??
< )
!
'
2
%
-
&
F, %;F 2
<
8!
)
&
'2 < ?? JM*
,
0
( ! >E 0
2
P
'2
%
! "#$% &
"
'
#
0
% '
+ 5. '
3
%
# /4 "
5
%
3 '
0 -#
& !
0
@
@
0 %
>6
' ( )
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
& * +,
# /
@ ,/ ////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 9: The Sound System // SoundTest Project // main.h header file ////////////////////////////////////////////////// typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; //define some video registers/values #define REG_DISPCNT *(u32*)0x4000000 #define BG2_ENABLE 0x400 #define SetMode(mode) REG_DISPCNT = (mode) //define some interrupt registers #define REG_IME
*(u16*)0x4000208
#define REG_IE
*(u16*)0x4000200
#define REG_IF
*(u16*)0x4000202
#define REG_INTERRUPT
*(u32*)0x3007FFC
#define REG_DISPSTAT
*(u16*)0x4000004
#define INT_VBLANK
0x0001
//define some timer and DMA registers/values #define REG_TM0D
*(volatile u16*)0x4000100
#define REG_TM0CNT
*(volatile u16*)0x4000102
#define REG_DMA1SAD
*(volatile u32*)0x40000BC
#define REG_DMA1DAD
*(volatile u32*)0x40000C0
#define REG_DMA1CNT_H
*(volatile u16*)0x40000C6
#define TIMER_ENABLE
0x80
#define DMA_DEST_FIXED
64
#define DMA_REPEAT
512
#define DMA_32
1024
#define DMA_ENABLE
32768
#define DMA_TIMING_SYNC_TO_DISPLAY
4096 | 8192
//define some sound hardware registers/values Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define REG_SGCNT0_H *(volatile u16*)0x4000082 #define REG_SGCNT1 *(volatile u16*)0x4000084 #define DSOUND_A_RIGHT_CHANNEL
256
#define DSOUND_A_LEFT_CHANNEL
512
#define DSOUND_A_FIFO_RESET
2048
#define SOUND_MASTER_ENABLE
128
'
'
0
@
' +
3
# /
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 9: The Sound System // SoundTest Project // main.c source code file ////////////////////////////////////////////////// #define MULTIBOOT int __gba_multiboot; MULTIBOOT #include "main.h" #include "splash.c" //global variables u16 len = 0; ////////////////////////////////////////////////// // Function: MyHandler // Custom interrupt callback function ////////////////////////////////////////////////// void MyHandler(void) { //disable/store interrupts REG_IME = 0x00; u16 Int_Flag = REG_IF; //look for vertical refresh if((REG_IF & INT_VBLANK) == INT_VBLANK) { if (!len--) Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
.
{ //stop playback: disable the timer and DMA REG_TM0CNT = 0; REG_DMA1CNT_H = 0; } } //restore/enable interrupts REG_IF = Int_Flag; REG_IME = 0x01; } ////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main(void) { u16 samplerate = 8000; u16 samplelen = 11568; u16 samples; SetMode(3 | BG2_ENABLE); //create custom interrupt handler for vblank (chapter 8) REG_IME = 0x00; REG_INTERRUPT = (u32)MyHandler; REG_IE |= INT_VBLANK; REG_DISPSTAT |= 0x08; REG_IME = 0x01; //output to both channels and reset the FIFO REG_SGCNT0_H = DSOUND_A_RIGHT_CHANNEL | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET; //enable all sound REG_SGCNT1 = SOUND_MASTER_ENABLE; //DMA1 source address REG_DMA1SAD = (u32)splash; //DMA1 destination address Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
REG_DMA1DAD = 0x40000A0; //write 32 bits into destination every vblank REG_DMA1CNT_H =
DMA_DEST_FIXED | DMA_REPEAT | DMA_32 |
DMA_TIMING_SYNC_TO_DISPLAY | DMA_ENABLE; //set the sample rate samples = 16777216 / samplerate; REG_TM0D = 65536 - samples; //determine length of playback in vblanks len = samplelen / samples * 15.57; //enable the timer REG_TM0CNT = TIMER_ENABLE; //run forever while(1); return 0; }
@
3
% '
! P ) *
& &
&- / /
'
&
' (
%
! 8
%
%
2 ;/ I
! !
' C (
! &
'
0
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
>J
# . . " .
'
.
& '
B
'
&
% % (
: '
B
'
&
% , -
%
- &7
$ samples = 16777216 / samplerate; SampleLength = samplelength / samples * 15.57;
?J JI )
&
'
0 %
'
&
'
# '
void PlaySound(sound *theSound) { u16 samples;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+ .$
//output to both channels and reset the FIFO REG_SGCNT0_H = DSOUND_A_RIGHT_CHANNEL | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET; //enable all sound REG_SGCNT1 = SOUND_MASTER_ENABLE; //DMA1 source address REG_DMA1SAD = (u32)theSound->pBuffer; //DMA1 destination address REG_DMA1DAD = 0x40000A0; //write 32 bits into destination every vblank REG_DMA1CNT_H =
DMA_DEST_FIXED | DMA_REPEAT | DMA_32 |
DMA_TIMING_SYNC_TO_DISPLAY | DMA_ENABLE; //set the sample rate samples = 16777216 / theSound->samplerate; //2097 REG_TM0D = 65536 - samples; //keep track of the playback position and length SampleLength = theSound->length / samples * 15.57; SamplePosition = 0; //enable the timer REG_TM0CNT = TIMER_ENABLE; }
C
'
"
&
'
Q ) . # typedef struct tagSound { void *pBuffer; u16 samplerate; u32 length; }sound;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
+ $
@
%)
R & #
'
%
@
2
) 9
+
)
.
sound s_panther = {&panther, 8000, 16288}; sound s_thunder = {&thunder, 8000, 37952}; sound s_door = {&door, 8000, 16752}; sound s_birds = {&birds, 8000, 29280};
' H
&
'
+H
H
H
. N (
)
$ SamplePosition++; if (SamplePosition > SampleLength) { REG_TM0CNT = 0; REG_DMA1CNT_H = 0; SampleLength = 0; }
8
' ' ,/ '
&
B , - <
&
'
B 4
4
:
' '
& @ &
'
'
#
'
0
%
& '
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
%
'
'
<
)
3
# /
&
'
1
0 &
'
$ ////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 9: The Sound System // PlaySamples Project // main.h header file ////////////////////////////////////////////////// typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32; #include "font.h" #include <stdlib.h> #include <string.h> //function prototypes void Print(int left, int top, char *str, unsigned short color); void DrawChar(int left, int top, char letter, unsigned short color); void DrawPixel3(int x, int y, unsigned short color); //define some video registers/values unsigned short* videoBuffer = (unsigned short*)0x6000000; #define REG_DISPCNT *(u32*)0x4000000 #define BG2_ENABLE 0x400 #define SetMode(mode) REG_DISPCNT = (mode) //define some interrupt registers #define REG_IME
*(u16*)0x4000208
#define REG_IE
*(u16*)0x4000200
#define REG_IF
*(u16*)0x4000202
#define REG_INTERRUPT
*(u32*)0x3007FFC
#define REG_DISPSTAT
*(u16*)0x4000004
#define INT_VBLANK
0x0001
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//define some timer and DMA registers/values #define REG_TM0D
*(volatile u16*)0x4000100
#define REG_TM0CNT
*(volatile u16*)0x4000102
#define REG_DMA1SAD
*(volatile u32*)0x40000BC
#define REG_DMA1DAD
*(volatile u32*)0x40000C0
#define REG_DMA1CNT_H
*(volatile u16*)0x40000C6
#define TIMER_ENABLE
0x80
#define DMA_DEST_FIXED
64
#define DMA_REPEAT
512
#define DMA_32
1024
#define DMA_ENABLE
32768
#define DMA_TIMING_SYNC_TO_DISPLAY
4096 | 8192
//define some sound hardware registers/values #define REG_SGCNT0_H *(volatile u16*)0x4000082 #define REG_SGCNT1 *(volatile u16*)0x4000084 #define DSOUND_A_RIGHT_CHANNEL
256
#define DSOUND_A_LEFT_CHANNEL
512
#define DSOUND_A_FIFO_RESET
2048
#define SOUND_MASTER_ENABLE
128
//define button hardware register/values volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130; #define BUTTON_A 1 #define BUTTON_B 2 #define BUTTON_R 256 #define BUTTON_L 512 ////////////////////////////////////////////////// // Function: Print // Prints a string using the hard-coded font ////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
pos += 8; } } ////////////////////////////////////////////////// // Function: DrawChar // Draws a character one pixel at a time ////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color) { int x, y; int draw; for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { // grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; // if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); } } ////////////////////////////////////////////////// // Function: DrawPixel3 // Draws a pixel in mode 3 ////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; } ///////////////////////////////////////////////////////////// // Function: DrawBox3 // Draws a filled box ///////////////////////////////////////////////////////////// void DrawBox3(int left, int top, int right, int bottom, unsigned short color) { Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
int x, y; for(y = top; y < bottom; y++) for(x = left; x < right; x++) DrawPixel3(x, y, color); }
&
'
' &
0 '
+ @
3 $
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 9: The Sound System // PlaySamples Project // main.c source code file ////////////////////////////////////////////////// #define MULTIBOOT int __gba_multiboot; MULTIBOOT #include "main.h" #include "panther.c" #include "thunder.c" #include "door.c" #include "birds.c" //create a struct to keep track of sound data typedef struct tagSound { void *pBuffer; u16 samplerate; u32 length; }sound; //create variables that describe the sounds sound s_panther = {&panther, 8000, 16288}; sound s_thunder = {&thunder, 8000, 37952}; sound s_door = {&door, 8000, 16752};
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# /.
sound s_birds = {&birds, 8000, 29280}; //global variables u16 SamplePosition = 0; u16 SampleLength = 0; char temp[20]; ////////////////////////////////////////////////// // Function: PlaySound // Plays a sound sample using DMA ////////////////////////////////////////////////// void PlaySound(sound *theSound) { u16 samples; //output to both channels and reset the FIFO REG_SGCNT0_H = DSOUND_A_RIGHT_CHANNEL | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET; //enable all sound REG_SGCNT1 = SOUND_MASTER_ENABLE; //DMA1 source address REG_DMA1SAD = (u32)theSound->pBuffer; //DMA1 destination address REG_DMA1DAD = 0x40000A0; //write 32 bits into destination every vblank REG_DMA1CNT_H =
DMA_DEST_FIXED | DMA_REPEAT | DMA_32 |
DMA_TIMING_SYNC_TO_DISPLAY | DMA_ENABLE; //set the sample rate samples = 16777216 / theSound->samplerate; //2097 REG_TM0D = 65536 - samples; //keep track of the playback position and length SampleLength = theSound->length / samples * 15.57; SamplePosition = 0; //enable the timer REG_TM0CNT = TIMER_ENABLE;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
} ////////////////////////////////////////////////// // Function: MyHandler // Custom interrupt callback function ////////////////////////////////////////////////// void MyHandler(void) { u16 Int_Flag; //disable interrupts REG_IME = 0x00; //backup the interrupt flags Int_Flag = REG_IF; //look for vertical refresh if((REG_IF & INT_VBLANK) == INT_VBLANK) { //is a sample currently playing? if (SampleLength) { //display the current playback position DrawBox3(80, 80, 120, 100, 0x0000); sprintf(temp, "%i", SamplePosition); Print(80, 80, temp, 0xDFFD); sprintf(temp, "%i", SampleLength); Print(80, 90, temp, 0xDFFD); //increment the position, check if complete SamplePosition++; if (SamplePosition > SampleLength) { //stop playback: disable the timer and DMA REG_TM0CNT = 0; REG_DMA1CNT_H = 0; //reset length SampleLength = 0; } }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
} //restore the interrupt flags REG_IF = Int_Flag; //enable interrupts REG_IME = 0x01; } ////////////////////////////////////////////////// // Function: main() // Entry point for the program ////////////////////////////////////////////////// int main(void) { SetMode(3 | BG2_ENABLE); Print(0, 0, "PLAYSAMPLES DEMO", 0xFFFF); Print(0, 20, "A - THUNDER", 0x0FF0); Print(0, 30, "B - BIRDS", 0xF00F); Print(0, 40, "L - PANTHER", 0x00FF); Print(0, 50, "R - DOOR", 0xFF00); Print(0, 80, "POSITION: ", 0xCFFC); Print(0, 90, "LENGTH
: ", 0xCFFC);
//create custom interrupt handler for vblank (chapter 8) REG_IME = 0x00; REG_INTERRUPT = (u32)MyHandler; REG_IE |= INT_VBLANK; REG_DISPSTAT |= 0x08; REG_IME = 0x01; //run forever while(1) { if (!SampleLength) { if (!(*BUTTONS & BUTTON_A)) PlaySound(&s_thunder); if (!(*BUTTONS & BUTTON_B)) PlaySound(&s_birds); Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
if (!(*BUTTONS & BUTTON_L)) PlaySound(&s_panther); if (!(*BUTTONS & BUTTON_R)) PlaySound(&s_door); } } return 0; }
%
! )
' F
F
! !
' " ,
'
,
'
0 !
%
C
!
- , ;< / ' '
9
9
!
! !
&
'
"
&
'
/ B
8 7
,
B
;
'
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
; $
-
S
2
1 2 1 2 1 2
?:
1 !,
? # 9 6 - M , * 9
0
$
0 E ( 0 1
/
,
'
- ,
'
, 0/ '
?
,
'
,
'
9
(
6 ( 9 9 -
9
,
9
J (
) * ?9 - ?M , 96
M (
1 1
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
66 ? # 2
,
66 ?::
I (
:!:6::::*9 ;8 H'@ , - @ ;8 H'< 7 @ , H- @ HB - ;8 H'< 7 @ , H-@ H# , ;8 H, 'H- @
* #
- &7
!
E9 IM* ?M III 9?M - ? :96 , MJ JEJ > (
! &- / D -
B
(
-/ (
, , 3%D%/ ?: (
, &-/ !
( - C 2 , C
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
&
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
"
# #
$
%
& # $
(
)
• • •
# *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
' #
# #
+,
.
.
$
/
!
" 0
-
! " 1
+, +
*
2
3 # ,$,',,,+4, # 2
5
6 5
# .
/
2 78
1
78 9
6 5
#
,$,',,,+4,
4:/
4:/
4:/ ;
.
+,
< %
=
< >
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
4:/
!7
+?
"#
) unsigned int *BUTTONS = (unsigned int *)0x04000130;
# !
2 @"
@ A ## = .
!
4:
")
volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130;
#
%
. =
< 1 & A ## = . , 3 <
)
while(1) { if(*BUTTONS) // yes, a button was pressed! else // nothing yet }
,! " # 6>2
2
( # 3 <
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6 2<
<
#
.
=
<
. 1
=
2<
1 = B
B
( 8 2<
( 8 .
= 2
/ .
1
(
1
C.
#
B
1
1 C
!"
,9 2
<
( 8
!!
2
*
$ 4
*
# 2 2<
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 10: Interfacing With The Buttons // ScanButtons Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include <stdio.h> #include "font.h"
//define boolean #define bool short #define true 1
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#define false 0
//define some useful colors #define BLACK 0x0000 #define WHITE 0xFFFF #define BLUE 0xEE00 #define CYAN 0xFF00 #define GREEN 0x0EE0 #define RED 0x00FF #define MAGENTA 0xF00F #define BROWN 0x0D0D
//define register for changing the video mode #define REG_DISPCNT *(unsigned long*)0x4000000
//background 2 #define BG2_ENABLE 0x400
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//create pointer to the button interface in memory volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130;
//declare some function prototypes void SetMode(int mode); void DrawPixel3(int, int, unsigned short); void Print(int, int, char *, unsigned short); void PrintT(int, int, char *, unsigned short); void DrawChar(int, int, char, unsigned short, bool);
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
///////////////////////////////////////////////////////////// int main() { char str[20];
SetMode(3); Print(1, 1, "SCANBUTTONS PROGRAM", WHITE); Print(1, 30, "SCANNING...", GREEN);
// continuous loop while(1) { //check for button presses if (*BUTTONS) { sprintf(str, "BUTTON CODE = %i
", (unsigned int)*BUTTONS);
Print(10, 40, str, BLUE); } }
return 0; }
void SetMode(int mode) { REG_DISPCNT = (mode | BG2_ENABLE); }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draw a pixel on the mode 3 video buffer ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short c) {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
videoBuffer[y * 240 + x] = c; }
///////////////////////////////////////////////////////////// // Function: Print // Prints a string using a hard-coded font, must be all caps ///////////////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color, false); pos += 8; } }
///////////////////////////////////////////////////////////// // Function: PrintT // Prints a string with transparency ///////////////////////////////////////////////////////////// void PrintT(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color, true); pos += 8; } }
///////////////////////////////////////////////////////////// // Function: DrawChar // Draws a single character from a hard-coded font
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
///////////////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color, bool trans) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { //grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; //if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); else //fill in black pixel if no transparency if (!trans) DrawPixel3(left + x, top + y, BLACK); } }
2
.
19 1
+, :
# + ,:4
8
.
B
-
+
,
# .
D+ .
D:
6# < D4 D'
.
$ 2 2
@ A ## = . 1 Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# +, 4
# =*<
+ ,:4
! "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
<
2 3 <
$ 2
* /7 8 * /7 8
C.
C
+,C. )
: #
!+"
(
// continuous loop while(1) { //check for button presses for (n=1; n < 1000; n++) { if (!((*BUTTONS) & n)) { sprintf(str, "BUTTON CODE = %i
", n);
Print(10, 40, str, BLUE); break; } } }
#
<
+ +, 2
E+:
1 6#
1
2 ( .
! +, '
A
/ " = ?' A
/ 2 :!
+ ,,, # 2 <
6 #
+, +"
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
#
/ -
"# " $ $
% % + :
.F3F #
'
.# 7#
;
72 ( #
+?
3F1#
4:
A
?'
* -=
+:;
7
:E?
3
E+:
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6#
*
. #
$
. 22
< 2
/ 0
=
< %
2< G
) #include <string.h>
&
)
char name[10];
2
.
4 (
) int main() { char str[20]; unsigned int n; char name[10];
SetMode(3); Print(1, 1, "SCANBUTTONS PROGRAM", WHITE); Print(1, 30, "SCANNING...", GREEN);
// continuous loop while(1) { //check for button presses for (n=1; n < 1000; n++) { if (!((*BUTTONS) & n)) { sprintf(str, "BUTTON CODE = %i Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
", n);
Print(10, 40, str, BLUE);
//figure out the button name switch(n) { case 1: strcpy(name, "A"); break; case 2: strcpy(name, "B"); break; case 4: strcpy(name, "SELECT"); break; case 8: strcpy(name, "START"); break; case 16: strcpy(name, "RIGHT"); break; case 32: strcpy(name, "LEFT"); break; case 64: strcpy(name, "UP"); break; case 128: strcpy(name, "DOWN"); break; case 256: strcpy(name, "R"); break; case 512: strcpy(name, "L"); break; default: strcpy(name, ""); break; } sprintf(str, "BUTTON NAME = %s
", name);
Print(10, 50, str, RED); break; } //if } //for } //while } //main
#
.
4
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
1
+, E
" #
(
2
=
G (
2
) #define BUTTON_A 1 #define BUTTON_B 2 #define BUTTON_SELECT 4 #define BUTTON_START 8 #define BUTTON_RIGHT 16 #define BUTTON_LEFT 32 #define BUTTON_UP 64 #define BUTTON_DOWN 128 #define BUTTON_R 256 #define BUTTON_L 512
#
@ A ## = . . ! " . < 0 6
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
<
( .
/
< 2 # 1
0
1
*/ */ H
(
2
8
#
/ 0
!
+
,
bool buttons[10];
A = $ =* %
# , 0
+
buttons[0] = !((*BUTTONS) & BUTTON_A); buttons[1] = !((*BUTTONS) & BUTTON_B); buttons[2] = !((*BUTTONS) & BUTTON_LEFT); buttons[3] = !((*BUTTONS) & BUTTON_RIGHT); buttons[4] = !((*BUTTONS) & BUTTON_UP); buttons[5] = !((*BUTTONS) & BUTTON_DOWN); buttons[6] = !((*BUTTONS) & BUTTON_START); Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
")
buttons[7] = !((*BUTTONS) & BUTTON_SELECT); buttons[8] = !((*BUTTONS) & BUTTON_L); buttons[9] = !((*BUTTONS) & BUTTON_R);
<
2 < -
-
!
" )
bool Pressed(int button) { switch(button) { case BUTTON_A: return buttons[0]; case BUTTON_B: return buttons[1]; case BUTTON_LEFT: return buttons[2]; case BUTTON_RIGHT: return buttons[3]; case BUTTON_UP: return buttons[4]; case BUTTON_DOWN: return buttons[5]; case BUTTON_START: return buttons[6]; case BUTTON_SELECT: return buttons[7]; case BUTTON_L: return buttons[8]; case BUTTON_R: return buttons[9]; } }
#
( #
0
0
2
2
/ #
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
(
* /7 8
C.
C
+,C
(
0
=
B
% # G -
<
/ (
= !
( *
$ 4
.
#
"
///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 10: Interfacing With The Buttons // ButtonHandler Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include "font.h"
//define boolean #define bool short #define true 1 #define false 0
//declare some function prototypes void CheckButtons(); bool Pressed(int); void SetMode(int); void DrawPixel3(int, int, unsigned short); void Print(int, int, char *, unsigned short); void DrawChar(int, int, char, unsigned short, bool); Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
( 8
//define some colors #define BLACK 0x0000 #define WHITE 0xFFFF #define BLUE 0xEE00 #define CYAN 0xFF00 #define GREEN 0x0EE0 #define RED 0x00FF #define MAGENTA 0xF00F #define BROWN 0x0D0D
//define the buttons #define BUTTON_A 1 #define BUTTON_B 2 #define BUTTON_SELECT 4 #define BUTTON_START 8 #define BUTTON_RIGHT 16 #define BUTTON_LEFT 32 #define BUTTON_UP 64 #define BUTTON_DOWN 128 #define BUTTON_R 256 #define BUTTON_L 512
//define register for changing the video mode #define REG_DISPCNT *(unsigned long*)0x4000000
//use background 2 #define BG2_ENABLE 0x400
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//create pointer to the button interface in memory volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
//keep track of the status of each button bool buttons[10];
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main() { SetMode(3); Print(1, 1, "BUTTONHANDLER PROGRAM", WHITE); Print(1, 30, "PRESS A BUTTON:", GREEN);
// continuous loop while(1) { //check for button presses CheckButtons();
//display the status of each button if (Pressed(BUTTON_A)) Print(10, 40, "A PRESSED", BLUE); else Print(10, 40, "
", 0);
if (Pressed(BUTTON_B)) Print(10, 50, "B PRESSED", BLUE); else Print(10, 50, "
", 0);
if (Pressed(BUTTON_SELECT)) Print(10, 60, "SELECT PRESSED", BLUE); else Print(10, 60, " if (Pressed(BUTTON_START))
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
", 0);
Print(10, 70, "START PRESSED", BLUE); else Print(10, 70, "
", 0);
if (Pressed(BUTTON_LEFT)) Print(10, 80, "LEFT PRESSED", BLUE); else Print(10, 80, "
", 0);
if (Pressed(BUTTON_RIGHT)) Print(10, 90, "RIGHT PRESSED", BLUE); else Print(10, 90, "
", 0);
if (Pressed(BUTTON_UP)) Print(10, 100, "UP PRESSED", BLUE); else Print(10, 100, "
", 0);
if (Pressed(BUTTON_DOWN)) Print(10, 110, "DOWN PRESSED", BLUE); else Print(10, 110, "
", 0);
if (Pressed(BUTTON_R)) Print(10, 120, "R PRESSED", BLUE); else Print(10, 120, "
", 0);
if (Pressed(BUTTON_L)) Print(10, 130, "L PRESSED", BLUE); else Print(10, 130, "
", 0);
} return 0; }
///////////////////////////////////////////////////////////// // Function: CheckButtons // Polls the status of all the buttons
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
///////////////////////////////////////////////////////////// void CheckButtons() { //store the status of the buttons in an array buttons[0] = !((*BUTTONS) & BUTTON_A); buttons[1] = !((*BUTTONS) & BUTTON_B); buttons[2] = !((*BUTTONS) & BUTTON_LEFT); buttons[3] = !((*BUTTONS) & BUTTON_RIGHT); buttons[4] = !((*BUTTONS) & BUTTON_UP); buttons[5] = !((*BUTTONS) & BUTTON_DOWN); buttons[6] = !((*BUTTONS) & BUTTON_START); buttons[7] = !((*BUTTONS) & BUTTON_SELECT); buttons[8] = !((*BUTTONS) & BUTTON_L); buttons[9] = !((*BUTTONS) & BUTTON_R); }
///////////////////////////////////////////////////////////// // Function: Pressed // Returns the status of a button ///////////////////////////////////////////////////////////// bool Pressed(int button) { switch(button) { case BUTTON_A: return buttons[0]; case BUTTON_B: return buttons[1]; case BUTTON_LEFT: return buttons[2]; case BUTTON_RIGHT: return buttons[3]; case BUTTON_UP: return buttons[4]; case BUTTON_DOWN: return buttons[5]; case BUTTON_START: return buttons[6]; case BUTTON_SELECT: return buttons[7]; case BUTTON_L: return buttons[8]; case BUTTON_R: return buttons[9];
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
} return false; }
///////////////////////////////////////////////////////////// // Function: SetMode // Changes the video mode ///////////////////////////////////////////////////////////// void SetMode(int mode) { REG_DISPCNT = (mode | BG2_ENABLE); }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draw a pixel on the mode 3 video buffer ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
///////////////////////////////////////////////////////////// // Function: Print // Prints a string using a hard-coded font, must be all caps ///////////////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color, false); pos += 8; }
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
}
///////////////////////////////////////////////////////////// // Function: DrawChar // Draws a single character from a hard-coded font ///////////////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color, bool trans) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { //grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; //if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); else //fill in black pixel if no transparency if (!trans) DrawPixel3(left + x, top + y, BLACK); } }
=
( 1
+, ?
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ % #
#
#
* & < I
<
/
6I
1 ((< J J !
0
*
*
K7
'
7
$
"
7
! " -
* *7 7 2
; IA #
I
$
2
2
/
! L
"
0
<
M
6
# . 2<
1
# 2 # 2 int ButtonsPressed() {
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
)
int n; int total = 0; for (n=0; n < 10; n++) total += buttons[n]; return total; }
(
<
#
H
< ///////////////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 10: Interfacing With The Buttons // ComboTest Project // main.c source code file /////////////////////////////////////////////////////////////
#define MULTIBOOT int __gba_multiboot; MULTIBOOT
#include <stdio.h> #include "font.h"
//define boolean #define bool short #define true 1 #define false 0
//declare some function prototypes int ButtonsPressed(); void CheckButtons(); bool Pressed(int); void SetMode(int); void DrawPixel3(int, int, unsigned short); void Print(int, int, char *, unsigned short);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
void DrawChar(int, int, char, unsigned short, bool);
//define some colors #define BLACK 0x0000 #define WHITE 0xFFFF #define BLUE 0xEE00 #define CYAN 0xFF00 #define GREEN 0x0EE0 #define RED 0x00FF #define MAGENTA 0xF00F #define BROWN 0x0D0D
//define the buttons #define BUTTON_A 1 #define BUTTON_B 2 #define BUTTON_SELECT 4 #define BUTTON_START 8 #define BUTTON_RIGHT 16 #define BUTTON_LEFT 32 #define BUTTON_UP 64 #define BUTTON_DOWN 128 #define BUTTON_R 256 #define BUTTON_L 512
//define register for changing the video mode #define REG_DISPCNT *(unsigned long*)0x4000000
//use background 2 #define BG2_ENABLE 0x400
//create a pointer to the video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//create pointer to the button interface in memory
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130;
//keep track of the status of each button bool buttons[10];
///////////////////////////////////////////////////////////// // Function: main() // Entry point for the program ///////////////////////////////////////////////////////////// int main() { int counter = 0; char str[20]; int delay; int combo[10] = {BUTTON_UP,BUTTON_UP,BUTTON_DOWN,BUTTON_DOWN, BUTTON_LEFT,BUTTON_RIGHT,BUTTON_LEFT,BUTTON_RIGHT, BUTTON_B,BUTTON_A};
SetMode(3); Print(1, 1, "COMBOTEST PROGRAM", WHITE); Print(1, 30, "PRESS U,U,D,D,L,R,L,R,B,A:", GREEN);
// continuous loop while(1) { //check for button presses CheckButtons();
if (ButtonsPressed() == 1) { sprintf(str, "COUNTER = %i ", counter + 1); Print(10, 50, str, BLUE);
if (Pressed(combo[counter]))
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
{ counter++;
if (counter == 10) { Print(10, 70, "CHEAT MODE ACTIVATED!", RED); counter = 0; }
//slow down the program delay = 500000; while (delay--); } else counter = 0; } } return 0; }
///////////////////////////////////////////////////////////// // Function: ButtonsPressed // Returns the number of buttons being pressed ///////////////////////////////////////////////////////////// int ButtonsPressed() { int n; int total = 0; for (n=0; n < 10; n++) total += buttons[n]; return total; }
/////////////////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
// Function: CheckButtons // Polls the status of all the buttons ///////////////////////////////////////////////////////////// void CheckButtons() { //store the status of the buttons in an array buttons[0] = !((*BUTTONS) & BUTTON_A); buttons[1] = !((*BUTTONS) & BUTTON_B); buttons[2] = !((*BUTTONS) & BUTTON_LEFT); buttons[3] = !((*BUTTONS) & BUTTON_RIGHT); buttons[4] = !((*BUTTONS) & BUTTON_UP); buttons[5] = !((*BUTTONS) & BUTTON_DOWN); buttons[6] = !((*BUTTONS) & BUTTON_START); buttons[7] = !((*BUTTONS) & BUTTON_SELECT); buttons[8] = !((*BUTTONS) & BUTTON_L); buttons[9] = !((*BUTTONS) & BUTTON_R); }
///////////////////////////////////////////////////////////// // Function: Pressed // Returns the status of a button ///////////////////////////////////////////////////////////// bool Pressed(int button) { switch(button) { case BUTTON_A: return buttons[0]; case BUTTON_B: return buttons[1]; case BUTTON_LEFT: return buttons[2]; case BUTTON_RIGHT: return buttons[3]; case BUTTON_UP: return buttons[4]; case BUTTON_DOWN: return buttons[5]; case BUTTON_START: return buttons[6]; case BUTTON_SELECT: return buttons[7];
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
case BUTTON_L: return buttons[8]; case BUTTON_R: return buttons[9]; } return false; }
///////////////////////////////////////////////////////////// // Function: SetMode // Changes the video mode ///////////////////////////////////////////////////////////// void SetMode(int mode) { REG_DISPCNT = (mode | BG2_ENABLE); }
///////////////////////////////////////////////////////////// // Function: DrawPixel3 // Draw a pixel on the mode 3 video buffer ///////////////////////////////////////////////////////////// void DrawPixel3(int x, int y, unsigned short c) { videoBuffer[y * 240 + x] = c; }
///////////////////////////////////////////////////////////// // Function: Print // Prints a string using a hard-coded font, must be all caps ///////////////////////////////////////////////////////////// void Print(int left, int top, char *str, unsigned short color) { int pos = 0; while (*str) { DrawChar(left + pos, top, *str++, color, false);
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
pos += 8; } }
///////////////////////////////////////////////////////////// // Function: DrawChar // Draws a single character from a hard-coded font ///////////////////////////////////////////////////////////// void DrawChar(int left, int top, char letter, unsigned short color, bool trans) { int x, y; int draw;
for(y = 0; y < 8; y++) for (x = 0; x < 8; x++) { //grab a pixel from the font char draw = font[(letter-32) * 64 + y * 8 + x]; //if pixel = 1, then draw it if (draw) DrawPixel3(left + x, top + y, color); else //fill in black pixel if no transparency if (!trans) DrawPixel3(left + x, top + y, BLACK); } }
#
#
1
+, 9 2 = F.
& .
) A /A /* /* /3/7/3/7/ / / /
2
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
0 IJ
. I
) & #
#
. #
< % < 2
# & "' #
.
4 8
& (' #
(
& )' #
#
8
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
8
N # #
5
0 5 0 5 0 5
+,
/
0 $
+ (
#
> ? ; +, * +:
: -
> ,$,',,,+4, ,$,E,:,+,, ,$,+,,,O,, * ,$?,,,,,,,
4 -
> 82 . .
78
.( 4 * ' #
78 9
P1
)
4:
>
# 1 E -
> (
8
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
* 8 ? -
> +:; :E? E+: * + ,:'
9 (
!
4:"
>
; +, +? * ? ; -
> 8
,
8
:
8
E
* 8
4
O -
> =* 7 = # * Q 7
+, -
> + , /+ * :
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
" #
$
% &
$ " '
"
#
( *
&
) ( + ,
• • •
'
#
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
#
$
'
#
-
#
'
$
(
# .
&
&
/0 1
!
'
$ 2
$
3 .
3
$ 3
$
3' &
(
$ .
&
%4
%
$
$
& (
5"
$
3
'
" $ '7
6 &
$
$ 3 $ #
* 6 +
2
'7
$
$ 8
7
*
+
# "
# "
#0
6
"
0 9/
7
.
9#
&
* 2
-
'7
(
////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 11: ARM7 Assembly Language Primer // TestBuild Project // main.c source code file //////////////////////////////////////////////////
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
::9" (
+
int main(void)
)( ;'7 <
{ //create pointer to video buffer unsigned short* videoBuffer = (unsigned short*)0x6000000;
//enter video mode 3 *(unsigned long*)0x4000000 = (0x3 | 0x400);
//draw a white pixel centered on the screen videoBuffer[80 * 240 + 120] = 0xFFFF;
while(1); return 0; }
#
#
%
#
! ;
$
'7
$
/
2 '7
(
$ '
2
* $
%
+
&
,
arm-thumb-elf-gcc.exe -I %HAMDIR%\gcc-arm\include -I %HAMDIR%\include -I %HAMDIR%\gcc-arm\arm-thumb-elf\include -I %HAMDIR%\system -c -DHAM_HAM -DHAM_MULTIBOOT -DHAM_ENABLE_MBV2LIB -O2 -DHAM_WITH_LIBHAM -mthumb-interwork -mlong-calls -Wall -save-temps -fverbose-asm %1.c -o%1.o
0
7
7
; ##
# 2
7 #
)
'
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
/ $ $ %
= :: :
$
)
2 '7
* +
* " #0 '7
3 ,3 ( / 06 /
' 9
9/
9#
>
'7
(
5+ '7
:: '
9/
6
CD \GBA\Sources\Chapter11\TestBuild
" %
:: ?
7
'
#0
::
#
)
#
2 6
#
" 9&
'
& "
&
7 $
$ ,
set PATH=g:\ham\gcc-arm\bin;g:\ham\tools\win32;%PATH% set HAMDIR=g:\ham
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6
!
"
"
& $
" &
@
"
#
"
)
8 &
,
gcc main
2
'
7
(
(
"
7
'
( '
'
## 2 3
3
' 8
$
" "
"
$ $
" *
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
+ '
$
'
$
$
%
:: A
# $" %
#
-
'
(
"
$
"
!
$
$
$
* '
"
+
'
$
& "
(
3
3 3 3 ' # )<
$ ( (
# )< / '7 "
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
6
B "
B
;/
$
* +
"
B C 6
"
B
)# "
+
)#
$
'6 / * )#
$
< $
)# 6
)# "
#0
6
'6 / %
= / 06 /
"
B
)# 6 6 ;
' " "
B
& ' ,
arm-thumb-elf-as.exe -mthumb-interwork crt0.s -ocrt0.o
"
7
" "
"& <
A?
"& <
:D
=
'
*
+
#
% B
"
$ $
8 *
+
#
(
,
arm-thumb-elf-as.exe -mthumb-interwork %1.s -o%1.o
" E:
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
2
$ '
*
, :: F
%
+
$
( $
& '
$
$ ' ()
- $
#
$" $
-
" B
$ B
"
'7
$ (
##
# 6$
- $
%
7
' $
#
$
7
2
7 $ $ /
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$ $
!
@echo off arm-thumb-elf-ld.exe -L %HAMDIR%\gcc-arm\lib\gcc-lib\arm-thumb-elf\3.2.2\normal -L %HAMDIR%\gcc-arm\arm-thumb-elf\lib\normal -L %HAMDIR%\gcc-arm\lib --script %HAMDIR%\system\lnkscript-afm -o%1.elf %1.o crt0.o -lafm -lham -lm -lstdc++ -lsupc++ -lc -lgcc
arm-thumb-elf-objcopy.exe -v -O binary %1.elf %1.gba
$
$ >
$
$
,
link main
' =
;
"
$ $ %
:: 4 '
$
$
* ! +
'
+
C $
$ $
$
8
$
1
$ (
'7 $
$
(
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
7
0
7
.
&
&
/0 1
$
& .
&
%
:: D
$
(
, -
$" +
*.
+
$
-
'
'7
$ # $
C
$ <
' (
%
"0 ' # )< *
3 "
3+
$*
( ,GG$? ,GG < -
( + =
G G H
$
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
=
#)< "
7
7 :
?
A
F
" =
4
7 !
$ %
* '/# + '
0
)#
(
*# '/# +
"
$ ,
'/#
# '/# "
(
'/#
" ?B
'
'
)
'/# *
+ "
A *
;+ " $
'
7
7
/
)
"
' #
%
'7 "
% (
:: :BB
2
% 7 5'7
;&
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
F
. ' +
" "
% % $
) A ?
( I 2
( @/////////////////////////////////////////////////// @ Programming The Game Boy Advance @ Chapter 11: ARM7 Assembly Language Primer @ FirstAsm Program @ pixel.s assembly file @///////////////////////////////////////////////////
.text .align2 .globalmain
@main entry point of program main:
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
'
@set video mode 3 using background 2 mov
r2, #1024
@BG2_ENABLE
add
r2, r2, #3
@mode 3
mov
r3, #67108864
@REG_DISPCNT
str
r2, [r3, #0]
@set value
@draw a white pixel at 80x120 @remember, mode 3 is 2 bytes/pixel mov
r1, #38400@80*240*2
add
r1, r1, #240@X=120
add
r3, r3, #33554432@videoMemory
mvn
r2, #0
strh
@draw pixel
r2, [r3, r1]
@endless loop .forever: b
.forever
@define object size of main .end: .sizemain,.end-main
5
;2
7
'
' 8
(
6 B
6 @
2
" #0 6 #0 ,
asm pixel
' '7
B
' 2
7
$
$,
link pixel
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
"
7
;8
(
.
$
#
;8
#
%
#
"
C # " ( %
( )(
0
#
'
>(
' #
" $
' "
$
$
,
extern void DrawPixel32 (u32 x, u32 y, u32 color, u32 videobuffer);
#
5' C
#
$
6 '
7
'$
DJBBB
/ (
%
$ C
C
$ #
"
$
'
%
#
"
( 5' (
# ' 7
# ;&
7
>(
( '
( ////////////////////////////////////////////////// // Programming The Game Boy Advance // Chapter 11: ARM7 Assembly Language Primer // ExternAsm Project // extern.c source code file //////////////////////////////////////////////////
typedef unsigned long u32; Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# 0
) ( A?
//declare prototype for the external assembly function extern void DrawPixel32 (u32 x, u32 y, u32 color, u32 videobuffer);
//video mode register #define REG_DISPCNT *(unsigned long*)0x4000000
int main(void) { u32 x, y;
//set video mode 3 REG_DISPCNT = (3 | 0x400);
//fill screen with a pattern for (y = 0; y < 159; y++) for (x = 0; x < 239; x++) DrawPixel32(x, y, x*y%31, 0x6000000);
while(1); return 0; }
"
0
2
) ( A? 0
#
) ( A?
" /
* A?+ * + #
J (
:D (
@ Draw pixel in GBA graphics mode 3 @ DrawPixel32(u32 x, u32 y, u32 color, u32 videobuffer); @ r0 = x @ r1 = y @ r2 = color @ r3 = videobuffer Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
A?
.ARM .ALIGN .GLOBL
DrawPixel32
DrawPixel32: stmfd
sp!,{r4-r5}
@ Save register r4 and r5 on stack
mov
r4,#480
@ r4 = 480
mul
r5,r4,r1
@ r5 = r4 * y
add
r5,r5,r0,lsl #1 @ r5 = r5 + (x << 1)
add
r4,r5,r3
@ r4 = r5 + videobuffer
strh
r2,[r4]
@ *(unsigned short *)r4 = color
ldmfd
sp!,{r4-r5}
@ Restore registers r4 and r5
bx
lr
#
>(
"
)
>( (
$
"
( 7
$
'
*
@
$? *K +
>(
E?
+ ' $ "
' "
(
7 ,
gcc extern
"
(
,
asm drawpixel
$
,
link2 extern drawpixel
'
$ ;L $
$
"
7
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
$
. %
:: J
2
7
$ ;" ;"
( (
1
' $
5=
7
/ 0+
'
+
$
/ =
' "
'
1
38
3
7$
'
"
8 $
$
#
$ %
' -
$
#
$ "
$
$
8 $;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
C $
# " "
%
(
/ (
" / *
>( AJ FBB % /
#
L
" "
! C ! C ! C
: =
( 0 + A?
) ( A? (
8
C :B
!
"
$
(0
(
5
/ / # 0
#
? =
:D
5
"& < # & 20 0 %'2 > A =
A?
5
"& < # & 20 0 %'2 >
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
!
F =
##
5
( ( #
(
0
(
4 =
5 ( C
(
#
(
0
(
D =
(
$ 5
& " >-% #
6 #
0
& 2
=
( '
$
' # '
>-% >-% >-% '/#
'
0 M &
6
5 '
#
#
$
0 ' J =
5
/ /
'
# /
/
#
#
# #
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
5
'
# /
$
0 0 :B "
%
,"
" %
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
# '/#
"
#
"
$
$' ' $ '
;= '
$
'
(
=
(
; '
$
'
$
$ '
$ '
( $
" '
;"
( !
'
A0 $
(
$ ' $
'7
$
$
;8
' $
$ '
;
%
' 8 ! H
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
;
> 6
,GG /
'
" & =
!!! $ $ ;
Programming The Nintendo Game Boy Advance: The Unofficial Guide Copyright (c)2003 by Jonathan S. Harbour -- http://www.jharbour.com
'
$
!"
#$ %
&'( $
""
))***' + $
'
!"#
%$*
+ ,
*
+),#
*
+ ,(
*
+!,
*
+0,1
!"
#$ %
&'( $
& ''
) )
. .
.
""
# / ''
!"#
%$))***' + $
'
(
)
!"
#$ %
&'( $
""
))***' + $
'
.
2
344 .
)
Y
*
Z
+
[
,
\
-
B
]
./012
C
^
3
D
_
4
E
`
5
F
a
6
G
b
7
H
c
8
I
d
9
J
e
:
K
f
;
L
g
<
M
h
=
N
0
>
O
i
?
P
1
!
@
Q
j
"
A
R
2
#
S
k
$
T
l
%
U
m
&
V
n
'
W
o
(
X
p
!"
#$ %
&'( $
""
))***' + $
'
‰
¦
Ã
Š
§
Ä
‹
¨
Å
r
Œ
©
Æ
/
•
ª
Ç
s
Ž
«
È
t
•
¬
É
.
•
-
Ê
u
‘
®
Ë
’
¯
Ì
v
“
°
Í
w
”
±
Î
x
•
²
Ï
y
–
³
Ð
z
—
´
Ñ
{
˜
µ
Ò
|
™
¶
Ó
}
š
·
Ô
~
›
¸
Õ
•
œ
¹
Ö
€
•
º
×
•
ž
»
Ø
‚
Ÿ
¼
Ù
½
Ú
q
ƒ „
¡
¾
Û
…
¢
¿
Ü
†
£
À
Ý
‡
¤
Á
Þ
ˆ
¥
Â
ß
!"
#$ %
&'( $
""
))***' + $
'
à
ü
á
ý
â
i0 p
ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ù ú û
!"
#$ %
&'( $
""
))***' + $
'
!"
#$ %
&'( $
""
))***' + $
'
.
"
Z21rqq2 j2j Jrrp. 5
(
) #%
!
6
"
.
)7 23289:98;8
+
#%
)<
"
)7 2328=948;=
. #%
1
!"
# $
-
6
6 . !
% "
"
"
&
#
)7 8"4;322"22;"= !
:!
>
&
'
%
)7 8";:8?@8"43"9
.
( (
)
B
A B
5 B
!"
#$ %
&'( $
""
))***' + $
'
:!
(( & !
'
-
%
C
)7 8";:8?@8"@:"? DD
.
DD "
" )
#
)*
)
+ .
" )7 2"9=84":8=4":
.
E""F "
"
&
)
%
. +
)7 8";:8?@8"3:":
.
!"
)
C !
,
-*
#
!%
%
, 6
C
"
>
" % (
"- G$
)7 2"29"333@3?"3
. B " " (
7 )
.&
'
-
)7 8";:8?@8"8="2
1
H
" 5 ,
$-
&
-
.
!
" +
!"
#$ %
&'( $
""
))***' + $
'
/ 6
0 1 *&
'
-
)7 8"4;322"223"; )
70.
) )"
=2 70.
5 )
&
70.
"
& $ & " 6
&
)2
-
3
4
"
&%
)7 2"9=84":249"=
. DD 7
4 7
)
+
) #
6
!"
-
.
&
"
)7 2"9=84":3;;"@
.
"&
"
. /
/
"
6
&
4
-
#
5
)7 8";:8?@8"34">
.
I
"
)
+
"
3! !
> 92
?8
!
>
!
:! <
"
Z21rqq2 j2j _2i [nu2. < )
!"
( <
#$ %
&'( $
""
))***' + $
'
( ,GG
B
)
)
,GG .
()
!"! ,GG
GJ90 B?:22G
# ) G
) ()
$ %
&'
#! ( )
,GG
G ()
'* #
()
% +
,GG .
- %
* ! "( ,GG % !
I
-
!, G !
+
>
!
>
> 5
)
'* ,GG
% -. "
.
!"
()
- %
#$ %
&'( $
""
))***' + $
(
'
)
"
$ % ( / # ,GG "
0# 1# / ,GG 6
+
2' 1 )
% -.
B I
3# #
%
,GG .
7
3# #
%
#&
,GG
& G
G
.
!"
#$ %
&'( $
""
))***' + $
'
! #
!"
#$ %
$
&'( $
""
))***' + $
'
"
. ()
-
. +
+
.
U unirru
Jnu ^0 2.
!
"
" "
!
\y/2j2k. #$
%
&' (
#$
%
%' (
#$
%
#$
%
&' (
%
#$
%
%' (
%
#$
%
!"
#$ %
%
&'( $
""
))***' + $
'
"
#$
%
&' (
#$
%
%' (
#$
%
# ') ( ) (
#$
*
%
&' (
*
#$
*
%
%' (
*
#$
*
%
#$
*
%
&' (
*%
#$
*
%
%' (
*%
#$
*
%
*
*%
J uur . *
+
,- . /*
+0 1
, 2 , , -3 34 , - 25 , 5 67 ,
38
,
9
, : ;, , 5 ,
[/tnu2. 2
/
+0 1!
2
/
+0 1
/
+0 1
<9
==2
(
* 5
2
% , 8 26
- >3 :
1
3
1
:3 , 5 2
1
:3
1
52,-9253,
:3 ; ,: ;3:
!"
#$ %
&'( $
1
""
))***' + $
'
-2 4
1
4
5
1
4
5
1
-? 253
1
; :3
1
2
==2
1
(
* 5
%
:2 2/ 0
// 0 @@ "0
7 5 > , 2 A35
==2
8
9 9
1 1
- >3
1
- >3
1
- >3
1
- >3
14
(
* 95 92 3
J01pltr
!"
42
8
5
% B/ 0 3/ 0
// 0 @@
0
// 0 @@
0
j.
536
6 4,
+/
+0 1
536
6 4,
+/
+0 1
2
536
6 4,
+/
+0 1
4
536
6 4,
+/
+0 1
3
536
6 7 8-
+/
+0 1
536
6 A 8-
+/
+0 1
536
6 7 8-
+/
+0 1
536
6 A 8-
+/
+0 1
536
6 7 8-
+/
+0 1
536
6 A 8-
+/
+0 1
2
536
6 7 8-
+/
+0 1
4
536
6 A 8-
+/
+0 1
3
536
6 92
+/
+0 1
536
6 9
+/
+0 1
#$ %
&'( $
""
))***' + $
'
536
6 94
+/
+0 1
536
6 9:
+/
+0 1
536
6 C
+/
+0 1
536
6 C
+/
+0 1
536
6 C 7
+/
+0 1
2
536
6 B
+/
+0 1
4
536
6 B
+/
+0 1
4
536
6 B 7
+/
+0 1
3
536
6 92
+/
+0 1
536
6 9
+/
+0 1
536
6 94
+/
+0 1
536
6 9:
+/
+0 1
536
6 C
+/
+0 1
536
6 C
+/
+0 1
536
6 C 7
+/
+0 1
2
536
6 B
+/
+0 1
4
536
6 B
+/
+0 1
4
536
6 B 7
+/
+0 1
3
6
-2 4 3,2
1
6 4
5
1
6 4
5
1
3C
6 - >3
1
1
3C
6 - >3
1
1
3C
6 - >3
1
1
3C
6 - >3
1
14
5
6 - >3
1
1
5
6 - >3
1
1
5
6 - >3
1
1
5
6 - >3
;52925 4' ( -&(
!"
3
#$ %
1
,: %
14 1
&D/ 0 %
&'( $
&D/ 0
""
/// 0+ 1 /// 0+ 1
))***' + $
'
0E 1 0E 1
0 0
^nj2r -
/
0
A
( 69
536 : -94, /
+0 1
/
+0 1
536 : -94,
+/
+0 1
536 : -94,
+/
+0 1
+/
+0 1
536 : -9- 2
+/
+0 1
536 A4
,
+/
+0 1
536 ; , 7
+/
+0 1
536 ; , 7
+/
+0 1
536 ; , A
+/
+0 1
536 ; , A
+/
+0 1
536 ; , ,
+/
+0 1
536 ; ,
+/
+0 1
536 : -94,
24F 7
7
8835
0
2
1
2,F
2
1
<
29
:
1
<
29
:
1
2,F
1
8 543
. /
6
3,2
3
1
6
3,2
3
1
6
3,2
3
1
6
3,2
3
1
< 3,2
3
1
; ,
3,2
3
1
; ,
3,2
3
1
; ,
< 3,2
3
1
LUI : 2 3,2 : 2
!"
3
, 355 9
1 3,2
3
1
: 2
,6
3: 2 3
1
: 2
,6 A
2,F
1
&'( $
""
#$ %
))***' + $
'
: 2
,6 7
: 2
,6 -B,4
: 2
,6 :-
1 : -9 2B
,:
1 1
: 2
1
: 2
1
: 2 53932 3
1
: 2 -
543
,453 3,
1
: 2 -
543 :3453 3,
1
: 2 -
543 8 C3:
1
: 2 :3-
,453 3,
1
: 2 :3-
:3453 3,
1
: 2 :3-
8 C3:
1
: 2 :3-
53
1
2:
: 2
, ; /: 2 3,2
3 G : 2
,6
3: 2 3 G: 2
0
: 2
, ; /: 2 3,2
3 G : 2
,6
3: 2 3 G: 2
0
536 :
-2:
+/
+0 1
536 : 2 -2:
+/
+0 1
536 : 2 -2: 7
+/
+0 1
536 : 2 :2:
+/
+0 1
536 : 2 :2:
+/
+0 1
536 : 2 :2: 7
+/
+0 1
536 : 2 4,
+/
+0 1
536 : 2 4,
+/
+0 1
+/
+0 1
2
536 : 2 -2:
+/
+0 1
4
536 : 2 -2:
+/
+0 1
4
536 : 2 -2: 7
+/
+0 1
3
536 : 2 :2:
+/
+0 1
4
536 : 2 :2:
+/
+0 1
4
536 : 2 :2: 7
+/
+0 1
4
536 : 2 4,
+/
+0 1
4
536 : 2 4,
+/
+0 1
4
+/
+0 1
4
536 : 2 -2:
+/
+0 1
4
536 : 2 -2:
+/
+0 1
4
536 : 2 4,
536 : 2 4,
!"
2,F
#$ %
7
7
&'( $
""
))***' + $
'
536 : 2 -2: 7
+/
+0 1
42
536 : 2 :2:
+/
+0 1
44
536 : 2 :2:
+/
+0 1
44
536 : 2 :2: 7
+/
+0 1
43
536 : 2 4,
+/
+0 1
:
536 : 2 4,
+/
+0 1
:
+/
+0 1
:
536 : 2 -2:
+/
+0 1
:
536 : 2 -2:
+/
+0 1
:
536 : 2 -2: 7
+/
+0 1
:
536 : 2 :2:
+/
+0 1
:
536 : 2 :2:
+/
+0 1
:
536 : 2 :2: 7
+/
+0 1
:2
536 : 2 4,
+/
+0 1
:4
536 : 2 4,
+/
+0 1
:4
+/
+0 1
:3
+/
+0 1
!884
536 : 2 4,
536 : 2 4,
7
7
Q u2tt /u. 536
!"
, 355 9
,
A
2,F
1
,
7
2,F
1
,
A4
,
1
,
35
1
,
35
1
,
35
1
,
35
1
,
4
,
: 2
1
,
: 2
1
,
: 2
1
,
: 2
1
,
F3B
,
425
1
,
2
1
#$ %
, 42
,
25:
&'( $
1
1
""
))***' + $
'
Un.12 0 2r . Z2ln.u2t. 536
-2 4
+/
+0 1
4
536
-2 4
+/
+0 1
4
536
-2 4 7
+/
+0 1
3
536
:
+/
+0 1
:
536 4
3A
+/
+0 1
536 4
3B
+/
+0 1
536 -6
+/
+0 1
536 -6
+/
+0 1
+/
+0 1
536 -6
+/
+0 1
536 -6
+/
+0 1
536 -6
+/
+0 1
536 -6
+/
+0 1
!
536 -6
+/
+0 1
!
+/
+0 1
!
536 -6
+/
+0 1
!
536 -6
+/
+0 1
!
536 -6
+/
+0 1
!4
536 -64,
+/
+0 1
536 -64,
+/
+0 1
+/
+0 1
+/
+0 1
+/
+0 1
536 -6;5
+/
+0 1
"
536 -6;5
+/
+0 1
"
+/
+0 1
"
536 -6;5
+/
+0 1
"
536 -6;5
+/
+0 1
"
+/
+0 1
"
536 -6;5
+/
+0 1
"
536 -6;5
+/
+0 1
"
+/
+0 1
"2
536 -6;5
+/
+0 1
"4
536 -6;5
+/
+0 1
"4
536 -6
7
536 -6
7
536 -64,
7
536 -64, 536 -6
2-
536 -6;5
536 -6;5
536 -6;5
!"
#$ %
7
7
7
&'( $
""
))***' + $
4
'
536 -6;5
7
+/
+0 1
"3
536 -68 8 2
+/
+0 1
2
536 -68 8 2
+/
+0 1
2
536 -68 8 2 7
+/
+0 1
2
536 -68 8
+/
+0 1
2
536 -68 8
+/
+0 1
2
+/
+0 1
2
536 -4:
+/
+0 1
536 -4:
+/
+0 1
536 -4:
+/
+0 1
536 -4:
+/
+0 1
536 -44,
+/
+0 1
536 -44,
+/
+0 1
+/
+0 1
536 9
+/
+0 1
536 9 4,
+/
+0 1
536 5
+/
+0 1
536 7- 4 5
+/
+0 1
536 < B53
+/
+0 1
536 < B53
+/
+0 1
536 < B53 7
+/
+0 1
536 < B 5
+/
+0 1
536 < B 5
+/
+0 1
536 < B 5 7
+/
+0 1
536 <- 2
+/
+0 1
536 <- 2
+/
+0 1
+/
+0 1
536 -68 8
536 -44,
536 <- 2
7
7
7
536
3
+/
+0 1
536
8
+/
+0 1
536 ;-4,
+/
+0 1
536
+/
+0 1
+/
+0 1
3
536 92 -3
!"
#$ %
&'( $
""
))***' + $
2
2
'
\nq2t. 536
:
+/
+0 1
536
4,
+/
+0 1
536
:
+/
+0 1
536
4,
+/
+0 1
536
:
+/
+0 1
536
4,
+/
+0 1
2
536
:
+/
+0 1
4
536
4,
+/
+0 1
3
853? 3,4B 853? 3,4B 853? 3,4B 853? 3,4B
G
35 42-42:3 35
5?
35 3,2
!"
#$ %
3
&'( $
""
))***' + $
'
% $ &' ((
!"
#$ %
&'( $
""
))***' + $
'
.
+
& '& A
& ' (
8
A
@
8 )
=
8
=)
3
9
3)
9)
:
? !
:
?
@ !
;
@
;!
4 )
82 )
4!
82
3
4
8
=
8)
=)
3
9 !
3
9
: !
?
:)
?
@
; )
@
;!
4 )
82
4!
82 !
:
=
8
= )
8
=
3 )
9
3
9
:
?
:)
?!
@ )
;
@!
;)
4 !
82 !
4)
82
!"
#$ %
&'( $
""
))***' + $
'
9
82
8)
=)
8
=
3
9)
3
9)
:!
?
:!
?!
@
;
@
;
4!
82
4
82 )
?
88
8
=)
8
=)
3
9)
3)
9!
:)
?
:
?
@!
;!
@
;)
4
82
4!
82 )
; 8
=!
3
9
:
?)
@)
;
4
82 !
!"
#$ %
&'( $
""
))***' + $
'
) *
+ %,
!"
#$ %
&'( $
""
))***' + $
'
.
!
" .
.
!
! K
' "
,K
K K
28 K
K
K
23 "
B .
(
)
(
- % "
- % - % #%
G DD
! L
L 0
( .
!"
#$ %
K . +3
&'( $
)
- %
)
""
))***' + $
'
"