123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- GraphToLCD_:
- ld hl,(BufPtr)
- ld de,(GrayBufPtr)
- BufferToLCD_:
- ;Input:
- ; HL points to the buffer to copy to the LCD
- ; DE points to a secondary buffer to use in grayscale
- ; (graymask) has the gray mask
- ; (graymask+1) is the method
- ; expects the LCD to be in X-increment mode
- ; (If you don't know what this means, you probably don't have to worry!)
- ;Outputs:
- ; HL is incremented by 12
- ; DE is incremented by 12
- ;Destroys:
- ; AF,BC,IX
- ; This might change in the future, but A and C are the gray mask, B is 0,
- ; and IX points to the routine that mixes the pixels from two layers
- di
- ld a,(graymask+1)
- or a
- ld ix,gray2
- jr z,+_
- ld ix,gray3
- dec a
- jr z,+_
- gbuftoLCD_4:
- ld ix,gray4
- sub 15
- jr c,+_
- dec a
- jp z,mask_buffer_to_LCD
- ld ix,LCD_buf_OR
- _:
- ; Expect that the LCD increment mode is already set to increment down
- ;
- ; We shouldn't need a delay here!
- ; in a,(16) \ rla \ jr c,$-3
- ; Set the LCD pointer to the top row
- ld a,$80
- out (16),a
- ;We have to wait for the LCD anyways, so may as well do something useful.
- ;Get the gray mask and put it in C
- ld a,(graymask)
- ld c,a
- ;Wait for the LCD to be ready for new data
- in a,(16) \ rla \ jr c,$-3
- ; Set the LCD pointer to the left-most column of 8 pixels
- ld a,$20
- col:
- ;Set the column
- out (10h),a
- ;Save the column number
- push af
- ;Set B to 64, we'll be writing a whole column, so 64 writes.
- ld b,64
- _:
- ;Now wait for the LCD to be ready
- in a,(16) \ rla \ jr c,$-3
- ;IX points to our mask routine. It rotates the mask and computes the next byte.
- call call_ix_01 ;rotate the mask
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- out (17),a
- ;We are drawing in columns, so we need to advance HL by 12
- ld a,12
- add a,l
- ld l,a
- jr nc,$+3
- inc h
- ;And advance DE by 12
- ld a,12
- add a,e
- ld e,a
- jr nc,$+3
- inc d
- djnz -_
- ;Rotate the mask an extra time. We want to keep it out of phase.
- dec ix
- call call_ix_01 ;rotate the mask
- inc ix
- ;Now point to HL to the start of the next column.
- ;If we subtract 768, it is where it started, so we'd need to increment 1 more.
- ;Basically, HL-(3*256)+1
- dec h
- dec h
- dec h
- inc hl
- ;Same with DE
- dec d
- dec d
- dec d
- inc de
- ;Restore A to the column number, then increment. If it hits $2C, we've drawn all
- ;12 columns, so no more looping. Otherwise, draw the next column.
- pop af
- inc a
- cp $2C
- jp nz,col
- ;Rotate the mask one final time. Our masks are either 2- or 3-cycles, and we
- ;want to avoid a static image if possible!
- call call_ix_01 ;rotate the mask one last time
- ld a,c
- ld (graymask),a
- ret
- gray2:
- ;This just grabs from the main buffer
- ld a,(hl)
- ret
- nop
- gray3:
- ;Toggles the mask between %10101010 and %01010101.
- rlc c
- ; Now we use C to select pixels from either (DE), or (HL).
- ; If a bit in C is 0, the corresponding bit in the output is from (HL),
- ; else it is from (DE). There is an explaination of this at the end.
- ld a,(de)
- xor (hl)
- and c
- xor (hl)
- ret
- gray4:
- ld a,c ;\
- cp $C0 ; | Rotate the graymask
- rra ; | Can be efficiently done by rotating left while
- ld c,a ;/ shifting in the XOR of the top two bits.
- ; Now we use C to select pixels from either (DE), or (HL).
- ; If a bit in C is 0, the corresponding bit in the output is from (HL),
- ; else it is from (DE). There is an explaination of this at the end.
- ld a,(de)
- xor (hl)
- and c
- xor (hl)
- ret
- LCD_buf_OR:
- ld a,(de)
- or (hl)
- ret
- mask_buffer_to_LCD:
- ;This will AND the secondary buf on to the tilemap_buf, then OR the primary buf
- ;on to that.
- ld ix,(tilemap_buf)
- ; Expect that the LCD increment mode is already set to increment down
- ;
- ; We shouldn't need a delay here!
- ; in a,(16) \ rla \ jr c,$-3
- ; Set the LCD pointer to the top row
- ld a,$80
- out (16),a
- ;Wait for the LCD to be ready for new data
- in a,(16) \ rla \ jr c,$-3
- ; Set the LCD pointer to the left-most column of 8 pixels
- ld a,$20
- maskcol:
- ;Set the column
- out (10h),a
- ;Save the column number
- push af
- ;Set B to 64, we'll be writing a whole column, so 64 writes.
- ld bc,$400C
- _:
- push bc
- ld a,(de)
- and (ix)
- xor (hl)
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- push af
- ld b,0
- add hl,bc
- ex de,hl
- add hl,bc
- ex de,hl
- add ix,bc
- ;Now wait for the LCD to be ready
- in a,(16) \ rla \ jr c,$-3
- pop af
- out (17),a
- pop bc
- djnz -_
- ;Now point to HL to the start of the next column.
- ;If we subtract 768, it is where it started, so we'd need to increment 1 more.
- ;Basically, HL-(3*256)+1
- dec h
- dec h
- dec h
- inc hl
- ;Same with DE
- dec d
- dec d
- dec d
- inc de
- ;Same with IX
- dec ixh
- dec ixh
- dec ixh
- inc ix
- ;Restore A to the column number, then increment. If it hits $2C, we've drawn all
- ;12 columns, so no more looping. Otherwise, draw the next column.
- pop af
- inc a
- cp $2C
- jp nz,maskcol
- ret
- ; How C can select from two different buffers
- ;
- ;
- ;We'll use this magical formula:
- ; ((x^y)&m)^y
- ;
- ;When m is 0:
- ; ((x^y)&m)^y
- ; = ((x^y)&0)^y
- ; = (0)^y
- ; = y
- ;
- ;When m is 1:
- ; ((x^y)&m)^y
- ; = ((x^y)&1)^y
- ; = (x^y)^y
- ; = x^(y^y) ;We can do this when all operations are XOR
- ; = x
- ;
- ;So a 0 in the mask will choose the pixel from (HL) (primary buffer),
- ;and a 1 will choose a pixel from (DE) (gray/back/secondary buffer).
|