
buildsna : bankset 0 : org #100 : run #100 : di : ld sp,#100

ld hl,#C000 ; HEAP dans la mémoire vidéo!
ld bc,16384 ; on prend les 16k
call memoryInit

; on alloue 4 zones de 64,64,96 et 64 octets
ld bc,64 : call memoryAlloc : push hl ; sauvegarder le pointeur
ld bc,64 : call memoryAlloc : push hl ; sauvegarder le pointeur
ld bc,96 : call memoryAlloc : push hl ; sauvegarder le pointeur
ld bc,64 : call memoryAlloc : push hl ; sauvegarder le pointeur

; et on rempli les zones allouées de couleurs différentes
pop hl : ld (hl),#F0 : ld de,hl : inc de : ld bc,63 : ldir
pop hl : ld (hl),#0F : ld de,hl : inc de : ld bc,95 : ldir
pop hl : ld (hl),#FF : ld de,hl : inc de : ld bc,63 : ldir
pop hl : ld (hl),#C3 : ld de,hl : inc de : ld bc,63 : ldir
jr $ 


guruMeditation brk : jr $ ; breaker l'émulateur en cas de non allocation mémoire


struct memblock
taille defw ; taille utile (hors entête)
suivant defw ; bloc libre suivant
endstruct 

free_list defw 0 ; pas de mémoire disponible par défaut

memoryInit
; HL=début du bloc
; BC=taille du bloc
ld (free_list),hl
dec bc : dec bc : dec bc : dec bc ; corriger d'une taille d'entête
ld (hl),c : inc hl : ld (hl),b : inc hl
ld (hl),0 : inc hl : ld (hl),0 ; pas d'autre bloc libre
ret

memoryAlloc
; BC=taille souhaitée
ld ix,(free_list) : ld iy,0
.boucleSurLesBlocs
ld a,xh : or xl : jp z,guruMeditation ; plus de mémoire disponible
; est-ce que le bloc courant est assez grand?
ld hl,(ix+memblock.taille)
sbc hl,bc : jp m,.blocSuivant
; est-ce qu'on va découper le bloc?
ld hl,(ix+memblock.taille) : dec hl : dec hl : dec hl : dec hl
sbc hl,bc : jp m,.blocEntier : jr nz,.decoupeBloc
.blocEntier
ld hl,(ix+memblock.suivant)
ld a,yl : or yh : jr z,.entierMAJFreeList; A-t'on déjà lu un bloc avant celui là?
ld (iy+memblock.suivant),hl
.renvoieZone ld hl,{sizeof}memblock : ld de,ix : add hl,de : ret ; HL=zone mémoire allouée
.entierMAJFreeList ld (free_list),hl : jr .renvoieZone

.decoupeBloc
; on créé un nouveau bloc HL dans le bloc courant + size
ld de,ix : ld hl,4 : add hl,de : add hl,bc ; HL=nouveau bloc
; on relie ce nouveau bloc à free_list ou au bloc précédent
ld a,yl : or yh : jr z,.decoupeMAJFreeList
ld (iy+memblock.suivant),hl : jr .apresLien
.decoupeMAJFreeList ld (free_list),hl
.apresLien
push hl : pop iy ; IY=nouveau bloc (plus besoin du précédent ici)
ld hl,(ix+memblock.taille) : sbc hl,bc : ld de,-{sizeof}memblock : add hl,de : ld (iy+memblock.taille),hl
ld hl,(ix+memblock.suivant) : ld (iy+memblock.suivant),hl
ld (ix+memblock.taille),bc
ld hl,{sizeof}memblock : ld de,ix : add hl,de : ret ; HL=zone mémoire allouée

.blocSuivant ; IY=IX, IX=IX.suivant
push ix : ld de,(ix+memblock.suivant) : ld ix,de : pop iy
jp .boucleSurLesBlocs 

