[atari7800] sample 7800 source code
- From: "Eric Ball" <ek-ball@xxxxxxxxxx>
- To: <atari7800@xxxxxxxxxxxxx>
- Date: Wed, 21 Mar 2007 19:46:13 -0400
This is hopefully the start of a series of 7800 source code skeletons, each
building on the next (or variations on a theme). I'll also put this on the
mailing list for good measure.
This skeleton contains both a simple DLL builder and display list builder.
Nothing fancy, no scrolling backgrounds or wrap-around, not even any error
checking to make sure you don't add too many sprites to a display list. This
is also not a complete program, though I've tried to include almost
everything required. (I've already found one problem, I forgot the5 byte
display list entry to set the write mode.)
YRES EQU 192 ; screen resolution
DLHIGH EQU 16 ; display list height
NUMDL EQU YRES/DLHIGH ; number of display lists
DLLEN EQU
NUMSPR EQU
DLIFLAG DS 1
DLPTR DS 2
DLTEMP DS 1
DLIDX DS NUMDL
SPRYPOS DS NUMSPR ; sprite Y postion, 0 = top
SPRXPOS DS NUMSPR ; sprite X position, 0 = left
SPRIDX DS NUMSPR ; sprite table index
SPRPALW DS NUMSPR ; palette/width
DLNULL DS 2 ; null display list
DLLON DS (NUMDL+4)*3
DL00 DS DLLEN
DL10 DS DLLEN
DL20 DS DLLEN
DL30 DS DLLEN
DL40 DS DLLEN
DL50 DS DLLEN
DL60 DS DLLEN
DL70 DS DLLEN
DL80 DS DLLEN
DL90 DS DLLEN
DLA0 DS DLLEN
DLB0 DS DLLEN
DLC0 DS DLLEN
DLD0 DS DLLEN
DLE0 DS DLLEN
; A flag in each DLL header causes an NMI when MARIA completes DMA for the
; previous zone. This can be used for a variety of things (changing
colours,
; resolutions, scrolling backgrounds). Here it is just used to signal when
; MARIA is done displaying the visible screen so the display lists can be
; updated.
DLLNMI INC DLIFLAG
IRQRTI RTI
; Start routine (stub)
START SEI ; disable IRQ
CLD ; binary arithmetic
LDA #$67
STA INPTCTRL ; lock in 7800 mode
STA CTRL ; disable DMA
LDX #$FF
TXS ; set stack pointer
; Missing: Initialize MARIA/TIA/RIOT registers and zero page variables
; Build the DLL automatically.
CPYDLL LDY #0 ; copy DLL from ROM to RAM
STY DLNULL+1
1$ LDA DLLTOP,Y ; copy top from ROM
STA DLLON,Y
INY
CPY #DLLBOT-DLLTOP
BNE 1$
LDX #0 ; build active screen DLLs
2$ LDA #$4F ; 16 high zone, 4K (16 line) holey DMA
STA DLLON,Y
INY
LDA DLPTRM,X
STA DLLON,Y
INY
LDA DLPTRL,X
STA DLLON,Y
INY
INX
CPX #NUMDL
BNE 2$
LDX #0
3$ LDA DLLBOT,X ; copy bottom from ROM
STA DLLON,Y
INY
INX
CPX #DLLEND-DLLBOT
BNE 3$
; Wait for VBLANK to start, turn on DMA, and fall into the display
; list builder routine.
MSTAT0 BIT MSTAT ; wait for MARIA enabled
BMI MSTAT0
MSTAT1 BIT MSTAT ; wait for MARIA disabled
BPL MSTAT1
LDA #%01000000 ; color, DMA on, single char, black border
STA CTRL ; transparent, 160res
; This is the display list builder which could be considered the kernel of
; a 7800 game. The code takes the X/Y positions (top left) of each sprite,
; figures out which display list they belong it and adds a sprite header to
the
; end of the list. There are several sections to this routine.
;
; DLINI zeros the end of list index
; DLCPY figures out which display list a sprite belongs in (via a
; table lookup of Ypos/16), puts the end of list index in Y,
; copies the data for each sprite into two display lists
; DLFIN writes a zero one byte beyond the end of the current display
; list. This is the null header which tells MARIA it's
; reached the end of the list.
DLINI LDA #0 ; skip over background tile headers
LDX #NUMDL
1$ STA DLIDX-1,X ; reset end of list index
DEX
BNE 1$ ; X = 0
DLCPY LDA SPRYPOS,X ; determine display list
LSR ; Y / DLHIGH
LSR
LSR
LSR
TAY
LDA DLPTRL,Y ; display list lookup table
STA DLPTR
LDA DLPTRM,Y
STA DLPTR+1
LDA DLIDX,Y ; fetch end of list pointer
STY DLTEMP ; save for later
TAY
LDA SPRIDX,X
STA (DLPTR),Y ; low address
INY
LDA SPRPALW,X
STA (DLPTR),Y ; palette + width
INY
LDA SPRYPOS,X
AND #$DLHIGH-1 ; mask
ORA #>SPRDATA ; base address
STA (DLPTR),Y ; high address
INY
LDA SPRXPOS,X
STA (DLPTR),Y ; horizontal position
INY
TYA ; update end of list pointer
LDY DLTEMP
STA DLIDX,Y
CPY #NUMDL-1 ; bottom of screen?
BEQ 1$
INY
LDA DLPTRL,Y ; display list lookup table
STA DLPTR
LDA DLPTRM,Y
STA DLPTR+1
LDA DLIDX,Y ; fetch end of list pointer
TAY
LDA SPRIDX,X
STA (DLPTR),Y ; low address
INY
LDA SPRPALW,X
STA (DLPTR),Y ; palette + width
INY
LDA SPRYPOS,X
AND #$DLHIGH-1 ; mask
ORA #>SPRDATA-DLHIGH; base address
STA (DLPTR),Y ; high address
INY
LDA SPRXPOS,X
STA (DLPTR),Y ; horizontal position
INY
TYA ; update end of list pointer
LDY DLTEMP
INY ; cheaper to increment again than STY
STA DLIDX,Y
1$ INX ; next sprite
CPX #NUMSPR
BEQ DLCPY
DLFIN LDX #NUMDL
LDA #0
1$ LDY DLPTRL-1,X ; display list lookup table
STY DLPTR
LDY DLPTRM-1,X
STY DLPTR+1
LDY DLIDX-1,X ; end of display list index
INY
STA (DLPTR),Y ; null header
DEX
BNE 1$
; Now that the display list is built (hopefully before the active screen
; begins) it is now time to start preparing for the next screen. Once this
; processing is done, the code waits for the DLL NMI flag to be tripped and
; returns to DLINI to rebuild the display lists again.
VWAIT LDA DLIFLAG
1$ CMP DLIFLAG ; wait for end of visible screen
BEQ 1$
JMP DLINI
; This is a ROM version of the the non-visible part of the DLL. The onscreen
; portion is generated programatically.
DLLTOP DC.B $4B, >DLNULL, <DLNULL ; 12 raster
DC.B $0C, >DLNULL, <DLNULL ; +13 raster = 25 blank
DLLBOT DC.B $8C, >DLNULL, <DLNULL ; NMI, 13 raster
DC.B $0C, >DLNULL, <DLNULL ; +13 raster = 26 blank
DLLEND EQU .
; These are the two lookup tables used by the display list builder routine
; to find the correct display list. These tables are also used
; to programatically generated the onscreen portion of the DLL.
DLPTRM DC.B >DL00, >DL10, >DL20, >DL30, >DL40, >DL50, >DL60, >DL70
DC.B >DL80, >DL90, >DLA0, >DLB0, >DLC0, >DLD0, >DLE0
DLPTRL DC.B <DL00, <DL10, <DL20, <DL30, <DL40, <DL50, <DL60, <DL70
DC.B <DL80, <DL90, <DLA0, <DLB0, <DLC0, <DLD0, <DLE0
; The next chunk is the sprite graphics laid out in 7800 order - $Elnn,
where
; l is the line number (so the sprites are upside down with each line on a
; separate page) and nn is the sprite index.
SPRDATA ORG $E000 ; sprite table
Other related posts:
- » [atari7800] sample 7800 source code