diff --git a/05. Screen Scrolling/Constants.asm b/05. Screen Scrolling/Constants.asm new file mode 100644 index 0000000..3ab1a88 --- /dev/null +++ b/05. Screen Scrolling/Constants.asm @@ -0,0 +1,205 @@ +//=============================================================================== +// $00-$FF PAGE .label Zero (256 bytes) + + // $00-$01 Reserved for IO +.label ZeroPageTemp = $02 + // $03-$8F Reserved for BASIC + // using $73-$8A CHRGET as BASIC not used for our game +.label ZeroPageParam1 = $73 +.label ZeroPageParam2 = $74 +.label ZeroPageParam3 = $75 +.label ZeroPageParam4 = $76 +.label ZeroPageParam5 = $77 +.label ZeroPageParam6 = $78 +.label ZeroPageParam7 = $79 +.label ZeroPageParam8 = $7A +.label ZeroPageParam9 = $7B + // $90-$FA Reserved for Kernal +.label ZeroPageLow = $45 +.label ZeroPageHigh = $46 +.label ZeroPageLow2 = $47 +.label ZeroPageHigh2 = $48 + // $FF Reserved for Kernal + +//=============================================================================== +// $0200-$9FFF RAM (40K) + +.label SCREENRAM = $4000 +.label SPRITE0 = $43F8 +.label COLOURRAM = $d800 + +// $0801 +// Game code is placed here by using the *=$0801 directive +// in gameMain.asm + + +// 192 decimal * 64(sprite size) = 10880(hex $2A80) +.label SPRITERAM = 170 + +//=============================================================================== +// $D000-$DFFF IO (4K) + +// These are some of the C64 registers that are mapped into +// IO memory space +// Names taken from 'Mapping the Commodore 64' book + +.label SP0X = $D000 +.label SP0Y = $D001 +.label MSIGX = $D010 +.label SCROLY = $D011 +.label RASTER = $D012 +.label SPENA = $D015 +.label SCROLX = $D016 +.label YXPAND = $D017 +.label VMCSB = $D018 +.label VICIRQ = $D019 +.label SPBGPR = $D01B +.label SPMC = $D01C +.label XXPAND = $D01D +.label SPSPCL = $D01E +.label SPBGCL = $D01F +.label EXTCOL = $D020 +.label BGCOL0 = $D021 +.label BGCOL1 = $D022 +.label BGCOL2 = $D023 +.label BGCOL3 = $D024 +.label SPMC0 = $D025 +.label SPMC1 = $D026 +.label SP0COL = $D027 +.label FRELO1 = $D400 //(54272) + +.label FREHI1 = $D401 //(54273) +.label PWLO1 = $D402 //(54274) +.label PWHI1 = $D403 //(54275) +.label VCREG1 = $D404 //(54276) +.label ATDCY1 = $D405 //(54277) +.label SUREL1 = $D406 //(54278) +.label FRELO2 = $D407 //(54279) +.label FREHI2 = $D408 //(54280) +.label PWLO2 = $D409 //(54281) +.label PWHI2 = $D40A //(54282) +.label VCREG2 = $D40B //(54283) +.label ATDCY2 = $D40C //(54284) +.label SUREL2 = $D40D //(54285) +.label FRELO3 = $D40E //(54286) +.label FREHI3 = $D40F //(54287) +.label PWLO3 = $D410 //(54288) +.label PWHI3 = $D411 //(54289) +.label VCREG3 = $D412 //(54290) +.label ATDCY3 = $D413 //(54291) +.label SUREL3 = $D414 //(54292) +.label SIGVOL = $D418 //(54296) +.label CIAPRA = $DC00 +.label CIAPRB = $DC01 + +// Kernel Jump Vectors +.label krljmp_PCINT = $FF81 +.label krljmp_IOINIT = $FF84 +.label krljmp_RAMTAS = $FF87 +.label krljmp_RESTOR = $FF8A +.label krljmp_VECTOR = $FF8D +.label krljmp_SETMSG = $FF90 +.label krljmp_SECOND = $FF93 +.label krljmp_TKSA = $FF96 +.label krljmp_MEMTOP = $FF99 +.label krljmp_MEMBOT = $FF9C +.label krljmp_SCNKEY = $FF9F +.label krljmp_SETTMO = $FFA2 +.label krljmp_ACPTR = $FFA5 +.label krljmp_CIOUT = $FFA8 +.label krljmp_UNTALK = $FFAB +.label krljmp_UNLSN = $FFAE +.label krljmp_LISTEN = $FFB1 +.label krljmp_TALK = $FFB4 +.label krljmp_READST = $FFB7 +.label krljmp_SETLFS = $FFBA +.label krljmp_SETNAM = $FFBD +.label krljmp_OPEN = $FFC0 +.label krljmp_CLOSE = $FFC3 +.label krljmp_CHKIN = $FFC6 +.label krljmp_CHKOUT = $FFC9 +.label krljmp_CLRCHN = $FFCC +.label krljmp_CHRIN = $FFCF +.label krljmp_CHROUT = $FFD2 +.label krljmp_LOAD = $FFD5 +.label krljmp_SAVE = $FFD8 +.label krljmp_SETTIM = $FFDB +.label krljmp_RDTIM = $FFDE +.label krljmp_STOP = $FFE1 +.label krljmp_GETIN = $FFE4 +.label krljmp_CLALL = $FFE7 +.label krljmp_UDTIM = $FFEA +.label krljmp_SCREEN = $FFED +.label krljmp_PLOT = $FFF0 +.label krljmp_BASE = $FFF3 + +.label krljmpLSTX = 197 + +//Peek(197) Codes +.const scanCode_INS_DEL = 0 +.const scanCode_RET = 1 +.const scanCode_CUR_RI = 2 +.const scanCode_F7 = 3 +.const scanCode_F1 = 4 +.const scanCode_F3 = 5 +.const scanCode_F5 = 6 +.const scanCode_CUR_DN = 7 +.const scanCode_3 = 8 +.const scanCode_W = 9 +.const scanCode_A = 10 +.const scanCode_4 = 11 +.const scanCode_Z = 12 +.const scanCode_S = 13 +.const scanCode_E = 14 +.const scanCode_5 = 16 +.const scanCode_R = 17 +.const scanCode_D = 18 +.const scanCode_6 = 19 +.const scanCode_C = 20 +.const scanCode_F = 21 +.const scanCode_T = 22 +.const scanCode_X = 23 +.const scanCode_7 = 24 +.const scanCode_Y = 25 +.const scanCode_G = 26 +.const scanCode_8 = 27 +.const scanCode_B = 28 +.const scanCode_H = 29 +.const scanCode_U = 30 +.const scanCode_V = 31 +.const scanCode_9 = 32 +.const scanCode_I = 33 +.const scanCode_J = 34 +.const scanCode_0 = 35 +.const scanCode_M = 36 +.const scanCode_K = 37 +.const scanCode_O = 38 +.const scanCode_N = 39 +.const scanCode_PLUS = 40 +.const scanCode_P = 41 +.const scanCode_L = 42 +.const scanCode_MINUS = 43 +.const scanCode_FULSTP = 44 +.const scanCode_COLON = 45 +.const scanCode_AT = 46 +.const scanCode_COMMA = 47 +.const scanCode_POUND = 48 +.const scanCode_ASTRIK = 49 +.const scanCode_SEMICOLON = 50 +.const scanCode_CLEAR_HOME = 51 +.const scanCode_EQUALS = 53 +.const scanCode_EXPONENT_ARROW = 54 +.const scanCode_FWD_SLASH = 55 +.const scanCode_1 = 56 +.const scanCode_LEFT_ARROW = 57 +.const scanCode_2 = 59 +.const scanCode_SPACEBAR = 60 +.const scanCode_Q = 62 +.const scanCode_RUNSTOP = 63 +.const scanCode_NO_KEY = 64 + +.const joystickUp = %00000001 +.const joystickDown = %00000010 +.const joystickLeft = %00000100 +.const joystickRight = %00001000 +.const joystickFire = %00010000 \ No newline at end of file diff --git a/05. Screen Scrolling/MapLoader.asm b/05. Screen Scrolling/MapLoader.asm new file mode 100644 index 0000000..435c889 --- /dev/null +++ b/05. Screen Scrolling/MapLoader.asm @@ -0,0 +1,420 @@ +#import "Constants.asm" + +BasicUpstart2(start) + +.label Row = $02B0 +.label Col = $02B1 +.label TileNumber = $02B2 +.label FrameCounter = $02A8 +.label BellFrameCounter = $02B3 +.label ScrollFrameCounter = $02B4 +.label Direction = $02B5 + +start: + + lda 1 + and #%11111110 + sta 1 + + lda #BLACK + sta EXTCOL + lda #BLUE + sta BGCOL0 + + lda $DD00 + and #%11111100 + ora #%00000010 //<- your desired VIC bank value, Bank 1 + sta $DD00 + + lda $D018 + and #%00000001 + ora #%00001000 //<- your desired CharMem bank value, Screem @ $4000, Character @ $6000 + sta $D018 + + lda SCROLX + and #%11110111 + ora #%00010000 // Set multicolour mode for characters + sta SCROLX + + lda #BROWN + sta BGCOL1 + lda #GREY + sta BGCOL2 + + jsr DrawScreen // Draw Map on the Screen + +loop: + sei + lda #90 // Scanline -> A + cmp RASTER // Compare A to current raster line + bne loop + + inc $D020 + +EndControls: + inc FrameCounter // increase frame counter + lda FrameCounter + and #127 // Only count 0 -> 127 (128 cycles) + cmp #2 // 4 second frame counter (4 frames = .5 secs per frame) + bne !ByPassReSet+ + lda #0 // reset frame + sta FrameCounter + + lda Direction + beq !ByPassScroll+ + cmp #1 + bne DirectionLeft + dec ScrollFrameCounter + lda ScrollFrameCounter + and #%00000111 + sta ScrollFrameCounter + + lda SCROLX + and #%11111000 + ora ScrollFrameCounter + sta SCROLX + + lda ScrollFrameCounter + bne !ByPassScroll+ + jsr ScrollLeft + jmp !ByPassScroll+ + +DirectionLeft: + inc ScrollFrameCounter + lda ScrollFrameCounter + and #%00000111 + sta ScrollFrameCounter + + lda ScrollFrameCounter + bne !ByPassScrollHere+ + jsr ScrollRight + +!ByPassScrollHere: + lda SCROLX + and #%11111000 + ora ScrollFrameCounter + sta SCROLX + +!ByPassScroll: + + lda 197 + cmp #scanCode_A + bne TestForDKey + lda #1 + sta Direction + jmp EndControls + +TestForDKey: + cmp #scanCode_D + bne Nothing + lda #2 + sta Direction + jmp EndControls + +Nothing: + lda #0 + sta Direction + +!ByPassReSet: + cli + + dec $D020 + jmp loop + +CalculateBellFrame: + lda FrameCounter + lsr // /2 + lsr // /4 + lsr // /8 + lsr // 16 + lsr // 32 + //sta BellFrameCounter + rts + +DrawScreen: + lda #SCREENRAM + (5*40) + sta Screen + 1 + + lda #COLOURRAM + (5*40) + sta Colour + 1 + + lda #MAP_1 + sta MapTile + 1 + + lda #0 + sta Row + +DrawRowLoop: + lda #0 + sta Col + +DrawColumnLoop: + ldy #0 + + lda #0 + sta TileCharLookup + sta TileCharLookup + 1 + + lda MapTile: $DEAD // Get Current Tile Number + + sta TileNumber + sta TileCharLookup + + asl TileCharLookup // * 2 + rol TileCharLookup + 1 + asl TileCharLookup + rol TileCharLookup + 1 // * 4 + + clc + lda #MAP_TILES + adc TileCharLookup + 1 + sta TileCharLookup + 1 + +DrawTile: + lda TileCharLookup: $B00B, y // get Tile Character + + ldx TileLocationOffSet,y // Character Offset. + sta Screen: $BABE, x + + ldx TileNumber + lda COLOUR_TILES, x // Colour information for tile + + ldx TileLocationOffSet, y + sta Colour: $BEEF,x // Character Colour Ram + + iny + cpy #$04 + bne DrawTile + + LIBMATH_ADD8BITTO16BIT_AV(MapTile,$01) + + LIBMATH_ADD8BITTO16BIT_AV(Screen,$02) + + LIBMATH_ADD8BITTO16BIT_AV(Colour,$02) + + inc Col + ldx Col + cpx #$14 + beq EndDrawColumnLoop + jmp DrawColumnLoop + + EndDrawColumnLoop: + LIBMATH_ADD8BITTO16BIT_AV(Screen,$28) + + LIBMATH_ADD8BITTO16BIT_AV(Colour,$28) + + inc Row + ldx Row + cpx #$0A + beq EndDrawRowLoop + jmp DrawRowLoop + +EndDrawRowLoop: + rts + +TileLocationOffSet: + .byte 0, 1, 40, 41 + +BellAnimationTiles: + .byte 27, 29, 27, 31 + +* = $2000 "Map data" + MAP_TILES: + .import binary "..\02. CharPad\Quasidemo - Tiles.bin" + + COLOUR_TILES: + .import binary "..\02. CharPad\Quasidemo - TileAttribs.bin" + + CHAR_ColourS: + .import binary "..\02. CharPad\Quasidemo - CharAttribs.bin" + + MAP_1: + .import binary "..\02. CharPad\Quasidemo - Map (20x11).bin" + +* = $6000 "Chars data" + CHARS: + .import binary "..\02. CharPad\Quasidemo - Chars.bin" + +.macro LIBMATH_ADD8BITTO16BIT_AV(AddAddress,AddValue) +{ + clc + lda AddAddress + adc #AddValue + sta AddAddress + lda AddAddress + 1 + adc #$00 + sta AddAddress + 1 +} + +.macro DrawTile(TileLocationZeroPage, TileScreen, TileColour) +{ + ldy #0 +!Tile: + lda (TileLocationZeroPage), y // get Tile Character + + ldx TileLocationOffSet,y // Character Offset. + sta TileScreen, x + + ldx TileNumber + lda COLOUR_TILES, x // Colour information for tile + + ldx TileLocationOffSet, y + sta TileColour,x // Character Colour Ram + + iny + cpy #$04 + bne !Tile- +} + + // inc FrameCounter // increase frame counter + // lda FrameCounter + // and #127 // Only count 0 -> 127 (128 cycles) + //cmp #128 // 4 second frame counter (4 frames = .5 secs per frame) + //bne AnimateBell + //lda #0 // reset frame + // sta FrameCounter + +// AnimateBell: + //jsr CalculateBellFrame // work out which frame the bell is currently on + + //cmp BellFrameCounter // Bell Frame Counter same as before, no need to re-draw frame + //bne DrawBellFrame +// jmp EvaluateSpriteControl + +// DrawBellFrame: +// sta BellFrameCounter + +// lda #0 +// sta ZeroPageLow +// sta ZeroPageLow + 1 + +// ldx BellFrameCounter +// lda BellAnimationTiles,x // get bell tile frame for the frame counter +// sta TileNumber + +// sta ZeroPageLow // work out tile character offset +// asl ZeroPageLow // * 2 +// rol ZeroPageLow + 1 +// asl ZeroPageLow +// rol ZeroPageLow + 1 // * 4 + +// clc +// lda #MAP_TILES +// adc ZeroPageLow + 1 +// sta ZeroPageLow + 1 + +// DrawTile(ZeroPageLow, $4162, $D962) // Draw Tile + +// LIBMATH_ADD8BITTO16BIT_AV(ZeroPageLow,$04) +// inc TileNumber +// DrawTile(ZeroPageLow, $4164, $D964) // Draw Next Tile + +// EvaluateSpriteControl: + +* = * "Scroll Right" +ScrollRight: +{ + .label Rows = ZeroPageParam1 + .label Cols = ZeroPageParam2 + .label ScreenLoc = ZeroPageLow + .label ColourLoc = ZeroPageLow2 + + .label CharTransfer = ZeroPageParam3 + .label ColTransfer = ZeroPageParam3 + + .label StartOfScrollingScreen = SCREENRAM + (5 * 40) + .label StartOfScrollingColour = COLOURRAM + (5 * 40) + +RowColumnCollection: + .for (var row=0; row<20; row++) + { + lda StartOfScrollingScreen + (row * 40) + 39 + pha + lda StartOfScrollingColour + (row * 40) + 39 + pha + + .for (var col=38; col>=0; col--) + { + lda StartOfScrollingScreen + (row * 40) + col + sta StartOfScrollingScreen + (row * 40) + col + 1 + + lda StartOfScrollingColour + (row * 40) + col + sta StartOfScrollingColour + (row * 40) + col + 1 + } + + // ldy #38 + // !ColumnLooper: + // lda StartOfScrollingScreen + (row * 40),y + // iny + // sta StartOfScrollingScreen + (row * 40),y + // dey + + // lda StartOfScrollingColour + (row * 40),y + // iny + // sta StartOfScrollingColour + (row * 40),y + // dey + + // dey + // bpl !ColumnLooper- + + pla + sta StartOfScrollingColour + (row * 40) + pla + sta StartOfScrollingScreen + (row * 40) + } + rts +} + +* = * "Scroll Left" +ScrollLeft: +{ + .label Rows = ZeroPageParam1 + .label Cols = ZeroPageParam2 + .label ScreenLoc = ZeroPageLow + .label ColourLoc = ZeroPageLow2 + + .label CharTransfer = ZeroPageParam3 + .label ColTransfer = ZeroPageParam3 + + .label StartOfScrollingScreen = SCREENRAM + (5 * 40) + .label StartOfScrollingColour = COLOURRAM + (5 * 40) + + RowColumnCollection: + .for (var row=0; row<20; row++) + { + lda StartOfScrollingScreen + (row * 40) + pha + lda StartOfScrollingColour + (row * 40) + pha + + .for (var col=0; col<39; col++) + { + lda StartOfScrollingScreen + (row * 40) + col + 1 + sta StartOfScrollingScreen + (row * 40) + col + + lda StartOfScrollingColour + (row * 40) + col + 1 + sta StartOfScrollingColour + (row * 40) + col + } + + pla + sta StartOfScrollingColour + (row * 40) + 39 + pla + sta StartOfScrollingScreen + (row * 40) + 39 + } + rts +} + + + diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..ac380b2 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,15 @@ +## Twitch Stream Tutorials + +These tutorials are based around libraries to allow the "noob" coder to get there head around tricky topics of the C64. + +These topics are : +* Sprites +* CharPad and Tile Maps +* Sprite Multiplexing +* Screen Smooth Scrolling Left and Right + +All these libraries are free to use, for all you budding C64 game developers. + +Enjoy + +**OldSkoolCoder** \ No newline at end of file