In this version nothing much is added to the code. However an external level editor was added (Windows executable) which helps a lot in churning out pretty levels faster.
Most prominent addition are level elements. Before the level was built mostly of simple primitives (line of an character, etc.). With the editor so called Elements are added. These consist of a variable sized character and color block. Elements can be arranged as single object, lines or areas. This helps a lot in reusing bigger level parts and keeping memory usage down.
The elements are stored in several tables. A major lookup table that points to a elements character and color tables, and two lookup tables holding an elements width and height. The editor tries to fold element tables into each other to save memory. For example if there's a big brick sized 4x2 characters, and you have two smaller elements showing the left and right halfs of the brick, the element data is reused.
Note that the element area code is not implemented in this step.
Moral of the story:
As soon as you see you're going ahead with a project having an easy to use editor is quite important. It aids you in faster content creation, faster testing and overall usually prettier results. Nothing crushes productivity better than annoying tools (or manual boring work without tools).
;------------------------------------------------------------
;draws a level element
;PARAM1 = X
;PARAM2 = Y
;PARAM3 = TYPE
;returns element width in PARAM4
;returns element height in PARAM5
;------------------------------------------------------------
!zone DrawLevelElement
DrawLevelElement
ldy PARAM3
lda SNELEMENT_TABLE_LO,y
sta .LoadCode + 1
lda SNELEMENT_TABLE_HI,y
sta .LoadCode + 2
lda SNELEMENT_COLOR_TABLE_LO,y
sta .LoadCodeColor + 1
lda SNELEMENT_COLOR_TABLE_HI,y
sta .LoadCodeColor + 2
lda SNELEMENT_WIDTH_TABLE,y
sta PARAM4
lda SNELEMENT_HEIGHT_TABLE,y
sta PARAM5
sta PARAM6
ldy PARAM2
lda SCREEN_LINE_OFFSET_TABLE_LO,y
clcadc PARAM1
sta .StoreCode + 1
sta .StoreCodeColor + 1
sta ZEROPAGE_POINTER_4
lda SCREEN_LINE_OFFSET_TABLE_HI,y
adc #0
sta .StoreCode + 2adc #( ( >SCREEN_COLOR ) - ( >SCREEN_CHAR ) )
sta .StoreCodeColor + 2
.NextRow
ldx #0
;display a row
.Row
.LoadCode
lda $8000,x
.StoreCode
sta $8000,x
.LoadCodeColor
lda $8000,x
.StoreCodeColor
sta $8000,x
inx
cpx PARAM4
bne .Row
;eine zeile nach untendec PARAM6
beq .ElementDone
;should be faster?
lda .LoadCode + 1clcadc PARAM4
sta .LoadCode + 1
lda .LoadCode + 2adc #0
sta .LoadCode + 2
lda .LoadCodeColor + 1clcadc PARAM4
sta .LoadCodeColor + 1
lda .LoadCodeColor + 2adc #0
sta .LoadCodeColor + 2
lda .StoreCode + 1clcadc #40
sta .StoreCode + 1
lda .StoreCode + 2adc #0
sta .StoreCode + 2
lda .StoreCodeColor + 1clcadc #40
sta .StoreCodeColor + 1
lda .StoreCodeColor + 2adc #0
sta .StoreCodeColor + 2jmp .NextRow
.ElementDone
rts
!zone LevelElement
LevelElement
LevelElementArea
; !byte LD_ELEMENT,0,0,EL_BLUE_BRICK_4x3;X pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM1
;Y pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM2
;type
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM3
;store y for later
tya
pha
jsr DrawLevelElement
jmp NextLevelData
The element line primitives are very similar, they just loop over the element draw routine:
!zone LevelElementH
LevelElementH
; !byte LD_ELEMENT_LINE_H,x,y,width,element;X pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM1
;Y pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM2
;x count
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM7
;type
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM3
;store y for later
tya
pha
.NextElement
jsr DrawLevelElement
dec PARAM7
beq .Done
lda PARAM1
clcadc PARAM4
sta PARAM1
jmp .NextElement
.Donejmp NextLevelData
!zone LevelElementV
LevelElementV
; !byte LD_ELEMENT_LINE_V,x,y,num,element;X pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM1
;Y pos
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM2
;y count
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM7
;type
iny
lda (ZEROPAGE_POINTER_1),y
sta PARAM3
;store y for later
tya
pha
.NextElement
jsr DrawLevelElement
dec PARAM7
beq .Done
lda PARAM2
clcadc PARAM5
sta PARAM2
jmp .NextElement
.Donejmp NextLevelData
The editor exports the level structure to a separate file, this is then included in the main file via the !source macro.