123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- #define lcd_delay() ex (sp),hl \ ex (sp),hl
- GraphToLCD_:
- ld hl,(BufPtr)
- ld ix,(GrayBufPtr)
- BufferToLCD_:
- ;Input:
- ; HL points to the buffer to copy to the LCD
- ; IX 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
- ; Don't want interrupts interfering
- di
- ; 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
- lcd_delay() ;new calcs seem to ignore the LCD busy bit
- ;we'll need to increment HL by 12 each iteration anyways, so may as well make
- ;DE useful
- ld de,12
- ld a,(graymode)
- or a
- jr z,gray2
- dec a
- jp z,gray3
- dec a
- jp z,gray4
- sub 14
- jp z,LCD_buf_OR
- dec a
- jp z,mask_buffer_to_LCD
- gray2:
- ld c,16
- ; Set the LCD pointer to the left-most column of 8 pixels
- ld a,$20
- gray2_col:
- lcd_delay() ;new calcs seem to ignore the LCD busy bit
- ;Wait for the LCD to be ready for new data
- in f,(c) \ jp m,$-2
- ;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
- ld a,(hl)
- add hl,de
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- in f,(c) \ jp m,$-2
- out (17),a
- djnz -_
- dec h
- dec h
- dec h
- inc hl
- ;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,gray2_col
- ret
- gray3:
- ;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
- gray3_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
- _:
- ;Toggles the mask between %10101010 and %01010101.
- rlc c
- ;Now wait for the LCD to be ready
- in a,(16) \ rla \ jr c,$-3
- ; Now we use C to select pixels from either (IX), or (HL).
- ; If a bit in C is 0, the corresponding bit in the output is from (HL),
- ; else it is from (IX). There is an explaination of this at the bottom.
- ld a,(ix)
- xor (hl)
- and c
- xor (hl)
- add hl,de
- add ix,de
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- out (17),a
- 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 IX
- dec ixh
- dec ixh
- dec ixh
- inc ix
- ;Now wait for the LCD to be ready
- in a,(16) \ rla \ jr c,$-3
- ;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,gray3_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!
- ld a,c
- rlca
- ld (graymask),a
- ret
- gray4:
- ;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
- gray4_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
- 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 (IX), or (HL).
- ; If a bit in C is 0, the corresponding bit in the output is from (HL),
- ; else it is from (IX). There is an explaination of this at the end.
- ld a,(ix)
- xor (hl)
- and c
- xor (hl)
- add hl,de
- add ix,de
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- out (17),a
- 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 IX
- dec ixh
- dec ixh
- dec ixh
- inc ix
- ;Now wait for the LCD to be ready
- in a,(16) \ rla \ jr c,$-3
- ;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,gray4_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!
- ld a,c
- cp $C0
- rra
- ld (graymask),a
- ret
- LCD_buf_OR:
- ld c,16
- ; Set the LCD pointer to the left-most column of 8 pixels
- ld a,$20
- LCD_buf_OR_col:
- ;Wait for the LCD to be ready for new data
- in f,(c) \ jp m,$-2
- ;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
- ld a,(hl)
- or (ix)
- add hl,de
- add ix,de
- bit InvertLCDFlag,(iy+userflags)
- jr z,$+3
- cpl
- in f,(c) \ jp m,$-2
- out (17),a
- djnz -_
- dec h
- dec h
- dec h
- inc hl
- dec ixh
- dec ixh
- dec ixh
- inc ix
- in f,(c) \ jp m,$-2
- ;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,LCD_buf_OR_col
- 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 de,(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 (IX) (gray/back/secondary buffer).
|