Skip to content

Instantly share code, notes, and snippets.

@cbmeeks
Created December 13, 2011 03:26
Show Gist options
  • Save cbmeeks/1470406 to your computer and use it in GitHub Desktop.
Save cbmeeks/1470406 to your computer and use it in GitHub Desktop.
Commodore 64 full screen asm scroller
// Imports
.import source "../engine/vars.asm"
.import source "../engine/interrupts.asm"
.import source "../engine/map.asm"
.import source "../engine/misc.asm"
.import source "../engine/screen.asm"
.import source "../engine/sprites.asm"
.var XPIXSHIFT = 4
.var TIMER = 5
.pc = $0801 "Basic Upstart"
:BasicUpstart(start)
.pc = $4000 "Main Program"
start:
// set default map data
lda #<MAP_DATA
sta MAP_PTRL
lda #>MAP_DATA
sta MAP_PTRH
lda #3 // 3 rooms wide
sta MAP_WIDTH
lda #0
sta MAP_X
sta MAP_Y
lda #0
sta TILE_SIDE
lda #7
sta SCR_X_POS
lda SCR_X_POS
and #7
ora #16
sta $D016
lda #0
sta Y_TEMP
lda #0
sta MAP_COL_NUM
:SetVICBank0()
:SetScreenAndCharLocation(SCRBUFFER, CHARSET)
:ClearScreen(SCRBUFFER, 0)
:ClearScreen(DBLBUFFER, 0)
:ClearColorRam(10)
:SetBorderColor(BLACK)
:SetBackgroundColor(BLACK)
:SetMultiColor1(LIGHT_BLUE)
:SetMultiColor2(BLUE)
:SetMultiColorMode()
// :SetScrollMode()
lda #FLIP_BUF_COUNT
sta FLIP_COUNTER
:SetScreenAndCharLocation(SCRBUFFER, CHARSET) // $3400 visible at this point
lda #<SCRBUFFER
sta CURBUFFER_PTRL
lda #>SCRBUFFER
sta CURBUFFER_PTRH
lda #<DBLBUFFER
sta DBLBUFFER_PTRL
lda #>DBLBUFFER
sta DBLBUFFER_PTRH
jsr startdrawmap // draw initial map
lda #1
sta CURBUFFER
jsr flipbuffer
lda #60 // initial delay
sta TEMP1
// jsr shiftleft
:SetupIRQ(0, counters)
main:
jmp main
counters:
:BeginInterrupt()
dec TEMP1
bne !exit+
lda #1
sta TEMP1
// 7-6 Unused
//
// 5 ALWAYS SET THIS BIT TO 0 !
//
// 4 Multi-Color Mode: 1 = Enable (Text or
// Bit-Map);
// 3 Select 38/40 Column Text Display:
// 1 = 40 Cols
// 2-0 Smooth Scroll to X Pos
lda SCR_X_POS
and #7
ora #16
sta $D016
dec SCR_X_POS
lda SCR_X_POS
cmp #0
bne !exit+
jsr shiftleft
lda #7
sta SCR_X_POS
lda SCR_X_POS
and #7
ora #16
sta $D016
!exit:
:ReturnFromInterrupt()
shiftleft:
!draw_right_edge:
lda DBLBUFFER_PTRL // grab the DBLBUFFER_PTR
sta DLBBUFFER_EDGE_PTRL // and add 39 chars
lda DBLBUFFER_PTRH // so that we are on the RIGHT side
sta DLBBUFFER_EDGE_PTRH // of the screen
clc
lda DLBBUFFER_EDGE_PTRL // jump to the RIGHT edge
adc #39
sta DLBBUFFER_EDGE_PTRL
bcc *+4
inc DLBBUFFER_EDGE_PTRH
ldx #12 // number of tile rows to draw
stx MAP_ROW
lda MAP_COL_NUM // Y holds the offset of the room's map in tiles
sta Y_TEMP // so that 0 means upper-left of map, 240 lower right
!loop:
lda Y_TEMP
tay
lda (MAP_PTRL), y // A contains tile
tax // move tile number to X
clc // inc Y_TEMP by 20
lda Y_TEMP // so that next time we jump down a row in the map
adc #20
sta Y_TEMP
!continue:
lda TILE_SIDE // which side of the tile are we drawing?
beq !draw_left_side+
jmp !draw_right_side+
!draw_left_side:
ldy #0
lda TileCharLookupA, x // A now contains upper left char from tile
sta (DLBBUFFER_EDGE_PTRL), y // draw char on edge
ldy #40
lda TileCharLookupC, x // A now contains the lower left char from tile
sta (DLBBUFFER_EDGE_PTRL), y // draw char on edge
jmp !continue+
!draw_right_side:
ldy #0
lda TileCharLookupB, x // A now contains upper right char from tile
sta (DLBBUFFER_EDGE_PTRL), y // draw char on edge
ldy #40
lda TileCharLookupD, x // A now contains the lower right char from tile
sta (DLBBUFFER_EDGE_PTRL), y // draw char on edge
!continue:
clc
lda DLBBUFFER_EDGE_PTRL // jump down two rows (loop unrolled with 2x2 tile)
adc #80
sta DLBBUFFER_EDGE_PTRL
bcc *+4
inc DLBBUFFER_EDGE_PTRH
dec MAP_ROW // dec the row counter
bne !loop- // loop back if not at bottom
!start_screen_shift:
ldx #24 // Number of ROWS
ldy #38 // Number of COLUMNS
inc CURBUFFER_PTRL // shift over one char
!loop_shift:
lda (CURBUFFER_PTRL), y
sta (DBLBUFFER_PTRL), y
dey
bne !loop_shift-
lda (CURBUFFER_PTRL), y // load last char (0 actually)
sta (DBLBUFFER_PTRL), y // draw it
clc
lda CURBUFFER_PTRL // jump down to next line for the current buffer
adc #40
sta CURBUFFER_PTRL
bcc *+4
inc CURBUFFER_PTRH
clc
lda DBLBUFFER_PTRL // jump down to the next line for the double buffer
adc #40
sta DBLBUFFER_PTRL
bcc *+4
inc DBLBUFFER_PTRH
ldy #38 // reset Y
dex // dec X
bne !loop_shift- // have we reached the bottom?
jsr flipbuffer // flip buffers and reveal new content
lda TILE_SIDE // toggle tile side
eor #$01
sta TILE_SIDE
lda TILE_SIDE // OK, we just finished drawing a CHAR column
bne !exit+ // did we just toggle to the LEFT side? If so,
// then we are on a new ROOM column
inc MAP_COL_NUM
lda MAP_COL_NUM // Have we reached the end of a room column? (20)
cmp #20 // If so, reset back to 0 so that we don't
bcc !exit+ // get garbage room data.
lda #0 // also, at this point, we need to check the WORLD MAP
sta MAP_COL_NUM // to see what the next room number is....TBD
clc // for now, bump to the next room in ram
lda MAP_PTRL
adc #240
sta MAP_PTRL
bcc *+4
inc MAP_PTRH // this section needs to be replaced with WORLD MAP DATA
!exit:
rts // return
flipbuffer:
lda CURBUFFER
beq !flip+ // SCRBUFFER (compares to 0)
lda #<SCRBUFFER // make SCRBUFFER the visible buffer
sta CURBUFFER_PTRL
lda #>SCRBUFFER
sta CURBUFFER_PTRH
lda #<DBLBUFFER // make DBLBUFFER the hidden buffer
sta DBLBUFFER_PTRL
lda #>DBLBUFFER
sta DBLBUFFER_PTRH
lda #[[SCRBUFFER & $3FFF] / 64] | [[CHARSET & $3FFF] / 1024]
sta $D018
!exit:
lda CURBUFFER
eor #$01
sta CURBUFFER
rts
!flip:
lda #<DBLBUFFER // make DBLBUFFER the visible buffer
sta CURBUFFER_PTRL
lda #>DBLBUFFER
sta CURBUFFER_PTRH
lda #<SCRBUFFER // make SCRBUFFER the hidden buffer
sta DBLBUFFER_PTRL
lda #>SCRBUFFER
sta DBLBUFFER_PTRH
lda #[[DBLBUFFER & $3FFF] / 64] | [[CHARSET & $3FFF] / 1024]
sta $D018
!exit:
lda CURBUFFER
eor #$01
sta CURBUFFER
rts
startdrawmap:
lda #0 // Reset Row/Col
sta ColumnNumber
sta RowNumber
ldx #0
drawmap:
!loop:
ldy #0
lax (MAP_PTRL), y // X now contains tile number (from Map Data) $AF
lda TileCharLookupA, x // A now contains upper left char from tile
sta (CURBUFFER_PTRL), y // draw upper-left of tile
lda TileCharLookupB, x // A now contains upper-right char from tile
ldy #1
sta (CURBUFFER_PTRL), y // draw upper-right char from tile
lda TileCharLookupC, x // A now contains lower-left char from tile
ldy #40 // jump down to next line in screen buffer
sta (CURBUFFER_PTRL), y // draw lower-left char from tile
lda TileCharLookupD, x // A now contains lower-right char from tile
ldy #41
sta (CURBUFFER_PTRL), y // draw lower-right char from tile
clc // clear the carry bit
lda CURBUFFER_PTRL // screen buffer
adc #2 // add 2 to screen buffer (since our tiles are 2x2)
sta CURBUFFER_PTRL // update the screen buffer pointer
bcc *+4 // skip the next instruction if C is clear (didn't roll over)
inc CURBUFFER_PTRH // we rolled over so increase the HIGH byte (ie, $34FE + 2 = $3500)
inc MAP_PTRL // move to the next map data position
inc ColumnNumber // move to the next column
lda ColumnNumber // load the column number
cmp #20 // have we reached the right side?
bne !loop- // not yet...repeat loop
lda #0 // yes, now reset the column number
sta ColumnNumber // and store it.
clc // clear carry
lda CURBUFFER_PTRL // jump down to the next row
adc #40 // add 40 (jumps down a row)
sta CURBUFFER_PTRL // update current buffer pointer
bcc *+4 // have we rolled over?
inc CURBUFFER_PTRH // yes so increase the high byte
inc RowNumber // increase the row number
lda RowNumber // load current row number
cmp #12 // have we reached the bottom of the screen?
bne drawmap // no, continue drawing the next row
rts // yes, return
.var charname = "../51 pegasus/gfx/chars.raw"
.var room001_name = "../51 pegasus/rooms/room001"
.var room002_name = "../51 pegasus/rooms/room002"
.var room003_name = "../51 pegasus/rooms/room003"
.var room004_name = "../51 pegasus/rooms/room004"
.var room005_name = "../51 pegasus/rooms/room005"
.var room006_name = "../51 pegasus/rooms/room006"
.var tilename = "../51 pegasus/gfx/tiles.raw"
// variables ZP = $10 - $28
.var RowNumber = $10
.var ColumnNumber = $11
// Chars ZP = $29 - $39
.var CHARSET = $2000
.var CURRENT_TILE = $29
// Lookups
.var LOOKUPS = $C100 // ; various lookup tables
// Map ZP = $3A - $4F
// .var WORLD_DATA = $400
.var MAP_DATA = $C400
.var MAP_PTRL = $3A
.var MAP_PTRH = $3B
.var ROOM_PTRL = $3C
.var ROOM_PTRH = $3D
.var CUR_TILE = $3E
.var MAP_ROW = $3F
.var MAP_COL_NUM = $40
.var MAP_WIDTH = $41 // in ROOMS
.var MAP_HEIGHT = $42
.var MAP_X = $43 // position in tiles
.var MAP_Y = $44
.var NUM_TILES = 64
// Screen ZP = $50 - $70
.var FLIP_COUNTER = $50
.var FLIP_BUF_COUNT = 40
.var CURBUFFER_PTRL = $52 // the address of the current buffer (SCR or DBL) which is shown
.var CURBUFFER_PTRH = $53
.var DBLBUFFER_PTRL = $54
.var DBLBUFFER_PTRH = $55
.var DLBBUFFER_EDGE_PTRL = $56
.var DLBBUFFER_EDGE_PTRH = $57
.var SCR_X_POS = $58
.var SCR_Y_POS = $59
.var CURBUFFER = $67 // 0 = SCREENBUFFER 1 = DBLBUFFER
.var SCRBUFFER = $3400
.var DBLBUFFER = $3800
// Temp
.var TEMP1 = $70
.var TEMP2 = $71
.var X_TEMP = $72
.var Y_TEMP = $73
// Tiles ZP = ??
.var TILE_SIDE = $74
.var TILES_DATA = $C000
// Character Set
.pc = CHARSET "Chars"
.var chars = LoadBinary(charname)
.fill chars.getSize(), chars.get(i)
// Lookup Tables
.pc = LOOKUPS "Various Lookups"
TileCharLookupA: .for(var i=0; i < NUM_TILES; i++) .byte i * 4
TileCharLookupB: .for(var i=0; i < NUM_TILES; i++) .byte [i * 4] + 1
TileCharLookupC: .for(var i=0; i < NUM_TILES; i++) .byte [i * 4] + 2
TileCharLookupD: .for(var i=0; i < NUM_TILES; i++) .byte [i * 4] + 3
RoomNumberLookup: .word MAP_DATA + [0 * 240], MAP_DATA + [1 * 240], MAP_DATA + [2 * 240]
// Map (Room) Data
.pc = MAP_DATA
.var room001 = LoadBinary(room001_name)
.fill room001.getSize(), room001.get(i)
.var room002 = LoadBinary(room002_name)
.fill room002.getSize(), room002.get(i)
.var room003 = LoadBinary(room003_name)
.fill room003.getSize(), room003.get(i)
.var room004 = LoadBinary(room004_name)
.fill room004.getSize(), room004.get(i)
.var room005 = LoadBinary(room005_name)
.fill room005.getSize(), room005.get(i)
.var room006 = LoadBinary(room006_name)
.fill room006.getSize(), room006.get(i)
// Tiles
.pc = TILES_DATA "Tiles"
.var tilesdata = LoadBinary(tilename)
.fill tilesdata.getSize(), tilesdata.get(i)
// World
// .pc = WORLD_DATA "World Data"
// .byte 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment