I still have no idea what the question is really about. So what follows is a wild guess from what the OP posted in question, edits and comments as well as what I think he could be about:
Blowing Up an 8x8 Char Into a 24x21 Sprite
[I have no idea if this is right, but I can't believe it's just about copying, as that would be way too simple]
A character is stored within the character generator as a sequence of 8 bytes each holding a line with bits set for each pixel to be set, high to low as left to right. Example
00011000 (18) -> **
00111100 (3C) -> ****
01100110 (66) -> ** **
01111110 (7E) -> ******
01100110 (66) -> ** **
01100110 (66) -> ** **
00000000 (00) ->
To turn this into a sprite each bit needs to be tripled within a line - and similar each line (*1) as sprites are simply 3 bytes per line and 21 lines.
00000000 01111110 00000000 (00 7E 00) -> ******
00000000 01111110 00000000 (00 7E 00) -> ******
00000000 01111110 00000000 (00 7E 00) -> ******
00000011 11111111 11000000 (03 FF C0) -> ************
00000011 11111111 11000000 (03 FF C0) -> ************
00000011 11111111 11000000 (03 FF C0) -> ************
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 11111111 11111000 (1F FF F8) -> ******************
00011111 11111111 11111000 (1F FF F8) -> ******************
00011111 11111111 11111000 (1F FF F8) -> ******************
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
00011111 10000001 11111000 (1F 81 F8) -> ****** ******
[No line 22..24]
The following routine is a straight implementation without much tricks to get the job done. There might be some optimization possible, but I'd prefer to get it working first, before playing with alternative/more compact solutions.
Also, unlike the code posed with the question, this is made with pointers, keeping it as independent from any environment as possible (and free of self modifying code, so ROMable). So again, later optimizations may change this and save some code ... but as before I'd put that way at the end of all development. Having Independent subroutines help a lot to minimize development issues.
It's not neccessary made for shortest possible code, but execution time should be fairly good.
; Generic subroutiene to convert a character definition
; (a bitmap stored in 8 consecutive bytes) into a sprite
; of 24x21 pixel
; Called at
; convert
; In:
; chrptr, word, holding address of char definition, will be modified
; sptr, word, holding the address of a 63 byte area to be filled with sprite data
; Out:
; 63 bytes of sprite data processed from character data stored beginning at sptr
; chrptr pointing to the last line (not converted) of the character.
; In/Out
chrptr DW 0 ; A zp-pointer to an 8 byte character definition to be converted
sptr DW 0 ; A zp-pointer to a 64 byte area to be filled with the expanded character
; Local variables
sptr1 DW 0 ; Support pointer (zp) to the second line (copy of first+3)
sptr2 DW 0 ; Support pointer (zp) to the third line (copy of first+6)
temp DB 0 ; temporary value for conversion
; Entry
convert:
;Setup
LDA sptr ; prepare the pointers to save later on
LDX sptr+1
CLC
ADC #3
BCC nopage1
INX
nopage1:
STA sptr1 ; Pointer for second sprite line
STX sptr1+1
CLC
ADC #3
BCC nopage1
INX
nopge2:
STA sptr2 ; Pointer for third sprite line
STX sptr2+1
LDY #0 ; Offset within the character definition
LDX #7 ; 7 lines to be converted (no room for the 8th
;Conversion loop
loop:
LDA chrptr ; Load a character line and bring it into tmp
ROL A ; But lets extract the first bit first - saves 3 cycles and a byte :))
STA temp
LDA #0 ; Clear A
BCC J1A ; Was the top bit set ?
LDA #%11100000 ; Yes -> set the first 3 bits of the sprite
J1A:
ROL temp ; Check second bit
BCC J1B ; Was it set ?
ORA #%00011100 ; Yes -> set the second 3 bits of the sprite
J1B:
ROL temp ; Check third bit
BCC J1C ; Was it set?
ORA #%00000011 ; Yes -> set the third 3 bits of the sprite ... ups, there are only two left in this byte
J1C:
STA (sptr),Y ; Store first byte of first line
STA (sptr1),Y ; Store first byte of second line
STA (sptr2),Y ; Store first byte of third line
INY ; Next byte of the sprite
LDA #0 ; Clear A
ROR ; Bring the remaining bit into the second sprite byte
ROL temp ; Check bit 4
BCC J2A ; Was it set?
ORA #%01110000 ; Yes -> set the 4th 3 bits of the sprite
J2A:
ROL temp ; Check bit 5
BCC J2B ; Was it set?
ORA #%00001110 ; Yes -> set the 5th 3 bits of the sprite
J2B:
ROL temp ; Check bit 6
BCC J2C ; Was it set?
ORA #%00000001 ; Yes -> set the 6th 3 bits of the sprite - again wraping into the next byte
J2C:
STA (sptr),Y ; Store second byte of first line
STA (sptr1),Y ; Store second byte of second line
STA (sptr2),Y ; Store second byte of third line
INY ; Next byte of the sprite
LDA #0 ; Clear A
BCC J3A ; Was bit 6 set?
ORA #%11000000 ; Yes -> set the remaining bits of the 6th group
J3A:
BIT temp ; Check bit 7 (Now using BIT to save 2 cycles)
BPL J3B ; Was it set?
ORA #%00111000 ; Yes -> set the 7th 3 bits of the sprite
J3B:
BIT temp ; Check bit 8 (Now using BIT to save 2 cycles)
BVC J3C ; Was it set?
ORA #%00000111 ; Yes -> set the 8th 3 bits of the sprite
J3C:
STA (sptr),Y ; Store third byte of first line
STA (sptr1),Y ; Store third byte of second line
STA (sptr2),Y ; Store third byte of third line
DEX ; All 7 done?
BEQ end ; Yes -> end
; Adjust pointer(s)
; Y needs to skip three lines/9 bytes (which are already filled) minus the two INY that already happened. Doing it via A saves 2 bytes and 4 cycles. Also, writing so many INY just adds a chance of a miscount.
TYA
CLC
ADC #7 ; 9-2
TAY
; select next line in character
INC chrptr ; Select next line of character
BNE loop ; Next round if no page carry
INC chrptr+1 ; handle page carry
BNE loop ; next round (will fail if the character table wraps at $FFFF - not really likely)
end:
RTS
Lets see if this is in any way related to the question :))
[... thinking of it, there would also be a way for a table driven solution thay may be shoter and faster ... though, not sure, as above is ~127 bytes, while the table base solution neds already 32 bytes of table... :)]
*1 - Yes, I know, this doesn't end well, as there is no room for the lowest line.