The levels are currently rather ermm. sparse. Remember that a screen is built by several primitve types. To get things rolling a few new building types are added:
Namely a character/color area, an alternating line horizontally and vertically (alternating means toggling the characters +1/-1) and a quad (a 2x2 tile).
We'll start with the new constants:
LD_AREA = 4 ;data contains x,y,width,height,char,color
LD_LINE_H_ALT = 5 ;data contains x,y,width,char,color
LD_LINE_V_ALT = 6 ;data contains x,y,height,char,color
LD_QUAD = 7 ;data contains x,y,quad_id
...the new level building code table entries...
LEVEL_ELEMENT_TABLE_LO
!byte <.LevelComplete
!byte <LevelLineH
!byte <LevelLineV
!byte <LevelObject
!byte <LevelArea
!byte <LevelLineHAlternating
!byte <LevelLineVAlternating
!byte <LevelQuad
LEVEL_ELEMENT_TABLE_HI
!byte >.LevelComplete
!byte >LevelLineH
!byte >LevelLineV
!byte >LevelObject
!byte >LevelArea
!byte >LevelLineHAlternating
!byte >LevelLineVAlternating
!byte >LevelQuad
Here's the area code. Straight forward, fetch all needed parameters and build the area row by row:
!zone LevelAreaLevelArea
;X pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM1
;Y pos
iny
lda (ZEROPAGE_POINTER_1),y
tax
lda SCREEN_LINE_OFFSET_TABLE_LO,x
sta ZEROPAGE_POINTER_2
sta ZEROPAGE_POINTER_3
lda SCREEN_LINE_OFFSET_TABLE_HI,x
sta ZEROPAGE_POINTER_2 + 1clcadc #( ( SCREEN_COLOR - SCREEN_CHAR ) & 0xff00 ) >> 8
sta ZEROPAGE_POINTER_3 + 1
;width
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM2
sta PARAM6
;height
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM3
;char
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM4
;color
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM5
;store target pointers to screen and color ram
tya
pha
.NextLineArea
ldy PARAM1
.NextCharArea
lda PARAM4
sta (ZEROPAGE_POINTER_2),y
lda PARAM5
sta (ZEROPAGE_POINTER_3),y
iny
dec PARAM2
bne .NextCharArea
dec PARAM3
beq .AreaDone
;move pointers down a line
tya
sec
sbc #40
tay
lda ZEROPAGE_POINTER_2
clcadc #40
sta ZEROPAGE_POINTER_2
sta ZEROPAGE_POINTER_3
lda ZEROPAGE_POINTER_2 + 1adc #0
sta ZEROPAGE_POINTER_2 + 1clcadc #( ( SCREEN_COLOR - SCREEN_CHAR ) & 0xff00 ) >> 8
sta ZEROPAGE_POINTER_3 + 1
lda PARAM6
sta PARAM2
jmp .NextLineArea
.AreaDonejmp NextLevelData
I won't go into details about the alternating lines, they are almost the same as the common lines, with one small addition: After every set character the lowest bit of the character number is toggled.
Way more interesting is the quad where we fall back to a hint from one of the first steps: Tables, tables, tables!
The quad primitive uses indices into quad tables. To easy the workload every quad is split into 8 tables, characters upper left, upper right, lower left, lower right and the same for the colors. This way the quad index can also be used for the content.
For the record: This makes building the quad tables really annoying but the speedup is worth it.
!zone LevelQuad
LevelQuad
;X pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM1
;Y pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM2
;item
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM3
;store y for next data
tya
pha
ldy PARAM2
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_2
sta ZEROPAGE_POINTER_3
lda SCREEN_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_2 + 1
clc
adc #( ( SCREEN_COLOR - SCREEN_CHAR ) & 0xff00 ) >> 8
sta ZEROPAGE_POINTER_3 + 1
ldy PARAM1
ldx PARAM3
;put image
lda BLOCK_TABLE_UL_LOCATION0,x
sta (ZEROPAGE_POINTER_2),y
lda BLOCK_TABLE_UL_COLOR_LOCATION0,x
sta (ZEROPAGE_POINTER_3),y
iny
lda BLOCK_TABLE_UR_LOCATION0,x
sta (ZEROPAGE_POINTER_2),y
lda BLOCK_TABLE_UR_COLOR_LOCATION0,x
sta (ZEROPAGE_POINTER_3),y
tya
clc
adc #39
tay
lda BLOCK_TABLE_LL_LOCATION0,x
sta (ZEROPAGE_POINTER_2),y
lda BLOCK_TABLE_LL_COLOR_LOCATION0,x
sta (ZEROPAGE_POINTER_3),y
iny
lda BLOCK_TABLE_LR_LOCATION0,x
sta (ZEROPAGE_POINTER_2),y
lda BLOCK_TABLE_LR_COLOR_LOCATION0,x
sta (ZEROPAGE_POINTER_3),y
jmp NextLevelData