Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Fast tile renderer

216 views
Skip to first unread message

BLuRry

unread,
Jun 10, 2013, 12:40:35 PM6/10/13
to
Using the text page 1 bank to hold the information about what tiles to render, this routine does a quick render to hi-res page 1. It's pretty tight, but could probably be more optimized. What do you guys think? Useless over-use of self-modifying code? I'm all for keeping the cycle count low if there is a better way...

The shape table is organized in chunks of 32 bytes, such that each tile is 2 x 16 bytes (or 14x32 pixels).

Right now I just threw together three test tile patterns so I could validate my multiply-by-32 routine worked, but the idea is to have a real tile editor and take the tile shape table stored in a separate file.

The "sp" and "flip" macros are used for convenience to make it easier to represent tiles as recognizable bit patterns in the code.

-------------------------------------------------------------------

; @com.wudsn.ide.asm.hardware=APPLE2
!cpu 65c02
*=$6000
MAX_COLS=12
MAX_ROWS=11
VIEWPORT_META = $400
currentRow = $FA
currentCol = $FB
tileYcounter = $FC
unused = $FD
VIEWPORT = $2000

;--- Main tile drawing loop ---
drawTileView
lda #MAX_ROWS
sta currentRow
.drawRow
lda #MAX_COLS
sta currentCol
.drawCol jsr drawTile
dec currentCol
bpl .drawCol
dec currentRow
bpl .drawRow
rts

;--- Draw tile indicated at currentRow and currentCol ---
drawTile
lda currentRow ; A tile is 16 lines tall, which is 2 groups of 8 lines each
asl
tay ; Save currentRow*2 into x
lda lookupLo,y
adc currentCol ; Tile is two bytes wide so add X twice
adc currentCol
sta .getTile+1
lda lookupHi,y
sec
sbc #$1C
sta .getTile+2
.getTile lda $0000
tax
asl
asl
asl
asl
asl
clc
adc #(<ShapeTable)
php
sta .drawTileRead1 + 1 ; Store lo-byte
sta .drawTileRead2 + 1 ; Store lo-byte
txa
lsr
lsr
lsr
plp
adc #(>ShapeTable)
sta .drawTileRead1 + 2
sta .drawTileRead2 + 2
ldx #0 ; Set up offset for tile reads
lda #16 ; Set up row counter
sta tileYcounter
.drawTileUpdatePointers
lda lookupLo,y
clc
adc currentCol ; Tile is two bytes wide so add X twice
adc currentCol
sta .drawTileStore1 + 1
inc
sta .drawTileStore2 + 1
lda lookupHi,y
sta .drawTileStore1 + 2
sta .drawTileStore2 + 2
.drawTileLoop
.drawTileRead1
lda ShapeTable,x
.drawTileStore1 ; Store even column
sta $0000
inx
.drawTileRead2
lda ShapeTable,x
.drawTileStore2 ; Store odd column
sta $0001
inx
dey
dec tileYcounter
beq .drawTileLoopEnd
lda #$07
and tileYcounter
beq .drawTileFinishLoop
lda .drawTileStore1 + 2
clc
adc #$04
sta .drawTileStore1 + 2
sta .drawTileStore2 + 2
bne .drawTileLoop
.drawTileFinishLoop
lda currentRow ; A tile is 16 lines tall
asl ; Draw bottom half of the tile now
inc
tay ; Accum should be the (current row * 2)+1
bne .drawTileUpdatePointers
.drawTileLoopEnd
rts
lookupLo !by $d0, $50, $d0, $50
!by $d0, $50, $d0, $50
!by $a8, $28, $a8, $28
!by $a8, $28, $a8, $28
!by $00, $80, $00, $80
!by $00, $80, $00, $80
lookupHi !by (>VIEWPORT)+3, (>VIEWPORT)+3, (>VIEWPORT)+2, (>VIEWPORT)+2
!by (>VIEWPORT)+1, (>VIEWPORT)+1, (>VIEWPORT)+0, (>VIEWPORT)+0
!by (>VIEWPORT)+3, (>VIEWPORT)+3, (>VIEWPORT)+2, (>VIEWPORT)+2
!by (>VIEWPORT)+1, (>VIEWPORT)+1, (>VIEWPORT)+0, (>VIEWPORT)+0
!by (>VIEWPORT)+3, (>VIEWPORT)+3, (>VIEWPORT)+2, (>VIEWPORT)+2
!by (>VIEWPORT)+1, (>VIEWPORT)+1, (>VIEWPORT)+0, (>VIEWPORT)+0
!macro flip .v {
!by (.v & 128) | ((.v & 1) << 6) | ((.v & 2) << 4) | ((.v & 4) << 2) | (.v & 8) | ((.v & 16) >> 2) | ((.v & 32) >> 4) | ((.v & 64) >> 6)
}
!macro sp .v {
;!by (.v>>8)&255, .v&255
+flip (.v>>8)&255
+flip .v&255
}
ShapeTable ;-------------0
; H6543210H6543210
+sp %...#.#..........
+sp %.#.#.#.#........
+sp %.#.#.#.#........
+sp %.#.#.#.#........
+sp %...#........#.#.
+sp %#....#....#.#.#.
+sp %#..#......#.#.#.
+sp %#....#....#.#.#.
+sp %#..#..........#.
+sp %........#...#...
+sp %........#.....#.
+sp %........#...#...
+sp %........#.....#.
+sp %................
+sp %.#.#.#.#.#.#.#.#
+sp %#.#.#.#.#.#.#.#.
;-------------1
; H6543210H6543210
+sp %......##.##.....
+sp %#....#######....
+sp %....####.####...
+sp %#..###########..
+sp %..######.######.
+sp %################
+sp %.#######.#######
+sp %#.#############.
+sp %...#####.#####..
+sp %#...#########...
+sp %.....###.###....
+sp %#.....#####.....
+sp %.......#.#......
+sp %.###...........#
+sp %....###.....###.
+sp %.......#.###....
;-------------2
; H6543210H6543210
+sp %.#...#....#...#.
+sp %..#...#....#...#
+sp %.#.#...#....#...
+sp %..#.#....#...#..
+sp %...#.#....#...#.
+sp %....#.#....#...#
+sp %.#...#.#....#...
+sp %..#...#..#...#..
+sp %...#...#..#...#.
+sp %....#....#.#...#
+sp %.#...#....#.#...
+sp %..#...#....#.#..
+sp %...#...#....#.#.
+sp %....#....#...#.#
+sp %.....#....#...#.
+sp %......#....#...#
;-------------3
; H6543210H6543210
+sp %.....###.###....
+sp %...#####.#####..
+sp %..##........###.
+sp %.##..........##.
+sp %.............##.
+sp %..........###...
+sp %.......#.###....
+sp %...........###..
+sp %............###.
+sp %.............##.
+sp %.............##.
+sp %.............##.
+sp %.............##.
+sp %.##.........##..
+sp %..######.####...
+sp %...#####.###....

Antoine Vignau

unread,
Jun 10, 2013, 1:48:12 PM6/10/13
to
Interesting code, thanks for sharing.

I would make a second lookupHi table with values minus #$1C to remove the SEC SBC #$1C code.

I wonder whether your sprites should be aligned, I cannot say right now if you lose a cycle if they are not aligned or if you cross a page.

Antoine

BLuRry

unread,
Jun 10, 2013, 4:47:07 PM6/10/13
to
It would incur a 1-cycle penalty (so up to 16 cycles slower) if a tile overlaps a page boundary. Since the tiles are 32 bytes in size, I can fit 8 in a page neatly, so no harm there...

Good catch!

-B

qkumba

unread,
Jun 11, 2013, 12:08:11 PM6/11/13
to
dey
dec tileYcounter

why the 'dey'?

BLuRry

unread,
Jun 11, 2013, 12:54:55 PM6/11/13
to
Good catch! I was using Y as a counter at some point and scrapped it in that loop. I'll make it a point to remove that and re-test. Right now I'm making a tile editor (well, actually the basic tile editor is more or less done) so I'll follow up on this topic more holistically as I have something more concrete to show.

-B

qkumba

unread,
Jun 11, 2013, 1:29:44 PM6/11/13
to
clc
adc #$04

It looks like your carry will be always clear before this point, the clc might not be needed.

BLuRry

unread,
Jun 11, 2013, 5:31:43 PM6/11/13
to
I was questioning that same thing. also good catch!

-B

Mark Calderbank

unread,
Jun 17, 2013, 10:38:06 AM6/17/13
to
Antoine Vignau <antoine...@laposte.net> wrote:
> Interesting code, thanks for sharing.
>
> I would make a second lookupHi table with values minus #$1C to remove the
> SEC SBC #$1C code.

Or at least ditch the SEC and use SBC #$1B instead, since carry is
guaranteed to be clear from the preceding ADC instruction.

cybernesto

unread,
Jun 21, 2013, 1:30:13 PM6/21/13
to
Hi BLuRry, which assembler are you using? I tried WUDSN with MADS but it does not like the !cpu 65c02 directive. I also don't see the possibility to choose 65c02 in the preferences.

D Finnigan

unread,
Jun 21, 2013, 2:04:17 PM6/21/13
to
I believe that is ca65, a part of the cc65 compiler.

David Schmidt

unread,
Jun 21, 2013, 2:13:55 PM6/21/13
to
No, BLuRry's an ACME guy.

cybernesto

unread,
Jun 22, 2013, 4:07:56 AM6/22/13
to
That's right, ACME assembles it correctly.
I also wanted to try ca65, which is actually bundled in the WUDSN "archive containing all supported 6502 compilers" but I could not find the option in the preferences menu. ACME, ASM6, ATASM, DASM, KICKASS, MADS, TASS, TEST and XASM are listed, but not CA65. Does anyone know why?

BLuRry

unread,
Jun 24, 2013, 10:46:36 AM6/24/13
to
On Saturday, June 22, 2013 3:07:56 AM UTC-5, cybernesto wrote:
> That's right, ACME assembles it correctly.
>
> I also wanted to try ca65, which is actually bundled in the WUDSN "archive containing all supported 6502 compilers" but I could not find the option in the preferences menu. ACME, ASM6, ATASM, DASM, KICKASS, MADS, TASS, TEST and XASM are listed, but not CA65. Does anyone know why?

Oh, Acme works with Wudsn. I've used it quite a bit. :-) Make sure you have a recent build of it.

-B
0 new messages