;процедуры для генерации карты, нижнего уровня (зависят от типа экрана)
ClearMap
ld a,PGMAP
call OUTME
LD HL,MAP
LD DE,MAP+1
LD BC,0xffff-MAP
LD (HL),0
LDIR
ret
FindPlacesForGrass ;записывает в grassbuf
ld a,PGMAP
call OUTME
;по чётным столбцам сверху вниз ищем переходы 0->1
ld ix,grassbuf
ld hl,MAP
ld de,MAPWID
ld c,128 ;1 bit >>2 every time
ld b,MAPWID
xor a ;RLE counter
ex af,af' ;'
findgrass_columns0
push bc
push hl
ld b,MAPHGT-1
findgrass1
ld a,(hl)
cpl
and c
add hl,de
and (hl)
ex af,af' ;'
inc a
jr nz,findgrass_nooverflow
ld (ix),a;0 ;0=просто пропуск 255 пикс
inc ix
ld a,hx
cp (grassbuf+grassbufsz)/256
jp z,nowhere ;buffer overflow
ld a,1
findgrass_nooverflow
ex af,af' ;'
jr z,findgrass_empty
ex af,af' ;'
ld (ix),a
inc ix
ld a,hx
cp (grassbuf+grassbufsz)/256
jp z,nowhere ;buffer overflow
xor a
ex af,af' ;'
findgrass_empty
djnz findgrass1
pop hl
pop bc
rrc c
rrc c
jr nc,findgrass_columns0
inc hl
djnz findgrass_columns0
ld (ix),b;0 ;иначе в последнем столбце может появиться лажа
ret
MakeMaskFromMap
;FIXME в случае неполной маски (нужна защита от влетания в стену на краю карты - надо полную маску или при любой порче ландшафта крайний левый пикс маски формировать из 5 левых пикс, справа аналогично?)
;x в маске считается для центра червя, x=0 соответствует x=4 в карте
;то есть берём байт маски из карты так: ----M-M- M-M-m-m- m-m-----
LD HL,MAP;+1
LD DE,MASK;MASKBUF
LD B,MASKHGT;88
MKMAP41 PUSH BC
ld a,PGMAP
call OUTME
push de
ld de,MKMASKBUF
LD B,MASKWID
MKMAP42 LD A,(HL)
RLA
RLA
RLA
RLA
DUP 2
RLA
RLA
RL C
EDUP
INC HL
LD A,(HL)
DUP 4
RLA
RLA
RL C
EDUP
INC HL
LD A,(HL)
DUP 2
RLA
RLA
RL C
EDUP
LD A,C
LD (DE),A
INC DE
DJNZ MKMAP42
call SetPgMask
pop de
push hl
ld hl,MKMASKBUF
ld bc,MASKWID
ldir
pop hl
LD bc,(MAPWID-MASKWID)*2
ADD HL,BC
POP BC
DJNZ MKMAP41
;extra bottom line of mask is always filled (for element placement)
LD HL,MASKSZ+MASK;MASKBUF
LD BC,MASKWID*256+255
LD (HL),C
INC HL
DJNZ $-2
ret
TexturizeGroundInMap
ld a,PGMAP
call OUTME
LD HL,MAP
LD DE,MAPWID
ld bc,texture
ld lx,MAPWID
MkMapTex0 PUSH BC
PUSH HL
MkMapTex1 LD A,(BC)
AND (HL)
LD (HL),A
LD A,C
inc a
xor c
and 0x7f
xor c
LD C,A
ADD HL,DE
JR NC,MkMapTex1
POP HL
INC L
POP BC
ld a,c
add a,128
ld c,a
jr nc,MkMapTex0ok
inc b
ld a,b
cp texture/256+8
jr c,MkMapTex0ok
ld b,texture/256
MkMapTex0ok
dec lx
jr NZ,MkMapTex0
ret
AddGrassInMap
LD A,PGMAP;16
CALL OUTME
ld ix,grassbuf
ld de,MAPWID
ld hl,MAP
ld c,0xc0 ;2 bits >>2 every time
ld b,MAPWID
xor a ;RLE counter
ex af,af' ;'
addgrass_columns0
ld a,c
ld (addgrassmask),a
push bc
push hl
ld b,MAPHGT-1
addgrass0
add hl,de
ex af,af' ;'
addgrass_noadd1
inc a
cp (ix)
jr nz,addgrass_noadd
inc ix
or a
jr z,addgrass_noadd1 ;0=просто пропуск 255 пикс
push bc
push hl
LD bc,sprgrass
addgrass1
ld a,(bc)
or a
jr z,addgrass1q
addgrassmask=$+1
and 0
or (hl)
ld (hl),a
add hl,de
jr c,addgrass1q ;end of column
inc bc
jr addgrass1
addgrass1q
pop hl
pop bc
xor a
addgrass_noadd
ex af,af' ;'
djnz addgrass0
pop hl
pop bc
rrc c
rrc c
jr nc,addgrass_columns0
inc hl
djnz addgrass_columns0
ret
sprgrass
DB #29,-1,#DB,#7E,#D5,#AA,0
;DB #52,-1,#BF,-4,#AB,#55,0
PRLMNerror
INC C ;don't fit, next x
POP DE
LD A,C
CP MASKWID-5 ;ширина элемента не более 10 знакомест
jp C,PRLMN00
; pop de
pop af
; scf
ret
PRLMN
;draw element in map and mask
;c=X (in chr)
;hl=gfx
LD D,(HL) ;width
INC HL
LD E,(HL) ;hgt
INC HL
call SetPgMask
PUSH HL ;gfx
PRLMN00
LD HL,MASK+(MASKWID*(MAPHGT-TERRAINHGT));MASKBUF+(MASKWID*(MAPHGT-TERRAINHGT))
XOR A
LD B,A
ADD HL,BC ;+x
LD B,E ;hgt
PUSH DE
LD DE,MASKWID
;есть ли достаточная высота неба под элемент?
OR (HL)
ADD HL,DE
DJNZ $-2
jr NZ,PRLMNerror ;don't fit, next x
;ищем грунт (он точно есть, мы в маске сделали лишнюю залитую строку)
INC B
OR (HL)
ADD HL,DE
JR Z,$-3
POP DE
LD A,D ;wid
DEC A
srl a;RRA
NEG
ADD A,C
LD C,A ;x
ld a,b
add a,MAPHGT-TERRAINHGT
ld b,a ;y
;PGMASK уже включено
;b=y
;c=x
;d=width
;e=hgt
POP HL ;gfx
PUSH BC ;c=x
XOR A
OR B ;y
PUSH HL ;gfx
PUSH DE ;width,hgt
LD HL,MASK;MASKBUF
LD DE,MASKWID
JR Z,$+5
ADD HL,DE
DJNZ $-1 ;hl=MASK+(y*MASKWID)
ADD HL,BC ;hl=MASK+(y*MASKWID)+x
POP BC ;width,hgt
POP DE ;gfx
;hl=MASK+
;de=gfx
;b=width
;c=hgt
PRLMNmask1
PUSH BC
PUSH HL
xor a
ld c,a
PRLMNmask2
LD A,(DE)
rra
rl c
rra
rr c
push af
OR (HL)
LD (HL),A
INC HL
INC DE
pop af
DJNZ PRLMNmask2
ld a,0
rra
rl c
rra
OR (HL)
LD (HL),A
POP HL
LD C,MASKWID
ADD HL,BC
POP BC
DEC C
JR NZ,PRLMNmask1
ex de,hl
LD D,(HL) ;width
INC HL
LD E,(HL) ;hgt
INC HL
POP BC ;yx
PUSH BC ;yx
XOR A
OR B ;y
PUSH HL ;gfx
PUSH DE ;width,hgt
LD HL,MAP;+(MAPWID*(MAPHGT-TERRAINHGT));#C000
LD DE,MAPWID*2
JR Z,$+5
ADD HL,DE
DJNZ $-1
ADD HL,BC
ADD HL,BC ;hl=MAP+(y*MAPWID*2)+(x*2)
LD A,PGMAP;16
CALL OUTME
POP BC ;width,hgt
POP DE ;gfx
PRLMN2 PUSH BC
PUSH HL
LD A,(DE)
INC HL
OR (HL)
LD (HL),A
INC DE
DJNZ $-5
POP HL
LD C,MAPWID
ADD HL,BC
POP BC
DEC C
JR NZ,PRLMN2
;de=end of gfx
ex de,hl ;hl=end of gfx
LD A,B ;width
POP BC ;c=x
ADD A,C
LD C,A ;update x (чтобы не лепить объекты совсем рядом)
;or a ;NC
RET
CopyLMNGfx ;копируем графику выбранных элементов в LMNGFX (не более LMNGFXSZ)
;нужно только для 48/128, а на АТМ будет выводиться непосредственно из LMNS
;TODO с распаковкой? или добавить распаковку при использовании?
ld a,PGLMN
call OUTME
ld a,(LMNS)
LMNSfirstbyte=$+1
cp 0x81
ret nz;jr nz,MKMAP_copyLMNbug ;48K повтор карты - используем элементы, которые успели спасти в экране (при послеигровой генерации в экране лежит 0)
ld hl,LMNlist ;впритык к концу параграфа
ld de,LMNGFX
copyLMN0
ld (copyLMN_lastgood),de
ld a,(hl)
push hl
scf
rla ;a=N*2+1
LD HL,LMNS
copyLMNfind0
LD c,(HL)
INC HL
LD b,(HL) ;size in bytes
INC HL
DEC A
JR Z,copyLMNfindq
ADD HL,bc
JR copyLMNfind0
copyLMNfindq
push hl
ld h,d
ld l,e
add hl,bc
ld a,h
cp (LMNGFX+LMNGFXSZ)/256
pop hl
jr nc,copyLMNfail
ldir
dec de ;skip 0
LD c,(HL)
INC HL
LD b,(HL) ;size in bytes
INC HL
push hl
ld h,d
ld l,e
add hl,bc
ld a,h
cp (LMNGFX+LMNGFXSZ)/256
pop hl
jr nc,copyLMNfail
ldir
dec de ;skip 0
pop hl
inc l
jr nz,copyLMN0
jr copyLMNok
copyLMNfail
pop hl
copyLMN_lastgood=$+1
ld de,0
copyLMNok
xor a
ld (de),a ;end of gfx
;MKMAP_copyLMNbug ;при послеигровой генерации на 48K {0x4000}=0
ret
if 0
CheckGroundExist ;проверяем, есть ли земля на ниж. линии (CY=error)
ld a,PGMAP
call OUTME ;технически не нужно, т.к. вызывается после MKMAPPP
LD HL,MAP+((MAPHGT-1)*MAPWID);#FFEF
LD B,MAPWID
XOR A
OR (HL) ;проверяем, есть ли земля на ниж. линии
inc HL ;
DJNZ $-2 ;
ret nz
scf
ret ;error ;нет земли на ниж. линии
endif
EorFillInMap
LD A,PGMAP;16
CALL OUTME
LD HL,MAP;#C000
LD DE,MAPWID
LD C,E
MKMAPF PUSH HL
LD B,MAPHGT
XOR A
MKMAPF0 XOR (HL)
LD (HL),A
ADD HL,DE
DJNZ MKMAPF0
POP HL
INC L
DEC C
JR NZ,MKMAPF
ret