CopyTilesToMap:
CopyTilesToMapUnsafe:
  ; copy tiles from where they are linearly packed at an origin (hl)
  ; to a rectangle in the tilemap in vram (de)
  ; assuming it has height in b and width in c.
  ld a, b
  or a, c
  ret z
  push bc
.copyTile
  ld a, [hl] ; load from the tile map into a
  ld [de], a ; load from a into the destination
  inc hl ; this is slower than using hli but i'm trying to work with this here
  inc de
  dec c
  ; check if we've completed a line?
  ld a, 0
  or a, c ; check if c is zero, if it's not zero go back and copy more bytes
  jp nz, .copyTile
.doneWithLine
  pop bc

  ld a, e
  add a, 32
  ld e, a
  ld a, d
  adc a, 0
  ld d, a
  ld a, e
  sub a, c
  ld e, a
  ld a, d
  sbc a, 0
  ld d, a

  dec b
  ld a, b
  cp a, 0
  jp nz, CopyTilesToMap
  ret
  
BuildMetaSprite:
  ; takkes similar args as copytilestomapunsafe but builds several sprites
  ; instead.
  ; location of source tile map: hl
  ; location in memory to write to: de
  ; y and x in b and c 
  ; height and width in a & %11110000 and a & %00001111 ??? that's deranged
  push hl
  push de
  pop hl ; want hl and de to be swapped just for the sake of consistent apis
  pop de ; hl now holds the OAM location, de holds the sprite map
  push af ; save to the stack so we can retrieve it for row-wise decrement
  push bc ; hold onto the upper-left corner so we can update it each row

  
.writeRow
  pop bc 
  pop af
  push af
  push bc ; refresh af and bc from their authoritative stack versions
  and a, $0F ; take only the horizontal tile count

.buildSprite
  ; 
  ld [hl], b ; write y byte
  inc hl 
  ld [hl], c ; write x byte
  inc hl 
  push af ; save a before we use it for transferring de to hl
  ld a, [de]
  inc de ; move to the next sprite
  ld [hl], a 
  inc hl 
  res OAMB_XFLIP, [hl] ; make sure xflip is turned off
  inc hl ; skip the attributes byte
  ; we're going to wait to get our a value (number of tiles left to draw in this
  ; row) until after we've used a for changing c
  
  ;we've written a whole sprite. hl and de are in the right state, we need to 
  ; update a and bc.
  
  ; update bc
  ld a, c 
  add a, 8 
  ld c, a 
  pop af ; get back the number of tiles to draw in this row 
  dec a
  jp nz, .buildSprite ; if there are still tiles left to draw in this row, do it!
  
  ; otherwise we have no more tiles to write this row bc needs to be updated
  
  
  pop bc
  ld a, b 
  add a, 8
  ld b, a ; add 8 to the y coordinate
  
  pop af 
  sub a, $10
  push af 
  push bc
  
  and a, $F0
  ; stakc has bc and af, ready for repeating from the top
  jp nz, .writeRow ; last numerical operation was and a, $F0 so checking if upper byte is zero
  
  pop bc
  pop af 
  
  ret
  
BuildMetaSpriteHFlip:
  ; takkes similar args as copytilestomapunsafe but builds several sprites
  ; instead.
  ; location of source tile map: hl
  ; location in memory to write to: de
  ; y and x in b and c 
  ; height and width in a & %11110000 and a & %00001111 ??? that's deranged
  push hl
  push de
  pop hl ; want hl and de to be swapped just for the sake of consistent apis
  pop de ; hl now holds the OAM location, de holds the sprite map
  push af ; save to the stack so we can retrieve it for row-wise decrement
  and a, $0F
  ;sla a ;times 2 
  ;sla a ; times 4
  ;sla a ; times 8
  ;add a, c
  
  ;ld a, b 
  ;adc a, 0 
  ;ld b, a 
  pop af
  push af
  push bc ; hold onto the upper-left corner so we can update it each row

  
.writeRow
  pop bc 
  pop af
  push af
  push bc ; refresh af and bc from their authoritative stack versions
  and a, $0F ; take only the horizontal tile count

.buildSprite
  ; 
  ld [hl], b ; write y byte
  inc hl 
  ld [hl], c ; write x byte
  inc hl 
  push af ; save a before we use it for transferring de to hl
  ld a, [de]
  inc de ; move to the next sprite
  ld [hl], a 
  inc hl 
  set OAMB_XFLIP, [hl] ; make sure xflip is turned on
  inc hl ; skip the attributes byte
  ; we're going to wait to get our a value (number of tiles left to draw in this
  ; row) until after we've used a for changing c
  
  ;we've written a whole sprite. hl and de are in the right state, we need to 
  ; update a and bc.
  
  ; update bc
  ld a, c 
  sub a, 8 
  ld c, a 
  pop af ; get back the number of tiles to draw in this row 
  dec a
  jp nz, .buildSprite ; if there are still tiles left to draw in this row, do it!
  
  ; otherwise we have no more tiles to write this row bc needs to be updated
  
  
  pop bc
  ld a, b 
  add a, 8
  ld b, a ; add 8 to the y coordinate
  
  pop af 
  sub a, $10
  push af 
  push bc
  
  and a, $F0
  ; stakc has bc and af, ready for repeating from the top
  jp nz, .writeRow ; last numerical operation was and a, $F0 so checking if upper byte is zero
  
  pop bc
  pop af 
  
  ret
  
  
  
BuildMetaSpritePackedHflip:
  ; takkes similar args as copytilestomapunsafe but builds several sprites
  ; instead.
  ; location of source tile map: hl
  ; location in memory to write to: de
  ; y and x in b and c 
  ; height and width in a & %11110000 and a & %00001111 ??? that's deranged
  push hl
  push de
  pop hl ; want hl and de to be swapped just for the sake of consistent apis
  pop de ; hl now holds the OAM location, de holds the sprite map
  push af ; save to the stack so we can retrieve it for row-wise decrement
  push bc ; hold onto the upper-left corner so we can update it each row

  
.writeRow
  pop bc 
  pop af
  push af
  push bc ; refresh af and bc from their authoritative stack versions
  and a, $0F ; take only the horizontal tile count

.buildSprite
  ; 
  ld [hl], b ; write y byte
  inc hl 
  ld [hl], c ; write x byte
  inc hl 
  push af ; save a before we use it for transferring de to hl
  
  ld a, [de]
  inc de ; move to the next sprite
  ld [hl], a
  cp a, 0 
  jp nz, :+

  dec hl 
  dec hl
  jp :++
:
  inc hl 
  set OAMB_XFLIP, [hl] ; make sure xflip is turned off
  inc hl ; skip the attributes byte
  ; we're going to wait to get our a value (number of tiles left to draw in this
  ; row) until after we've used a for changing c
  
  ;we've written a whole sprite. hl and de are in the right state, we need to 
  ; update a and bc.
  
  ; update bc
: ld a, c 
  sub a, 8 
  ld c, a 
  pop af ; get back the number of tiles to draw in this row 
  dec a
  jp nz, .buildSprite ; if there are still tiles left to draw in this row, do it!
  
  ; otherwise we have no more tiles to write this row bc needs to be updated
  
  
  pop bc
  ld a, b 
  add a, 8
  ld b, a ; add 8 to the y coordinate
  
  pop af 
  sub a, $10
  push af 
  push bc
  
  and a, $F0
  ; stakc has bc and af, ready for repeating from the top
  jp nz, .writeRow ; last numerical operation was and a, $F0 so checking if upper byte is zero
  
  pop bc
  pop af 
  
  ret
  
  
BuildMetaSpritePacked:
  ; takkes similar args as copytilestomapunsafe but builds several sprites
  ; instead.
  ; location of source tile map: hl
  ; location in memory to write to: de
  ; y and x in b and c 
  ; height and width in a & %11110000 and a & %00001111 ??? that's deranged
  push hl
  push de
  pop hl ; want hl and de to be swapped just for the sake of consistent apis
  pop de ; hl now holds the OAM location, de holds the sprite map
  push af ; save to the stack so we can retrieve it for row-wise decrement
  push bc ; hold onto the upper-left corner so we can update it each row

  
.writeRow
  pop bc 
  pop af
  push af
  push bc ; refresh af and bc from their authoritative stack versions
  and a, $0F ; take only the horizontal tile count

.buildSprite
  ; 
  ld [hl], b ; write y byte
  inc hl 
  ld [hl], c ; write x byte
  inc hl 
  push af ; save a before we use it for transferring de to hl
  
  ld a, [de]
  inc de ; move to the next sprite
  ld [hl], a
  cp a, 0 
  jp nz, :+

  dec hl 
  dec hl
  jp :++
:
  inc hl 
  res OAMB_XFLIP, [hl] ; make sure xflip is turned off
  inc hl ; skip the attributes byte
  ; we're going to wait to get our a value (number of tiles left to draw in this
  ; row) until after we've used a for changing c
  
  ;we've written a whole sprite. hl and de are in the right state, we need to 
  ; update a and bc.
  
  ; update bc
: ld a, c 
  add a, 8 
  ld c, a 
  pop af ; get back the number of tiles to draw in this row 
  dec a
  jp nz, .buildSprite ; if there are still tiles left to draw in this row, do it!
  
  ; otherwise we have no more tiles to write this row bc needs to be updated
  
  
  pop bc
  ld a, b 
  add a, 8
  ld b, a ; add 8 to the y coordinate
  
  pop af 
  sub a, $10
  push af 
  push bc
  
  and a, $F0
  ; stakc has bc and af, ready for repeating from the top
  jp nz, .writeRow ; last numerical operation was and a, $F0 so checking if upper byte is zero
  
  pop bc
  pop af 
  
  ret