1
0
mirror of https://github.com/gbdev/awesome-gbdev.git synced 2025-08-13 11:34:11 +02:00

Move salvaged articles to dedicated gb-archive repo due to licensing issues described in #67

This commit is contained in:
Antonio Vivace
2017-12-11 16:27:20 +01:00
parent 3945cf5def
commit 50dfc36a6e
23 changed files with 0 additions and 2742 deletions

View File

@@ -1,142 +0,0 @@
Fast Two Player Code using RGBASM
(or Fast OOP using RGBASM)
Written by GeeBee
With an addition by Otaku
As an example, let's say you have an assembly language two
player game that you are working on where the majority of
the code for player one might be identical for player two.
There are basically two ways of handling this:
1) Pass a pointer to these routines that points to the
"object" structure that you wish to process.
2) Repeat all of these code routines using slightly
different function/variable names.
The advantage to using approach number 1 is that you can
have two or more objects that share the same code routines.
One disadvantage is the code will be slower than approach
2 because you have to access the object structure through
a pointer. Also this pointer can tie up valuable GB registers
which can cause longer/slower code due to fewer available
registers.
The advantage to using approach number 2 is that since your
object data doesn't have to be accessed through a pointer the
code can be much quicker which sometimes is very important
on the limited GB/GBC platform. The disadvantages are that
code must be repeated for each object (which can rapidly eat
up ROM space for a large number of objects) and having several
identical routines (with different function & variable names)
is a big maintenance problem when the same changes need to be
applied to each object.
If you can get around the maintenance problems of approach
number 2, this can be ideal in some cases where you need
fast execution speed OR in cases where you have just finished
coding a 1 player game and as an after-thought you decide to
add 2 player support but you don't want to rewrite your code
to use object pointers.
RGBASM is powerful enough that you can eliminate the majority
of the maintenance problems in this case. Here's example code:
(The macro operator '@' is incremented with each macro included
in your source code so this code needs to be compiled stand-alone
and then linked with other code or you must guarantee that no
macros are included before this code. The macro FOO below is
only used to increment '@' from 0 to 1 so that the first object
ends with _1 instead of _0.)
ObjectX_1: DB
ObjectY_1: DB
ObjectX_2: DB
ObjectY_2: DB
FOO: MACRO
db 0
ENDM
; Set Object X,Y coordinates to H,L
OBJCODE: MACRO
SetObjectPos\@:
ld a,h
ld [ObjectX\@],a
ld a,l
ld [ObjectY\@],a
ret
GetObjectPos\@:
ld a,[ObjectX\@]
ld h,a
ld a,[ObjectY\@]
ld l,a
ret
ENDM
; Include code for object #1
OBJCODE
; Include code for object #2
OBJCODE
; Set Object 1 coordinates to 0,0
ld hl,0
call SetObjectPos_1
; Set Object 2 coordinates to 0,0
ld hl,0
call SetObjectPos_2
; Return Object 1 coordinates in H,L
call GetObjectPos_1
; Return Object 2 coordinates in H,L
call GetObjectPos_2
--
added by Otaku
Using SET to point to the start of your object
structure, and then calculating offsets into the
object structure is a neater way of doing this,
without having to worry about an idle use of MACRO
incrementing the @ counter.
So:
Object1: DS 16
Object2: DS 16
RSRESET
X_POS RB 2
Y_POS RB 2
HEALTH RB 1
; assume that x & y are passed in BC & DE
; assume for this example that GB has the ability
; to move registers directly to memory without using
; the A register
SetObjectPos: MACRO
ObjectBase SET \1
LD [ObjectBase+X_POS],C
LD [ObjectBase+X_POS+1],B
LD [ObjectBase+Y_POS],E
LD [ObjectBase+Y_POS+1],D
PURGE ObjectBase
ENDM
SetObject1Pos:
SetObjectPos Object1
RET
SetObject2Pos:
SetObjectPos Object2
RET

View File

@@ -1,28 +0,0 @@
Some ideas for why sprites would disappear in 2x Speed Mode
Written by Jan-Lieuwe Koopmans
moa@gelrevision.nl
- You move your sprites using an ISR (interrupt service routine) and that
particular interrupt is disabled by the cpu-speed switch routine (IE_REG
being altered);
- Bit 1 of the LCDC register is somehow set to zero;
- The DMA copy of OAM workram to real OAM ram is not done anymore (that
routine is in HiRam and is being called by the default VBL ISR).
- Your sprite-tiles are not being copied to VRAM in a proper way.
You can check all these easily using No$Gmb (press F10 in debug mode to see
register contents, check HiRam (starting at $FF80) using the debugger, check
Video RAM using F5 in debug mode).

View File

@@ -1,70 +0,0 @@
by The ZenPsycho
;*****************************
;* Jump table code *
;*****************************
;
;******************************************************************
;
; on entry:
; A = Address offset
;
; Registers used:
; A, HL, DE
;
; on exit:
; A destroyed
; hl contains address from jump table
;
; place this routine at reset $08
;
; [example code]
; (If A=0 then jp this)
; (if A=1 then jp that)
; (if A=2 then jp theother)
;
; RST $08 ;call function to jump to address from pointer table
; DB this ;pointer table
; DB that
; DB theother
;
;
;******************************************************************
pop hl ;get address of first pointer from stack
push de ;preserve DE
add a,a ;multiply A by two
ld e,a ;store A in E
ld d,00 ;so that we can
add hl,de ;add the offset to hl
ldi a,(hl) ;and now
ld h,(hl) ;get an address from the pointer table
ld l,a ;
pop de ;restore DE
jp hl ;and jump to address from table
;*****************************************************************
pop hl ;get address
push bc ;preserve BC
ld c,a ;get offset from A into BC
ld b,00 ;
ldi a,(hl) ;load from address into A and increment address
push hl ;store address+1
add hl,bc ;add offset to address+1
ld c,a ;get data from address+1 into BC (B still=0)
ld a,(hl) ;get data from address+1+offset
pop hl ;restore address+1
add hl,bc ;
pop bc ;
jp hl ;
;*****************************************************************

View File

@@ -1,46 +0,0 @@
;***************************************
;* Lookup table function *
;***************************************
;
; On entry:
; A contains table index
;
; registers used:
; A, HL, BC
;
; On exit:
; A contains table entry
; HL contains address of the end of the table
; BC is preserved
;
; this function is placed at $0018
;
; [Example Code]
; LD A, $04
; CALL TABLE
;
; TABLE:
; RST $18 ;call table look up function , push PC onto stack
; DB $06 ;number of bytes in table
; DB $06, $05, $04, $03, $02, $01 ;table data
; ret
;
; after running this code the accumulator (A) contains $02
;
;************************************************************************
POP HL ;Load address from stack
PUSH BC ;preserve BC
LD C,A ;Load index
LD B,0 ;into BC
LD A,[HLI] ;Load size of table into A
PUSH HL ;preserve the address of the start of the table
ADD HL,BC ;HL now points to table index
LD C,A ;load size of table into BC
LD A,[HL] ;A now contains Table entry at the specified index
POP HL ;to the start address of the table,
ADD HL,BC ;add the size of the table
POP BC ;restore BC
JP HL ;and jump to the instruction AFTER the table

View File

@@ -1,78 +0,0 @@
Ok so you want sprites in your gameboy game/demo. You've got a DMA routine, you know how it works. What you don't know is what is the quickest, best way to copy it into HRAM at $FF80. That's where document comes in. I'm going to teach you how to use a routine that will allow you to easily copy data to ram. and this isn't only good for copying your DMA routine, you can use it to copy tile data and other bits of assorted code into ram, easily. the first thing you do is you put the following routine at $0028, like this:
SECTION "COPY DATA",home[$0028]
POP HL
PUSH BC
LD A,[HLI]
LD B,A
LD A,[HLI]
LD C,A
copydataloop:
LD A,[HLI]
LD [DE],A
INC DE
DEC BC
LD A,B
OR C
JR NZ, copydataloop
POP BC
JP [HL]
The reason we put it at $0028 is because it's a reset code. which means you only need one byte to call the code that's there, as opposed to the 3 bytes you use in a normal call.
I'll explain this code a little later, but for now I will show you how to use it. We'll create a new file called "DMA.INC". in this file you put this:
DMACOPY:
LD DE, $FF80 ;$FF80 is where we want to copy this data
RST $28 ;Call the copy routine
DB $00, $0D ;the amount of bytes we want to copy,
;represented in a 16 bit unsigned integer.
;And now the data. This is a DMA routine.
;Hand assembled. It copies data from $C100
DB $F5, $3E, $C1, $EA, $46, $FF, $3E, $28, $3D, $20, $FD, $F1, $D9
RET
now save this file, and include it in your main file. then when you want to copy the DMA routine to $FF80,
CALL DMACOPY
simple huh?
ok now let's explore how the routine itself works.
POP HL ;when you call RST $28, it pushes the address of the
;byte immediately following it, onto the stack.
;this instruction stores that address into HL
PUSH BC ;(preserve BC)
LD A,[HLI] ;This copies the byte at that address into B
LD B,A ;which is the MSB of the amount of bytes we want to
LD A,[HLI] ;copy. Then this copies the LSB into C.
LD C,A ;Now HL should point at the first byte of our data
copydataloop:
LD A,[HLI] ;Copy that byte into a
LD [DE],A ;then copy a to the address contained in DE ($FF80)
INC DE ;Increment the address in DE.
DEC BC ;One byte down, BC to go
LD A,B ;then OR B and C together
OR C ;to find out if BC = 0
JR NZ, copydataloop ;if it isn't, copy another byte
POP BC ;(restore BC)
JP [HL] ;Jump to the byte after the data, which is a RET
Pretty clever eh?
If you have any questions or comments, E-mail me at ZenPsycho@yahoo.com

View File

@@ -1,81 +0,0 @@
Common Gameboy Development Acronyms
Written by GeeBee and Jason
*plug* http://www.devrs.com/gb/
*plug* http://www.tripmode.com/gbdev/
Read up, because GeeBee likes to give pop quizes. =)
AdvGBIDE - GB IDE assembler by MegaMan_X. Abandoned(?).
AI - Artificial Intelligence
APA - All points accessable. Used in pixel-based graphics.
API - Application Program Interface
ASxxxx - Assembler used in GBDK.
BG - Background
C3 - Carbon Copy Card
CGB - Reference to the Gameboy Color
CPU - Central Processing Unit
DA - Digital Audio
DX - Term adapted indicating Gameboy Color enhanced.
GB - Game Boy
GBC - Gameboy Color.
GBCAM - Gameboy Camera.
GBDEV - Gameboy Development (well duh.) =)
GBDK - C compiler for GB by Pascal Felber now maintained by
Michael Hope. http://gbdk.sourceforge.net
GBMB - Map builder for GB by Harry Mulder.
GBP - Game Boy Pocket
GBTD - Tile editor for GB by Harry Mulder.
GBX - Gameboy XChanger. Flash cart programmer manufactured by Bung.
Product is not currently being manufactured.
GG - Game Genie
DMA - Direct Memory Access
EPROM - A chip that works like a ROM but is reprogrammable
but requires an ultaviolet light source to do so.
Flash - A chip that works like a ROM but that can be
reprogrammed many times easily.
Flash EPROM - Same as Flash.
Flash Cart - Any cart that has had the original ROM removed
and a Flash installed in its place as shown
in the ReadPlus cart reader/writer docs.
FMV - Full Motion Video
GUI - Graphical User Interface
HBL - Horizontal Blank
HBlank - Horizontal Blank
HC - High color. Involves palette updates during Horizontal Blank.
IDE - Integrated Development Environment
HuC - Hudson Controller (selects memory banks + other features)
LCC - GBDK's original compiler.
LCD - Liquid Crystal Display
LSB - Least Significant Bit (or Byte)
MBC - Memory Bank Controller
MSB - Most Significant Bit (or Byte)
NDA - Non-Disclosure Agreement
OAM - Object (Sprite) Attribute Memory
PAL - Palette
PV - Pocketvoice. Flash cart with microphone and speaker built in.
RAM - Random Access Memory (read / write memory)
RGBDS - Powerful GB assembler by Carsten Sorensen now maintained by
Otaku. http://www.otakunozoku.com
RGBASM - Powerful GB assembler by Carsten Sorensen now maintained by
Otaku. http://www.otakunozoku.com
ROM - Read Only Memory (new carts contain this)
SDCC - New compiler used in GBDK.
SGB - Super Game Boy
SPR - Sprite
SRAM - Save RAM. Battery backed up random access memory.
SRC - Source Code
SSC - Super Smart Card (programmable cart, no longer made)
TASM - Table assembler for GB (not related to Turbo Assembler)
TIM - Timer
TIMINT - Timer Interrupt
VBK - Video RAM Bank
VBL - Vertical Blank
VBLINT - Vertical Blank Interrupt
VRAM - Video RAM
WIN - Window

View File

@@ -1,50 +0,0 @@
How to animate the water as seen in Zelda DX
By Marc Gale
marc@sbirmc.ac.uk
The way I've done it uses the following:
1. Four seperate animation tiles which will cycle around happily. In
other words, displaying tile 1, 2, 3, 4, 1 will look good.
2. A byte in RAM somewhere for the frame counter
3. Use a specific single tile number for all water
4. A byte in RAM somewhere for the water animation delay
5. A byte in RAM somewhere for the water animation count
What I did was to ensure that the specified tile number was used
for all water on the map. Then, in the V-Blank interrupt, copy the
appropriate frames' tile from ROM to the tile data area, and then
update the frame counter. Of course, checking to see if we're
ready for the animation first. A pseudo code for the interrupt
follows:
VBlank_Int:
grab the animation counter
increase it by one
put it back
compare the counter to the animation delay value
if we haven't reached the delay value, return
reset the animation counter
grab the frame number
increase the frame number, resetting it if neccessary
copy the appropriate tile data from rom into the specified
tile to be used for water
fin:
Or something like that. When I have some replacement graphics
for my project, I'll release the full source code (any volunteers?) as
I can't release the project whilst it still uses Zelda's graphics.

View File

@@ -1,202 +0,0 @@
GeeBee's GB Assembly Code Tips v1.0
-----------------------------------
Note: The following references to 'cycles' refers
to machine cycles. To convert to clock cycles
multiply by 4. (i.e. 1 machine cycle = 4 clock cycles)
; **** Load A with $00 ****
Method 1:
ld a,0 ; 2 bytes, 2 cycles, Doesn't affect flags
Method 2:
xor a ; 1 byte, 1 cycle, Flag results: C=0, Z=1
; **** Compare A to $00 ****
Method 1:
cp 0 ; 2 bytes, 2 cycles
Method 2:
or a ; 1 byte, 1 cycle
Method 3:
and a ; 1 byte, 1 cycle
; **** Call/Return ****
Method 1: ; 4 bytes, 10 cycles
...
call sub
ret
Method 2: ; 3 bytes, 4 cycles
...
jp sub
; **** Exchange DE & HL ****
Method 1: ; 6 bytes, 6 cycles
ld a,d
ld d,h
ld h,a
ld a,e
ld e,l
ld l,a
Method 2: ; 4 bytes, 9 cycles
push de
ld d,h
ld e,l
pop hl
; **** Load hl,[Address] ****
Method 1:
ld a,[Address] ; 8 bytes, 10 cycles
ld l,a
ld a,[Address+1]
ld h,a
Method 2:
ld hl,Address ; 6 bytes, 8 cycles
ld a,[hl+]
ld h,[hl]
ld l,a
; **** Call [HL] ****
Method 1: ; 5 bytes, 8 cycles
ld de,.retadr
push de
jp [hl]
.retadr:
Method 2: ; 4 bytes, 7 cycles
call DoJump
...
...
DoJump:
jp [hl]
; **** HL = -HL ****
Method 1: ; 7 bytes, 8 cycles
ld a,l
cpl
ld l,a
ld a,h
cpl
ld h,a
inc hl
Method 2: ; 7 bytes, 7 cycles
xor a
sub l
ld l,a
ld a,0
sbc h
ld h,a
; **** A = CONST - A ****
Method 1: ; 4 bytes, 4 cycles
ld b,a
ld a,CONST
sub b
Method 2: ; 3 bytes, 3 cycles
cpl
add CONST+1
; **** HL = HL + A ****
Method 1: ; 6 bytes, 6 cycles
add l
ld l,a
ld a,0
adc h
ld h,a
Method 2: ; 5 bytes, 5 cycles
add l
ld l,a
jr nc,.notcarry
inc h
.notcarry:
; **** Parameter Setup ****
Method 1: ; 10 bytes
Entry1:
ld a,1
jr Sub
Entry2:
ld a,2
jr Sub
Entry3:
ld a,3
Sub:
...
...
Method 2: ; 8 bytes
Entry1:
ld a,1
DB 1 ; Opcode for LD BC,xxxx
Entry2:
ld a,2
DB 1 ; Opcode for LD BC,xxxx
Entry3:
ld a,3
Sub:
...
...
; **** Fast subroutine execution ***
Method 1:
ld hl,param1
call sub1
ld hl,param2
call sub2
ld hl,param3
call sub1
...
...
.sub1:
...
ret
.sub2:
...
ret
Method 2:
ld sp,calltable
ret ; jump to sub1
.sub1:
pop hl
...
ret
.sub2:
pop hl
...
ret
calltable:
dw sub1,param1
dw sub2,param2
dw sub1,param3
** End of File ***

View File

@@ -1,105 +0,0 @@
Notes for getting assembly language programs
that run on VGB to run on a real GB
by kOOPa, 2-Jan-98:
--------------------------------------------
1. Emulators tend to set all of RAM to $00 on power up.
Real GBs do NOT initialize RAM on power up. RAM is filled
with random values on power up. You must clear it yourself
if you wish it to be set to some known value.
2. The real hardware could care less about the ROM checksum
($14e,$14f) but the complement check ($14d) MUST be correct
or programs will "lock up" after scrolling the Nintendo logo.
Use RGBFIX -V in the RGBDS development system to set
the checksum and the complement byte after each source
code compile. It doesn't matter whether you program in
C or assembly, this program will fix it.
3. The Nintendo scrolling graphic from $104 - $133 must be
accurate. If one byte of it is changed then your programs
will "lock up" after scrolling this graphic logo.
4. When the LCD display is off (bit 7 of $ff40 set to 0) you
can write to video memory at any time with out restrictions.
While it is on you can only write to video memory during
H-Blank and V-Blank. Code similar to this will work:
; Write B to Video RAM location HL
WriteVRAM:
di ;turn off interrupts
Write1:
ldh a,[$41] ;read $ff41
and 2
jr nz,Write1
ld [hl],b
ei ;turn on interrupts
ret
There should not be many instructions between the "jr nz" and
write to memory "ld [hl],b". A worst case of 64 CPU clock cycles
are available to access main video memory (not OAM!) following
the "jr nz" command.
The "di" and "ei" commands above are only required if you
are using Serial, Timer, or Hi-2-Lo interrupts.
5. The LCD display is on at reset (bit 7 of $ff40 set to 1).
Before the LCD display can be turned off you must wait for
V-Blank. One popular way of doing this is the following:
; Turn off LCD display
LCDOff:
ldh a,[$44h] ; $ff44=LCDC Y-Pos
cp $90 ; $90 and bigger = in VBL
jr nz,LCDOff ; Loop until = $90
xor a
ldh [$41],a ; Turn off LCD display
ret
Note you should disable interrupts, if they are enabled,
before executing the above code or else the test of $ff44
could prove invalid.
Turning the LCD display on can be done at any time.
6. If you are using sprites then you should not use the
following commands when their register contents are in
the range $fe00-$feff.
inc bc
inc de
inc hl
If you don't follow this rule, sprite trash in the form
of sprite "blink" will randomly affect your sprites.
7. Normally you should only make changes to Sprite RAM
during V-Blank unless you are an expert and know exactly
what you are doing. The common way to do this is to use
the GB DMA register ($ff46) to do a fast copy from your
sprite table in RAM to $fE00-$fe9f.
A. You need a sprite table in RAM with a starting address
of $XX00 and with a length of 160 ($a0). Many often
use $c000-$c09f for this purpose but anywhere in RAM
starting with $XX00 is fine.
B. You need to create a VBlank interrupt routine that
contains the DMA command, followed by a short delay
to allow the DMA to complete, and copy this routine
to high RAM ($ff00-$fffe). The DMA command WILL NOT
WORK in ROM or low RAM because these are disabled
during DMA.
C. After copying this routine to high RAM you then
need to enable the VBLANK interrupt and then enable
interrupts.

View File

@@ -1,540 +0,0 @@
Making your first Gameboy Game
by Mike Mika, Genetic Fantasia
mmika@geneticfantasia.com
You will find many incredible tools out there to make gameboy games, but to make
life easy for you at this point, find these programs:
TASM with Gameboy Table by Jeff Frohwein
GFTILE by Genetic Fantasia (Only because its easy output, I recommend TILE256)
VGB-DOS by Marcel De Kogel (Port of Marat Fayzullin's emulator)
PAN97DOC the Gameboy Hacker Bible by Pan of Anthrox and Jeff Frohwein
Z80 command list
GAMEBOY memory map
GBTOOL
Terminology:
A CHARACTER is an 8x8 graphic tile. The gameboy screen is comprised of 32x32
characters, with only 20x18 visible.
A MAP is the coordinate information of all the characters to be displayed on the
screen. A 20x18 map would cover the visible screen.
A SPRITE is a form of tile that is not a part of the background, but
may move freely over or under the background character map. It is also not
restricted to 8x8 coordinates, but moves pixel by pixel.
A PALETTE is the color set used by the gameboy. The gameboy has four empty indexes
where you can place the order of the four grey scale.
These are essential tools to begin with. It also helps to know a little bit about
assembly. Even if you don't, you can figure it out pretty easy as the Z80 processor
is very basic.
First Step
You should find yourself a good text editor. If not, just use the DOS text editor
to write this program, or even use notepad. A gameboy program needs a header and
checksum to run correctly on a gameboy. Any source you find will have this header.
Here is an example (Used from Hero Zero's Text Demo):
.org $0000 ; Start of the binary
.org $0040 ; VBlank IRQ
reti ; Do nothing
.org $0048 ; LCDC Status IRQ
reti ; Do nothing
.org $0050 ; Timer Owerflow
reti ; Do nothing
.org $0058 ; Serial Transfear Completion
reti ; Do nothing
.org $0060 ; Hmm, this is a wierd on
; Im not sure how this one works
; Transition from high to low
; of pin p10-p13
; I think Its a hardware thing
reti ; Do nothing :)
; Irqs done..
.org $0100
; GameBoy Header with correct checksum
.db $00,$C3,$50,$01,$CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83
.db $00,$0C,$00,$0D,$00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6
.db $DD,$DD,$D9,$99,$BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F
.db $BB,$B9,$33,$3E ; Standard Nintendo DO NOT CHANGE...
.db "MY FIRST GAME " ; Cart name 16bytes
.db $00,$00,$00 ; Not used
.db $00 ; Cart type ROM Only
.db $00 ; ROM Size 32k
.db $00 ; RAM Size 0k
.db $fe,$ba ; Maker ID $bafe=Genetic Fantasia
.db $01 ; Version =1
.db $DA ; Complement check (Important)
.db $ff,$ff ; Cheksum, fix this if you are going to
; run this in VGB, or simpy use the -NOCRC
; switch in the VGB-DOS command line.
start ; This is addr $0150
ld sp,$fff4 ; Put the stack where the GB wants it
ld a,%00000000 ; No IRQs at all
ldh ($ff),a
sub a ; Misc standard init things..
ldh ($41),a ; LCDC Status
ldh ($42),a ; Screen scroll Y=0
ldh ($43),a ; Screen scroll X=0
(Start program here)
Here we are! Our first delve into a program. Now let's make a map
and a character set. Use GFTILE to draw a character set and save it as a binary,
and also save it as a TASM file called "chr.tsm". Draw a map and save it as binary
and also as a tasm file "map.tsm". Make sure the map dimensions are 32x32 before
you save it! The gameboy screen routine we will be writing will be 32 characters
wide by 32 characters tall.
After that, we will have to set up the screen. By setting all the bits to on,
the remarks on the right become effective. If we turn on the screen, we will set
bit 1 to 1, (I.E. a,%10000000)
ld a,%00000000 ; LCD Controller = Off (No picture on screen)
; WindowBank = $9800 (Not used)
; Window = OFF
; BG Chr = $8000
; BG Bank= $9800
; Sprites= 8x8 (Size Assembly, 1=8x16)
; Sprites= Off (Sprites on or off)
; BG = On
ldh ($40),a
The gameboy has only four colors to deal with, making life both easy and difficult
for you. Let's set up the palette for the screen and the future implementation of
sprites to the same palette configuration we used in GFTILE, the index is in bit
order (I.E. Color index0=11, index1=01, etc.). The reason I set up the sprite
palettes now is to prevent confusion later. You have two sprite palettes that each
sprite can choose from. For now, we will make them both the same as the background
palette:
nor_col ; Sets the colors to normal palette
ld a,%11011000 ; grey 3=11 (Black)
; grey 2=10 (Dark grey)
; grey 1=01 (Ligth grey)
; grey 0=00 (Transparent)
ldh ($47),a
ldh ($48),a ; 48,49 are sprite palettes
; set same as background
ldh ($49),a
ret
Now we need to write the routines that will load the character set that you drew
into the character memory ($8000), and the map onto the screen ($9800).
mchar
ld hl,$8000
ld d,$00 ; move 256 bytes
ld e,$12 ; x2=512. Increase this value
; to copy more of the character set.
mchar_loop
ldh a,($41) ; There are only certain times you
and 2 ; can write out scrn/tile. This
jr nz,mchar_loop ; loop waits for those times.
ld a,(bc)
ld (hli),a
inc bc
dec d
jp nz,mchar_loop
dec e
jp nz,mchar_loop
ret
map
ld hl,$9800
ld d,$00
ld e,$04 ; 256*4=1024=32x32=One whole GB Screen
map_loop
ldh a,($41)
and 2
jr nz,map_loop
ld a,(bc)
ld (hli),a
inc bc
dec d
jp nz,map_loop
dec e
jp nz,map_loop
ret
Also, we'll add a routine to clear any sprites that may be randomly lingering around
the screen.
spr_cls ; Clear Sprites
ld l,0
ld h,$ce
spclear
ld a,$ff
ld (hl),a
inc l
ld a,l
cp $ff
jp nz,spclear
ret
Now, let's include our Tasm files we made with GFTILE:
chrset:
#include "chr.tsm"
chrmap:
#include "map.tsm"
If you do not have a map/tile editor, then create these files:
"chr.tsm"
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$82,$82,$C6,$C6
.DB $EE,$EE,$BA,$BA,$92,$92,$82,$82,$0,$0,$0,$0
.DB $0,$0,$C0,$C0,$23,$23,$1E,$1E,$C,$C,$78,$78
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$8,$8
.DB $F,$F,$8,$8,$8,$8,$0,$0,$0,$0,$0,$0
.DB $0,$0,$1C,$1C,$E0,$E0,$0,$0,$0,$0,$F,$F
.DB $8,$8,$8,$8,$8,$8,$0,$0,$0,$0,$0,$0
.DB $0,$0,$80,$80,$10,$10,$0,$0,$10,$10,$10,$10
.DB $18,$18,$8,$8,$0,$0,$8,$8,$78,$78,$C8,$C8
.DB $CC,$CC,$7E,$7E,$33,$33,$61,$61,$40,$40,$0,$0
.DB $3C,$3C,$70,$70,$C,$C,$4,$4,$EC,$EC,$78,$78
.DB $0,$0,$0,$0,$20,$20,$20,$20,$7C,$7C,$20,$20
.DB $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$30,$30
.DB $18,$18,$C,$C,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$3E,$3E,$7E,$7E,$60,$60,$60,$60,$6E,$6E
.DB $6E,$6E,$0,$0,$0,$0,$38,$38,$7C,$7C,$C6,$C6
.DB $C6,$C6,$FE,$FE,$FE,$FE,$0,$0,$0,$0,$C3,$C3
.DB $E7,$E7,$FF,$FF,$DB,$DB,$C3,$C3,$C3,$C3,$0,$0
.DB $0,$0,$7F,$7F,$7F,$7F,$60,$60,$60,$60,$7C,$7C
.DB $60,$60,$0,$0,$0,$0,$7E,$7E,$7F,$7F,$63,$63
.DB $63,$63,$7E,$7E,$63,$63,$0,$0,$0,$0,$3E,$3E
.DB $7F,$7F,$63,$63,$63,$63,$63,$63,$63,$63,$0,$0
.DB $0,$0,$63,$63,$63,$63,$63,$63,$77,$77,$3E,$3E
.DB $1C,$1C,$66,$66,$7E,$7E,$3E,$3E,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$C6,$C6,$C6,$C6,$C6,$C6
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$C3,$C3
.DB $C3,$C3,$C3,$C3,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$60,$60,$7F,$7F,$7F,$7F
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$63,$63
.DB $7F,$7F,$7E,$7E,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$63,$63,$7F,$7F,$3E,$3E,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$1C,$1C,$1C,$1C,$1C,$1C
"map.tsm"
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$1,$2,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$3,$4,$0
.DB $0,$9,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$5,$6,$7,$8,$A,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$B,$C,$D,$E
.DB $F,$10,$11,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$12,$13,$14,$16,$17,$18,$19,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
.DB $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
Now that we've type this all in, go back to the position just before the palette
routine (nor_pal). Enter this code:
setup
ld bc,chrset
call mchar
ld bc,chrmap
call map
call nor_col
call spr_cls
ld a,%10010101 ; LCD Controller = Off (No picture on screen)
; WindowBank = $9800 (Not used)
; Window = OFF
; BG Chr = $8000
; BG Bank= $9800
; Sprites= 8x8 (Size Assembly, 1=8x16)
; Sprites= Off (Sprites on or off)
; BG = On
ldh ($40),a
loop
jr loop
Now, finally, at the end of our program, type:
.block $008000-$
.end
This tells Tasm we are done and to make the binary 32k. Now save your file as
prog1.asm.
TIME TO COMPILE!
Here is the big moment. Using TASM, type:
TASM -69 -b prog1.asm prog1.gb
This will now compile your program. "-69" tells tasm to use the gameboy opcode
table, and "-b" tells TASM to create a binary image. It will do all this in file
PROG1.GB
To run this on a real gameboy or vgb, you now need to use GBTOOL and type these two
command lines in the following order (IMPORTANT!):
GBTOOL C PROG1.GB
(Answer yes to inquiry)
GBTOOL F PROG1.GB
(Answer yes to inquiry)
You may also use the crcfix programs available on the net, feel free to experiment
as this can be tedious everytime you try your program. If you want to bypass this
step with VGB-DOS, you can. Without doing the above, type:
VGB-DOS PROG1.GB -NOCRC
This tells VGB-DOS to not worry about the CRC check or Complement check (Nintendo's
cartridge protection).
NOW! If you are using VGB-DOS, type:
VGB-DOS PROG1.GB
Voila! The program runs!
If you have uploaded this binary to the Smart Cart, make sure you rename the file
to GBPROG1.GB (Just in case) and try it out. Bingo!
This is your first lesson.
The final file should look like:
.org $0000 ; Start of the binary
.org $0040 ; VBlank IRQ
reti ; Do nothing
.org $0048 ; LCDC Status IRQ
reti ; Do nothing
.org $0050 ; Timer Owerflow
reti ; Do nothing
.org $0058 ; Serial Transfear Completion
reti ; Do nothing
.org $0060 ; Hmm, this is a wierd on
; Im not sure how this one works
; Transition from high to low
; of pin p10-p13
; I think Its a hardware thing
reti ; Do nothing :)
; Irqs done..
.org $0100
; GameBoy Header with correct checksum
.db $00,$C3,$50,$01,$CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83
.db $00,$0C,$00,$0D,$00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6
.db $DD,$DD,$D9,$99,$BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F
.db $BB,$B9,$33,$3E ; Standard Nintendo DO NOT CHANGE...
.db "MY FIRST GAME " ; Cart name 16bytes
.db $00,$00,$00 ; Not used
.db $00 ; Cart type ROM Only
.db $00 ; ROM Size 32k
.db $00 ; RAM Size 0k
.db $fe,$ba ; Maker ID $bafe=Genetic Fantasia
.db $01 ; Version =1
.db $DA ; Complement check (Important)
.db $ff,$ff ; Cheksum, fix this if you are going to
; run this in VGB, or simpy use the -NOCRC
; switch in the VGB-DOS command line.
start ; This is addr $0150
ld sp,$fff4 ; Put the stack where the GB wants it
ld a,%00000000 ; No IRQs at all
ldh ($ff),a
sub a ; Misc standard init things..
ldh ($41),a ; LCDC Status
ldh ($42),a ; Screen scroll Y=0
ldh ($43),a ; Screen scroll X=0
ld a,%00000000 ; LCD Controller = Off (No picture on screen)
; WindowBank = $9800 (Not used)
; Window = OFF
; BG Chr = $8000
; BG Bank= $9800
; Sprites= 8x8 (Size Assembly, 1=8x16)
; Sprites= Off (Sprites on or off)
; BG = On
ldh ($40),a
setup
ld bc,chrset
call mchar
ld bc,chrmap
call map
call nor_col
call spr_cls
ld a,%10010101 ; LCD Controller = Off (No picture on screen)
; WindowBank = $9800 (Not used)
; Window = OFF
; BG Chr = $8000
; BG Bank= $9800
; Sprites= 8x8 (Size Assembly, 1=8x16)
; Sprites= Off (Sprites on or off)
; BG = On
ldh ($40),a
loop
jr loop
nor_col ; Sets the colors to normal palette
ld a,%11011000 ; grey 3=11 (Black)
; grey 2=10 (Dark grey)
; grey 1=01 (Ligth grey)
; grey 0=00 (Transparent)
ldh ($47),a
ldh ($48),a ; 48,49 are sprite palettes
; set same as background
ldh ($49),a
ret
mchar
ld hl,$8000
ld d,$00 ; move 256 bytes
ld e,$12 ; x2=512. Increase this value
; to copy more of the character set.
mchar_loop
ldh a,($41) ; There are only certain times you
and 2 ; can write out scrn/tile. This
jr nz,mchar_loop ; loop waits for those times.
ld a,(bc)
ld (hli),a
inc bc
dec d
jp nz,mchar_loop
dec e
jp nz,mchar_loop
ret
map
ld hl,$9800
ld d,$00
ld e,$04 ; 256*4=1024=32x32=One whole GB Screen
map_loop
ldh a,($41)
and 2
jr nz,map_loop
ld a,(bc)
ld (hli),a
inc bc
dec d
jp nz,map_loop
dec e
jp nz,map_loop
ret
spr_cls ; Clear Sprites
ld l,0
ld h,$ce
spclear
ld a,$ff
ld (hl),a
inc l
ld a,l
cp $ff
jp nz,spclear
ret
chrset:
#include "chr.tsm"
chrmap:
#include "map.tsm"
.block $008000-$
.end

View File

@@ -1,63 +0,0 @@
Brief introduction to Gameboy Color art
Written by Jason
The Gameboy Color doesn't use APA (all points accessable) graphics such
as your computer uses. Instead it uses tiles to draw everything. While
this has certain advantages, it also makes simple things such as
drawing a line really difficult.
The Gameboy Color uses 8x8 pixel tiles to create the background. The
Gameboy Color's screen has a resolution of 20x18 tiles or 160x144 pixels.
Inside its ram it has the ability to store 32x32 tiles or 256x256 pixels.
This is useful for games that scroll the background. The Gameboy Color
can display 256 unique tiles on the screen at one time. It has an additional
RAM bank to display an additional 256 tiles, although this kills any chance
of backwards compatability with the original Gameboy.
Sprites are tiles independant of the background. These are used for things
such as the main character and badguys. The Gameboy Color can display either
8x8 or 8x16 pixels per tile. It can display 40 sprites simultaniously. One
of its main drawbacks is that it can only display 10 sprites per horizontal
line. The Gameboy Color features a few hardware sprite manipulations. While
it does not feature resizing the sprites or more useful things, you can
flip the horizontal and vertical axis on each sprite. This is useful
to make a character walk in 2 directions without needing to load a new
tile into the sprite. The Gameboy Color can hold 256 8x8 pixel tiles
or 128 8x156 pixel tiles into sprite ram. This is useful since it takes
alot less computing power to change which ram location to display the tile
than to load a unique tile into its place. You can layer sprites on top
of each other to add an additional 3 colors to that tile. Keep in
consideration the 10 sprites per horizontal line when you do this, though.
You can fake create more sprites by changing their location during horizontal
blank, however this isn't really useful since horizontal blank is rather
quick and it is rarely needed to have the exact same sprite in multiple
locations.
The Gameboy Color can display 56 simultanious colors. The background consists
of 8 palettes. Each palette contains 4 colors to fill each tile. This creates
the first 32 colors. The other 24 are created by the sprites. The sprites
have 8 palettes of 3 colors. The loss of the fourth color is caused by
sprites needing one color (default white with GBTD) to be transparent.
Without this, every sprite would have to be square shaped. There is a trick
to create more colors by changing palettes during horizontal blank, however
this doesn't prove to be very useful in gameplay as the Gameboy Color has
to stop the gameplay to update the palettes, and if one palette isn't updated
in time, the picture will become miscolored. A faster CPU would eliminate
this problem, but with the Gameboy Advance being released soon, Gameboy
Color artists just have to deal with it for the time being.
The window is a nontransparent layer that can be applied on top of the
background. It does not use its own palettes, but rather shares its
palettes with the background's palettes. The window is useful for things
such as pop-up maps, status bars that don't scroll with the background,
and many other uses.
In order to prevent graphical glitches from being displayed, sprite and
background data should only be updated when the screen is not rendering.
Good times to do this are during vertical blank and horizontal blank.
Unfortunately that is about it for the Gameboy Color's display.

View File

@@ -1,26 +0,0 @@
GameBoy CPU Timing v0.01 13.04.2000/GPZ-HIT
-------------------------------------------------------------------------------
standard gameboy:
Clock Speed: 4.194304 MHz - 0,2384 <20>s per cycle
cycles=microseconds/0,2384
microseconds=cycles*0,2384
Horiz Sync: 9198 KHz - 456 Cycles per line (109<30>s)
Vert Sync: 59.73 Hz - 70224 Cycles per frame (16.6ms)
color gameboy at 2x speed:
Clock Speed: 8.388688 MHz - 0,1192 <20>s per cycle
Horiz Sync: 9198 KHz - 912 Cycles per line (109<30>s)
Vert Sync: 59.73 Hz - 140448 Cycles per frame (16.6ms)
super gameboy:
Clock Speed: 4.295454 MHz
Horiz Sync: 9420 KHz
Vert Sync: 61.17 Hz

View File

@@ -1,89 +0,0 @@
GameBoy Color DMA-Transfers v0.0.1 13.04.2000/GPZ-HIT
-------------------------------------------------------------------------------
"old" DMA Transfer (aka 'OAM-DMA')
----------------------------------
source: - anywhere from $0000 to $dfff
- must be page-aligned
destination: - always OAM-Ram at $fe00 - $fe8f
length: - always 4*40 (=160 / $a0) bytes
- when cpu speed is 2x, transfer speed is also 2x
- transfer takes 671 cycles (160 microseconds)
rDMA $FF46 - source LSB
CAUTION:
- dma should be executed during v-blank period
- no memory except for HRAM is available for the cpu while DMA is in progress,
the common method is to place this routine in HRAM:
dma:
ld a,$c0 ; oam-buffer is at $c000
ld [rDMA],a
ld a,$28 ; wait until DMA completes (160 microseconds)
.lp
dec a
jr nz,.lp
ret
"new" DMA Transfer
------------------
source: - from $0000 to $7fff and $a000-$dfff
- must be page-aligned
destination: - always in VRAM at $8000-$9fff
- must be page-aligned
length: - can be set in 16-bytes increments (ie, its ALWAYS n*16 long),
(1*16)=$0010 to (128*16)=$0800 bytes
- DMA speed is constant regardless of CPU-Speed
- cpu is halted during dma transfer
- transfer takes 220+n*7,68 microseconds (1x speed)
110+n*7,68 microseconds (2x speed)
- has 2 different modes:
1) Horizontal blanking DMA (aka 'HDMA')
- transfers 16 bytes at each horizontal blank
- can be stopped/restarted at each h-blank period
2) General Purpose DMA (aka 'GDMA')
- can not be stopped or suspended once started
rHDMA1 $ff51 bit 7-0 bit 7-0 of Source MSB
rHDMA2 $ff52 bit 7-4 bit 7-4 of Source LSB
bit 3-0 unused (set to 0)
rHDMA3 $ff53 bit 7-5 unused (set to 0)
bit 4-0 bit 4-0 of Destination MSB
rHDMA4 $ff54 bit 7-4 bit 7-4 of Destination LSB
bit 3-0 unused (set to 0)
rHDMA5 $ff55 bit 7 DMA Mode / Control
read:
0 : DMA in progress
1 : DMA completed
write:
- after set to 0, GDMA starts
- after set to 1, HDMA starts at next h-blank
- once started, HDMA can be stopped at next
h-blank by setting this bit to 0
bit 6-0 length (number of 16-byte blocks - 1)
- amount of bytes transferred is (n+1)*$10
CAUTION:
- don't switch ROM banks if DMA source is in the range of $4000-$7fff
- don't switch ROM banks if DMA source is in the range of $d000-$dfff
- don't switch VRAM banks until DMA has completed
- halt can not be used while a DMA is in progress
- dma must have completed before another dma is started or registers are
altered
- display must be enabled for a HDMA transfer taking place
- GDMA is only reliable during v-blank when display is enabled

View File

@@ -1,75 +0,0 @@
GameBoy Video-Interupts v0.01 201299/GPZ-HIT
-------------------------------------------------------------------------------
Type priority jumps to
V-Blank highest $0040
LCDC . $0048
Timer . $0050
serial . $0058
pad lowest $0060
general IRQ registers:
----------------------
$ffff (rIE) IRQ Enable (read/write)
bit:
7-5 ?
4 Transition High=>Low Pin P10-P13 0:disabled 1:enabled
3 serial i/o transfer complete 0:disabled 1:enabled
2 Timer overflow 0:disabled 1:enabled
1 LCDC 0:disabled 1:enabled
0 V-Blank 0:disabled 1:enabled
$ff0f (rIF) IRQ Flag (read)
- if an interupt has occured, this register tells what kind
of interupt it was.
bit:
7-5 ?
4 Transition High=>Low Pin P10-P13
3 serial i/o transfer complete
2 Timer overflow
1 LCDC
0 V-Blank
LCDC IRQ-Registers:
-------------------
$ff44 (rLY) LCDC Y-Coordinate
read: current Rasterline
write: reset lcd-y counter
$ff45 (rLYC) LY-Compare (read/write)
- if rLYC = rLY then bit 2 of rSTAT is set
$ff41 (rSTAT) LCDC Status
bit:
7 ?
IRQ source selection:
6 rLYC=rLY <
5 mode %10 (searching OAM) | write
4 mode %01 (V-Blank) |
3 mode %00 (H-Blank) <
2 rLYC=rLY Flag <
|
1-0 current mode: |
|
%00 H-Blank | read
%01 V-Blank |
%10 searching OAM |
%11 transfering data to LCD <

View File

@@ -1,42 +0,0 @@
GameBoy Video-timing v0.01 201299/GPZ-HIT
-------------------------------------------------------------------------------
- all values referring to CPU at 'single' speed (CPU-clock 4.194304 MHz,
0,2384 <20>s per cycle)
Pixel
0 159 ?
Raster 0 -|-----------------------------|--------------- < <
Line | | | |
| OAM-Search Data Transfer | H-Blank | |
| ----------> --------------> | -------------> | |
| (mode %10) (mode %11) | (mode %00) | 65664 | 70224
| | | Cycles | Cycles
| | | (15.5ms) | (16.6ms)
| | | |
| | | | total
| | | | per
| | | | frame
$90 143 -|-----------------------------|- V-Blank < 4560 |
| vertical offscreen area | (mode %01) | Cycles |
$9a 153 ----------------------------------------------- < (1.08ms) <
^------------^----------------^----------------^
77-83 Cycles 169-297 Cycles 78-207 Cycles (*1)
^----------------------------------------------^
456 Cycles (109<30>s) total per line
(*1) timing in a line depends on the amount of sprites to be displayed:
sprites mode %10 mode %11 mode %00
in line
0 ? (41.37<EFBFBD>s) 204 Cycles (48.6<EFBFBD>s)
10 ? 297 Cycles (70.69<EFBFBD>s) 78 Cycles (18.7<EFBFBD>s)

View File

@@ -1,95 +0,0 @@
GameBoy Color Memormap v0.01 200300/GPZ-HIT
-------------------------------------------------------------------------------
General Memory Map Hardware Write Registers
------------------ ------------------------
0000 ---------------------------
16kB ROM bank #0 0000-1FFF rRAMG MBC5+Ram RAM-Bank Enable ($00 == disabnled/$0a == enabled)
- 0000-00ff header 2000-2FFF rROMB0 ROM-Bank LSB
- hardware vectors 3000-3FFF rROMB1 ROM-Bank MSB (only bit 0 used)
- 0100 start of user code,
usally:
NOP
jp START
- nintendo logo
- cartridge hardware
info
--------------------------- 014F
0150 ---------------------------
~16kb ROM 'Home' Bank
START: should be located
here somewhere
--------------------------- 3FFF
4000 ---------------------------
16kB switchable ROM bank 4000 Rumble Motor on Rumble-Cards (obvious =P)
4000-5FFF rRAMB MBC5+Ram RAM-Bank (bit 3-0 used)
6000-7FFF MBC1 ROM/RAM Select
--------------------------- 7FFF
8000 ---------------------------
8kB Video RAM
- switchable config, refer to reg. $ff40 (rLCDC)
STD-Config 1|Bank 0 |Bank 1
------------+--------------+---------------
8000-8FFF |Charset-Tiles |Charset-Tiles
|$00-$FF/b0 |$00-$FF/b1
9000-97FF |Sprite-Tiles |Sprite-Tiles
|$00-$7F/b0 |$00-$7F/b1
9800-9BFF |Window-Map |Window-Attribs
9C00-9FFF |Screen-Map |Screen-Attribs
(*) 9800-9FFF can be used for Sprite-Tiles
$80-$FF if not used otherwhise
STD-Config 2|Bank 0 |Bank 1
------------+--------------+---------------
8000-87FF |Sprite-Tiles |Sprite-Tiles
|$00-$7F/b0 |$00-$7F/b1
8800-8FFF |shared Sprite+|shared Sprite+
|Charset-Tiles0|Charset-Tiles
|$80-$FF/b0 |$80-$FF/b1
9000-97FF |Charset-Tiles |Charset-Tiles
|$00-$7F/b0 |$00-$7F/b1
9800-9BFF |Screen-Map |Screen-Attribs
9C00-9FFF |Window-Map |Window-Attribs
--------------------------- 9FFF
A000 ---------------------------
8kB switchable RAM bank
--------------------------- BFFF
C000 ---------------------------
4kB Internal RAM
--------------------------- CFFF
D000 ---------------------------
4kB Internal RAM Banks 0-7
--------------------------- DFFF
E000 ---------------------------
Echo of 8kB Internal RAM
--------------------------- FDFF
FE00 ---------------------------
Sprite Attrib Memory (OAM)
--------------------------- FE9F
FEA0 ---------------------------
Empty but unusable for I/O
--------------------------- FEFF
FF00 ---------------------------
I/O ports / Hardware regs.
--------------------------- FF4B
FF4C --------------------------- FF40 rSVBK GBC internal RAM Bank Select
GBC I/O - Hardware area
--------------------------- FF7F
FF80 ---------------------------
Internal RAM - "Zero-Page"
- stack is located here by
default (after reset)
--------------------------- FFFE
FFFF ---------------------------
Interrupt Enable Register
--------------------------- FFFF

View File

@@ -1,58 +0,0 @@
ISTAT98.TXT 1998 BY MARTIN KORTH
--------------------------------
Interrupt INT 48h - LCD STAT
----------------------------
The STAT register (FF41) selects the conditions that will generate this
interrupt (expecting that interrupts are enabled via EI or RETI and that
IE.1 (FFFF.1) is set).
STAT.3 HBLANK (start of mode 0)
STAT.4 VBLANK (start of mode 1) (additional to INT 40)
STAT.5 OAM (start of mode 2 and mode 1)
STAT.6 LY=LYC (see info about LY=00)
If two STAT-condiditions come true at the same time only one INT 48 is
generated. This happens in combinations
LYC=01..90 and OAM at the same time (see info about LY=00)
LYC=90 and VBLANK at the same time
OAM and VBLANK at the same time
HBLANK and LYC=00 and LYC=91..99 are off-grid and cannot hit others.
Some STAT-conditions cause the following STAT-condition to be ignored:
Past VBLANK following LYC=91..99,00 is ignored
Past VBLANK following OAM (at 00) is ignored
Past LYC=00 at 99.2 following OAMs (at 00 and 01) are ignored
Past LYC=01..8F following OAM (at 02..90) is ignored
Past LYC=00..8F following HBLANK (at 00..8F) is ignored
Past LYC=8F following VBLANK is ignored
Past HBLANK following OAM is ignored
Past HBLANK at 8F following VBLANK is ignored
If the OAM condition occurs, everything following -is- recognized.
An ignored VBLANK condition means that INT 48h does not produce a V-Blank
interrupt, INT 40h is not affected and still produces V-Blank interrupts.
The last LY period (LY=99) is a shorter than normal LY periodes. It is followed
by the first LY period (LY=00) this period is longer than normal periodes.
LY value clks description
-------------------------------
LY=01..8F 456 at the same moment than OAM
LY=90 456 at the same moment than pseudo-OAM and VBLANK
LY=91..98 456 during vblank (similiar to LY=01..8F)
LY=99 ca.56 similiar to LY=91..98, but shorter
LY=00 ca.856 starts during vblank, then present until second OAM
Because of the pre-started long LY=00 period, LYC=00 occurs within vblank
period and before first OAM (where we would have expected it)
*EOF*

View File

@@ -1,36 +0,0 @@
I have been recently coding some serial transfer routines and have found a
few interesting things that I thought may be useful to anyone also
contemplating doing link up.
Keeping the two gameboys in sync is the most difficuly things to do as the
vblanks are almost always different.
A few things to bear in mind:
* Always delay the data by one frame. This gives an entire frame for
transfer to occur which is good if one machine is behind.
* Strangely, on performing a serial transfer (SC register set to $81) the
serial interrupt occurs on the master first and then the slave.
* On peforming a transfer and no machine is linked then SB will be $FF
* On peforming a transfer and a machine is linked but swiched OFF then SB
will be $0 (must be due to ground pin)
* On peforming a transfer and a machine is linked but slave is in an
interrupt then SB will be $FF
* Keep all interrupt code as short as possible.
* Be careful when using AC adaptors on gameboy Pockets as this sometimes
causes interference on the serial port.
If anyone is interested I may make my serial link code for GBDK(but using
asm for interrupts) public.
Hopefully this info helps someone at there in Game Boy land.......
Cheers
Ian.

View File

@@ -1,65 +0,0 @@
Memory Bank Controller (MBC) 3 for GameBoy Information
by bRILLO hEAD, 1-Jan-98
THe MBC3 is a memory controller for GameBoy that supports
ROMs up to 16megabits (2megabytes) and RAM up to 256kbits
(32kbytes). It has a built-in clock counter that requires
an external 32.768KHz crystal for operation.
Reg 0 - $0000-$1fff - RAM/clock write protect
$0A - Enable
$00 - Disable
Reg 1 - $2000-$3fff - ROM Bank Select
$00-$7F - Rom bank #
Reg 2 - $4000-$5fff - RAM Bank/Clock Reg Select
$00-$03 - RAM bank #
$08-$0c - Clock register #
Reg 3 - $6000-$7fff - Latch clock counter data
Writing $00 and then $01 latches clock data.
Another write $00 and write $01 is required
to latch data again.
Reg SEC - $08 - Seconds counter
Reg MIN - $09 - Minutes counter
Reg HRS - $0A - Hours counter
Reg DAYL- $0B - Lower 8 bits of day counter
Reg DAYH- $0C - bit 0 = Upper 1 bit of day counter
bit 6 = start(0)/stop(1) clock counter
bit 7 = Day counter carry bit
Notes:
Bit 7 of Reg DAYH once set stays set until a 0 is written.
To access the clock counter the ram bank must first be turned
on by writing $0A to Reg 0.
To read the clock counter value, set Reg 3 to $01. This latches
the values of all registers so they won't change on you while your
trying to read them. However, this does not prevent the internal
counters from keeping correct time. If reg 3 is already set to
$01 then write $00 and then $01.
For example, to read Reg SEC write $08 to Reg 2. The value of
Reg SEC can then be read from any address in $A000-$BFFF range.
Use a similar process for writing to a register.
Due to slow MBC3/clock interfacing, 4 machine cycles (16 clock cycles)
are required between register accesses.

View File

@@ -1,294 +0,0 @@
-------------------------------------------------------------------------------------------------------------------------------------------
Multiple CPU Assembly Mnemonic Table v0.1 210299/GPZ-HIT
-------------------------------------------------------------------------------------------------------------------------------------------
Registers:
----------
A : akku
F : flag-register
B,C,D,E,H,L : 8080/z80 registers
X,Y : 6502/6510 index registers
SP : 8080/z80 Stack Pointer
AF,BC,DE,HL : 8080/z80 register pairs
PSW : alias for the AF register pair on 8080
M : alias for the HL register pair on 8080
Flags:
------
Z : zero flag
C : carry flag
H : 8080/z80 half-carry flag (carry from least significant nibble)
N : 6502 negative (sign) flag
8080/z80 substract flag (?!)
Arguments:
----------
x8 : 8 bit constant that is implied with the opcode
p8 : 8 bit Port-Address
r8,r8' : one of the 8 bit registers
r16,r16' : one of the register-pairs/16 bit registers
m8,m8' : 8 bit memory adress or offset (eg zeropage adressing modes)
i8,i8' : 8 bit immediate value
m16,m16' : 16 bit memory adress
i16,i16' : 16 bit immediate value
markers:
--------
~ : opcode doesnt exactly match the comparison
* : opcode is undocumented ('illegal')
-------------------------------------------------------------------------------------------------------------------------------------------
Gameboy note:
-------------
zero-page location: $ff00-$ffff (only $ff80-$ffff useable)
stack-location: set by user, SP after reset: $ffff
opcode-syntax referring to: Rednex Gameboy Development System (asMotor of RGBDS)
6502 note:
----------
since there is no HL register for pointers, absolute memory adresses are used
instead. Also 6502 cpu's dont have the (limited) support for 16-bit stuff like
some other 8 bit cpu's (aka register-pairs) so respective opcodes work in 8 bit
only.
zero-page location: $0000-$00ff (only $0002-$00ff useable)
stack-location: $0100-$01ff (fixed), SP after reset: $01ff
opcode-syntax referring to: Omikron Turbo Assembler (c64)
-------------------------------------------------------------------------------------------------------------------------------------------
8080 Z80 Gameboy(~z80) 6502/6510
------ ------ --------------- -----------
loading/storing data:
---------------------
MVI r8 [i8] LD r8, i8 LD r8, i8 LDA #i8 / LDX #i8 / LDY #i8
MOV r8, r8' LD r8, r8' LD r8, r8' TAX / TXA / TAY / TYA / TXS / TSX
LDA [m8] [m8'] LD A, (m16) LD A, [m16] LDA m16
LDAX B LD A, (BC) LD A, [BC] -
LDAX D LD A, (DE) LD A, [DE] -
LHLD [m8] [m8'] LD HL, (m16) LD HL, [m16] -
LXI B [i8] [i8'] LD BC, i16 LD BC, i16 -
LDID [i8] [i8'] LD DE, i16 LD DE, i16 -
LXI H [i8] [i8'] LD HL, i16 LD HL, i16 -
STA [m8] [m8'] LD (m16), A LD [m16], A STA m16
SHLD [m8] [m8'] LD (m16), HL LD [m16], HL -
STAX B LD (BC), A LD [BC], A -
STAX D LD (DE), A LD [DE], A -
MOV M, r8 LD (HL), r8 LD [HL], r8 -
MOV r8, M LD r8, (HL) LD r8, [HL] -
MVI M [i8] LD (HL), i8 LD [HL], i8 -
store via HL and inc. HL - - LDI [HL],A -
load via HL and inc. HL - - LDI A,[HL] -
store via HL and dec. HL - - LDD [HL],A -
load via HL and dec. HL - - LDD A,[HL] -
load from zeropage - - LDH A,[$ff00+m8] LDA $00+m8
store to zeropage - - LDH [$ff00+m8],A STA $00+m8
load indexed from zeropage - - LD A,[$ff00+C] LDA $00,Y
store indexed to zeropage - - LD [$ff00+C],A STA $00,Y
logical instructions:
---------------------
logical AND ANA M AND (HL) AND [HL] ~AND m16
" ANA r8 AND r8 AND r8 -
" ANI [i8] AND i8 AND i8 AND #i8
logical OR ORA M OR (HL) OR [HL] ~OR m16
" ORA r8 OR r8 OR r8 -
" ORI [i8] OR i8 OR i8 ORA #i8
logical EXCLUSIVE OR XRA M XOR (HL) XOR [HL] ~EOR m16
" XRA r8 XOR r8 XOR r8 -
" XRI [i8] XOR i8 XOR i8 EOR #i8
arithmetic instructions:
------------------------
dec. byte in memory - - DEC [HL] ~DEC m16
dec. register DCR r8 DEC r8 DEC r8 DEX / DEY
dec. register-pair DCX B DEC BC DEC BC -
" DCX D DEC DE DEC DE -
" DCX H DEC HL DEC HL -
inc. byte in memory INR M INC (HL) INC [HL] ~INC m16
inc. register INR r8 INC r8 INC r8 INX / INY
inc. register-pair INX B INC BC INC BC -
" INX D INC DE INC DE -
" INX H INC HL INC HL -
add with carry ACI [i8] ADC A, i8 ADC A, i8 ADC #i8
" ADC M ADC A, (HL) ADC A, [HL] ~ADC m16
" ADC r8 ADC A, r8 ADC A, r8 -
add ADD M ADD A, (HL) ADD A, [HL] ~CLC ; ADC m16
" ADD r8 ADD A, r8 ADD A, r8 -
" ADI [i8] ADD A, i8 ADD A, i8 CLC ; ADC #i8
" DAD B ADD HL, BC ADD HL, BC -
" DAD D ADD HL, DE ADD HL, DE -
" DAD H ADD HL, HL ADD HL, HL -
substract with carry SBB M SBC A, (HL) SBC A, [HL] SBC m16
" SBB r8 SBC A, r8 SBC A, r8 -
" SBI [i8] SBC A, i8 SBC A, i8 SBC #i8
substract SUB M SUB (HL) SUB [HL] ~SEC ; SBC m16
" SUB r8 SUB r8 SUB r8 -
" SUI [i8] SUB i8 SUB i8 SEC ; SBC #i8
compares:
---------
comp. with memory CMP M CP (HL) CP [HL] ~CMP m16
comp. with register CMP r8 CP r8 CP r8 -
comp. with immediate byte CPI [i8] CP i8 CP i8 CMP #i8
bit-shifts:
-----------
shift left with Carry RAL RLA RLA ROL A
" - - RL r8 -
shift right with Carry RAR RRA RRA ROR A
" - - RR r8 -
shift left - - SLA ASL A
shift right - - SRL LSR A
RLC RLCA RLCA -
- - RLC r8 -
RRC RRCA RRCA -
- - RRC r8 -
- - SRA -
misc operations on registers:
-----------------------------
Complement A CMA CPL CPL EOR #$ff
Decimal Adjust A DAA DAA DAA -
Swap low and high nibble - - SWAP r8 -
exchange DE and HL XCHG EX DE, HL - -
setting/resetting flags:
------------------------
Set Carry Flag STC SCF SCF SEC
Clear Carry Flag STC ; CMC SCF ; CCF SCF ; CCF CLC
Complement Carry Flag CMC CCF CCF -
far branch:
-----------
jump to address JMP [m8] [m8'] JP m16 JP m16 JMP m16
jump indirekt via pointer PCHL JP (HL) JP [HL] ~JMP (m16)
far conditional branch:
-----------------------
branch if Z==1 JZ [m8] [m8'] JP Z, m16 JP Z, m16 BNE *+3 ; JMP m16
Z==0 JNZ [m8] [m8'] JP NZ, m16 JP NZ, m16 BEQ *+3 ; JMP m16
C==1 JC [m8] [m8'] JP C, m16 JP C, m16 BCC *+3 ; JMP m16
C==0 JNC [m8] [m8'] JP NC, m16 JP NC, m16 BCS *+3 ; JMP m16
JM [m8] [m8'] JP M, m16 - -
JP [m8] [m8'] JP P, m16 - -
JPE [m8] [m8'] JP PE, m16 - -
JPO [m8] [m8'] JP PO, m16 - -
near conditional branch:
------------------------
branch if Z==1 - - JR Z, m16 BEQ m16
Z==0 - - JR NZ, m16 BNE m16
C==1 - - JR C, m16 BCS m16
C==0 - - JR NC, m16 BCC m16
- - - -
- - - -
- - - -
- - - -
subroutine call:
----------------
CALL [m8] [m8'] CALL m16 CALL m16 JSR m16
conditional subroutine call:
----------------------------
call if Z==1 CZ [m8] [m8'] CALL Z, m16 CALL Z, m16 BNE *+3 ; JSR m16
Z==0 CNZ [m8] [m8'] CALL NZ, m16 CALL NZ, m16 BEQ *+3 ; JSR m16
C==1 CC [m8] [m8'] CALL C, m16 CALL C, m16 BCC *+3 ; JSR m16
C==0 CNC [m8] [m8'] CALL NC, m16 CALL NC, m16 BCS *+3 ; JSR m16
CM [m8] [m8'] CALL M, m16 - -
CP [m8] [m8'] CALL P, m16 - -
CPE [m8] [m8'] CALL PE, m16 - -
CPO [m8] [m8'] CALL PO ,m16 - -
subroutine return:
------------------
RET RET RET RTS
conditional subroutine return:
------------------------------
return if Z==1 RZ RET Z RET Z BNE *+1 ; RTS
Z==0 RNZ RET NZ RET NZ BEQ *+1 ; RTS
C==1 RC RET C RET C BCC *+1 ; RTS
C==0 RNC RET NC RET NC BCS *+1 ; RTS
RM RET M - -
RP RET P - -
RPE RET PE - -
RPO RET PO - -
interupt related instructions:
------------------------------
set irq flag (irq's off) DI DI DI SEI
clear irq flag (irq's on) EI EI EI CLI
issue a hard irq RST RST x8 RST x8 BRK
i/o specific:
-------------
Get Byte from In-Port IN [p8] IN A, (p8) - -
Send Byte to Out-Port OUT [p8] OUT (p8), A - -
stack related:
--------------
put reg. on Stack PUSH B PUSH BC PUSH BC -
PUSH D PUSH DE PUSH DE -
PUSH H PUSH HL PUSH HL -
PUSH PSW PUSH AF PUSH AF PHA ; PHP
get reg. from Stack POP B POP BC POP BC -
POP D POP DE POP DE -
POP H POP HL POP HL -
POP PSW POP AF POP AF PLP ; PLA
load Stack Pointer LXI SP [i8] [i8'] LD SP, i16 LD SP, i16 LDX #i8 ; TXS
SPHL LD SP, HL LD SP, HL -
- - LD [m16], SP -
- - LD HL,SP+n -
dec. Stack-Pointer DCX SP DEC SP DEC SP TSX ; DEX ; TXS
inc. Stack-Pointer INX SP INC SP INC SP TSX ; INX ; TXS
DAD SP ADD HL, SP ADD HL, SP -
add to Stack-Pointer - - ADD SP, i8 TSX ; TXA ; CLC ; ADC #i8 ; TAX ; TXS
XTHL EX (SP), HL - -
misc:
-----
No Operation (Delay) NOP NOP NOP NOP
halt operation (until irq) HALT HLT HLT *JAM
stop cpu (until exception) - - STOP *JAM
-------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -1,462 +0,0 @@
Super GameBoy Commands, Extracted by kOOPa, 15-Feb-98
-----------------------------------------------------
Last updated by: Bowser, 13-June-98
Updates:
Block Area mode ($04) control codes updated
Line mode ($05) written
Divide mode ($06) written
1CHR mode ($07) written
A SGB command transfer is 128 bits + a zero bit. The first five
bits of the first byte is the command byte. The last 3 bits of
the first byte represent the number of 128 bit packages to be
sent. Unused bits in a SGB command transfer should be set to 0.
Most of the commands listed below only transfer one package.
The command bytes below are preceded by the # character to remind
you that they have to be shifted left three times before used.
Palettes
--------
There are several different types of palettes in the SGB.
One type is the System color palette. It is a virtual palette
rather than a hardware palette. The hardware color palette
is shown at the bottom of this document and contains what
are called the SGB color palettes and also holds the SGB Border
palette.
As far as SGB onscreen colors are concerned there are
only really two palette types: SGB color palettes and
the SGB border palette.
The SGB border palette is setup using command $14.
There are 64 colors in this palette.
The SGB color palettes may be set directly using
commands $00-$03. There are a total of four of
these palettes and they determine which colors are
used in the main game action window. The color for
bit 00 will be the same for all SGB color palettes.
The color most recently stored in bit 00 will be used.
The SGB color palettes may be set indirectly using
the System color palettes using commands $0a-$0b.
There are a total of 512 of these palettes.
SGB Border
----------
The SGB border is often shown as colorful graphics that
surround the main game action window. The truth is that the
SGB border actually covers the whole viewing screen and
has the highest viewing priority. The reason it appears be
just a "border" around most games is due to the fact that
usually a 160x144 pixel wide box is drawn in the center of
the SGB "border" using color 0. Since this color is
transparent, the main game action window under it is visible.
Creating a program to convert a 16-color GIF to a SGB
border is relatively easy and has been done for DOS.
(i.e.gif2sopt.exe) What is not so easy is converting a
64-color GIF to a SGB border because each tile only has
access to 16-colors. The 16-color palette that the tile
has access to is determined by the tile attribute byte.
The tile attribute byte is described in the 'Picture
Transfer' command ($14) below.
Main Action Window
------------------
The SGB cartridge that plugs into the SNES contains
a GB CPU. The SNES is able to video capture the video
output of this GB CPU and display it on the screen as
the main game action window. Since the SNES is only
doing a raw video capture it only knows about 4 levels
of grey coming from the GB CPU. In order to add more
than 4 colors to the main game action window, the SGB
software allows you to assign 1 of the 4 SGB color
palettes for each 8x8 tile position in this window.
"Block"($4), "Line"($5), "Divide"($6), "1Chr"($7),
and "Set Attr from ATF"($15) all are different means
for setting the palettes for each 8x8 tile location.
On reset, each 8x8 tile position defaults to SGB
color palette 0.
Commands $4-$7 are various methods for block-setting
the 8x8 tile color palettes. The "Set Attr from ATF"
($15) allows you to select 1 of 45 "ATtribute Files".
Each "ATtribute File" contains 90 bytes (20x18x2 bits).
By selecting an "ATtribute File", you can exactly
select 1 of 4 SGB color palettes for each 8x8 tile
location due to the fact that these files contain
2 bits of information for each 8x8 tile location.
Commands
--------
Set SGB color Palettes
0 & 1 ($00,data) - Download color palettes 0 & 1
2 & 3 ($01,data) - Download color palettes 2 & 3
0 & 3 ($02,data) - Download color palettes 0 & 3
1 & 2 ($03,data) - Download color palettes 1 & 2
--------------------------------------------------
Here is example data for setting SGB color palettes 0 & 1:
DW $7fff ;white ;bit 00 color
;Pallete 0
DW $7c00 ;blue ;bit 01 color
DW $03e0 ;green ;bit 10 color
DW $0000 ;black ;bit 11 color
;Palette 1
DW $03ff ;yellow ;bit 01 color
DW $001f ;red ;bit 10 color
DW $0000 ;black ;bit 11 color
Please note that all four SGB color palettes share the
same bit 00 color. The color most recently stored in
bit 00 will be used.
Information for calculating the DW color value is given later
in this text.
When using the following four Palette Direct Set commands,
the GameBoy image will be altered (colors changed) even if
you used the GameBoy Window Mask command to freeze the screen.
Therefore use arguments Black or White with the Window Mask
command before using the following four commands. If you want
to freeze the screen, send palette data with the Attribute
File ATF0-ATF44. In the event you are changing the screen by
sending attribute data and color data at the same time, use
Set SGB Palette Indirect command.
"Block" Area Designation Mode ($04) (other data shown below)
-----------------------------------------------------------
$00 - %00100xxx xxx = # of packets
$01 - %///xxxxx xxxxx = # of data sets - One data set is control
code, color palette designation, & the coords.
$02 - %/////xxx xxx = Control code
000 = don't care
001 = set pal (inside block + surrounding block line) to 'zz' of $03
010 = set pal of surrounding block line to 'yy' of $03
011 = set pal inside block to 'yy' & surrounding block line to 'yy'
100 = set pal outside the block to 'xx'
101 = set pal inside to 'zz' & outside the block to 'xx'
110 = set pal outside the block to 'xx'
111 = set pal inside block tp 'zz' + surrounding line to 'yy' + outside block to 'xx'
$03 - %//xxyyzz Color Palette Designation
xx = color palette outside surrounded area
yy = color palette on surrounding block line
zz = color palette inside surrounded area
$04 - %///xxxxx xxxxx = start point H
$05 - %///xxxxx xxxxx = start point V
$06 - %///xxxxx xxxxx = end point H
$07 - %///xxxxx xxxxx = end point V
$08-$0d Repeat of $02-$07 data if # of data sets > 1.
If number of packets is 1, set $0e & $0f to $00.
"Line" Area Designation Mode ($05)
----------------------------------
$00 - %00101xxx xxx = # packets
$01 - %xxxxxxxx number of data sets ($1 - $6E), one data set controls:
code, colours palette designation, and coords.
$02 - %xyyzzzzz control code 1'st data set
x = Mode (0 = Horizontal line, 1 = Vertical line)
yy = Palette number
zzzzz = Line number
One dataset is 1 byte just as $02.
If # data sets = 1, fill with 0's up to $0F
"Divide" Area Designation Mode ($06)
-----------------------------------
$00 - %00101001 (number of packets must be 1)
$01 - %/vxxyyzz control code
v = Mode (0 = divide horizontally, 1 = Divide vertical)
xx = Colour palette ON division line
yy = Colour palette ABOVE & LEFT of division
zz = colour palette BELOW & RIGHT of division
$02 - %///xxxxx xxxxx = Character line number to divide at
fill with 0's to $0F
"1CHR" Area Designation Mode ($07)
----------------------------------
$00 - %00111xxx xxx = number of packets ($01 - $06)
$01 - %///xxxxx Beginning X coordinate
$02 - %///yyyyy Beginning Y coordinate
$03 - %xxxxxxxx Number of datasets, 2 bits = 1 dataset
$04 - %///////x MSB of data in $03. Max number = 360.
$05 - %///////x Writing style ( 0 = Left -> right, 1 = up -> down)
$06 - %vvxxyyzz data
vv = pal for dataset 1
xx = pal for dataset 2
yy = pal for dataset 3
zz = pal for dataset 4
$07 - %vvxxyyzz data
etc...
Sound On/Off ($08)
------------------
Transfer Sound PRG/DATA ($09)
-----------------------------
This transfers your score (in .GAK format) data.
Set SGB Palette Indirect ($0a)
------------------------------
Set System Color Palette Data ($0b)
-----------------------------------
Enable/Disable Attraction Mode ($0c)
------------------------------------
Speed Function ($0d)
--------------------
SGB Function ($0e)
------------------
Super NES WRAM Transfer 1 ($0f)
-------------------------------
Super NES WRAM Transfer 2 ($10)
-------------------------------
Controller 2 Request (#11) ($00) - Request 1 play
-------------------------------------------------
Controller 2 Request (#11) ($01) - Request 2 play
-------------------------------------------------
Is used to determine if system is SGB or regular GB.
Set Program Counter ($12)
-------------------------
CharSet Transfer ($13) (%00000xyy)
(x=Char Type:0=BG,1=OBJ y=CharSet Range:0=00-7f,1=80-ff)
-----------------------------------------------------------
The tiles that are downloaded to the SNES for the border
are regular GB tiles that have been modified for extra colors.
Every tile consists of 32 bytes. The format is:
16 bytes - Standard 4 color GB character set
16 bytes - Extended color information
The same way GB uses two bytes to convey 8 pixels
and the 4 colors for each pixel, the extended color
info uses the same technique for determining extended
colors. This tells the SNES which color palette to
use to display each pixel. This allows a total of 16
colors per tile. Since SGB borders support up to 64 colors,
access to the other colors are achieved by changing the
Major palette number in the picture transfer tile map.
Picture Transfer ($14) - Download border to SNES.
------------------------------------------------
The border (or tile map) that is downloaded is 32x28 tiles
or 256x224 pixels. The regular GB screen fits right in the
middle like this:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXX....................XXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The tile map consists of a tile number byte & a tile attribute
byte at each position on the map. A total of 32 lines are
downloaded even though the last 4 lines are not visible. This
would equal 64 bytes per line and a total of 2048 bytes per map.
Next, a 64 x 2 byte color palette for the map is downloaded.
The first palette entry color is transparent. Use this color
to display regular GB screen underneath.
The tile number comes before the tile attribute of each position.
There can be up to 1024 tiles from which to select. The SGB only
supports 256 so bits 0 & 1 of the tile attribute must be set to 0.
Here are the tile attributes I understand so far:
Bit 7 - Vertical flip tile
Bit 6 - Horizontal flip tile
Bit 5 - Does nothing (Set to 0.)
Bit 4 - Select Major Palette MSB (Usually set to 1.)
Bit 3 - Select Major Palette -
Bit 2 - Select Major Palette LSB
Bit 1 - Tile # MSB (Most significant bit) (Set to 0.)
Bit 0 - Tile # NSB (Next most significant bit) (Set to 0.)
This is often called the SGB border but in fact it covers
the whole SNES screen. The Major Palette select has 8
different settings. Only the last 4 - 7 are normally used
thought to access all 64 colors transfered with cmd (#14).
(NOTE: If using 'gif2sopt.exe' to generate a border, the
range of the palette selections is 1-8 so select palette
5 since that program only allows up to 16 colors.)
Set Attribute from ATF ($15)
----------------------------
The data for 45 Attribute files is transfered with
this command. Each ATtribute File is 90 bytes so
90x45 or 4050 bytes of data are transfered. Each
attribute file uses 5 bytes per 8x8 horizontal
line (20 x 4 char/byte x 2 bits/palette) to
describe the color palettes of a line.
Example ATF data:
DB $ff,$00,$00,$00,$02 ; Line #1
DB $ff,$00,$00,$00,$02 ; Line #2
DB $ff,$00,$00,$00,$02 ; Line #3
.....
DB $ff,$00,$00,$00,$02 ; Line #18
The above ATtribute File would set the SGB color
palette selection to 3 for the first 4 columns
of the main game action window. The last column
would have SGB color palette 2 selected. All the
other columns would have palette 0 selected.
Set Data from ATF ($16) (data)
------------------------------
Transfer specified ATtribute File to GameBoy window.
data:
%/xyyyyyy x - 0 = No Change, 1 = Cancel mask after xfer ATF
yyyyyy = ATtribute File number ($00-$2c)
GameBoy Window Mask ($17) (data)
--------------------------------
data:
$00 = Off
$01 = Transfers VRAM to SNES until cancelled.
$02 = Mask so that all color codes in SGB
color palette are black.
$03 = Mask so that all color codes in SBG
color palette are white.
Super NES OBJ Mode ($18)
------------------------
SNES Color Palette Info
-----------------------
The Nintendo Super Famicom is capable of displaying 256 colors from a
palette of 32,768. These 256 colors are split into 16 palettes of 16 colors
each. Only 8 of these palettes are accessible by the SGB.
Color data is made up of 3 components (Red,Green,Blue) each of 5 bits (The
Amiga uses exactly the same system, but only using 4 bits per component).
00000 00000 00000
\ / \ / \ /
\ / \ / \ /
B G R
Examples:
~~~~~~~~~
00000 10111 11100
11111 00000 00000 = $7C00 (Bright Blue)
00000 11111 00000 = $03E0 (Bright Green)
00000 00000 11111 = $001F (Bright Red)
00000 00000 00000 = $0000 (Black)
11111 11111 11111 = $7FFF (White)
SGB Palette Selection
---------------------
There is actually only one color palette in the SNES
but it is divided up into several sections for different
SGB functions. These sections are referred to as Major (M)
sections 0-7. Some SGB functions even divided some of these
sections into sections. These sections are referred to as
minor (m) sections. The large blocks below represent Major
sections or palettes and smaller ones below them represent
minor palettes. There are 4 colors per minor palette and
16 colors per Major palette:
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+-------+-------+-------+-------+-------+-------+-------+-------+
|0|1|2|3| ^ ^
+-------+ | |
^ ^ +--------------+--------------+
+--+--+ |
| |
Set with Commands Set with 64 colors in Picture Transfer (#14)
#00,#01,#02, & #03 (holds SGB Border colors)

View File

@@ -1,67 +0,0 @@
Spare GBC Sprite RAM
written by GeeBee
Thanks to tips from Shawn Freeman about there being
an area that you can read/write from $fea0-$feff on
the GBC I decided to research further and came up with
the following info.
In theory the following information could also be used
to detect emulators since none of them currently accurately
emulate this RAM as far as I know.
The following RAM seems to be spare in the GBC and not
read/written by the GBC itself. I'll add this info to
the FAQs soon.
Spare GBC Sprite RAM
--------------------
1. There are 3 sets of 8 bytes of
RAM available or 24 bytes total.
This RAM is only available on the
GBC and not on any of the older GBs.
Set #1 $fea0-$fea7
Set #2 $fec0-$fec7
Set #3 $fee0-$fee7
2. Each set is repeated 4 times in
the following address spaces:
$fea0-$febf
$fec0-$fedf
$fee0-$feff
3. If you read/write any of the
repeated data sets you will read/write
the original data set itself. i.e. All
repeated data bytes serve as echo RAM.
4. Reading/writing of this RAM is only
reliable in video modes 0 & 1. As a result,
it is best to wait for vblank to reliably
read/write this area.
Example data:
fea0 00 01 02 03 04 05 06 07
fea8 00 01 02 03 04 05 06 07
feb0 00 01 02 03 04 05 06 07
feb8 00 01 02 03 04 05 06 07
fec0 10 11 12 13 14 15 16 17
fec8 10 11 12 13 14 15 16 17
fed0 10 11 12 13 14 15 16 17
fed8 10 11 12 13 14 15 16 17
fee0 80 81 82 83 84 85 86 87
fee8 80 81 82 83 84 85 86 87
fef0 80 81 82 83 84 85 86 87
fef8 80 81 82 83 84 85 86 87

View File

@@ -1,28 +0,0 @@
Timer Interrupt Document
Written by Jonathan Waugh
There are 2 registers you need to set to use the timer interrupt:
1) $FF07 (TAC) selects the clock frequency. You set it to 4 for a frequency of 4.096Khz
But this is not when the interrupt occurs. It determines when the TIMA ($FF05) is incremented.
ie. In your example, the TIMA is incremented 4096 times a sec.
The interrupt occurs when the TIMA generates an overflow. ie goes from 255 -> 0
2) $FF06 (TMA) sets the starting point for the TIMA register.
If you set it to 255 (-1), a timer interrupt would occur at the clock frequency. (4096Hz)
If you set it to 240 (-16), a timer interrupt will occur at the clock frequency /16 (256Hz)
It follows that the largest time interval you can get via the timer interrupt is 16Hz. Clock = 4096Hz, TMA = 0 (-256)
To get a delay of 2 secs, you will have to wait for 32 timer interrupts.
Option: Set up your own variable that counts down from 32. When it reaches 0, reset to 32 and process your interrupt code.