ChibiAkumas Tutorials
|
Lesson P4 - Bitmap Functions on the Atari Lynx |
Lesson P13 - Joystick Reading on the Atari Lynx | |
Lesson P19 - Palette definitions on the Atari Lynx | |
Lesson P24 - Sound on the Atari Lynx | |
Memory Map
From
|
To
|
Use |
$0000 | $00FF | Zero Page |
$0100 | $01FF | Stack |
$0200 | $FBFF | Program RAM |
$FC00 | $FCFF | Suzy |
$DF00 | $FDFF | Mikey |
$FE00 | $FFF7 | ROM |
$FFFA | $FFFB | NMI Address |
$FFFC | $FFFD | Reset Address |
$FFFE | $FFFF | IRQ Address |
While real cartridges are encrypted (causing copyright problems
for the hobbyist), the Handy emulator can work with an unencrypted O
file... this also means we do not need an official rom to run the
emulator! There is a 10 byte header... FixedBytes:Many of the bytes are fixed, and should not be changed StartPoint: Bytes 2 and 3 are the startpoint in Big Endian format.. . in our example the first program byte is $0300 Length: Bytes 4 and 5 are the length of the file. |
Sprites can be 'Literal' (plain bmp) or 'RLE compressed' (defined
by bit 7 of byte two of the SCB - SCBCTL1).... the colordepth is
defined in SPRCTL0 (See later) Each line of a sprite starts with a byte - this an offset to the next line... effectively the number of bytes in the line +1 .... effectively the pointer to the next line. 1 or 0 in this position have special meanings!... 0 means the end of the sprite... 1 means the end of the 'quardrent'... note this is optional! Akusprite does not use it! Quadrent rendering is where the sprite is drawn in 4 sections from the middle... with a 1 byte marking each 1/4 of the sprite... (followed by another 'offset to next line' byte) the first quadrent is DownRight (default)... the second quadrent is UpRight the third quadrent is UpLeft)... the fourth quadrent is DownLeft Apparently there is a bug in the hardware - the last bit of each line must be 0! - we should always have a 0 at the end of our sprites to counter it - color 0 is transparent anyway! You can see a Literal Sprite to the right... the Literal bitmap data is in green, and the header bytes are in cyan |
Literal
Sprite Example (BMP) LynxSprite: db $8, $11, $11, $11, $11, $11, $10,0 db $8, $10, $0, $0, $0, $0, $10,0 db $8, $10, $04, $44, $44, $0, $10,0 db $8, $10, $04, $3, $04, $0, $10,0 db $8, $10, $04, $3, $04, $0, $10,0 db $8, $10, $04, $44, $44, $0, $10,0 db $8, $10, $0, $0, $0, $0, $10,0 db $8, $11, $11, $11, $11, $11, $10,0 db 0 |
RLE Sprite
Data is a bit more tricky.... The first byte in a line is again an offset to the next line as before The next BIT will be a 'block definition'... defining what the following data is... 1 marks that the next data will be LITERAL 0 marks that the next data will be RLE The next 4 bits will be the number of pixels to draw-1... so 0 means 1 pixel, and 15 means 16 pixels... we will call this N If the block is RLE the next 1/2/3/4 bits (depending on bitdepth) will be used for the color to fill the next N pixels If the block LITERAL the next N *(1/2/3/4) bits (depending on bitdepth) will be used for the color of the next N pixels the next bit will be the next 'block definition'... this pattern repeats until the line is done. |
4bpp
RLE Sprite Example db $8 (offset to next line) db %01111000,%00000000 (RLE block...16 pixels... Color 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) db %00001001,%10000000 (RLE block...2 pixles... Color 3,3) db %10010000,%10010001,%10000000 (Literal block...3 pixels... Color 1,2,3) (next line starts here) |
The sprite control block defines the
sprite onscreen, The first two bytes define the sprite type, how
it's drawn, and the other data in the block... note if RR<2
we don't need the Scale or Tilt words... so these can be
removed. SPRCTL0 bits 7,6 defines the Colordepth 1/2/3/4 bits per pixel for 2/4/8/16 colors SPRCTL1 bit 7 defines the sprite type 1=Literal... 0=RLE Note... if you have the BPP wrong on a RLE sprite it will be a total mess... a Literal sprite would just be stretched and a bit weird! (colors would be sort of 'dithered') The Xpos and Ypos are relative to the defined screen boundaries... Wid and Hei are scales $100=100% $200=200% The 'Palette' maps each 'color' in the sprite to a palette setting... this is most useful for 1/2bpp sprites - where we will need to select the colors each combination of bits will use. the example shown is a 4bpp 16 color sprite |
SCB: ;BBHV-TTT - SPRCTL0... B=bits per pixel H=hflip V=vflip T=type (7=normal) db %11000101 ;LSRRPSUl - SPRCTL1... L=Literal S=Sizing choice (0 only!) RR=Reloadable depth (1=Use Size 3=Use Size,ScaleTilt) db %10010000 ;P=Palette reload (0=yes) s=skipsprite u=draw up l=draw left db 0 ;- SPRCOL - 0= OFF dw 0 ;Next SCB (0=none) dw LynxSprite ;Sprite pointer dw 10 ;Xpos dw 10 ;Yos dw $200 ;Wid ($100 = 100%) dw $200 ;Hei ($100 = 100%) ; dw 0 ;Scale - not needed if B4,B5 of SPRCTL<3 ; dw 0 ;Tilt - not needed if B4,B5 of SPRCTL<2 ;Palette - maps nibbles to colors (useful for <4 bpp) db $01,$23,$45,$67,$89,$AB,$CD,$EF |
Lets Draw a sprite... if our visible
screen is at &C000 - the following will work! Note when setting 16-bit Suzy values, we must set the LSB before the MSB... A write to the LSB will ZERO the MSB automatically... so if we set FC09 first in this example it WILL NOT WORK! |
lda #$0
;MUST SET LSB FIRST! ;WRITE TO LSB will ZERO MSB sta $FC08 ;For sprites lda #$C0 ;Set screen ram pointer to $C000 sta $FC09 ;For sprites lda #<(SCB) sta $fc10 ldy #>(SCB) sty $fc11 lda #$5 ; 1 SprStart + 4 Everon sta $FC91 ;SPRGO sta $FD90 ;SDONEACK WaitSuzy: stz $FD91 ;CPUSLEEP lda $fc92 ;DISPCTL lsr bcs WaitSuzy stz $FD90 ;SDONEACK |
If we want our sprites to clip at the top left, we can set a
screen offset - for example to set an offset of 8: |
LDA #8 STA $FC04 ;SCR OFFSET STA $FC06 ;SCR OFFSET |
From | To | Name | Description | Bits | Meaning |
FC00 | FC01 | TMPADRL | Temporary Address LH | ||
FC02 | FC03 | TILTACUM | Accumulator for tilt value LH | ||
FC04 | FC05 | HOFF | Offert to H edge of screen | ||
FC06 | FC07 | VOFF | Offert to V edge of screen | ||
FC08 | FC09 | VIDBAS | Base address of video build buffer | ||
FC0A | FC0B | COLLBAS | Base address of Coll build buffer | ||
FC0C | FC0D | VIDADRL | Current Video Build Addres | ||
FC0E | FC0F | COLLARL | Current Collision Build Address | ||
FC10 | FC11 | SCBNEXT | Address of next SCB | ||
FC12 | FC13 | SPRDLINE | Start of Sprite Data Line Address | ||
FC14 | FC15 | HPOSSTRT | Starting Hpos | ||
FC16 | FC17 | VPOSSTRT | Starting Vpos | ||
FC18 | FC19 | SPRHSIZ | Hsize | ||
FC1A | FC1B | SPRVSIZ | Vsize | ||
FC1C | FC1D | STRETCH | H Size Adder | ||
FC1E | FC1F | TILT | H Position Adder | ||
FC20 | FC21 | SPRDOFF | Offset to next sprite data line | ||
FC22 | FC23 | SPRVPOS | Current Vpos | ||
FC24 | FC25 | COLLOFF | Offset to collision depository | ||
FC26 | FC27 | VSIZACUM | Vertical Size Accumulator | ||
FC28 | FC29 | HSIZOFF | Horizontal size offset | ||
FC2A | FC2B | VSIZOFF | Vertical Size Offeet | ||
FC2C | FC2D | SCBADR | Address of current SCB | ||
FC2E | FC2F | PROCADR | Current Spr data Proc Address | |
|
FC80 | FC80 | SPRCTRL0 | BBHV-TTT | B=bits per
pixel H=hflip V=vflip T=type (7=normal) |
|
FC81 | FC81 | SPRCTRL1 | LSRRPSUl | L=Literal S=Sizing choice (0 only!) RR=Reloadable depth P=Palette reload (0=yes) s=skipsprite u=draw up l=draw left |
|
FC82 | FC82 | SPRCOLL | |||
FC83 | FC83 | SPRINT | |||
FC88 | FC88 | SUZYHrev | Suzy Hardware Revision R | ||
FC89 | FC89 | SUZYHrev | Suzy Hardware Revision W | ||
FC90 | FC90 | SUZYBUSEN | Suzy bus enable FF | ||
FC91 | FC91 | SPRGO | Sprite Process start bit | ---E-S | S=Sprites on E=Everon detector(?) |
FC92 | FC92 | SPRSYS | System Cotrlol Bits (RW) | ||
FCB0 | FCB0 | JOYSTICK | Read Joystick and Switches | UDLR12IO | |
FCB1 | FCB1 | SWITCHES | Read other switches | -----CCP | |
FCB2 | FCB3 | RCART | Rcart (RW) | ||
FCC0 | FCC0 | LEDS | Leds (W) | ||
FCC2 | FCC2 | PPT | Paralell port Status RW | ||
FCC3 | FCC3 | PPT DATA | Paralell port Data RW | ||
FCC4 | FCC4 | Howie | Howie (RW) | ||
FD00 | TIM0BKUP | HTIMBKUP Timer 0 backup value (Hblank) | Count +1 | ||
FD01 | TIM0CTLA | HTIMCTL0 Timer 0 static control (Hblank) | ID-RCSSS | I=enable Interrupt, D=Reset Timer Done R=enable Reload C enable Count S=Clock Select | |
FD02 | TIM0CNT | Timer 0 current count (Hblank) | Timer Current Value | ||
FD03 | TIM0CTLB | Timer 0 dynamic control (Hblank) | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD04 | TIM1BKUP | MAGA Timer 1 backup vatue | Count +1 | ||
FD05 | TIM1CTLA | Timer 1 static control | IDMRCSSS | I=enable Interrupt, D=Reset Timer Done M=Magmode (1,3,5,7 only) R=enable Reload C enable Count S=Clock Select | |
FD06 | TIM1CNT | Timer 1 current count | Timer Current Value | ||
FD07 | TlM1CTLB | Timer 1 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD08 | TlM2BKUP | VTIMBKUP Timer 2 backup value (Vblank) | Count +1 | ||
FD09 | TIM2CTLA | Timer 2 static control (Vblank) | ID-RCSSS | I=enable Interrupt, D=Reset Timer Done R=enable Reload C enable Count S=Clock Select | |
FD0A | TIM2CNT | Timer 2 current count (Vblank) | Timer Current Value | ||
FD0B | TIM2CTLB | Timer 2 dynamic control (Vblank) | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD0C | TIM3BKUP | MAGB Timer 3 backup value | Count +1 | ||
FD0D | TIM3CTLA | Timer 3 static control | IDMRCSSS | I=enable Interrupt, D=Reset Timer Done M=Magmode (1,3,5,7 only) R=enable Reload C enable Count S=Clock Select | |
FD0E | TIM3CNT | Timer 3 current count | Timer Current Value | ||
FD0F | TIM3CTLB | Timer 3 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD10 | TIM4BKUP | BAUDBKUP Timer 4 backup value | Count +1 | ||
FD11 | TIM4CTLA | Timer 4 static control | ID-RCSSS | I=enable Interrupt, D=Reset Timer Done R=enable Reload C enable Count S=Clock Select | |
FD12 | TIM4CNT | Timer 4 current count | Timer Current Value | ||
FD13 | TlM4CTLB | Timer 4 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD14 | TIM5BKUP | MAGC Timer 5 backup value | Count +1 | ||
FD15 | TIMSCTLA | Timer 5 static control | IDMRCSSS | I=enable Interrupt, D=Reset Timer Done M=Magmode (1,3,5,7 only) R=enable Reload C enable Count S=Clock Select | |
FD16 | TIM5CNT | Timer 5 current count | Timer Current Value | ||
FD17 | TIMSCTLB | Timer 5 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD18 | TIM6BKUP | Timer 6 backup value | Count +1 | ||
FD19 | TIM6CTLA | Timer 6 static control | ID-RCSSS | I=enable Interrupt, D=Reset Timer Done R=enable Reload C enable Count S=Clock Select | |
FD1A | TIM6CNT | Timer 6 current count | Timer Current Value | ||
FD1B | TIM6CTLB | Timer 6 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD1C | TIM7BKUP | MAGD Timer 7 backup value | Count +1 | ||
FD1D | TIM7CTLA | Timer 7 static control | IDMRCSSS | I=enable Interrupt, D=Reset Timer Done M=Magmode (1,3,5,7 only) R=enable Reload C enable Count S=Clock Select | |
FD1E | TIM7CNT | Timer 7 current count | Timer Current Value | ||
FD1F | TIM7CTLB | Timer 7 dynamic control | ---DLIO | D=timer Done L=Last clock I=borrow In O=borrow Out | |
FD20 | FD20 | Audio Channel 0 � 2�s compliment Volume control | 0-127 |
||
FD21 | FD21 | Audio Channel 0 � Shift register feedback enable | eg %00010000 |
||
FD22 | FD22 | Audio Channel 0 � Audio Output Value (Raw Data) | Eg $80 |
||
FD23 | FD23 | Audio Channel 0 �Lower 8 bits of shift register | Eg 0 |
||
FD24 | FD24 | Audio Channel 0 � Audio Timer Backup Value | eg 0-63 |
||
FD25 | FD25 | Audio Channel
0 � Audio Control Bits |
FTIRCKKK | eg %00011110 |
|
FD26 | FD26 | Audio Channel 0 � Audio Counter | |||
FD27 | FD27 | Audio Channel 0 �Other Audio Bits | Eg 0 | ||
FD28 | FD2F | Audio Channel 1 � Same as Channel 0 |
|||
FD30 | FD37 | Audio Channel 2 � Same as Channel 0 | |||
FD38 | FD3F | Audio Channel 3 � Same as Channel 0 | |||
FD40 | FD40 | ATTENREG0 | LLLLRRRR � Audio Attenuation | ||
FD41 | FD41 | ATTENREG1 | LLLLRRRR � Audio Attenuation | ||
FD42 | FD42 | ATTENREG2 | LLLLRRRR � Audio Attenuation | ||
FD43 | FD43 | ATTENREG3 | LLLLRRRR � Audio Attenuation | ||
FD44 | FD44 | MPAN | Stereo attenuation selection | ||
FD50 | FD50 | MSTEREO | Stereo disable | LLLLRRRR | 0=all on 255=all off |
FD80 | FD80 | INTRST | Interrupt poll 0 | ||
FD81 | FD81 | INTSET | Interrupt poll 1 | ||
FD84 | FD84 | MAGRDY0 | Mag tape Ready Channel 0 | ||
FD85 | FD85 | MAGRDY1 | Mag tape Ready Channel 1 | ||
FD86 | FD86 | AUDI | Audio In | ||
FD87 | FD87 | SYSCTRL1 | |||
FD88 | FD88 | MIKEYHREV | Mikey Hardware Revision R | ||
FD89 | FD89 | MikeySREV | Mikey Software Revision W | ||
FD8A | FD8A | IODIR | Mikey Paralell IO Data direction | ||
FD8B | FD8B | IODAT | Mikey Paralell data | ||
FD8C | FD8C | SERCTL | Serial Control Register | ||
FD8D | FD8D | SERDAT | Serial Data | ||
FD90 | FD90 | SDONEACK | Suzy Done Acknowledge | ||
FD91 | FD91 | CPUSLEEP | Cpu Bus Request Disable | ||
FD92 | FD92 | DISPCTL | Video Bus Request Enable | ||
FD93 | FD93 | PBKUP | Magic P count | ||
FD94 | FD95 | DISPADR | Display Address LH | LLLLLLLL HHHHHHHH | Address of video screen |
FD9C | FD9C | MTEST0 | |||
FD9D | FD9D | MTEST1 | |||
FD9E | FD9E | MTEST2 | |||
FDA0 | FDAF | Green � Colors (0-15) | 0000GGGG | ||
FDB0 | FDBF | Blue/Red � Colors (0-15) | BBBBRRRR | ||
FE00 | FFF7 | ROM | |||
FFF9 | Memory Map Control | C---VRMS | C=CPU
Cycles Ram enable: S=Suzy Ram $FC00-$FCFF / M=Mikey $FD00-$FDFF / R=Rom $FE00-$FFF7 V=Vectors ($FFFA-$FFFF) |
||
FFFA | FFFB | CPU NMI Vector | LLLLLLLL HHHHHHHH | ||
FFFC | FFFD | CPU Reset Vector | LLLLLLLL HHHHHHHH | ||
FFFE | FFFF | CPU Interrupt Vector | LLLLLLLL HHHHHHHH |