├── Lesson_1 ├── GameHeader.i ├── Hello_World_Background.asm ├── README.md ├── article_images │ ├── Lesson1_DrawingWithInsertKey.png │ ├── Lesson1_ElysianVMU.png │ ├── Lesson1_GitBash.png │ └── Lesson1_YouDidIt.png ├── bin │ └── Lesson_1.vms ├── lib │ ├── LICENSE │ ├── libkcommon.asm │ ├── libperspective.asm │ └── sfr.i └── main.asm ├── Lesson_2 ├── Example_Sprite.asm ├── GameHeader.i ├── Hello_World_Background.asm ├── README.md ├── bin │ └── Lesson_2.vms ├── img │ ├── Lesson2_Coordinates.png │ ├── Lesson2_FinalAssembledCodeAnimation_ThanksEZGIF.gif │ ├── Lesson2_GetInputACCGraph.png │ └── Lesson2_GetInputACCGraph_FilledIn.png ├── lib │ ├── LICENSE │ ├── libkcommon.asm │ ├── libperspective.asm │ └── sfr.i └── main.asm ├── Lesson_3 ├── Article_Images │ ├── Lesson3_P_Draw_Sprite_CutOff.png │ ├── Lesson3_P_Draw_Sprite_Text_And_Commas_Example.png │ ├── Lesson3_P_Draw_Sprite_Text_And_Commas_Example_Smaller_Resized.png │ ├── Masking_Example_Animation_Start.png │ ├── Masking_Example_Right_Column_Explanation_Graphic.png │ ├── Sprite_Masking_Tutorial_Guide_Animation.gif │ └── Un-Masked_Sprite_With_Black_BG+Vertical_White_Stripes.gif ├── GameHeader.i ├── README.md ├── img │ ├── Example_Sprite.ASM │ ├── Example_Sprite_Mask.ASM │ ├── Hello_World_Background.asm │ └── Lesson3_P_Draw_Sprite_CutOff.png ├── lib │ ├── LICENSE │ ├── libkcommon.asm │ ├── libperspective.asm │ └── sfr.i └── main.asm ├── Lesson_4 ├── Article_Images │ ├── Lesson4_BackGroundTextGraphicPlusWithSprites_Example.png │ └── Lesson4_BackGroundTextGraphic_Example.png ├── Cursor_Gameplay.asm ├── GameHeader.i ├── Main_Menu.asm ├── README.md ├── bin │ ├── Lesson4.vms │ └── Lesson_4.vms ├── img │ ├── Digit_0.ASM │ ├── Digit_0.png │ ├── Digit_1.ASM │ ├── Digit_1.png │ ├── Digit_2.asm │ ├── Digit_2.png │ ├── Digit_3.ASM │ ├── Digit_3.png │ ├── Digit_4.asm │ ├── Digit_4.png │ ├── Digit_5.ASM │ ├── Digit_5.png │ ├── Digit_6.ASM │ ├── Digit_6.png │ ├── Digit_7.asm │ ├── Digit_7.png │ ├── Digit_8.ASM │ ├── Digit_8.png │ ├── Digit_9.ASM │ ├── Digit_9.png │ ├── ExampleBG_City.asm │ ├── ExampleBG_City.png │ ├── Example_Sprite.asm │ ├── Example_Sprite_HeroChao_Mask.asm │ ├── Example_Sprite_HeroChao_Mask.png │ ├── Example_Sprite_Mask.asm │ ├── Hello_World_Background.asm │ ├── Main_Menu_BG.asm │ ├── Menu_Text_Character_1.asm │ ├── Menu_Text_Character_1.png │ ├── Menu_Text_Character_1_Highlighted.asm │ ├── Menu_Text_Character_1_Highlighted.png │ ├── Menu_Text_Character_2.asm │ ├── Menu_Text_Character_2_Highlighted.asm │ ├── Menu_Text_Character_2_Smiley.asm │ ├── Menu_Text_Character_2_Smiley.png │ ├── Menu_Text_Character_2_Smiley_Highlighted │ ├── Menu_Text_Character_2_Smiley_Highlighted.png │ ├── Menu_Text_Character_3.asm │ ├── Menu_Text_Character_3_Highlighted.asm │ ├── Menu_Text_OK_Button_Resume.asm │ ├── Menu_Text_OK_Button_Resume.png │ ├── Menu_Text_OK_Button_Resume_Highlighted.asm │ ├── Menu_Text_OK_Button_Resume_Highlighted.png │ ├── Menu_Text_OK_Button_Start.asm │ ├── Menu_Text_OK_Button_Start.png │ ├── Menu_Text_OK_Button_Start_Highlighted.asm │ ├── Menu_Text_OK_Button_Start_Highlighted.png │ ├── Menu_Text_Player_Option.asm │ ├── Menu_Text_Player_Option.png │ ├── Menu_Text_Stage_1_City.asm │ ├── Menu_Text_Stage_1_City.png │ ├── Menu_Text_Stage_1_City_Highlighted.asm │ ├── Menu_Text_Stage_1_City_Highlighted.png │ ├── Menu_Text_Stage_2_Jungle.asm │ ├── Menu_Text_Stage_2_Jungle.png │ ├── Menu_Text_Stage_2_Jungle_Highlighted.asm │ ├── Menu_Text_Stage_Option.asm │ ├── Menu_Text_Stage_Option.png │ ├── Menu_Text_Welcome_Message.asm │ └── Menu_Text_Welcome_Message.png ├── lib │ ├── LICENSE │ ├── libkcommon.asm │ ├── libperspective.asm │ └── sfr.i └── main.asm ├── Lesson_5 ├── GameHeader.i ├── README.MD ├── bin │ └── Lesson_5.vms ├── img │ ├── Digit_1.ASM │ ├── Digit_2.asm │ ├── Digit_3.ASM │ ├── Digit_4.ASM │ ├── Digit_5.ASM │ ├── Digit_6.ASM │ ├── Digit_7.asm │ ├── Digit_8.ASM │ ├── Digit_9.ASM │ ├── ExampleBG_City.asm │ ├── Example_Sprite_Jump.asm │ ├── Example_Sprite_Mask.asm │ ├── Obstacle_Sprite_Mask.asm │ ├── Player_Running_1_Mask.asm │ ├── Player_Running_3_Mask.asm │ ├── Player_Running_Mask_2.asm │ ├── Runner_BackGround_1.asm │ ├── Runner_BackGround_2.asm │ ├── Runner_BackGround_3.asm │ └── Runner_BackGround_4.asm ├── lib │ └── libkcommon.asm ├── main.asm └── src │ ├── Runner_Gameplay.asm │ └── Runner_Menu.asm └── README.md /Lesson_1/GameHeader.i: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------------------- 2 | ; ROM info 3 | ;------------------------------------------------------------------------------- 4 | .org $200 5 | 6 | .byte "VMU Dev Lesson 1 " ; 16 bytes 7 | .byte "VMU Beginners' Tutorial #1." ; 32 byte 8 | ; Thanks To Marcus, Sebastian, And Tyro For Header Format! 9 | 10 | .org $240 11 | 12 | .word 1 ; number of icons (max = 3) 13 | .word 14 ; animation speed 14 | 15 | ;------------------------------------------------------------------------------- 16 | ; Game Icon Palette Table 17 | ; 18 | ; Each entry is 16-bit, as such AAAARRRR GGGGBBBB 19 | ; where a value of 0xF for alpha means opaque 20 | ;------------------------------------------------------------------------------- 21 | .org $260 22 | 23 | .word $fffe, $f114, $ffff, $f8df, $fa0f, $f02f, $ffae, $f000 24 | .word $f60a, $ff8d, $f406, $f051, $f081, $fd7b, $fd00, $f900 25 | 26 | ;------------------------------------------------------------------------------- 27 | ; Game Icon Data 28 | ;------------------------------------------------------------------------------- 29 | 30 | ; This is where the game icons are placed. Each icon is 512 byte long, 31 | ; 32 * 32 pixel, each pixel being represented by 4 bit (one nybble) that 32 | ; serve as a pointer into the color palette table. 33 | 34 | .org $280 35 | ; 0 5 10 15 20 25 30 36 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 37 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 38 | .byte $00,$10,$00,$10,$00,$00,$00,$01,$11,$01,$00,$00,$00,$00,$00,$00 39 | .byte $00,$11,$01,$10,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$10,$00 40 | .byte $00,$10,$10,$10,$10,$01,$00,$01,$10,$01,$01,$10,$11,$01,$11,$00 41 | .byte $00,$10,$00,$10,$10,$01,$00,$01,$00,$01,$01,$00,$10,$00,$10,$00 42 | .byte $00,$10,$00,$10,$01,$11,$00,$01,$00,$01,$01,$01,$10,$00,$10,$00 43 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 44 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 45 | .byte $00,$00,$00,$00,$01,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 46 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 47 | .byte $10,$00,$10,$10,$00,$10,$10,$00,$10,$00,$01,$10,$00,$00,$00,$00 48 | .byte $10,$00,$10,$11,$01,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 49 | .byte $10,$00,$10,$10,$10,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 50 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$11,$11,$01,$10,$01,$10 51 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$10,$01,$01,$01,$01,$01 52 | .byte $00,$10,$00,$10,$00,$10,$01,$11,$00,$00,$10,$01,$01,$10,$01,$10 53 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00 54 | .byte $00,$00,$00,$00,$00,$00,$00,$01,$11,$00,$00,$00,$01,$00,$01,$00 55 | .byte $00,$00,$00,$00,$00,$00,$01,$10,$00,$11,$00,$00,$00,$00,$00,$00 56 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 57 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 58 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 59 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 60 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 61 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 62 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$10,$00,$00,$00,$00,$00 63 | .byte $00,$00,$00,$00,$00,$00,$11,$11,$00,$01,$10,$00,$00,$00,$00,$00 64 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$01,$00,$10,$00,$00,$00,$00,$00 65 | .byte $00,$00,$00,$00,$00,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00 66 | .byte $00,$00,$00,$00,$00,$00,$00,$11,$11,$10,$00,$00,$00,$00,$00,$00 67 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -------------------------------------------------------------------------------- /Lesson_1/Hello_World_Background.asm: -------------------------------------------------------------------------------- 1 | Hello_World_BackGround: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 6 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 7 | .byte %00000000,%00100010,%01100010,%01000111,%00000000,%00000000 8 | .byte %00000000,%00111110,%10010010,%01001000,%10000000,%00000000 9 | .byte %00000000,%00100010,%11110010,%01001000,%10000000,%00000000 10 | .byte %00000000,%00100010,%10000010,%01001000,%10010000,%00000000 11 | .byte %00000000,%00100010,%01110010,%01000111,%00010000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00100000,%00000000 13 | .byte %00000001,%00000001,%00000000,%00000100,%00001001,%00000000 14 | .byte %00000001,%00010001,%00000000,%00000100,%00001001,%00000000 15 | .byte %00000001,%00010001,%00111001,%01100100,%01111001,%00000000 16 | .byte %00000000,%10101010,%01000101,%10000100,%10001001,%00000000 17 | .byte %00000000,%10101010,%01000101,%00000100,%10001001,%00000000 18 | .byte %00000000,%01000100,%01000101,%00000100,%10001000,%00000000 19 | .byte %00000000,%01000100,%00111001,%00000100,%01111001,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 26 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 27 | .byte %00000000,%00000000,%00100000,%00000100,%00000000,%00000000 28 | .byte %00000000,%00000000,%00100000,%10000100,%00000000,%00000000 29 | .byte %00000000,%00000000,%00100100,%00100100,%00000000,%00000000 30 | .byte %00000000,%00000000,%00100011,%11000100,%00000000,%00000000 31 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 32 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 33 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 34 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_1/README.md: -------------------------------------------------------------------------------- 1 | ## Lesson 1: Getting Started 2 | 3 | Hello, and welcome to the VMU Beginner's Development Tutorial! 4 | 5 | To start, you'll need these 3 things: 6 | 7 | - [WaterBear](https://wtetzner.github.io/waterbear/), by Walter Tetzner: This Assembler is awesome, as is its Documentation. It also provides a Disassembler to help you analyze existing VMU Programs' Code. 8 | - [LibPerspective](https://slum.online/dreamcast/), by Kresna Susila: This is an amazing Graphics Library for the VMU. I don't know how to draw to the screen without it. 9 | - [ElysianVMU](http://evmu.elysianshadows.com/), by Falco Girgis: This is the best VMU Emulator out there, and has handy tools for Developers. We'll be seeing them in action in later lessons. 10 | 11 | Once you've got those three installed, we're going to start by drawing a static image to the screen. Let's create and compile our first VMU Program! 12 | (main.asm) 13 | 14 | Create main.asm in your text editor of choice; you can use anything you'd like. I'll be using Visual Studio. You can do `touch main.asm` in Git Bash if your Text Editor doesn't allow you to make an `.asm` File. Once our blank file is created, we'll need to paste in a few things before we start coding. Namely, we'll need to reference a Header File, include our External Libraries, and paste in the Start Macro. 15 | 16 | Header Files include things like the name of the VMU Game/Application, a small description, and the byte data for the Animated Icon, all of which is viewable in the Dreamcast BIOS's "File" Tab. We'll learn how these work later; for now, i've included a template [GameHeader.i](https://github.com/Candle-Electric/VMU_Development_Beginners-Tutorial/blob/main/Lesson_1/GameHeader.i) for the tutorial. We can "include" it with the `.include` command, like so: 17 | 18 | .include "GameHeader.i" 19 | 20 | We'll be coding in Assembly, so if you're unfamiliar with Machine Language, we'll learn a bit as we go. WaterBear's [Instructions Page](https://wtetzner.github.io/waterbear/instructions.html) is a super valuable resource. The general syntax in assembly will be `instruction argument1, argument2, argument3...`. `.include` starts with a dot/period, as we can see, since it is a [Directive.](https://wtetzner.github.io/waterbear/directives.html#include) We can use it to include our other External Libraries, such as LibPerspective, which we'll be using to draw to the screen, SFR.I, which is used for the VMU's **S**pecial **F**unction **R**egisters, and LibKCommon, which LibPerspective requires. All of the files referenced in the `.include` statments will need to be located in your directory at the listed address. Let's Create a "`lib`" Folder in our File Explorer, download the Files from [LibPerspective's HomePage](https://slum.online/dreamcast/) or [this lesson page](https://github.com/Candle-Electric/VMU_Development_Beginners-Tutorial/blob/main/Lesson_1/lib/), paste them into our Directory, and include them. 21 | 22 | .include "./lib/libperspective.asm 23 | .include "./lib/libkcommon.asm" 24 | .include "./lib/sfr.i" 25 | 26 | Next, let's input the Start Macro. This comes in two parts, preparing the application and starting it off. We can section off the two halves using semicolons, which are the Comment Character in VMU Assembly. Let's start with the "Prepare Application" Chunk -- You'll need these lines of code for every VMU Application, so paste them in to begin: 27 | 28 | ;=======================; 29 | ; Prepare Application ; 30 | ;=======================; 31 | .org $00 32 | jmpf start 33 | 34 | .org $03 35 | reti 36 | 37 | .org $0b 38 | reti 39 | 40 | .org $13 41 | reti 42 | 43 | .org $1b 44 | jmpf t1int 45 | 46 | .org $23 47 | reti 48 | 49 | .org $2b 50 | reti 51 | 52 | .org $33 53 | reti 54 | 55 | .org $3b 56 | reti 57 | 58 | .org $43 59 | reti 60 | 61 | .org $4b 62 | clr1 p3int,0 63 | clr1 p3int,1 64 | reti 65 | 66 | ;nop_irq: 67 | ;reti 68 | 69 | .org $130 70 | t1int: 71 | push ie 72 | clr1 ie,7 73 | not1 ext,0 74 | jmpf t1int 75 | pop ie 76 | reti 77 | 78 | .org $1f0 79 | 80 | goodbye: 81 | not1 ext,0 82 | jmpf goodbye 83 | 84 | 85 | We can discuss what these do later; for now you don't need to worry about what they do under the hood. To be honest, I still don't know what a lot of them do! Next, we'll do the same thing with the `start` Macro, and paste it in like so: 86 | 87 | ;=======================; 88 | ; Main program 89 | ;=======================; 90 | start: 91 | clr1 ie,7 92 | mov #$a1,ocr 93 | mov #$09,mcr 94 | mov #$80,vccr 95 | clr1 p3int,0 96 | clr1 p1,7 97 | mov #$ff,p3 98 | set1 ie,7 99 | 100 | When we write our own code, we'll be doing so inside our Main Loop, similar to the one you'll see in Languages like C++ or C#. To "Loop" it, we'll simply jump back to the start of said Loop when it ends, using the [`jmpf` Instruction](https://wtetzner.github.io/waterbear/instructions.html#jmpf): 101 | 102 | Main_Loop: 103 | jmpf Main_Loop 104 | 105 | Now that we have everything ready, we can write our first bit of code! To start, we will do something analogous to "Hello World." Well, sort of. Writing text to the Screen is not as easy on the VMU as it is on other platforms. Lots of Games write text and scroll it, but to be honest with you I don't know how to do that. But, with LibPerspective, drawing to the screen is easy as pie! Specifically, we will be using the `P_Draw_Background_Constant` Macro to draw an image to the full screen. All we need to do is draw out the text that we want to write, as a Bitmap in Assembly. The Format that Libperspective expects is is a 6-By-32 Array of 8-Byte (1-Bit) Words, matching the 48-By-32 Resolution of the VMU's Screen. Preceding the Image itself is the Name of the Assembly File, with a Colon. Zeroes and Ones represent White and Black Pixels, respectively. A template, blank white screen, `Example_Blank_Screen.asm`, would look like this: 106 | 107 | Example_Blank_Screen: 108 | .byte 48,32 109 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 110 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 111 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 112 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 113 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 114 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 115 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 116 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 117 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 118 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 119 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 120 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 121 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 122 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 123 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 124 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 125 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 126 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 127 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 128 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 129 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 130 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 131 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 132 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 133 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 134 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 135 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 136 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 137 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 138 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 139 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 140 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 141 | 142 | These .ASM Images are a lot like ASCII Art. To fill in Pixels, simply replace the zeroes with ones. You can do this in your Text Editor. I like to CTRL+F for 1 and then hit the Insert Key and draw. The Former will "Highlight" your drawn image in some IDEs, and the latter will make sure that each Chunk has exactly 8 Numbers; any more or less will lead to an Error when Building. 143 | 144 | ![This is how I like to draw the Assembly Bitmaps.](./article_images/Lesson1_DrawingWithInsertKey.png) 145 | 146 | You can draw whatever you like! Just make sure to only overwrite the zeroes; if you place a digit where a comma or a percent sign should be, the code will fail to Build and the WaterBear Assembler will tell you when trying to Compile. Let's change our Filename to "`Hello_World_BackGround.asm`" and save it. So, now that we have our Bitmap, we can add it to our program with .include, like we did before. This way, Libperspective will be able to access the data to draw it. 147 | 148 | .include Hello_World_BackGround.asm 149 | 150 | The syntax to draw a static image to the full screen with LibPerspective is `P_Draw_Background_Constant` followed by the name of the image being referenced. So, in our case, it's: 151 | 152 | P_Draw_Background_Constant Hello_World_BackGround 153 | 154 | This adds the image to LibPerspective's WRAM/XRAM Screen Buffer. To draw everything in that Buffer at the end of each Frame, we need to Blit the Screen. LibPerspective does this for us with `P_Blit_Screen`. So, we want to call that at the end of our Main Loop, after we draw our background image. Thus, our Main Loop will look like this: 155 | 156 | Main_Loop: 157 | P_Draw_Background_Constant Hello_World_BackGround 158 | P_Blit_Screen 159 | jmpf Main_Loop 160 | 161 | Your Final `main.asm` File should now look something like this: 162 | 163 | ;=======================; 164 | ;Beginners' VMU Tutorial; 165 | ; Lesson 1 ; 166 | ;=======================; 167 | 168 | ;=======================; 169 | ; Prepare Application ; 170 | ;=======================; 171 | .org $00 172 | jmpf start 173 | 174 | .org $03 175 | reti 176 | 177 | .org $0b 178 | reti 179 | 180 | .org $13 181 | reti 182 | 183 | .org $1b 184 | jmpf t1int 185 | 186 | .org $23 187 | reti 188 | 189 | .org $2b 190 | reti 191 | 192 | .org $33 193 | reti 194 | 195 | .org $3b 196 | reti 197 | 198 | .org $43 199 | reti 200 | 201 | .org $4b 202 | clr1 p3int,0 203 | clr1 p3int,1 204 | reti 205 | 206 | ;nop_irq: 207 | ; reti 208 | 209 | .org $130 210 | t1int: 211 | push ie 212 | clr1 ie,7 213 | not1 ext,0 214 | jmpf t1int 215 | pop ie 216 | reti 217 | 218 | .org $1f0 219 | 220 | goodbye: 221 | not1 ext,0 222 | jmpf goodbye 223 | 224 | ;=======================; 225 | ;VMU Application Header ; 226 | ;=======================; 227 | .include "GameHeader.i" 228 | 229 | ;=======================; 230 | ; Include Libraries ; 231 | ;=======================; 232 | .include "./lib/libperspective.asm" 233 | .include "./lib/libkcommon.asm" 234 | .include "./lib/sfr.i" 235 | 236 | ;=======================; 237 | ; Define Variables: ; 238 | ;=======================; 239 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 240 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 241 | 242 | ;=======================; 243 | ; Main Program ; 244 | ;=======================; 245 | start: 246 | clr1 ie,7 247 | mov #$a1,ocr 248 | mov #$09,mcr 249 | mov #$80,vccr 250 | clr1 p3int,0 251 | clr1 p1,7 252 | mov #$ff,p3 253 | set1 ie,7 254 | 255 | Main_Loop: 256 | P_Draw_Background_Constant Hello_World_BackGround 257 | P_Blit_Screen 258 | jmpf Main_Loop 259 | 260 | ;=======================; 261 | ; Include Images ; 262 | ;=======================; 263 | .include "./Hello_World_BackGround.asm" 264 | 265 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 266 | 267 | Now that our code is ready, let's [use WaterBear to build it](https://github.com/wtetzner/waterbear#Usage)! 268 | 269 | waterbear assemble main.asm -o Lesson_1.vms 270 | 271 | The Syntax, as seen in the above command, is `waterbear assemble [Assembly Filename] -o [Output File]`, where the Output File is our final, executable VMU Application, in the .VMS File Format. Note that you will need to [Create A Shortcut](https://askubuntu.com/questions/660327/set-shortcut-for-executable-program-from-terminal) to run it in the above manner. You can also supply the Paths directly, if you prefer to take that route: 272 | 273 | C:/VMU/WaterBear/waterbear.exe assemble C:/VMU/Code/MyFirstGame/main.asm -o C:/VMU/Games/Lesson_1.vms 274 | 275 | Here's an example of how I do it: 276 | 277 | ![This is how I compile with WaterBear and File Paths.](./article_images/Lesson1_GitBash.png) 278 | 279 | Similarly, the Compiler will be looking for `main.asm` in the Directory you're running the Assemble Command from if you don't supply a Path, and the Output File will similarly be Created in that same place. 280 | 281 | We'll be using ElysianVMU now to see our code in action! Simply open up the Emulator, and "Open" the File we made: 282 | 283 | ![This is how I like to draw the Assembly Bitmaps.](./article_images/Lesson1_ElysianVMU.png) 284 | 285 | Running it, you can now see the image that you drew! 286 | 287 | ![This is how I like to draw the Assembly Bitmaps.](./article_images/Lesson1_YouDidIt.png) 288 | -------------------------------------------------------------------------------- /Lesson_1/article_images/Lesson1_DrawingWithInsertKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_1/article_images/Lesson1_DrawingWithInsertKey.png -------------------------------------------------------------------------------- /Lesson_1/article_images/Lesson1_ElysianVMU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_1/article_images/Lesson1_ElysianVMU.png -------------------------------------------------------------------------------- /Lesson_1/article_images/Lesson1_GitBash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_1/article_images/Lesson1_GitBash.png -------------------------------------------------------------------------------- /Lesson_1/article_images/Lesson1_YouDidIt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_1/article_images/Lesson1_YouDidIt.png -------------------------------------------------------------------------------- /Lesson_1/bin/Lesson_1.vms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_1/bin/Lesson_1.vms -------------------------------------------------------------------------------- /Lesson_1/lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Kresna Susila 2 | 3 | This software is provided 'as-is', without any express or implied warranty. 4 | In no event will the authors be held liable for any damages arising from 5 | the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software in 13 | a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not 17 | be misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /Lesson_1/lib/libkcommon.asm: -------------------------------------------------------------------------------- 1 | ;****************************************************************************** 2 | ; libkcommon 3 | ;****************************************************************************** 4 | ; Some common functions I use all the time 5 | ;****************************************************************************** 6 | ; Nicer names for button masks 7 | Button_Up equ %00000001 8 | Button_Down equ %00000010 9 | Button_Left equ %00000100 10 | Button_Right equ %00001000 11 | Button_A equ %00010000 12 | Button_B equ %00100000 13 | Button_Mode equ %01000000 14 | Button_Sleep equ %10000000 15 | 16 | Get_Input: 17 | ;---------------------------------------------------------------------- 18 | ; Get input from P3, compare input to previous P3 input to get buttons 19 | ; pressed this cycle. 20 | ;---------------------------------------------------------------------- 21 | ld p3_last_input 22 | st c 23 | ld p3 24 | bn acc, 6, .quit 25 | bn acc, 7, .sleep 26 | st p3_last_input 27 | xor #%11111111 28 | and c 29 | xor #%11111111 30 | st p3_pressed 31 | ret 32 | .quit 33 | jmpf goodbye 34 | .sleep 35 | mov #0, t1cnt ; Disable audio 36 | set1 pcon, 0 ; Activate HALT mode (saves power) 37 | bn p3, 7, .sleep ; wait until Sleep Key is released 38 | mov #0,vccr ; turn off LCD 39 | .sleepmore 40 | set1 pcon,0 ; activate HALT mode (saves power) 41 | bp p7, 0, .quit ; Docked? 42 | bp p3, 7, .sleepmore ; no Sleep Key pressed yet 43 | mov #$80, vccr ; turn on LCD again 44 | .waitsleepup: 45 | set1 pcon,0 ; activate HALT modus (saves power) 46 | bn p3,7,.waitsleepup 47 | ret 48 | 49 | Check_Button_Pressed: 50 | ;---------------------------------------------------------------------- 51 | ; Check if a button is pressed, not held, this cycle 52 | ;---------------------------------------------------------------------- 53 | ; acc = button to check 54 | ;---------------------------------------------------------------------- 55 | st c 56 | ld p3_pressed 57 | xor #%11111111 58 | and c 59 | ret 60 | -------------------------------------------------------------------------------- /Lesson_1/lib/sfr.i: -------------------------------------------------------------------------------- 1 | 2 | * 3 | * Special Function Register addresses 4 | * 5 | 6 | ACC EQU $100 7 | PSW EQU $101 8 | B EQU $102 9 | C EQU $103 10 | TRL EQU $104 11 | TRH EQU $105 12 | SP EQU $106 13 | PCON EQU $107 14 | IE EQU $108 15 | IP EQU $109 16 | EXT EQU $10D 17 | OCR EQU $10E 18 | T0CON EQU $110 19 | T0PRR EQU $111 20 | T0L EQU $112 21 | T0LR EQU $113 22 | T0H EQU $114 23 | T0HR EQU $115 24 | T1CNT EQU $118 25 | T1LC EQU $11A 26 | T1L EQU $11B 27 | T1LR EQU $11B 28 | T1HC EQU $11C 29 | T1H EQU $11D 30 | T1HR EQU $11D 31 | MCR EQU $120 32 | STAD EQU $122 33 | CNR EQU $123 34 | TDR EQU $124 35 | XBNK EQU $125 36 | VCCR EQU $127 37 | SCON0 EQU $130 38 | SBUF0 EQU $131 39 | SBR EQU $132 40 | SCON1 EQU $134 41 | SBUF1 EQU $135 42 | P1 EQU $144 43 | P1DDR EQU $145 44 | P1FCR EQU $146 45 | P3 EQU $14C 46 | P3DDR EQU $14D 47 | P3INT EQU $14E 48 | P7 EQU $15C 49 | I01CR EQU $15D 50 | I23CR EQU $15E 51 | ISL EQU $15F 52 | VSEL EQU $163 53 | VRMAD1 EQU $164 54 | VRMAD2 EQU $165 55 | VTRBF EQU $166 56 | VLREG EQU $167 57 | BTCR EQU $17F 58 | XRAM EQU $180 59 | 60 | 61 | * 62 | * PSW bits 63 | * 64 | 65 | CY EQU 7 66 | AC EQU 6 67 | IRBK1 EQU 4 68 | IRBK0 EQU 3 69 | OV EQU 2 70 | RAMBK0 EQU 1 71 | P EQU 0 72 | 73 | -------------------------------------------------------------------------------- /Lesson_1/main.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ;Beginners' VMU Tutorial; 3 | ; Lesson 1 ; 4 | ;=======================; 5 | 6 | ;=======================; 7 | ; Prepare Application ; 8 | ;=======================; 9 | .org $00 ; Thanks To TheCBarpsch For Explaining The Address Order Here! 10 | jmpf start 11 | 12 | .org $03 13 | reti 14 | 15 | .org $0b 16 | reti 17 | 18 | .org $13 19 | reti 20 | 21 | .org $1b 22 | jmpf t1int 23 | 24 | .org $23 25 | reti 26 | 27 | .org $2b 28 | reti 29 | 30 | .org $33 31 | reti 32 | 33 | .org $3b 34 | reti 35 | 36 | .org $43 37 | reti 38 | 39 | .org $4b 40 | clr1 p3int,0 41 | clr1 p3int,1 42 | reti 43 | 44 | ;nop_irq: 45 | ; reti 46 | 47 | .org $130 48 | t1int: 49 | push ie 50 | clr1 ie,7 51 | not1 ext,0 52 | jmpf t1int 53 | pop ie 54 | reti 55 | 56 | .org $1f0 57 | 58 | goodbye: 59 | not1 ext,0 60 | jmpf goodbye 61 | 62 | ;=======================; 63 | ;VMU Application Header ; 64 | ;=======================; 65 | .include "GameHeader.i" 66 | 67 | ;=======================; 68 | ; Include Libraries ; 69 | ;=======================; 70 | .include "./lib/libperspective.asm" 71 | .include "./lib/libkcommon.asm" 72 | .include "./lib/sfr.i" 73 | 74 | ;=======================; 75 | ; Define Variables: ; 76 | ;=======================; 77 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 78 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 79 | 80 | ;=======================; 81 | ; Main Program ; 82 | ;=======================; 83 | start: 84 | clr1 ie,7 85 | mov #$a1,ocr 86 | mov #$09,mcr 87 | mov #$80,vccr 88 | clr1 p3int,0 89 | clr1 p1,7 90 | mov #$ff,p3 91 | set1 ie,7 92 | 93 | Main_Loop: 94 | P_Draw_Background_Constant Hello_World_BackGround 95 | P_Blit_Screen 96 | jmpf Main_Loop 97 | 98 | ;=======================; 99 | ; Include Images ; 100 | ;=======================; 101 | .include "./Hello_World_BackGround.asm" 102 | 103 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 104 | -------------------------------------------------------------------------------- /Lesson_2/Example_Sprite.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite: 2 | .byte 8,8 3 | .byte %01111110 4 | .byte %10000001 5 | .byte %10100101 6 | .byte %10000001 7 | .byte %10100101 8 | .byte %10011001 9 | .byte %10000001 10 | .byte %01111110 -------------------------------------------------------------------------------- /Lesson_2/GameHeader.i: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------------------- 2 | ; ROM Info 3 | ;------------------------------------------------------------------------------- 4 | .org $200 5 | 6 | .byte "VMU Dev Lesson 2 " ; 16 bytes 7 | .byte "VMU Beginners' Tutorial #2." ; 32 byte 8 | ; Thanks To Marcus, Sebastian, And Tyro For Header Format! 9 | 10 | .org $240 11 | 12 | .word 1 ; number of icons (max = 3) 13 | .word 14 ; animation speed 14 | 15 | ;------------------------------------------------------------------------------- 16 | ; Game Icon Palette Table 17 | ; 18 | ; Each entry is 16-bit, as such AAAARRRR GGGGBBBB 19 | ; where a value of 0xF for alpha means opaque 20 | ;------------------------------------------------------------------------------- 21 | .org $260 22 | 23 | .word $fffe, $f114, $ffff, $f8df, $fa0f, $f02f, $ffae, $f000 24 | .word $f60a, $ff8d, $f406, $f051, $f081, $fd7b, $fd00, $f900 25 | 26 | ;------------------------------------------------------------------------------- 27 | ; Game Icon Data 28 | ;------------------------------------------------------------------------------- 29 | 30 | ; This is where the game icons are placed. Each icon is 512 byte long, 31 | ; 32 * 32 pixel, each pixel being represented by 4 bit (one nybble) that 32 | ; serve as a pointer into the color palette table. 33 | 34 | .org $280 35 | ; 0 5 10 15 20 25 30 36 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 37 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 38 | .byte $00,$10,$00,$10,$00,$00,$00,$01,$11,$01,$00,$00,$00,$00,$00,$00 39 | .byte $00,$11,$01,$10,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$10,$00 40 | .byte $00,$10,$10,$10,$10,$01,$00,$01,$10,$01,$01,$10,$11,$01,$11,$00 41 | .byte $00,$10,$00,$10,$10,$01,$00,$01,$00,$01,$01,$00,$10,$00,$10,$00 42 | .byte $00,$10,$00,$10,$01,$11,$00,$01,$00,$01,$01,$01,$10,$00,$10,$00 43 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 44 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 45 | .byte $00,$00,$00,$00,$01,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 46 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 47 | .byte $10,$00,$10,$10,$00,$10,$10,$00,$10,$00,$01,$10,$00,$00,$00,$00 48 | .byte $10,$00,$10,$11,$01,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 49 | .byte $10,$00,$10,$10,$10,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 50 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$11,$11,$01,$10,$01,$10 51 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$10,$01,$01,$01,$01,$01 52 | .byte $00,$10,$00,$10,$00,$10,$01,$11,$00,$00,$10,$01,$01,$10,$01,$10 53 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00 54 | .byte $00,$00,$00,$00,$00,$00,$00,$01,$11,$00,$00,$00,$01,$00,$01,$00 55 | .byte $00,$00,$00,$00,$00,$00,$01,$10,$00,$11,$00,$00,$00,$00,$00,$00 56 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 57 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 58 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 59 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 60 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 61 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 62 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$10,$00,$00,$00,$00,$00 63 | .byte $00,$00,$00,$00,$00,$00,$11,$11,$00,$01,$10,$00,$00,$00,$00,$00 64 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$01,$00,$10,$00,$00,$00,$00,$00 65 | .byte $00,$00,$00,$00,$00,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00 66 | .byte $00,$00,$00,$00,$00,$00,$00,$11,$11,$10,$00,$00,$00,$00,$00,$00 67 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 68 | -------------------------------------------------------------------------------- /Lesson_2/Hello_World_Background.asm: -------------------------------------------------------------------------------- 1 | Hello_World_BackGround: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 6 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 7 | .byte %00000000,%00100010,%01100010,%01000111,%00000000,%00000000 8 | .byte %00000000,%00111110,%10010010,%01001000,%10000000,%00000000 9 | .byte %00000000,%00100010,%11110010,%01001000,%10000000,%00000000 10 | .byte %00000000,%00100010,%10000010,%01001000,%10010000,%00000000 11 | .byte %00000000,%00100010,%01110010,%01000111,%00010000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00100000,%00000000 13 | .byte %00000001,%00000001,%00000000,%00000100,%00001001,%00000000 14 | .byte %00000001,%00010001,%00000000,%00000100,%00001001,%00000000 15 | .byte %00000001,%00010001,%00111001,%01100100,%01111001,%00000000 16 | .byte %00000000,%10101010,%01000101,%10000100,%10001001,%00000000 17 | .byte %00000000,%10101010,%01000101,%00000100,%10001001,%00000000 18 | .byte %00000000,%01000100,%01000101,%00000100,%10001000,%00000000 19 | .byte %00000000,%01000100,%00111001,%00000100,%01111001,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 26 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 27 | .byte %00000000,%00000000,%00100000,%00000100,%00000000,%00000000 28 | .byte %00000000,%00000000,%00100000,%10000100,%00000000,%00000000 29 | .byte %00000000,%00000000,%00100100,%00100100,%00000000,%00000000 30 | .byte %00000000,%00000000,%00100011,%11000100,%00000000,%00000000 31 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 32 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 33 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 34 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_2/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 2: Drawing Sprites And Capturing User Input 2 | 3 | Now that we have learned how to draw an Image to the Full Screen, we can start to draw smaller Sprites as well! To do so, we will call on LibPerspective once again. 4 | 5 | ## Drawing Sprites 6 | 7 | The Syntax to Draw A Sprite is as follows: 8 | 9 | P_Draw_Sprite sprite_address, sprite_x_coordinate, sprite_y_coordinate 10 | 11 | The X-Coordinate and Y-Coordinate determine where onscreen our Sprite will be drawn. The Sprite Address is an assigned section of Memory that contains the Data for Image itself. We will head back to the "Start" Section of our Code, before the Main Loop, and assign the Memory Addresses for all three of these: 12 | 13 | ;=======================; 14 | ; Include Libraries ; 15 | ;=======================; 16 | ... 17 | 18 | ;=======================; 19 | ; Define Variables: ; 20 | ;=======================; 21 | test_sprite_x = $6 ; 1 Byte 22 | test_sprite_y = $7 ; 1 Byte 23 | test_sprite_sprite_address = $8 ; 2 Bytes 24 | 25 | ;=======================; 26 | ; Prepare Application ; 27 | ;=======================; 28 | .org $00 29 | ... 30 | 31 | Now that we have allocated where in Memory these will be, let's assign the actual Numbers and Image to them: 32 | 33 | start: 34 | ... 35 | set1 ie,7 36 | 37 | ; Set Sprite Addresses 38 | mov #20, test_sprite_x 39 | mov #12, test_sprite_y 40 | mov #Example_Sprite, test_sprite_sprite_address+1 42 | 43 | Main_Loop: 44 | ... 45 | 46 | As we can see, these are assigned after our Start Macro, but before the Main Loop. We can reassign them later, during the Main Loop, but in this instance we want to make sure they're populated before we begin; Errors can arise if we try to call on them when they're empty. Note that we have four variables here; the "<" and ">" for the Sprite Address are the two halves of the Image. Since the Origin, at 0,0, is at the Top-Left, then the Point we choose for drawing will be where the Top-Left of our Sprite is. The X- and Y-Coordinates count to the right and downward as the numbers increase: 47 | 48 | ![The X- And Y-Coordinates For LibPerspective's Screen Drawing Functions Go To The Right And Down, Respectively.](./img/Lesson2_Coordinates.png) 49 | 50 | The format for drawing sprites is pretty much the same as the one we used to draw our background in the previous lesson, but just smaller height and width. You can use any dimesions you want, but the `.byte` statements will all need the full 8 digits in the X-Direction, with ones out of the range being ignored. We'll practice that later though, with more details to come in Lesson 3; for now, here's another Template for our Example Sprite, which we will name `Example_Sprite.asm`: 51 | 52 | Example_Sprite: 53 | .byte 8,8 54 | .byte %00000000 55 | .byte %00000000 56 | .byte %00000000 57 | .byte %00000000 58 | .byte %00000000 59 | .byte %00000000 60 | .byte %00000000 61 | .byte %00000000 62 | 63 | For instance, I've drawn this Smiley Face: 64 | 65 | Example_Sprite: 66 | .byte 8,8 67 | .byte %01111110 68 | .byte %10000001 69 | .byte %10100101 70 | .byte %10000001 71 | .byte %10100101 72 | .byte %10011001 73 | .byte %10000001 74 | .byte %01111110 75 | 76 | Just like last time, you can draw whatever you like! We'll then need to `.include` our sprite image. Let's make a section for that, after our included libraries: 77 | 78 | ;=======================; 79 | ; Include Libraries ; 80 | ;=======================; 81 | ... 82 | 83 | ;=======================; 84 | ; Include Images ; 85 | ;=======================; 86 | .include "./Hello_World_BackGround.asm" 87 | .include "./Example_Sprite.asm" 88 | 89 | So, we're ready to Draw our Sprite! 90 | 91 | .Draw_Screen 92 | P_Draw_Background_Constant Hello_World_BackGround 93 | P_Draw_Sprite test_sprite_sprite_address, test_sprite_x, test_sprite_y 94 | P_Blit_Screen 95 | 96 | Depending on which X/Y Coordinates you used, the Sprite may look a little funky, or cut off. We'll discuss why that is in a bit. Next, we'll learn how to Capture User Input and Move our Sprite! 97 | 98 | ## Capturing User Input 99 | 100 | We'll be calling on LibKCommon, which we've already included for its use with LibPerspective, to capture the Button Inputs from our Game's User.Specifically, its `Get_Input` Command will be very useful for us. We'll also be learning a bit more Assembly Code in this step. `Get_Input` takes no arguments, and fills in the `p3` Variable, which we then move to our `acc` Variable. `acc` is one of the VMU's Default Registers, and we will be using it a lot. It's an 8-Bit Word, not unlike the ones we were filling in for our example sprite earlier. And the VMU has 8 Buttons -- the Four Cardinal Directions, A, B, Mode, And Sleep. The Word will be 255 by default, meaning that all of the bits will be filled if nothing is pressed. `Get_Input` will empty the 8 bits of `acc` depending on which buttons are pressed when it is called. Our most significant bit, the seventh, is on the far left. Zero, the least significat bit, is on the far right. So, from Bit 0 to Bit 7, we have Up, Down, Left, Right, A, B, Mode, And Sleep, in that order. Let's add these as Constants, before the Start Macro: 101 | 102 | ;=======================; 103 | ; Constants ; 104 | ;=======================; 105 | T_BTN_SLEEP equ 7 106 | T_BTN_MODE equ 6 107 | T_BTN_B1 equ 5 108 | T_BTN_A1 equ 4 109 | T_BTN_RIGHT1 equ 3 110 | T_BTN_LEFT1 equ 2 111 | T_BTN_DOWN1 equ 1 112 | T_BTN_UP1 equ 0 113 | 114 | ;=======================; 115 | ; Prepare Application ; 116 | ;=======================; 117 | ... 118 | 119 | Since they go right-to-left in increasing order, `acc` will look like this with no inputs: 120 | 121 | ![ACC with nothing pressed.](./img/Lesson2_GetInputACCGraph.png) 122 | 123 | Since having a button pressed when `Get_Input` is called will fill the respective bit, `acc` would look like this if we were pressing Diagonally Up-Left and A while `Get_Input` was called: 124 | 125 | ![ACC with Up, Left, and A pressed.](./img/Lesson2_GetInputACCGraph_FilledIn.png) 126 | 127 | Thus, we can use WaterBear's [`bp`](https://wtetzner.github.io/waterbear/instructions.html#bp) and [`bn`](https://wtetzner.github.io/waterbear/instructions.html#bn) Functions, which check whether a Bit is Set or Cleared, respectively, to move our Sprite in various ways according to which Buttons are Pressed/Held. As we can see in the WaterBear Documentation, the Syntax is `bp variable, bit_number, .where_to_jump_to`. In other words, when we call `bp` or `bn`, we follow it with whose Bit we're checking, which of the 8 Bits we're checking, and where we want to jump to if it's set or empty (for `bp` and `bn`, respectively.). 128 | Let's dive back into our Main Loop and call `Get_Input` before we check for an "Up" Input. We'll do all this before we draw our Sprite and Background: 129 | 130 | Main_Loop: 131 | ; Check Input 132 | callf Get_Input ; This Function Is In LibKCommon.ASM 133 | ld p3 134 | .Draw_Screen 135 | ... 136 | 137 | The [`ld`](https://wtetzner.github.io/waterbear/instructions.html#ld) call in `ld p3` takes the value of `p3`, which `Get_Input` populated, and moves it into `acc`, which we will then be calling on to see if "Up" is pressed at the current Frame: 138 | 139 | bp acc, T_BTN_UP1, .Draw_Screen 140 | 141 | So, in this above line, we will "Jump" to the `.Draw_Screen` Section of our code if the "Up" button isn't pressed, A.K.A. if the 0-Bit of `p3`/`acc` is filled in. That means that we will code our desired behavior for when that up button is pressed in between our `bp` call and the `.Draw_Screen` marker. We know from earlier in this lesson that the X-Y Coordinates move to the right and downward, respectively, as their numbers increase, right? So, to move our Sprite upward on the screen when that direection is pressed, we can decrement our Y-Value with [`dec`](https://wtetzner.github.io/waterbear/instructions.html#dec). The Syntax for this one is easy, as you simply specify whose value you want to decrease by 1: 142 | 143 | dec test_sprite_y 144 | 145 | So, our Main Loop will now look like this: 146 | 147 | Main_Loop: 148 | ; Check Input 149 | callf Get_Input ; This Function Is In LibKCommon.ASM 150 | ld p3 151 | .Check_Up 152 | bp acc, T_BTN_UP1, .Draw_Screen 153 | dec test_sprite_y 154 | .Draw_Screen 155 | P_Draw_Background_Constant Hello_World_BackGround 156 | P_Draw_Sprite test_sprite_sprite_address, test_sprite_x, test_sprite_y 157 | P_Blit_Screen 158 | jmpf Main_Loop 159 | 160 | The opposite of `dec` is [`inc`](https://wtetzner.github.io/waterbear/instructions.html#inc); that being that it increments the chosen variable. Let's add the other three Directional Buttons, editing where we jump to accordingly: 161 | 162 | Main_Loop: 163 | ; Check Input 164 | callf Get_Input ; This Function Is In LibKCommon.ASM 165 | ld p3 166 | .Check_Up 167 | bp acc, T_BTN_UP1, .Check_Down 168 | dec test_sprite_y 169 | .Check_Down 170 | bp acc, T_BTN_DOWN1, .Check_Left 171 | inc test_sprite_y 172 | .Check_Left 173 | bp acc, T_BTN_LEFT1, .Check_Right 174 | dec test_sprite_x 175 | .Check_Right 176 | bp acc, T_BTN_RIGHT1, .Draw_Screen 177 | inc test_sprite_x 178 | .Draw_Screen 179 | P_Draw_Background_Constant Hello_World_BackGround 180 | P_Draw_Sprite test_sprite_sprite_address, test_sprite_x, test_sprite_y 181 | P_Blit_Screen 182 | jmpf Main_Loop 183 | 184 | Our final `main.asm` should like this: 185 |
186 | Final Code File 187 | 188 | ;=======================; 189 | ;Beginners' VMU Tutorial; 190 | ; Lesson 2 ; 191 | ;=======================; 192 | 193 | ;=======================; 194 | ;VMU Application Header ; 195 | ;=======================; 196 | .include "GameHeader.i" 197 | 198 | ;=======================; 199 | ; Include Libraries ; 200 | ;=======================; 201 | .include "./lib/libperspective.asm" 202 | .include "./lib/libkcommon.asm" 203 | .include "./lib/sfr.i" 204 | 205 | ;=======================; 206 | ; Include Images ; 207 | ;=======================; 208 | .include "./Hello_World_BackGround.asm" 209 | .include "./Example_Sprite.asm" 210 | 211 | ;=======================; 212 | ; Define Variables: ; 213 | ;=======================; 214 | p3_pressed = $4 ; 1 Byte(For LibKCommon) 215 | p3_last_input = $5 ; 1 Byte(For LibKCommon) 216 | test_sprite_x = $6 ; 1 Byte 217 | test_sprite_y = $7 ; 1 Byte 218 | test_sprite_sprite_address = $8 ; 2 Bytes 219 | 220 | ;=======================; 221 | ; Constants; 222 | ;=======================; 223 | T_BTN_SLEEP equ 7 224 | T_BTN_MODE equ 6 225 | T_BTN_B1 equ 5 226 | T_BTN_A1 equ 4 227 | T_BTN_RIGHT1 equ 3 228 | T_BTN_LEFT1 equ 2 229 | T_BTN_DOWN1 equ 1 230 | T_BTN_UP1 equ 0 231 | 232 | ;=======================; 233 | ; Prepare Application; 234 | ;=======================; 235 | .org $00 236 | jmpf start 237 | 238 | .org $03 239 | reti 240 | 241 | .org $0b 242 | reti 243 | 244 | .org $13 245 | reti 246 | 247 | .org $1b 248 | jmpf t1int 249 | 250 | .org $23 251 | reti 252 | 253 | .org $2b 254 | reti 255 | 256 | .org $33 257 | reti 258 | 259 | .org $3b 260 | reti 261 | 262 | .org $43 263 | reti 264 | 265 | .org $4b 266 | clr1 p3int,0 267 | clr1 p3int,1 268 | reti 269 | 270 | ; nop_irq: 271 | ; reti 272 | 273 | .org $130 274 | t1int: 275 | push ie 276 | clr1 ie,7 277 | not1 ext,0 278 | jmpf t1int 279 | pop ie 280 | reti 281 | 282 | .org $1f0 283 | 284 | goodbye: 285 | not1 ext,0 286 | jmpf goodbye 287 | 288 | ;=======================; 289 | ; Main Program; 290 | ;=======================; 291 | start: 292 | clr1 ie,7 293 | mov #$a1,ocr 294 | mov #$09,mcr 295 | mov #$80,vccr 296 | clr1 p3int,0 297 | clr1 p1,7 298 | mov #$ff,p3 299 | set1 ie,7 300 | ; Set Sprite Addresses 301 | mov #20, test_sprite_x 302 | mov #12, test_sprite_y 303 | mov #Example_Sprite, test_sprite_sprite_address+1 305 | 306 | Main_Loop: 307 | ; Check Input 308 | callf Get_Input ; This Function Is In LibKCommon.ASM 309 | ld p3 310 | .Check_Up 311 | bp acc, T_BTN_UP1, .Check_Down 312 | dec test_sprite_y 313 | .Check_Down 314 | bp acc, T_BTN_DOWN1, .Check_Left 315 | inc test_sprite_y 316 | .Check_Left 317 | bp acc, T_BTN_LEFT1, .Check_Right 318 | dec test_sprite_x 319 | .Check_Right 320 | bp acc, T_BTN_RIGHT1, .Draw_Screen 321 | inc test_sprite_x 322 | .Draw_Screen 323 | P_Draw_Background_Constant Hello_World_BackGround 324 | P_Draw_Sprite test_sprite_sprite_address, test_sprite_x, test_sprite_y 325 | P_Blit_Screen 326 | jmpf Main_Loop 327 | 328 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 329 | 330 |
331 | 332 | ([Thanks to Joshua Sullivan for the Spoiler Tag Markdown!](https://gist.github.com/jbsulli/03df3cdce94ee97937ebda0ffef28287)) 333 | 334 | Building our code with WaterBear like before and running it in ElysianVMU, you should now be able to move your Sprite with the Arrow Keys! 335 | 336 | ![An Animation Of The Final Assembled Code For Lesson 2. Thanks EZGIF.Com For The .MP4 To .GIF File Conversion!](./img/Lesson2_FinalAssembledCodeAnimation_ThanksEZGIF.gif) 337 | 338 | You'll notice that the Sprite draws oddly, with a white border chunk resizing around it, and part of its graphic cut off. This is due to the way the 8-Bit Words of the VMU Screen are arranged, and we'll find out how to work around that, along with much more, in Lesson 3! 339 | -------------------------------------------------------------------------------- /Lesson_2/bin/Lesson_2.vms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_2/bin/Lesson_2.vms -------------------------------------------------------------------------------- /Lesson_2/img/Lesson2_Coordinates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_2/img/Lesson2_Coordinates.png -------------------------------------------------------------------------------- /Lesson_2/img/Lesson2_FinalAssembledCodeAnimation_ThanksEZGIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_2/img/Lesson2_FinalAssembledCodeAnimation_ThanksEZGIF.gif -------------------------------------------------------------------------------- /Lesson_2/img/Lesson2_GetInputACCGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_2/img/Lesson2_GetInputACCGraph.png -------------------------------------------------------------------------------- /Lesson_2/img/Lesson2_GetInputACCGraph_FilledIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_2/img/Lesson2_GetInputACCGraph_FilledIn.png -------------------------------------------------------------------------------- /Lesson_2/lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Kresna Susila 2 | 3 | This software is provided 'as-is', without any express or implied warranty. 4 | In no event will the authors be held liable for any damages arising from 5 | the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software in 13 | a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not 17 | be misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /Lesson_2/lib/libkcommon.asm: -------------------------------------------------------------------------------- 1 | ;****************************************************************************** 2 | ; libkcommon 3 | ;****************************************************************************** 4 | ; Some common functions I use all the time 5 | ;****************************************************************************** 6 | ; Nicer names for button masks 7 | Button_Up equ %00000001 8 | Button_Down equ %00000010 9 | Button_Left equ %00000100 10 | Button_Right equ %00001000 11 | Button_A equ %00010000 12 | Button_B equ %00100000 13 | Button_Mode equ %01000000 14 | Button_Sleep equ %10000000 15 | 16 | Get_Input: 17 | ;---------------------------------------------------------------------- 18 | ; Get input from P3, compare input to previous P3 input to get buttons 19 | ; pressed this cycle. 20 | ;---------------------------------------------------------------------- 21 | ld p3_last_input 22 | st c 23 | ld p3 24 | bn acc, 6, .quit 25 | bn acc, 7, .sleep 26 | st p3_last_input 27 | xor #%11111111 28 | and c 29 | xor #%11111111 30 | st p3_pressed 31 | ret 32 | .quit 33 | jmpf goodbye 34 | .sleep 35 | mov #0, t1cnt ; Disable audio 36 | set1 pcon, 0 ; Activate HALT mode (saves power) 37 | bn p3, 7, .sleep ; wait until Sleep Key is released 38 | mov #0,vccr ; turn off LCD 39 | .sleepmore 40 | set1 pcon,0 ; activate HALT mode (saves power) 41 | bp p7, 0, .quit ; Docked? 42 | bp p3, 7, .sleepmore ; no Sleep Key pressed yet 43 | mov #$80, vccr ; turn on LCD again 44 | .waitsleepup: 45 | set1 pcon,0 ; activate HALT modus (saves power) 46 | bn p3,7,.waitsleepup 47 | ret 48 | 49 | Check_Button_Pressed: 50 | ;---------------------------------------------------------------------- 51 | ; Check if a button is pressed, not held, this cycle 52 | ;---------------------------------------------------------------------- 53 | ; acc = button to check 54 | ;---------------------------------------------------------------------- 55 | st c 56 | ld p3_pressed 57 | xor #%11111111 58 | and c 59 | ret 60 | -------------------------------------------------------------------------------- /Lesson_2/lib/sfr.i: -------------------------------------------------------------------------------- 1 | 2 | * 3 | * Special Function Register addresses 4 | * 5 | 6 | ACC EQU $100 7 | PSW EQU $101 8 | B EQU $102 9 | C EQU $103 10 | TRL EQU $104 11 | TRH EQU $105 12 | SP EQU $106 13 | PCON EQU $107 14 | IE EQU $108 15 | IP EQU $109 16 | EXT EQU $10D 17 | OCR EQU $10E 18 | T0CON EQU $110 19 | T0PRR EQU $111 20 | T0L EQU $112 21 | T0LR EQU $113 22 | T0H EQU $114 23 | T0HR EQU $115 24 | T1CNT EQU $118 25 | T1LC EQU $11A 26 | T1L EQU $11B 27 | T1LR EQU $11B 28 | T1HC EQU $11C 29 | T1H EQU $11D 30 | T1HR EQU $11D 31 | MCR EQU $120 32 | STAD EQU $122 33 | CNR EQU $123 34 | TDR EQU $124 35 | XBNK EQU $125 36 | VCCR EQU $127 37 | SCON0 EQU $130 38 | SBUF0 EQU $131 39 | SBR EQU $132 40 | SCON1 EQU $134 41 | SBUF1 EQU $135 42 | P1 EQU $144 43 | P1DDR EQU $145 44 | P1FCR EQU $146 45 | P3 EQU $14C 46 | P3DDR EQU $14D 47 | P3INT EQU $14E 48 | P7 EQU $15C 49 | I01CR EQU $15D 50 | I23CR EQU $15E 51 | ISL EQU $15F 52 | VSEL EQU $163 53 | VRMAD1 EQU $164 54 | VRMAD2 EQU $165 55 | VTRBF EQU $166 56 | VLREG EQU $167 57 | BTCR EQU $17F 58 | XRAM EQU $180 59 | 60 | 61 | * 62 | * PSW bits 63 | * 64 | 65 | CY EQU 7 66 | AC EQU 6 67 | IRBK1 EQU 4 68 | IRBK0 EQU 3 69 | OV EQU 2 70 | RAMBK0 EQU 1 71 | P EQU 0 72 | 73 | -------------------------------------------------------------------------------- /Lesson_2/main.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ;Beginners' VMU Tutorial; 3 | ; Lesson 2 ; 4 | ;=======================; 5 | 6 | ;=======================; 7 | ;VMU Application Header ; 8 | ;=======================; 9 | .include "GameHeader.i" 10 | 11 | ;=======================; 12 | ; Include Libraries ; 13 | ;=======================; 14 | .include "./lib/libperspective.asm" 15 | .include "./lib/libkcommon.asm" 16 | .include "./lib/sfr.i" 17 | 18 | ;=======================; 19 | ; Define Variables: ; 20 | ;=======================; 21 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 22 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 23 | test_sprite_x = $6 ; 1 Byte 24 | test_sprite_y = $7 ; 1 Byte 25 | test_sprite_sprite_address = $8 ; 2 Bytes 26 | 27 | ;=======================; 28 | ; Constants ; 29 | ;=======================; 30 | T_BTN_SLEEP equ 7 31 | T_BTN_MODE equ 6 32 | T_BTN_B1 equ 5 33 | T_BTN_A1 equ 4 34 | T_BTN_RIGHT1 equ 3 35 | T_BTN_LEFT1 equ 2 36 | T_BTN_DOWN1 equ 1 37 | T_BTN_UP1 equ 0 38 | 39 | ;=======================; 40 | ; Prepare Application ; 41 | ;=======================; 42 | .org $00 43 | jmpf start 44 | 45 | .org $03 46 | reti 47 | 48 | .org $0b 49 | reti 50 | 51 | .org $13 52 | reti 53 | 54 | .org $1b 55 | jmpf t1int 56 | 57 | .org $23 58 | reti 59 | 60 | .org $2b 61 | reti 62 | 63 | .org $33 64 | reti 65 | 66 | .org $3b 67 | reti 68 | 69 | .org $43 70 | reti 71 | 72 | .org $4b 73 | clr1 p3int,0 74 | clr1 p3int,1 75 | reti 76 | 77 | ;nop_irq: 78 | ; reti 79 | 80 | .org $130 81 | t1int: 82 | push ie 83 | clr1 ie,7 84 | not1 ext,0 85 | jmpf t1int 86 | pop ie 87 | reti 88 | 89 | .org $1f0 90 | 91 | goodbye: 92 | not1 ext,0 93 | jmpf goodbye 94 | 95 | ;=======================; 96 | ; Main Program ; 97 | ;=======================; 98 | start: 99 | clr1 ie,7 100 | mov #$a1,ocr 101 | mov #$09,mcr 102 | mov #$80,vccr 103 | clr1 p3int,0 104 | clr1 p1,7 105 | mov #$ff,p3 106 | set1 ie,7 107 | ; Set Sprite Addresses 108 | mov #20, test_sprite_x 109 | mov #12, test_sprite_y 110 | mov #Example_Sprite, test_sprite_sprite_address+1 112 | 113 | Main_Loop: 114 | ; Check Input 115 | callf Get_Input ; This Function Is In LibKCommon.ASM 116 | ld p3 117 | .Check_Up 118 | bp acc, T_BTN_UP1, .Check_Down 119 | dec test_sprite_y 120 | .Check_Down 121 | bp acc, T_BTN_DOWN1, .Check_Left 122 | inc test_sprite_y 123 | .Check_Left 124 | bp acc, T_BTN_LEFT1, .Check_Right 125 | dec test_sprite_x 126 | .Check_Right 127 | bp acc, T_BTN_RIGHT1, .Draw_Screen 128 | inc test_sprite_x 129 | .Draw_Screen 130 | P_Draw_Background_Constant Hello_World_BackGround 131 | P_Draw_Sprite test_sprite_sprite_address, test_sprite_x, test_sprite_y 132 | P_Blit_Screen 133 | jmpf Main_Loop 134 | 135 | ;=======================; 136 | ; Include Images ; 137 | ;=======================; 138 | .include "./Hello_World_BackGround.asm" 139 | .include "./Example_Sprite.asm" 140 | 141 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 142 | -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_CutOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_CutOff.png -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_Text_And_Commas_Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_Text_And_Commas_Example.png -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_Text_And_Commas_Example_Smaller_Resized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Lesson3_P_Draw_Sprite_Text_And_Commas_Example_Smaller_Resized.png -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Masking_Example_Animation_Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Masking_Example_Animation_Start.png -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Masking_Example_Right_Column_Explanation_Graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Masking_Example_Right_Column_Explanation_Graphic.png -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Sprite_Masking_Tutorial_Guide_Animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Sprite_Masking_Tutorial_Guide_Animation.gif -------------------------------------------------------------------------------- /Lesson_3/Article_Images/Un-Masked_Sprite_With_Black_BG+Vertical_White_Stripes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/Article_Images/Un-Masked_Sprite_With_Black_BG+Vertical_White_Stripes.gif -------------------------------------------------------------------------------- /Lesson_3/GameHeader.i: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------------------- 2 | ; ROM info 3 | ;------------------------------------------------------------------------------- 4 | .org $200 5 | 6 | .byte "VMU Dev Lesson 3 " ; 16 bytes 7 | .byte "VMU Beginners' Tutorial #1." ; 32 byte 8 | ; Thanks To Marcus, Sebastian, And Tyro For Header Format! 9 | 10 | .org $240 11 | 12 | .word 1 ; number of icons (max = 3) 13 | .word 14 ; animation speed 14 | 15 | ;------------------------------------------------------------------------------- 16 | ; Game Icon Palette Table 17 | ; 18 | ; Each entry is 16-bit, as such AAAARRRR GGGGBBBB 19 | ; where a value of 0xF for alpha means opaque 20 | ;------------------------------------------------------------------------------- 21 | .org $260 22 | 23 | .word $fffe, $f114, $ffff, $f8df, $fa0f, $f02f, $ffae, $f000 24 | .word $f60a, $ff8d, $f406, $f051, $f081, $fd7b, $fd00, $f900 25 | 26 | ;------------------------------------------------------------------------------- 27 | ; Game Icon Data 28 | ;------------------------------------------------------------------------------- 29 | 30 | ; This is where the game icons are placed. Each icon is 512 byte long, 31 | ; 32 * 32 pixel, each pixel being represented by 4 bit (one nybble) that 32 | ; serve as a pointer into the color palette table. 33 | 34 | .org $280 35 | ; 0 5 10 15 20 25 30 36 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 37 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 38 | .byte $00,$10,$00,$10,$00,$00,$00,$01,$11,$01,$00,$00,$00,$00,$00,$00 39 | .byte $00,$11,$01,$10,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$10,$00 40 | .byte $00,$10,$10,$10,$10,$01,$00,$01,$10,$01,$01,$10,$11,$01,$11,$00 41 | .byte $00,$10,$00,$10,$10,$01,$00,$01,$00,$01,$01,$00,$10,$00,$10,$00 42 | .byte $00,$10,$00,$10,$01,$11,$00,$01,$00,$01,$01,$01,$10,$00,$10,$00 43 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 44 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 45 | .byte $00,$00,$00,$00,$01,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 46 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 47 | .byte $10,$00,$10,$10,$00,$10,$10,$00,$10,$00,$01,$10,$00,$00,$00,$00 48 | .byte $10,$00,$10,$11,$01,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 49 | .byte $10,$00,$10,$10,$10,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 50 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$11,$11,$01,$10,$01,$10 51 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$10,$01,$01,$01,$01,$01 52 | .byte $00,$10,$00,$10,$00,$10,$01,$11,$00,$00,$10,$01,$01,$10,$01,$10 53 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00 54 | .byte $00,$00,$00,$00,$00,$00,$00,$01,$11,$00,$00,$00,$01,$00,$01,$00 55 | .byte $00,$00,$00,$00,$00,$00,$01,$10,$00,$11,$00,$00,$00,$00,$00,$00 56 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 57 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 58 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 59 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 60 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 61 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 62 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$10,$00,$00,$00,$00,$00 63 | .byte $00,$00,$00,$00,$00,$00,$11,$11,$00,$01,$10,$00,$00,$00,$00,$00 64 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$01,$00,$10,$00,$00,$00,$00,$00 65 | .byte $00,$00,$00,$00,$00,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00 66 | .byte $00,$00,$00,$00,$00,$00,$00,$11,$11,$10,$00,$00,$00,$00,$00,$00 67 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 68 | -------------------------------------------------------------------------------- /Lesson_3/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 3: Masking Sprites And Handling Collision 2 | 3 | When we left off at Lesson 2, we learned how to draw a sprite onto the screen, but it behaved erratically, looking odd when we moved it using the D-Pad. This is due to the way that the VMU's screen is arranged, in its 6-by-48 array of 8-pixel lines. Using `P_Draw_Sprite` will cut off everything outside of the horizontal line where we set the X-point of our sprite coordinates. 4 | 5 | ![An Example Of How Sprites Can Get Cut Off When Pixels Go Past The 8th Dot Of A Screen Chunk.](./Article_Images/Lesson3_P_Draw_Sprite_CutOff.png) 6 | 7 | This makes sense when we think about how we drew our sprites: 8 | 9 | ![A Textual Representation Of Said Pixels, Shown Here As Those Highlighted Past The Comma.](./Article_Images/Lesson3_P_Draw_Sprite_Text_And_Commas_Example_Smaller_Resized.png) 10 | 11 | This is what the above screenshot's sprite looks like on our "blank canvas" in that position. Vertically, the sprite will always draw properly as we move it up and down since the chunks, or `.byte` words in the .ASM, are only one pixel tall. If we move it left and right and shift everything around to the sides, however, whatever is past the commas won't be drawn, and the rest of the chunk will be empty. This is exemplified well by using an all-black background with vertical white stripes at the edge of each eight pixel interval: 12 | 13 | ![An Animated Example Of How Sprites Can Get Cut Off When Pixels Go Past The 8th Dot Of A Screen Chunk. Thanks Again EZGIF!](./Article_Images/Un-Masked_Sprite_With_Black_BG+Vertical_White_Stripes.gif) 14 | 15 | How can we circumvent this, and see our full sprite on screen whenever and wherever we move it? The answer lies in LibPerspective's `P_Draw_Sprite_Mask` command. 16 | 17 | ## Masking Sprites 18 | 19 | Systems such as the NES or Sega Genesis allow a transparency in sprites' pallettes, using up one of the colors as the invisible space around the artwork. The VMU doesn't have this luxury (after all, it would be hard to dedicate one color to transparency when the VMU can only draw... one color.). Programmers for earlier systems that lacked this functionality found a clever answer in [Sprite Masking](http://www.breakintoprogram.co.uk/software_development/masking-sprites), explained here spectacularly by BreakIntoProgram. Basically, space is cleared for the mask, and then Logic `AND` and `OR` Calls are used to draw the sprite over the mask, keeping the areas around its boundaries "transparent." LibPerspective's Code for masking sprites is very impressive, and its implementation is a very useful resource for higher-level VMU programming, albeit far beyond where we're at in our beginners' tutorials at the moment. For today, we'll focus on what we need to do mask our sprites, and let LibPerspective handle the rest. Conveniently, our syntax isn't changing at all beyond the function we're calling, as we will still supply the X- and Y-coordinates along with the sprite address: 20 | 21 | P_Draw_Sprite_Mask sprite_x, sprite_y, sprite_address 22 | 23 | What will change is how we feed the data into our sprite address. We'll need to double our drawing, and basically make a border with inverted colors that fits our sprite inside its boundaries and append that to our existing sprite. This will often take us outside the 8x8 dimesions we set earlier, which is not an issue. You'll just need to make sure that each horizontal line has all 8 bytes, and is separated by a comma; vertically, any dimension is fine. For example, a 9x7 square would be masked like this: 24 | 25 | Player_Car_B_Mask: 26 | .byte 11,9 27 | .byte %10000000,%00111111 28 | .byte %00000000,%00011111 29 | .byte %00000000,%00011111 30 | .byte %00000000,%00011111 31 | .byte %00000000,%00011111 32 | .byte %00000000,%00011111 33 | .byte %00000000,%00011111 34 | .byte %00000000,%00011111 35 | .byte %10000000,%00111111 36 | .byte %00000000,%00000000 37 | .byte %01111111,%11000000 38 | .byte %01111111,%11000000 39 | .byte %01111111,%11000000 40 | .byte %01111111,%11000000 41 | .byte %01111111,%11000000 42 | .byte %01111111,%11000000 43 | .byte %01111111,%11000000 44 | .byte %00000000,%00000000 45 | 46 | The top half is the "Mask," which is surrounded by 1s/black pixels, conversely to the original sprite we created previously, whose border was 0s/whitespace. Note that it's the dimensions of the _Mask_ Half specifically that we want to define above the sprite data. Every pixel in the bottom sprite will need to be contained and bordered on all sides by a pixel in the mask. In other words, the mask will need to be the same size as the sprite, + 1 pixel in every up, down, left, and right direction: 47 | 48 | ![Animation Detailing How To Draw A Masked Sprite In LibPerspective's Format.](./Article_Images/Sprite_Masking_Tutorial_Guide_Animation.gif) 49 | 50 | Usually, keeping the border boundaries at the edges of the masked sprite will work fine. However, notice the addendum at the end of the Animated Guide just above: sometimes, your masked sprite might look off as it's drawn to the screen, and adding a space around the border has helped alleviate this in the past for me. I've noticed that sometimes only the right-side border needs a column of 1s to its right in the mask, and sometimes the other three sides -- top, bottom, and left -- have been fine with their the mask edges at the dimensions' boundary. However, I've also had to Add a Column on the left-hand side a few times. So, if your Masked Sprite doesn't look quite right when you see it drawn onscreen, try adding an empty border around it in each direction, and that should fix it. In other words, visually speaking: 51 | 52 | ![Graphic Detailing The Requirement For A Column To The Right Of The Masked Sprite.](./Article_Images/Masking_Example_Right_Column_Explanation_Graphic.png) 53 | 54 | This is a rare occurrence though, and usually having the mask fit snugly inside the boundaries is enough. If you ever have a masked sprite that just isn't drawing right, feel free to start a thread here on GitHub and I'll be happy to try and help! Since we're dealing with a lot of Image Files now, let's make a New Folder for them. We can do this via the O.S. File Explorer or with Git Bash: 55 | 56 | ; *Navigate To Your Root Directory* 57 | mkdir img 58 | 59 | I'll call mine "img" for this tutorial, but you can give it any name you like; just remember to keep it consistent when you reference its path in your code. Let's also move our existing `.asm` images in there. Then, we'll `.include` our Image Assemblies with the New Folder's Path. 60 | 61 | ;=======================; 62 | ; Include Images ; 63 | ;=======================; 64 | .include "./img/Hello_World_BackGround.asm" 65 | .include "./img/Example_Sprite_Mask.asm" 66 | 67 | Once we've made those changes, let's rebuild our code in WaterBear. As mentioned before, it hasn't changed much since Lesson 2 (the `.include` Statement now pointing to the Masked Sprite and its requisite call to `P_Draw_Sprite_Mask` instead of `P_Draw_Sprite` are the only changes to `main.asm`.). In case you need it, here's the full code file: 68 | 69 |
70 | Final "Masked Sprite" Code File 71 | 72 | ;=======================; 73 | ;Beginners' VMU Tutorial; 74 | ; Lesson 3 ; 75 | ;=======================; 76 | 77 | ;=======================; 78 | ;VMU Application Header ; 79 | ;=======================; 80 | .include "GameHeader.i" 81 | 82 | ;=======================; 83 | ; Include Libraries ; 84 | ;=======================; 85 | .include "./lib/libperspective.asm" 86 | .include "./lib/libkcommon.asm" 87 | .include "./lib/sfr.i" 88 | 89 | ;=======================; 90 | ; Include Images ; 91 | ;=======================; 92 | .include "./img/Hello_World_BackGround.asm" 93 | .include "./img/Example_Sprite.asm" 94 | 95 | ;=======================; 96 | ; Define Variables: ; 97 | ;=======================; 98 | p3_pressed = $4 ; 1 Byte(For LibKCommon) 99 | p3_last_input = $5 ; 1 Byte(For LibKCommon) 100 | test_sprite_x = $6 ; 1 Byte 101 | test_sprite_y = $7 ; 1 Byte 102 | test_sprite_sprite_address = $8 ; 2 Bytes 103 | 104 | ;=======================; 105 | ; Constants; 106 | ;=======================; 107 | T_BTN_SLEEP equ 7 108 | T_BTN_MODE equ 6 109 | T_BTN_B1 equ 5 110 | T_BTN_A1 equ 4 111 | T_BTN_RIGHT1 equ 3 112 | T_BTN_LEFT1 equ 2 113 | T_BTN_DOWN1 equ 1 114 | T_BTN_UP1 equ 0 115 | 116 | ;=======================; 117 | ; Prepare Application; 118 | ;=======================; 119 | .org $00 120 | jmpf start 121 | 122 | .org $03 123 | reti 124 | 125 | .org $0b 126 | reti 127 | 128 | .org $13 129 | reti 130 | 131 | .org $1b 132 | jmpf t1int 133 | 134 | .org $23 135 | reti 136 | 137 | .org $2b 138 | reti 139 | 140 | .org $33 141 | reti 142 | 143 | .org $3b 144 | reti 145 | 146 | .org $43 147 | reti 148 | 149 | .org $4b 150 | clr1 p3int,0 151 | clr1 p3int,1 152 | reti 153 | 154 | ; nop_irq: 155 | ; reti 156 | 157 | .org $130 158 | t1int: 159 | push ie 160 | clr1 ie,7 161 | not1 ext,0 162 | jmpf t1int 163 | pop ie 164 | reti 165 | 166 | .org $1f0 167 | 168 | goodbye: 169 | not1 ext,0 170 | jmpf goodbye 171 | 172 | ;=======================; 173 | ; Main Program; 174 | ;=======================; 175 | start: 176 | clr1 ie,7 177 | mov #$a1,ocr 178 | mov #$09,mcr 179 | mov #$80,vccr 180 | clr1 p3int,0 181 | clr1 p1,7 182 | mov #$ff,p3 183 | set1 ie,7 184 | ; Set Sprite Addresses 185 | mov #20, test_sprite_x 186 | mov #12, test_sprite_y 187 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 189 | 190 | Main_Loop: 191 | ; Check Input 192 | callf Get_Input ; This Function Is In LibKCommon.ASM 193 | ld p3 194 | .Check_Up 195 | bp acc, T_BTN_UP1, .Check_Down 196 | dec test_sprite_y 197 | .Check_Down 198 | bp acc, T_BTN_DOWN1, .Check_Left 199 | inc test_sprite_y 200 | .Check_Left 201 | bp acc, T_BTN_LEFT1, .Check_Right 202 | dec test_sprite_x 203 | .Check_Right 204 | bp acc, T_BTN_RIGHT1, .Draw_Screen 205 | inc test_sprite_x 206 | .Draw_Screen 207 | P_Draw_Background_Constant Hello_World_BackGround 208 | P_Draw_Sprite_Mask test_sprite_sprite_address, test_sprite_x, test_sprite_y 209 | P_Blit_Screen 210 | jmpf Main_Loop 211 | 212 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 213 |
214 | 215 | Now that we're drawing our sprite with `P_Draw_Sprite_Mask`, we should see it with a smooth border no matter where we move it across the screen, fixing our sprite tearing issue from Lesson 2! 216 | 217 | Now that we've learned how to mask sprites, let's take a dive into calculating how those sprites will collide with other objects. 218 | 219 | ## Collision 220 | 221 | For our first experience with collision detection in our project, we will keep the moving sprite inside the bounds of the VMU Screen. That is, we'll prevent movement to the left when we're at the left wall, prevent upward movement when at the top of the screen, etc. In other words, if X <= 0, prevent leftward movement; if Y <= 0, prevent upward movement. You'll notice that we don't have a "Greater Than/Less Than" Function in our list of Assembly Commands. Luckily for us, there is a way around this using the unsigned 8-bit integers that make up our variables. These run from 0 to 255, or, in binary, from 00000000 to 11111111. If that leftmost digit is a zero, we know that the number is between 0 and 127; conversely, if that leftmost digit is a one, we know that the 8-bit integer is between 128 and 255. Since the VMU's screen dimensions are 48 by 32, with both directions well below that halfway point, we can use that leftmost digit to determine which of two values is larger. If we subtract and the final result is above 128, we know that the [subtrahend is larger than the minuend](https://math.stackexchange.com/questions/975541/what-are-the-formal-names-of-operands-and-results-for-basic-operations). That is, we'll know it as long as we aren't doing a larger operation like subtracting 200 from 1 -- we'll be keeping our scope small for now. For example, if we subtract 8 from 19: 222 | 223 | mov #19, test_variable_a 224 | mov #8, test_variable_b 225 | ld test_variable_a 226 | sub test_variable_b 227 | ld acc 228 | 229 | Our result will be 11, or 00001011 in Binary. Since that leftmost digit is a zero, we know that `test_variable_a` is larger than `test_variable_b`, as expected. So, we can check this programmatically: 230 | 231 | ld test_variable_a 232 | sub test_variable_b 233 | bn acc, 7, .it_is_greater_than 234 | .it_is_less_than 235 | ; It's Less Than! 236 | jmpf .example_over 237 | .it_is_greater_than 238 | ; It's Greater Than! 239 | .example_over 240 | 241 | We'll be doing just that to check the collision of our test sprite with the screen's boundaries. We already have a section for each of the four Cardinal Directions in our Main Loop, so let's start off by adding the collison for the Top: 242 | 243 | Main_Loop: 244 | ; Check Input 245 | callf Get_Input ; This Function Is In LibKCommon.ASM 246 | ld p3 247 | .Check_Up 248 | bp acc, T_BTN_UP1, .Check_Down 249 | ld test_sprite_y 250 | sub #1 251 | bp acc, 7, .Check_Down 252 | dec test_sprite_y 253 | .Check_Down 254 | bp acc, T_BTN_DOWN1, .Check_Left 255 | inc test_sprite_y 256 | .Check_Left 257 | bp acc, T_BTN_LEFT1, .Check_Right 258 | dec test_sprite_x 259 | .Check_Right 260 | bp acc, T_BTN_RIGHT1, .Draw_Screen 261 | inc test_sprite_x 262 | .Draw_Screen 263 | 264 | You'll need to adjust for the dimensions of your sprite. 265 | 266 | Now, when we move our sprite around, it is bounded by the top of the screen: 267 | 268 | It can still move offscreen past the other three sides of the screen, though, so let's finish coding our collision detection there. Note that we are using acc for the collision calculations now, so we will need to `ld p3` again in each block! Otherwise, our controls won't work properly since the bits we want to check for button presses will be overwritten by said collision subtraction values. 269 | 270 | ... 271 | Main_Loop: 272 | ; Check Input 273 | callf Get_Input ; This Function Is In LibKCommon.ASM 274 | ld p3 275 | .Check_Up 276 | bp acc, T_BTN_UP1, .Check_Down 277 | ld test_sprite_y 278 | sub #1 279 | bp acc, 7, .Check_Down 280 | dec test_sprite_y 281 | .Check_Down 282 | callf Get_Input 283 | ld p3 284 | bp acc, T_BTN_DOWN1, .Check_Left 285 | ld test_sprite_y 286 | sub #24 287 | bn acc, 7, .Check_Left 288 | inc test_sprite_y 289 | .Check_Left 290 | callf Get_Input 291 | ld p3 292 | bp acc, T_BTN_LEFT1, .Check_Right 293 | ld test_sprite_x 294 | sub #2 295 | bp acc, 7, .Check_Right 296 | dec test_sprite_x 297 | .Check_Right 298 | callf Get_Input 299 | ld p3 300 | bp acc, T_BTN_RIGHT1, .Draw_Screen 301 | ld test_sprite_x 302 | sub #40 303 | bn acc, 7, .Draw_Screen 304 | inc test_sprite_x 305 | .Draw_Screen 306 | ... 307 | 308 | And as before, you will need to adjust for the size of your sprite. One way to streamline this, as seen in LibPerspective's Example Demos, is to create and define variables for the Sprite Size: 309 | 310 | sprite_size_x = $10 311 | sprite_size_y = $11 312 | ... 313 | mov #11, sprite_size_x 314 | mov #9, sprite_size_y 315 | 316 |
317 | Final Lesson 3 Code File With Screen Boundary Collision 318 | 319 | ;=======================; 320 | ;Beginners' VMU Tutorial; 321 | ; Lesson 3 ; 322 | ;=======================; 323 | 324 | ;=======================; 325 | ;VMU Application Header ; 326 | ;=======================; 327 | .include "GameHeader.i" 328 | 329 | ;=======================; 330 | ; Include Libraries ; 331 | ;=======================; 332 | .include "./lib/libperspective.asm" 333 | .include "./lib/libkcommon.asm" 334 | .include "./lib/sfr.i" 335 | 336 | ;=======================; 337 | ; Include Images ; 338 | ;=======================; 339 | .include "./img/Hello_World_BackGround.asm" 340 | .include "./img/Example_Sprite.asm" 341 | .include "./img/Example_Sprite_Mask.asm" 342 | 343 | ;=======================; 344 | ; Define Variables: ; 345 | ;=======================; 346 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 347 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 348 | test_sprite_x = $6 ; 1 Byte 349 | test_sprite_y = $7 ; 1 Byte 350 | test_sprite_sprite_address = $8 ; 2 Bytes 351 | sprite_size_x = $10 352 | sprite_size_y = $11 353 | 354 | ;=======================; 355 | ; Constants ; 356 | ;=======================; 357 | T_BTN_SLEEP equ 7 358 | T_BTN_MODE equ 6 359 | T_BTN_B1 equ 5 360 | T_BTN_A1 equ 4 361 | T_BTN_RIGHT1 equ 3 362 | T_BTN_LEFT1 equ 2 363 | T_BTN_DOWN1 equ 1 364 | T_BTN_UP1 equ 0 365 | 366 | ;=======================; 367 | ; Prepare Application ; 368 | ;=======================; 369 | .org $00 370 | jmpf start 371 | 372 | .org $03 373 | reti 374 | 375 | .org $0b 376 | reti 377 | 378 | .org $13 379 | reti 380 | 381 | .org $1b 382 | jmpf t1int 383 | 384 | .org $23 385 | reti 386 | 387 | .org $2b 388 | reti 389 | 390 | .org $33 391 | reti 392 | 393 | .org $3b 394 | reti 395 | 396 | .org $43 397 | reti 398 | 399 | .org $4b 400 | clr1 p3int,0 401 | clr1 p3int,1 402 | reti 403 | 404 | .org $130 405 | t1int: 406 | push ie 407 | clr1 ie,7 408 | not1 ext,0 409 | jmpf t1int 410 | pop ie 411 | reti 412 | 413 | .org $1f0 414 | 415 | goodbye: 416 | not1 ext,0 417 | jmpf goodbye 418 | 419 | ;=======================; 420 | ; Main Program ; 421 | ;=======================; 422 | start: 423 | clr1 ie,7 424 | mov #$a1,ocr 425 | mov #$09,mcr 426 | mov #$80,vccr 427 | clr1 p3int,0 428 | clr1 p1,7 429 | mov #$ff,p3 430 | set1 ie,7 431 | ; Set Sprite Addresses 432 | mov #20, test_sprite_x 433 | mov #12, test_sprite_y 434 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 436 | mov #11, sprite_size_x 437 | mov #9, sprite_size_y 438 | 439 | Main_Loop: 440 | ; Check Input 441 | callf Get_Input ; This Function Is In LibKCommon.ASM 442 | ld p3 443 | .Check_Up 444 | bp acc, T_BTN_UP1, .Check_Down 445 | ld test_sprite_y 446 | sub #1 447 | bp acc, 7, .Check_Down 448 | dec test_sprite_y 449 | .Check_Down 450 | callf Get_Input 451 | ld p3 452 | bp acc, T_BTN_DOWN1, .Check_Left 453 | ld test_sprite_y 454 | sub #24 ; Because my sprite is 8 pixels tall. Alternately, you can do: 455 | ; ld test_sprite_y 456 | ; add sprite_size_y 457 | ; sub #32 ; VMU Screen Is 32 Pixels Tall 458 | bn acc, 7, .Check_Left 459 | inc test_sprite_y 460 | .Check_Left 461 | callf Get_Input 462 | ld p3 463 | bp acc, T_BTN_LEFT1, .Check_Right 464 | ld test_sprite_x 465 | sub #2 466 | bp acc, 7, .Check_Right 467 | dec test_sprite_x 468 | .Check_Right 469 | callf Get_Input 470 | ld p3 471 | bp acc, T_BTN_RIGHT1, .Draw_Screen 472 | ld test_sprite_x 473 | sub #40 ; Because my sprite is 8 pixels wide. Alternately, you can do: 474 | ; ld test_sprite_x 475 | ; add sprite_size_x 476 | ; sub #48 ; The VMU's Screen Is 48 Pixels Wide 477 | bn acc, 7, .Draw_Screen 478 | inc test_sprite_x 479 | .Draw_Screen 480 | P_Draw_Background_Constant Hello_World_BackGround 481 | P_Draw_Sprite_Mask test_sprite_sprite_address, test_sprite_x, test_sprite_y 482 | P_Blit_Screen 483 | jmpf Main_Loop 484 | 485 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 486 |
487 | 488 | Now, we should only be able to move our sprite within the confines of the screen boundaries: 489 | 490 | One thing to note is that what we've learned so far largely mirrors the example code in the LibPerspective example directory, specifically `demo_spritebounce.asm`. It's the first of the Example Demos seen when booting up LibPerspective's Compiled `main.asm`, and presents the user with a masked sprite, which moves diagonally around the screen and then bounces off the edges when collision with the borders is detected. The code can be found by downloading the [LibPerspective Library](https://slum.online/dreamcast/) and checking the `src/` Folder, but here's a snippet of the Main Loop to help show a bit of it to you: 491 | 492 | .demo_loop 493 | clr1 ocr, 5 494 | ; If sprite x = 0, reset x flag 495 | ld sb_spr_x_loc 496 | bnz .skip_x_reset 497 | clr1 sb_spr_flags, 0 498 | .skip_x_reset 499 | ; If sprite x + sprite x size = 48, set x flag 500 | add sb_spr_x_size 501 | sub #48 502 | bnz .skip_x_set 503 | set1 sb_spr_flags, 0 504 | .skip_x_set 505 | 506 | ; If sprite y = 0, reset y flag 507 | ld sb_spr_y_loc 508 | bnz .skip_y_reset 509 | clr1 sb_spr_flags, 1 510 | .skip_y_reset 511 | ; If sprite y + sprite y size = 32, set y flag 512 | add sb_spr_y_size 513 | sub #32 514 | bnz .skip_y_set 515 | set1 sb_spr_flags, 1 516 | .skip_y_set 517 | 518 | ; Update X pos 519 | bn sb_spr_flags, 0, .inc_x 520 | dec sb_spr_x_loc 521 | dec sb_spr_x_loc 522 | .inc_x 523 | inc sb_spr_x_loc 524 | 525 | ; Update Y pos 526 | bn sb_spr_flags, 1, .inc_y 527 | dec sb_spr_y_loc 528 | dec sb_spr_y_loc 529 | .inc_y 530 | inc sb_spr_y_loc 531 | 532 | ; Draw the sprite to the screen 533 | P_Draw_Background_Constant img_background 534 | P_Draw_Sprite_Mask sb_spr_address, sb_spr_x_loc, sb_spr_y_loc 535 | P_Blit_Screen 536 | 537 | set1 ocr, 5 538 | 539 | ; Generic input code to move between demos 540 | call Get_Input 541 | mov #Button_A, acc 542 | call Check_Button_Pressed 543 | bz .not_a 544 | ret 545 | .not_a 546 | jmp .demo_loop 547 | 548 | Other than the `ret` to leave the Loop and the `set1`/`clr1 ocr,5` calls to set the Oscillation Rate (which we'll get to later.), you'll notice that this has everything we've learned so far: masked sprites, collision, etc. There is much more to learn in that Folder -- these example programs by Kresna Susila are an amazing resource, and I highly recommend checking them out! In fact, I learned everything I've taught you so far from these demos! 549 | 550 | Stick around for Lesson 4, where we'll switch gears to drawing numbers and handling menus/scene changes. 551 | -------------------------------------------------------------------------------- /Lesson_3/img/Example_Sprite.ASM: -------------------------------------------------------------------------------- 1 | Example_Sprite: 2 | .byte 8,8 3 | .byte %01111110 4 | .byte %10000001 5 | .byte %10100101 6 | .byte %10000001 7 | .byte %10100101 8 | .byte %10011001 9 | .byte %10000001 10 | .byte %01111110 11 | -------------------------------------------------------------------------------- /Lesson_3/img/Example_Sprite_Mask.ASM: -------------------------------------------------------------------------------- 1 | Example_Sprite_Mask: 2 | .byte 10,8 3 | .byte %11000001,%11111111 4 | .byte %10000000,%11111111 5 | .byte %00000000,%01111111 6 | .byte %00000000,%01111111 7 | .byte %00000000,%01111111 8 | .byte %00000000,%01111111 9 | .byte %10000000,%11111111 10 | .byte %11000001,%11111111 11 | .byte %00000000,%00000000 12 | .byte %00111110,%00000000 13 | .byte %01010101,%00000000 14 | .byte %01000001,%00000000 15 | .byte %01010101,%00000000 16 | .byte %01001001,%00000000 17 | .byte %00111110,%00000000 18 | .byte %00000000,%00000000 19 | -------------------------------------------------------------------------------- /Lesson_3/img/Hello_World_Background.asm: -------------------------------------------------------------------------------- 1 | Hello_World_BackGround: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 6 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 7 | .byte %00000000,%00100010,%01100010,%01000111,%00000000,%00000000 8 | .byte %00000000,%00111110,%10010010,%01001000,%10000000,%00000000 9 | .byte %00000000,%00100010,%11110010,%01001000,%10000000,%00000000 10 | .byte %00000000,%00100010,%10000010,%01001000,%10010000,%00000000 11 | .byte %00000000,%00100010,%01110010,%01000111,%00010000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00100000,%00000000 13 | .byte %00000001,%00000001,%00000000,%00000100,%00001001,%00000000 14 | .byte %00000001,%00010001,%00000000,%00000100,%00001001,%00000000 15 | .byte %00000001,%00010001,%00111001,%01100100,%01111001,%00000000 16 | .byte %00000000,%10101010,%01000101,%10000100,%10001001,%00000000 17 | .byte %00000000,%10101010,%01000101,%00000100,%10001001,%00000000 18 | .byte %00000000,%01000100,%01000101,%00000100,%10001000,%00000000 19 | .byte %00000000,%01000100,%00111001,%00000100,%01111001,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 26 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 27 | .byte %00000000,%00000000,%00100000,%00000100,%00000000,%00000000 28 | .byte %00000000,%00000000,%00100000,%10000100,%00000000,%00000000 29 | .byte %00000000,%00000000,%00100100,%00100100,%00000000,%00000000 30 | .byte %00000000,%00000000,%00100011,%11000100,%00000000,%00000000 31 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 32 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 33 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 34 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_3/img/Lesson3_P_Draw_Sprite_CutOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_3/img/Lesson3_P_Draw_Sprite_CutOff.png -------------------------------------------------------------------------------- /Lesson_3/lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Kresna Susila 2 | 3 | This software is provided 'as-is', without any express or implied warranty. 4 | In no event will the authors be held liable for any damages arising from 5 | the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software in 13 | a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not 17 | be misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /Lesson_3/lib/libkcommon.asm: -------------------------------------------------------------------------------- 1 | ;****************************************************************************** 2 | ; libkcommon 3 | ;****************************************************************************** 4 | ; Some common functions I use all the time 5 | ;****************************************************************************** 6 | ; Nicer names for button masks 7 | Button_Up equ %00000001 8 | Button_Down equ %00000010 9 | Button_Left equ %00000100 10 | Button_Right equ %00001000 11 | Button_A equ %00010000 12 | Button_B equ %00100000 13 | Button_Mode equ %01000000 14 | Button_Sleep equ %10000000 15 | 16 | Get_Input: 17 | ;---------------------------------------------------------------------- 18 | ; Get input from P3, compare input to previous P3 input to get buttons 19 | ; pressed this cycle. 20 | ;---------------------------------------------------------------------- 21 | ld p3_last_input 22 | st c 23 | ld p3 24 | bn acc, 6, .quit 25 | bn acc, 7, .sleep 26 | st p3_last_input 27 | xor #%11111111 28 | and c 29 | xor #%11111111 30 | st p3_pressed 31 | ret 32 | .quit 33 | jmpf goodbye 34 | .sleep 35 | mov #0, t1cnt ; Disable audio 36 | set1 pcon, 0 ; Activate HALT mode (saves power) 37 | bn p3, 7, .sleep ; wait until Sleep Key is released 38 | mov #0,vccr ; turn off LCD 39 | .sleepmore 40 | set1 pcon,0 ; activate HALT mode (saves power) 41 | bp p7, 0, .quit ; Docked? 42 | bp p3, 7, .sleepmore ; no Sleep Key pressed yet 43 | mov #$80, vccr ; turn on LCD again 44 | .waitsleepup: 45 | set1 pcon,0 ; activate HALT modus (saves power) 46 | bn p3,7,.waitsleepup 47 | ret 48 | 49 | Check_Button_Pressed: 50 | ;---------------------------------------------------------------------- 51 | ; Check if a button is pressed, not held, this cycle 52 | ;---------------------------------------------------------------------- 53 | ; acc = button to check 54 | ;---------------------------------------------------------------------- 55 | st c 56 | ld p3_pressed 57 | xor #%11111111 58 | and c 59 | ret 60 | -------------------------------------------------------------------------------- /Lesson_3/lib/sfr.i: -------------------------------------------------------------------------------- 1 | 2 | * 3 | * Special Function Register addresses 4 | * 5 | 6 | ACC EQU $100 7 | PSW EQU $101 8 | B EQU $102 9 | C EQU $103 10 | TRL EQU $104 11 | TRH EQU $105 12 | SP EQU $106 13 | PCON EQU $107 14 | IE EQU $108 15 | IP EQU $109 16 | EXT EQU $10D 17 | OCR EQU $10E 18 | T0CON EQU $110 19 | T0PRR EQU $111 20 | T0L EQU $112 21 | T0LR EQU $113 22 | T0H EQU $114 23 | T0HR EQU $115 24 | T1CNT EQU $118 25 | T1LC EQU $11A 26 | T1L EQU $11B 27 | T1LR EQU $11B 28 | T1HC EQU $11C 29 | T1H EQU $11D 30 | T1HR EQU $11D 31 | MCR EQU $120 32 | STAD EQU $122 33 | CNR EQU $123 34 | TDR EQU $124 35 | XBNK EQU $125 36 | VCCR EQU $127 37 | SCON0 EQU $130 38 | SBUF0 EQU $131 39 | SBR EQU $132 40 | SCON1 EQU $134 41 | SBUF1 EQU $135 42 | P1 EQU $144 43 | P1DDR EQU $145 44 | P1FCR EQU $146 45 | P3 EQU $14C 46 | P3DDR EQU $14D 47 | P3INT EQU $14E 48 | P7 EQU $15C 49 | I01CR EQU $15D 50 | I23CR EQU $15E 51 | ISL EQU $15F 52 | VSEL EQU $163 53 | VRMAD1 EQU $164 54 | VRMAD2 EQU $165 55 | VTRBF EQU $166 56 | VLREG EQU $167 57 | BTCR EQU $17F 58 | XRAM EQU $180 59 | 60 | 61 | * 62 | * PSW bits 63 | * 64 | 65 | CY EQU 7 66 | AC EQU 6 67 | IRBK1 EQU 4 68 | IRBK0 EQU 3 69 | OV EQU 2 70 | RAMBK0 EQU 1 71 | P EQU 0 72 | 73 | -------------------------------------------------------------------------------- /Lesson_3/main.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ;Beginners' VMU Tutorial; 3 | ; Lesson 3 ; 4 | ;=======================; 5 | 6 | ;=======================; 7 | ;VMU Application Header ; 8 | ;=======================; 9 | .include "GameHeader.i" 10 | 11 | ;=======================; 12 | ; Include Libraries ; 13 | ;=======================; 14 | .include "./lib/libperspective.asm" 15 | .include "./lib/libkcommon.asm" 16 | .include "./lib/sfr.i" 17 | 18 | ;=======================; 19 | ; Include Images ; 20 | ;=======================; 21 | .include "./img/Hello_World_BackGround.asm" 22 | .include "./img/Example_Sprite.asm" 23 | .include "./img/Example_Sprite_Mask.asm" 24 | 25 | ;=======================; 26 | ; Define Variables: ; 27 | ;=======================; 28 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 29 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 30 | test_sprite_x = $6 ; 1 Byte 31 | test_sprite_y = $7 ; 1 Byte 32 | test_sprite_sprite_address = $8 ; 2 Bytes 33 | 34 | ;=======================; 35 | ; Constants ; 36 | ;=======================; 37 | T_BTN_SLEEP equ 7 38 | T_BTN_MODE equ 6 39 | T_BTN_B1 equ 5 40 | T_BTN_A1 equ 4 41 | T_BTN_RIGHT1 equ 3 42 | T_BTN_LEFT1 equ 2 43 | T_BTN_DOWN1 equ 1 44 | T_BTN_UP1 equ 0 45 | 46 | ;=======================; 47 | ; Prepare Application ; 48 | ;=======================; 49 | .org $00 50 | jmpf start 51 | 52 | .org $03 53 | reti 54 | 55 | .org $0b 56 | reti 57 | 58 | .org $13 59 | reti 60 | 61 | .org $1b 62 | jmpf t1int 63 | 64 | .org $23 65 | reti 66 | 67 | .org $2b 68 | reti 69 | 70 | .org $33 71 | reti 72 | 73 | .org $3b 74 | reti 75 | 76 | .org $43 77 | reti 78 | 79 | .org $4b 80 | clr1 p3int,0 81 | clr1 p3int,1 82 | reti 83 | 84 | .org $130 85 | t1int: 86 | push ie 87 | clr1 ie,7 88 | not1 ext,0 89 | jmpf t1int 90 | pop ie 91 | reti 92 | 93 | .org $1f0 94 | 95 | goodbye: 96 | not1 ext,0 97 | jmpf goodbye 98 | 99 | ;=======================; 100 | ; Main Program ; 101 | ;=======================; 102 | start: 103 | clr1 ie,7 104 | mov #$a1,ocr 105 | mov #$09,mcr 106 | mov #$80,vccr 107 | clr1 p3int,0 108 | clr1 p1,7 109 | mov #$ff,p3 110 | set1 ie,7 111 | ; Set Sprite Addresses 112 | mov #20, test_sprite_x 113 | mov #12, test_sprite_y 114 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 116 | 117 | Main_Loop: 118 | ; Check Input 119 | callf Get_Input ; This Function Is In LibKCommon.ASM 120 | ld p3 121 | .Check_Up 122 | bp acc, T_BTN_UP1, .Check_Down 123 | ld test_sprite_y 124 | sub #1 125 | bp acc, 7, .Check_Down 126 | dec test_sprite_y 127 | .Check_Down 128 | callf Get_Input 129 | ld p3 130 | bp acc, T_BTN_DOWN1, .Check_Left 131 | ld test_sprite_y 132 | sub #24 133 | bn acc, 7, .Check_Left 134 | inc test_sprite_y 135 | .Check_Left 136 | callf Get_Input 137 | ld p3 138 | bp acc, T_BTN_LEFT1, .Check_Right 139 | ld test_sprite_x 140 | sub #2 141 | bp acc, 7, .Check_Right 142 | dec test_sprite_x 143 | .Check_Right 144 | callf Get_Input 145 | ld p3 146 | bp acc, T_BTN_RIGHT1, .Draw_Screen 147 | ld test_sprite_x 148 | sub #40 149 | bn acc, 7, .Draw_Screen 150 | inc test_sprite_x 151 | .Draw_Screen 152 | P_Draw_Background_Constant Hello_World_BackGround 153 | P_Draw_Sprite_Mask test_sprite_sprite_address, test_sprite_x, test_sprite_y 154 | P_Blit_Screen 155 | jmpf Main_Loop 156 | 157 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 158 | -------------------------------------------------------------------------------- /Lesson_4/Article_Images/Lesson4_BackGroundTextGraphicPlusWithSprites_Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/Article_Images/Lesson4_BackGroundTextGraphicPlusWithSprites_Example.png -------------------------------------------------------------------------------- /Lesson_4/Article_Images/Lesson4_BackGroundTextGraphic_Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/Article_Images/Lesson4_BackGroundTextGraphic_Example.png -------------------------------------------------------------------------------- /Lesson_4/Cursor_Gameplay.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ; Gameplay ; 3 | ;=======================; 4 | Cursor_Gameplay: 5 | test_sprite_x = $6 ; 1 Byte ; Moving These Three To "Cursor_Gameplay." 6 | test_sprite_y = $7 ; 1 Byte 7 | test_sprite_sprite_address = $8 ; 2 Bytes 8 | ones_digit = $1a 9 | tens_digit = $1b 10 | hundreds_digit = $1c 11 | thousands_digit = $1d 12 | score = $1e 13 | digit_sprite_address = $1f 14 | 15 | ; Populate Character And Stage Flags 16 | ld cursor_flags 17 | ld stage_flags 18 | ; Set Sprite Addresses 19 | mov #20, test_sprite_x 20 | mov #12, test_sprite_y 21 | .Draw_Example_Character_1 22 | ld character_flags 23 | bnz .Draw_Example_Character_2 24 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 26 | jmpf Cursor_Gameplay_Loop 27 | .Draw_Example_Character_2 28 | ld character_flags 29 | sub #1 30 | bnz .Draw_Example_Character_3 31 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 33 | jmpf Cursor_Gameplay_Loop 34 | .Draw_Example_Character_3 35 | ld character_flags 36 | sub #2 37 | bnz Cursor_Gameplay_Loop 38 | mov #Example_Sprite_HeroChao_Mask, test_sprite_sprite_address+1 40 | 41 | Cursor_Gameplay_Loop: 42 | ; Check Input 43 | callf Get_Input ; This Function Is In LibKCommon.ASM 44 | ld p3 45 | .Check_Up 46 | bp acc, T_BTN_UP1, .Check_Down 47 | ld test_sprite_y 48 | sub #1 49 | bp acc, 7, .Check_Down 50 | dec test_sprite_y 51 | .Check_Down 52 | callf Get_Input 53 | ld p3 54 | bp acc, T_BTN_DOWN1, .Check_Left 55 | ld test_sprite_y 56 | sub #24 57 | bn acc, 7, .Check_Left 58 | inc test_sprite_y 59 | .Check_Left 60 | callf Get_Input 61 | ld p3 62 | bp acc, T_BTN_LEFT1, .Check_Right 63 | ld test_sprite_x 64 | sub #2 65 | bp acc, 7, .Check_Right 66 | dec test_sprite_x 67 | .Check_Right 68 | callf Get_Input 69 | ld p3 70 | bp acc, T_BTN_RIGHT1, .Check_Buttons 71 | ld test_sprite_x 72 | sub #40 73 | bn acc, 7, .Draw_Screen 74 | inc test_sprite_x 75 | .Check_Buttons ; Return To The "Main Menu/Pause Menu" If The Player Presses A Or B 76 | callf Get_Input 77 | ld p3 78 | bn acc, T_BTN_A1, .Return_To_Menu 79 | bn acc, T_BTN_B1, .Return_To_Menu 80 | jmpf .Draw_Screen 81 | .Return_To_Menu 82 | ret ; Leave `Cursor_Gameplay.ASM` And Return To `Main_Menu.ASM`, As Per `Main.ASM`'s Main Loop. 83 | .Draw_Screen 84 | .Draw_Example_Stage_1 85 | ld stage_flags 86 | bnz .Draw_Example_Stage_2 87 | P_Draw_Background_Constant ExampleBG_City 88 | jmpf .Draw_Character 89 | .Draw_Example_Stage_2 90 | ld stage_flags 91 | sub #1 92 | bnz .Draw_Example_Stage_3 93 | ; P_Draw_Background_Constant ExampleBG_Jungle 94 | jmpf .Draw_Character 95 | .Draw_Example_Stage_3 96 | ld stage_flags 97 | sub #2 98 | bnz .Draw_Character 99 | P_Draw_Background_Constant Hello_World_BackGround 100 | .Draw_Character 101 | P_Draw_Sprite_Mask test_sprite_sprite_address, test_sprite_x, test_sprite_y 102 | P_Blit_Screen 103 | jmpf Cursor_Gameplay_Loop 104 | 105 | Draw_Digit: 106 | ; b = the X-Position, c = the Number 107 | .Digit_0 108 | ld c 109 | bnz .Digit_1 110 | mov #Digit_0, digit_sprite_address+1 112 | jmpf .Digit_Decided 113 | .Digit_1 114 | ld c 115 | sub #1 116 | bnz .Digit_2 117 | mov #Digit_1, digit_sprite_address+1 119 | jmpf .Digit_Decided 120 | .Digit_2 121 | ld c 122 | sub #2 123 | bnz .Digit_3 124 | mov #Digit_2, digit_sprite_address+1 126 | jmpf .Digit_Decided 127 | .Digit_3 128 | ld c 129 | sub #2 130 | bnz .Digit_4 131 | mov #Digit_3, digit_sprite_address+1 133 | jmpf .Digit_Decided 134 | .Digit_4 135 | ld c 136 | sub #2 137 | bnz .Digit_5 138 | mov #Digit_4, digit_sprite_address+1 140 | jmpf .Digit_Decided 141 | .Digit_5 142 | .Digit_Decided 143 | mov #0, c ; Every Digit will be at the top of the screen. 144 | P_Draw_Sprite digit_sprite_address, b, c 145 | ret 146 | 147 | %macro Draw_Score 148 | mov #16, b 149 | ld ones_digit 150 | st c 151 | callf Draw_Digit 152 | mov #24, b 153 | ld tens_digit 154 | st c 155 | callf Draw_Digit 156 | mov #32, b 157 | ld hundreds_digit 158 | st c 159 | callf Draw_Digit 160 | mov #40, b 161 | ld thousands_digit 162 | st c 163 | callf Draw_Digit 164 | %end -------------------------------------------------------------------------------- /Lesson_4/GameHeader.i: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------------------- 2 | ; ROM info 3 | ;------------------------------------------------------------------------------- 4 | .org $200 5 | 6 | .byte "VMU Dev Lesson 4 " ; 16 bytes 7 | .byte "VMU Beginners' Tutorial #4." ; 32 byte 8 | ; Thanks To Marcus, Sebastian, And Tyro For Header Format! 9 | 10 | .org $240 11 | 12 | .word 1 ; number of icons (max = 3) 13 | .word 14 ; animation speed 14 | 15 | ;------------------------------------------------------------------------------- 16 | ; Game Icon Palette Table 17 | ; 18 | ; Each entry is 16-bit, as such AAAARRRR GGGGBBBB 19 | ; where a value of 0xF for alpha means opaque 20 | ;------------------------------------------------------------------------------- 21 | .org $260 22 | 23 | .word $fffe, $f114, $ffff, $f8df, $fa0f, $f02f, $ffae, $f000 24 | .word $f60a, $ff8d, $f406, $f051, $f081, $fd7b, $fd00, $f900 25 | 26 | ;------------------------------------------------------------------------------- 27 | ; Game Icon Data 28 | ;------------------------------------------------------------------------------- 29 | 30 | ; This is where the game icons are placed. Each icon is 512 byte long, 31 | ; 32 * 32 pixel, each pixel being represented by 4 bit (one nybble) that 32 | ; serve as a pointer into the color palette table. 33 | 34 | .org $280 35 | ; 0 5 10 15 20 25 30 36 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 37 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 38 | .byte $00,$10,$00,$10,$00,$00,$00,$01,$11,$01,$00,$00,$00,$00,$00,$00 39 | .byte $00,$11,$01,$10,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$10,$00 40 | .byte $00,$10,$10,$10,$10,$01,$00,$01,$10,$01,$01,$10,$11,$01,$11,$00 41 | .byte $00,$10,$00,$10,$10,$01,$00,$01,$00,$01,$01,$00,$10,$00,$10,$00 42 | .byte $00,$10,$00,$10,$01,$11,$00,$01,$00,$01,$01,$01,$10,$00,$10,$00 43 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 44 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 45 | .byte $00,$00,$00,$00,$01,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 46 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 47 | .byte $10,$00,$10,$10,$00,$10,$10,$00,$10,$00,$01,$10,$00,$00,$00,$00 48 | .byte $10,$00,$10,$11,$01,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 49 | .byte $10,$00,$10,$10,$10,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 50 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$11,$11,$01,$10,$01,$10 51 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$10,$01,$01,$01,$01,$01 52 | .byte $00,$10,$00,$10,$00,$10,$01,$11,$00,$00,$10,$01,$01,$10,$01,$10 53 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00 54 | .byte $00,$00,$00,$00,$00,$00,$00,$01,$11,$00,$00,$00,$01,$00,$01,$00 55 | .byte $00,$00,$00,$00,$00,$00,$01,$10,$00,$11,$00,$00,$00,$00,$00,$00 56 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 57 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 58 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 59 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 60 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 61 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 62 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$10,$00,$00,$00,$00,$00 63 | .byte $00,$00,$00,$00,$00,$00,$11,$11,$00,$01,$10,$00,$00,$00,$00,$00 64 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$01,$00,$10,$00,$00,$00,$00,$00 65 | .byte $00,$00,$00,$00,$00,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00 66 | .byte $00,$00,$00,$00,$00,$00,$00,$11,$11,$10,$00,$00,$00,$00,$00,$00 67 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 68 | -------------------------------------------------------------------------------- /Lesson_4/Main_Menu.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ; Main Menu ; 3 | ;=======================; 4 | Main_Menu: 5 | 6 | ;=======================; 7 | ; Define Variables: ; 8 | ;=======================; 9 | cursor_flags = $26 ; 1 Byte 10 | character_text_sprite_address = $7 ; 2 Bytes 11 | character_selection_sprite_address = $9 ; 2 Bytes 12 | stage_text_sprite_address = $11 ; 2 Bytes 13 | stage_selection_sprite_address = $13 ; 2 Bytes 14 | ok_button_sprite_address = $15 ; 2 Bytes 15 | ;character_flags = $17 ; 1 Byte 16 | ;stage_flags = $18 ; 1 Byte 17 | menu_heading_message_sprite_address = $19 ; 2 Bytes 18 | 19 | ;=======================; 20 | ; Initialize Variables ; 21 | ;=======================; 22 | mov #0, cursor_flags ; When The User "Pauses" To The Menu, We'll Always Put The Cursor On The Top Option. Character_Flags And Stage_Flags Will Be Inherited, As They're Already Set In Memory In Main.ASM Or In Cursor_Gameplay.ASM. 23 | mov #0, character_flags 24 | mov #0, stage_flags 25 | 26 | ;=======================; 27 | ; Set Sprite Addresses ; 28 | ;=======================; 29 | .Initialize_Welcome_Message 30 | mov #Menu_Text_Character_1_Highlighted, character_selection_sprite_address+1 38 | jmpf .Initialize_Stage_1 39 | .Initialize_Character_2 40 | ld character_flags 41 | sub #1 42 | bnz .Initialize_Character_3 43 | mov #Menu_Text_Character_2_Smiley_Highlighted, character_selection_sprite_address+1 45 | jmpf .Initialize_Stage_1 46 | .Initialize_Character_3 47 | ld character_flags 48 | sub #2 49 | bnz .Initialize_Stage_1 50 | mov #Menu_Text_Character_3_Highlighted, character_selection_sprite_address+1 52 | .Initialize_Stage_1 53 | ld stage_flags 54 | bnz .Initialize_Stage_2 55 | mov #Menu_Text_Stage_1_City_Highlighted, stage_selection_sprite_address+1 58 | ; mov #>Menu_Text_Character_1_Highlighted, stage_selection_sprite_address+1 59 | mov #Menu_Text_Character_1_Highlighted, stage_selection_sprite_address+1 61 | jmpf .Initialize_OK_Button 62 | .Initialize_Stage_2 63 | ld stage_flags 64 | sub #1 65 | bnz .Initialize_Stage_3 66 | ; mov #Menu_Text_Stage_2_Highlighted, stage_selection_sprite_address 68 | mov #Menu_Text_Character_2_Smiley_Highlighted, stage_selection_sprite_address+1 70 | jmpf .Initialize_OK_Button 71 | .Initialize_Stage_3 72 | ld stage_flags 73 | sub #2 74 | bnz .Initialize_OK_Button 75 | ; mov #Menu_Text_Stage_3_Highlighted, stage_selection_sprite_address+1 77 | mov #Menu_Text_Character_3_Highlighted, stage_selection_sprite_address+1 79 | .Initialize_OK_Button 80 | mov #Menu_Text_OK_Button_Start, ok_button_sprite_address+1 82 | 83 | ;=======================; 84 | ; Main Loop ; 85 | ;=======================; 86 | Main_Menu_Loop: 87 | ; Check Input 88 | .Check_Up 89 | callf Get_Input ; Note To Self: Note To Users That you Only Wanna Call This Once Per Frame, For p3_Last_PRessed. 90 | mov #Button_Up, acc 91 | callf Check_Button_Pressed 92 | bn acc, 0, .Check_Down 93 | ld cursor_flags 94 | bz .Reset_Cursor_Overflow_Up 95 | dec cursor_flags 96 | jmpf .Handle_Character_Selection_Text 97 | .Reset_Cursor_Overflow_Up 98 | mov #2, cursor_flags 99 | jmpf .Handle_Character_Selection_Text 100 | .Check_Down 101 | mov #Button_Down, acc 102 | callf Check_Button_Pressed 103 | bn acc, 1, .Check_Left ; bnz .Check_Left 104 | ld cursor_flags 105 | sub #2 106 | bz .Reset_Cursor_Overflow_Down 107 | inc cursor_flags 108 | jmpf .Handle_Character_Selection_Text 109 | .Reset_Cursor_Overflow_Down 110 | mov #0, cursor_flags 111 | jmpf .Handle_Character_Selection_Text 112 | .Check_Left 113 | mov #Button_Left, acc 114 | callf Check_Button_Pressed 115 | bn acc, 2, .Check_Right ; bnz .Check_Right 116 | .Left_Character_Select 117 | ld cursor_flags 118 | bnz .Left_Stage_Select 119 | ld character_flags 120 | bnz .decrement_character_flags 121 | mov #2, character_flags 122 | jmpf .Handle_Character_Selection_Text 123 | .decrement_character_flags 124 | dec character_flags 125 | jmpf .Handle_Character_Selection_Text 126 | .Left_Stage_Select 127 | ld cursor_flags 128 | sub #1 129 | bnz .Handle_Character_Selection_Text 130 | ld stage_flags 131 | bnz .decrement_stage_flags 132 | mov #2, stage_flags 133 | jmpf .Handle_Character_Selection_Text 134 | .decrement_stage_flags 135 | dec stage_flags 136 | jmpf .Handle_Character_Selection_Text 137 | .Check_Right 138 | mov #Button_Right, acc 139 | callf Check_Button_Pressed 140 | bn acc, 3, .Check_OK_Button ; bnz .Check_OK_Button 141 | .Right_Character_Select 142 | ld cursor_flags 143 | bnz .Right_Stage_Select 144 | ld character_flags 145 | sub #2 146 | bnz .increment_character_flags 147 | mov #0, character_flags 148 | jmpf .Check_OK_Button 149 | .increment_character_flags 150 | inc character_flags 151 | jmpf .Check_OK_Button 152 | .Right_Stage_Select 153 | ld cursor_flags 154 | sub #1 ; #2 155 | bnz .Handle_Character_Selection_Text 156 | ld stage_flags 157 | sub #2 158 | bnz .increment_stage_flags 159 | mov #0, stage_flags 160 | jmpf .Check_OK_Button 161 | .increment_stage_flags 162 | inc stage_flags 163 | .Check_OK_Button 164 | ld cursor_flags 165 | sub #2 166 | ;bnz .Handle_Character_Selection_Text 167 | 168 | ; callf Get_Input ; Will Change This To Get_Button_Pressed Later, Noting In The Article For Users That It Records The Button Press Once. 169 | ; bn acc, T_BTN_A1, .Click_OK 170 | ; bn acc, T_BTN_B1, .Click_OK 171 | 172 | ;mov #Button_A, acc 173 | ;callf Check_Button_Pressed 174 | ;bn acc, 4, .Click_OK ; bnz .Click_OK 175 | ;mov #Button_B, acc 176 | ;callf Check_Button_Pressed 177 | ;bn acc, 5, .Click_OK ; bnz .Click_OK 178 | ;jmpf .Handle_Character_Selection_Text 179 | .Click_OK 180 | ret 181 | 182 | ; callf Get_Input 183 | ld p3 184 | bn acc, T_BTN_A1, .Return_To_Menu 185 | bn acc, T_BTN_B1, .Return_To_Menu 186 | jmpf .Handle_Character_Selection_Text 187 | 188 | callf Check_Button_Pressed 189 | bn acc, 4, .Return_To_Menu 190 | bn acc, 5, .Return_To_Menu 191 | jmpf .Handle_Character_Selection_Text 192 | .Return_To_Menu 193 | ; mov #0, cursor_flags 194 | ret 195 | 196 | .Handle_Character_Selection_Text 197 | .Cursor_On_Character_Select 198 | ; bn Cursor_Flags, 0, .Cursor_Not_On_Character_Select ; Load Flag -- Is It Selected? If So, Which Character? 199 | ld cursor_Flags 200 | bnz .Cursor_Not_On_Character_Select 201 | .Handle_Character_Highlighted_Text 202 | .Character_1_Highlighted 203 | ld Character_Flags 204 | bnz .Character_2_Highlighted 205 | mov #Menu_Text_Character_1_Highlighted, character_selection_sprite_address+1 207 | jmpf .Handle_Stage_Selection_Text 208 | .Character_2_Highlighted 209 | ld Character_Flags 210 | sub #1 211 | bnz .Character_3_Highlighted 212 | mov #Menu_Text_Character_2_Smiley_Highlighted, character_selection_sprite_address+1 214 | jmpf .Handle_Stage_Selection_Text 215 | .Character_3_Highlighted 216 | ld Character_Flags 217 | sub #2 218 | bnz .Handle_Stage_Selection_Text ; Just In Case 219 | mov #Menu_Text_Character_3_Highlighted, character_selection_sprite_address+1 221 | jmpf .Handle_Stage_Selection_Text 222 | .Cursor_Not_On_Character_Select 223 | .Character_1_Not_Highlighted 224 | ld Character_Flags 225 | bnz .Character_2_Not_Highlighted 226 | mov #Menu_Text_Character_1, character_selection_sprite_address+1 228 | jmpf .Handle_Stage_Selection_text 229 | .Character_2_Not_Highlighted 230 | ld Character_Flags 231 | sub #1 232 | bnz .Character_3_Not_Highlighted 233 | mov #Menu_Text_Character_2, character_selection_sprite_address+1 235 | jmpf .Handle_Stage_Selection_text 236 | .Character_3_Not_Highlighted 237 | ld Character_Flags 238 | sub #2 239 | bnz .Handle_Stage_Selection_text 240 | mov #Menu_Text_Character_3, character_selection_sprite_address+1 242 | .Handle_Stage_Selection_Text 243 | .Cursor_On_Stage_Select 244 | ld cursor_Flags 245 | sub #1 246 | bnz .Cursor_Not_On_Stage_Select 247 | .Stage_1_Highlighted 248 | ld Stage_Flags 249 | bnz .Stage_2_Highlighted 250 | ; mov #Menu_Text_Stage_1_Highlighted, stage_selection_sprite_address+1 252 | mov #Menu_Text_Character_1_Highlighted, stage_selection_sprite_address+1 254 | jmpf .Draw_OK_Button_Highlighted 255 | .Stage_2_Highlighted 256 | ld Stage_Flags 257 | sub #1 258 | bnz .Stage_3_Highlighted 259 | ; mov #Menu_Text_Stage_2_Highlighted, stage_selection_sprite_address+1 261 | mov #Menu_Text_Stage_2_Jungle_Highlighted, stage_selection_sprite_address+1 263 | jmpf .Draw_OK_Button_Highlighted 264 | .Stage_3_Highlighted 265 | ld Stage_Flags 266 | sub #2 267 | bnz .Draw_Screen ; Just In Case 268 | ; mov #Menu_Text_Stage_3_Highlighted, stage_selection_sprite_address+1 270 | mov #Menu_Text_Character_3_Highlighted, stage_selection_sprite_address+1 272 | jmpf .Draw_OK_Button_Highlighted 273 | .Cursor_Not_On_Stage_Select 274 | .Stage_1_Not_Highlighted 275 | ld Stage_Flags 276 | bnz .Stage_2_Not_Highlighted 277 | mov #Menu_Text_Stage_1_City, stage_selection_sprite_address+1 279 | ; mov #Menu_Text_Character_1, stage_selection_sprite_address+1 281 | jmpf .Draw_OK_Button_Highlighted 282 | .Stage_2_Not_Highlighted 283 | ld Stage_Flags 284 | sub #1 285 | bnz .Stage_3_Not_Highlighted 286 | mov #Menu_Text_Stage_2_Jungle, stage_selection_sprite_address+1 288 | jmpf .Draw_Screen 289 | .Stage_3_Not_Highlighted 290 | ld Stage_Flags 291 | sub #2 292 | bnz .Draw_OK_Button_Highlighted 293 | ;mov #Menu_Text_Stage_3, stage_selection_sprite_address+1 295 | mov #Menu_Text_Character_3, stage_selection_sprite_address+1 297 | .Handle_OK_Button_Text ; Note: May Change These To "Start" And "Resume," Depending On If The User Has Come From Boot-Up Or From "Pausing." 298 | .Draw_OK_Button_Highlighted 299 | ld cursor_Flags 300 | sub #2 301 | bnz .Draw_OK_Button_Not_Highlighted 302 | mov #Menu_Text_OK_Button_Start_Highlighted, ok_button_sprite_address+1 304 | jmpf .Draw_Screen 305 | .Draw_OK_Button_Not_Highlighted 306 | ld cursor_Flags 307 | sub #2 308 | bz .Draw_Screen 309 | ; mov #Menu_Text_OK_Button_Resume, menu_heading_message_sprite_address+1 311 | mov #Menu_Text_OK_Button_Start, ok_button_sprite_address+1 313 | ; mov #Menu_Text_Character_1_Highlighted, character_selection_sprite_address+1 315 | ; mov #Menu_Text_Character_1, stage_selection_sprite_address+1 317 | .Draw_Screen 318 | mov #Menu_Text_Welcome_Message, menu_heading_message_sprite_address+1 320 | P_Draw_Background_Constant Main_Menu_BG 321 | mov #0, b 322 | mov #0, c 323 | P_Draw_Sprite menu_heading_message_sprite_address, b, c 324 | mov #24, b 325 | mov #8, c 326 | P_Draw_Sprite character_selection_sprite_address, b, c ; #8, #8 ; Change to b,c 327 | mov #24, b 328 | ;ld b 329 | ;add cursor_flags 330 | ;st b 331 | mov #16, c 332 | P_Draw_Sprite stage_selection_sprite_address, b, c ; #16, #16 333 | mov #0, b 334 | mov #24, c 335 | P_Draw_Sprite ok_button_sprite_address, b, c ; #8, #24 336 | P_Blit_Screen 337 | jmpf Main_Menu_Loop 338 | -------------------------------------------------------------------------------- /Lesson_4/bin/Lesson4.vms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/bin/Lesson4.vms -------------------------------------------------------------------------------- /Lesson_4/bin/Lesson_4.vms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/bin/Lesson_4.vms -------------------------------------------------------------------------------- /Lesson_4/img/Digit_0.ASM: -------------------------------------------------------------------------------- 1 | Digit_0: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %01000100 7 | .byte %01000100 8 | .byte %01000100 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_0.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_1.ASM: -------------------------------------------------------------------------------- 1 | Digit_1: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00001000 5 | .byte %00011000 6 | .byte %00001000 7 | .byte %00001000 8 | .byte %00001000 9 | .byte %00001000 10 | .byte %00111110 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_1.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_2.asm: -------------------------------------------------------------------------------- 1 | Digit_2: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00000100 7 | .byte %00011000 8 | .byte %00100000 9 | .byte %01000000 10 | .byte %01111100 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_2.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_3.ASM: -------------------------------------------------------------------------------- 1 | Digit_3: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00000100 7 | .byte %00011000 8 | .byte %00000100 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_3.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_4.asm: -------------------------------------------------------------------------------- 1 | Digit_4: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00001000 5 | .byte %00011000 6 | .byte %00101000 7 | .byte %01111100 8 | .byte %00001000 9 | .byte %00001000 10 | .byte %00001000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_4.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_5.ASM: -------------------------------------------------------------------------------- 1 | Digit_5: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %01111100 5 | .byte %01000000 6 | .byte %01000000 7 | .byte %01111000 8 | .byte %00000100 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_5.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_6.ASM: -------------------------------------------------------------------------------- 1 | Digit_6: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %01000000 7 | .byte %01111000 8 | .byte %01000100 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_6.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_7.asm: -------------------------------------------------------------------------------- 1 | Digit_7: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %01111100 5 | .byte %00000100 6 | .byte %00001000 7 | .byte %00010000 8 | .byte %00010000 9 | .byte %00100000 10 | .byte %00100000 -------------------------------------------------------------------------------- /Lesson_4/img/Digit_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_7.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_8.ASM: -------------------------------------------------------------------------------- 1 | Digit_8: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00101000 7 | .byte %00010000 8 | .byte %00101000 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_8.png -------------------------------------------------------------------------------- /Lesson_4/img/Digit_9.ASM: -------------------------------------------------------------------------------- 1 | Digit_9: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %01000100 7 | .byte %00111100 8 | .byte %00000100 9 | .byte %00001000 10 | .byte %00110000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Digit_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Digit_9.png -------------------------------------------------------------------------------- /Lesson_4/img/ExampleBG_City.asm: -------------------------------------------------------------------------------- 1 | ExampleBG_City: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%01010000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%01010000 5 | .byte %00000000,%01110000,%00000000,%00000000,%00000000,%01010000 6 | .byte %00000000,%10001000,%00000000,%00000000,%00000000,%11111000 7 | .byte %00000001,%00000100,%00000000,%00000000,%00000000,%10001000 8 | .byte %00000001,%00000100,%00000000,%00000000,%00000000,%10101000 9 | .byte %00000001,%00000100,%00001111,%11100000,%00000000,%10001000 10 | .byte %00000000,%10001000,%00001000,%00100000,%00000000,%10101000 11 | .byte %00000000,%01110000,%00001010,%10100000,%00000000,%10001110 12 | .byte %10100000,%00000000,%00001000,%00100000,%10000000,%10101010 13 | .byte %10100000,%00000000,%00001010,%10100001,%11000000,%10001010 14 | .byte %10100000,%00000000,%00001000,%00100000,%10000011,%10101010 15 | .byte %11110000,%00000000,%00001010,%10100000,%10000010,%10001010 16 | .byte %00010000,%00000000,%00001000,%00100000,%10000010,%10100010 17 | .byte %11010000,%00000000,%00001010,%10100001,%01000010,%10000010 18 | .byte %00010011,%11111111,%11101000,%00100010,%00100010,%10101010 19 | .byte %11010010,%00000000,%00101010,%10100010,%00100010,%00000010 20 | .byte %00010010,%00000000,%00101000,%00100100,%10010010,%10101010 21 | .byte %11010011,%10110110,%11101010,%10100101,%11010010,%00000010 22 | .byte %00010011,%10110110,%11101000,%00100100,%10010010,%10101010 23 | .byte %11010010,%00000000,%00101010,%10100100,%00010010,%00000010 24 | .byte %00010010,%00111110,%00101000,%00100100,%00010010,%10101010 25 | .byte %10010010,%00101010,%00101001,%00100100,%10010010,%00100010 26 | .byte %10010010,%00101010,%00101001,%00100100,%10010010,%00100010 27 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 28 | .byte %00011111,%10000111,%11100001,%11111000,%01111110,%00011111 29 | .byte %01111111,%00001111,%11100001,%11111000,%01111111,%00001111 30 | .byte %11111110,%00001111,%11000001,%11111000,%00111111,%10000011 31 | .byte %11111100,%00011111,%11000011,%11111100,%00111111,%01000001 32 | .byte %11111000,%00111111,%10000011,%11111100,%00011111,%11100000 33 | .byte %11110000,%00111111,%10000011,%11111100,%00011111,%11110000 34 | .byte %11100000,%01111111,%00000011,%11111100,%00001111,%11111000 35 | -------------------------------------------------------------------------------- /Lesson_4/img/ExampleBG_City.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/ExampleBG_City.png -------------------------------------------------------------------------------- /Lesson_4/img/Example_Sprite.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite: 2 | .byte 8,8 3 | .byte %01111110 4 | .byte %10000001 5 | .byte %10100101 6 | .byte %10000001 7 | .byte %10100101 8 | .byte %10011001 9 | .byte %10000001 10 | .byte %01111110 -------------------------------------------------------------------------------- /Lesson_4/img/Example_Sprite_HeroChao_Mask.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite_HeroChao_Mask: 2 | .byte 9,12 3 | .byte %11100011,%11111111 4 | .byte %11000001,%11111111 5 | .byte %10000000,%11111111 6 | .byte %11000001,%11111111 7 | .byte %11100011,%11111111 8 | .byte %11000001,%11111111 9 | .byte %11100011,%11111111 10 | .byte %11000001,%11111111 11 | .byte %10000000,%11111111 12 | .byte %10000000,%11111111 13 | .byte %11000001,%11111111 14 | .byte %11100011,%11111111 15 | .byte %00000000,%00000000 16 | .byte %00011100,%00000000 17 | .byte %00100010,%00000000 18 | .byte %00011100,%00000000 19 | .byte %00000000,%00000000 20 | .byte %00010100,%00000000 21 | .byte %00001000,%00000000 22 | .byte %00010100,%00000000 23 | .byte %00100010,%00000000 24 | .byte %00100010,%00000000 25 | .byte %00011100,%00000000 26 | .byte %00000000,%00000000 27 | -------------------------------------------------------------------------------- /Lesson_4/img/Example_Sprite_HeroChao_Mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Example_Sprite_HeroChao_Mask.png -------------------------------------------------------------------------------- /Lesson_4/img/Example_Sprite_Mask.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite_Mask: 2 | .byte 10,8 3 | .byte %11000001,%11111111 4 | .byte %10000000,%11111111 5 | .byte %00000000,%01111111 6 | .byte %00000000,%01111111 7 | .byte %00000000,%01111111 8 | .byte %00000000,%01111111 9 | .byte %10000000,%11111111 10 | .byte %11000001,%11111111 11 | .byte %00000000,%00000000 12 | .byte %00111110,%00000000 13 | .byte %01010101,%00000000 14 | .byte %01000001,%00000000 15 | .byte %01010101,%00000000 16 | .byte %01001001,%00000000 17 | .byte %00111110,%00000000 18 | .byte %00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_4/img/Hello_World_Background.asm: -------------------------------------------------------------------------------- 1 | Hello_World_BackGround: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 6 | .byte %00000000,%00100010,%00000010,%01000000,%00000000,%00000000 7 | .byte %00000000,%00100010,%01100010,%01000111,%00000000,%00000000 8 | .byte %00000000,%00111110,%10010010,%01001000,%10000000,%00000000 9 | .byte %00000000,%00100010,%11110010,%01001000,%10000000,%00000000 10 | .byte %00000000,%00100010,%10000010,%01001000,%10010000,%00000000 11 | .byte %00000000,%00100010,%01110010,%01000111,%00010000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00100000,%00000000 13 | .byte %00000001,%00000001,%00000000,%00000100,%00001001,%00000000 14 | .byte %00000001,%00010001,%00000000,%00000100,%00001001,%00000000 15 | .byte %00000001,%00010001,%00111001,%01100100,%01111001,%00000000 16 | .byte %00000000,%10101010,%01000101,%10000100,%10001001,%00000000 17 | .byte %00000000,%10101010,%01000101,%00000100,%10001001,%00000000 18 | .byte %00000000,%01000100,%01000101,%00000100,%10001000,%00000000 19 | .byte %00000000,%01000100,%00111001,%00000100,%01111001,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 26 | .byte %00000000,%00000000,%00100010,%01000100,%00000000,%00000000 27 | .byte %00000000,%00000000,%00100000,%00000100,%00000000,%00000000 28 | .byte %00000000,%00000000,%00100000,%10000100,%00000000,%00000000 29 | .byte %00000000,%00000000,%00100100,%00100100,%00000000,%00000000 30 | .byte %00000000,%00000000,%00100011,%11000100,%00000000,%00000000 31 | .byte %00000000,%00000000,%00010000,%00001000,%00000000,%00000000 32 | .byte %00000000,%00000000,%00001100,%00110000,%00000000,%00000000 33 | .byte %00000000,%00000000,%00000011,%11000000,%00000000,%00000000 34 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_4/img/Main_Menu_BG.asm: -------------------------------------------------------------------------------- 1 | Main_Menu_BG: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 7 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 8 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | .byte %11100100,%00000000,%00000010,%00000000,%00000000,%00000000 12 | .byte %10010100,%00000000,%00000000,%00000000,%00000000,%00000000 13 | .byte %10010100,%10010100,%10010100,%00000000,%00000000,%00000000 14 | .byte %11100101,%01010101,%11011000,%00000000,%00000000,%00000000 15 | .byte %10000101,%01001101,%00010000,%00000000,%00000000,%00000000 16 | .byte %10000100,%11100100,%11010010,%00000000,%00000000,%00000000 17 | .byte %00000000,%00000100,%00000000,%00000000,%00000000,%00000000 18 | .byte %00000000,%00011000,%00000000,%00000000,%00000000,%00000000 19 | .byte %00000110,%00000000,%00000010,%00000000,%00000000,%00000000 20 | .byte %00001000,%10000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000101,%11010001,%00010000,%00000000,%00000000,%00000000 22 | .byte %00000010,%10101010,%10111000,%00000000,%00000000,%00000000 23 | .byte %00000010,%10101010,%10100000,%00000000,%00000000,%00000000 24 | .byte %00001100,%10011101,%10011010,%00000000,%00000000,%00000000 25 | .byte %00000000,%00000000,%10000000,%00000000,%00000000,%00000000 26 | .byte %00000000,%00000011,%00000000,%00000000,%00000000,%00000000 27 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 28 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 29 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 30 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 31 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 32 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 33 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 34 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 35 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_1.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_1: 2 | .byte 24, 8 3 | .byte %01010000,%00000101,%00000000 4 | .byte %01010000,%00001011,%00000000 5 | .byte %01110110,%01001001,%10010010 6 | .byte %01011111,%10101001,%01101101 7 | .byte %01011010,%10101011,%01101101 8 | .byte %01010110,%01000101,%01011010 9 | .byte %00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Character_1.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_1_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_1_Highlighted: 2 | .byte 24, 8 3 | .byte %10101111,%11111010,%11111111 4 | .byte %10101111,%11110100,%11111111 5 | .byte %10001001,%10110110,%01101101 6 | .byte %10100000,%01010110,%10010010 7 | .byte %10100101,%01010100,%10010010 8 | .byte %10101001,%10111010,%10100101 9 | .byte %11111111,%11111111,%11111111 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_1_Highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Character_1_Highlighted.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_2: 2 | .byte 24, 8 3 | .byte %00110100,%00000000,%00011100 4 | .byte %01000100,%00000000,%00100010 5 | .byte %01000100,%01100010,%10000100 6 | .byte %01000110,%10010011,%00011000 7 | .byte %01000101,%10010010,%00100000 8 | .byte %00110101,%01111010,%00111110 9 | .byte %00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_2_Highlighted: 2 | .byte 24, 8 3 | .byte %11001011,%11111111,%11100011 4 | .byte %10111011,%11111111,%11011101 5 | .byte %10111011,%10011101,%01111011 6 | .byte %10111001,%01101100,%11100111 7 | .byte %10111010,%01101101,%11011111 8 | .byte %11001010,%10000101,%11000001 9 | .byte %11111111,%11111111,%11111111 10 | .byte %11111111,%11111111,%11111111 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2_Smiley.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_2_Smiley: 2 | .byte 24,8 3 | .byte %00110000,%00010100,%00000000 4 | .byte %01000000,%00000100,%00000000 5 | .byte %00100110,%10010100,%10010100 6 | .byte %00010101,%01010101,%11010100 7 | .byte %00010100,%01010101,%00001100 8 | .byte %01100100,%01010100,%11000100 9 | .byte %00000000,%00000000,%00011000 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2_Smiley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Character_2_Smiley.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2_Smiley_Highlighted: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_2_Smiley_Highlighted: 2 | .byte 24,8 3 | .byte %11001111,%11101011,%11111111 4 | .byte %10111111,%11111011,%11111111 5 | .byte %11011001,%01101011,%01101011 6 | .byte %11101010,%10101010,%00101011 7 | .byte %11101011,%10101010,%11110011 8 | .byte %10011011,%10101011,%00111011 9 | .byte %11111111,%11111111,%11100111 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_2_Smiley_Highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Character_2_Smiley_Highlighted.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_3.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_3: 2 | .byte 24, 8 3 | .byte %00110100,%00000000,%00011100 4 | .byte %01000100,%00000000,%00100010 5 | .byte %01000100,%01100010,%10000100 6 | .byte %01000110,%10010011,%00011000 7 | .byte %01000101,%10010010,%00000100 8 | .byte %00110101,%01111010,%00111110 9 | .byte %00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Character_3_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Character_3_Highlighted: 2 | .byte 24, 8 3 | .byte %11001011,%11111111,%11100011 4 | .byte %10111011,%11111111,%11011101 5 | .byte %10111011,%10011101,%01111011 6 | .byte %10111001,%01101100,%11100111 7 | .byte %10111010,%01101101,%11111011 8 | .byte %11001010,%10000101,%11000001 9 | .byte %11111111,%11111111,%11111111 10 | .byte %11111111,%11111111,%11111111 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Resume.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_OK_Button_Resume: 2 | .byte 48, 8 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00111000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00100100,%10001101,%00100101,%00010000,%00000000 7 | .byte %00000000,%00111001,%11011001,%00101010,%10111000,%00000000 8 | .byte %00000000,%00100101,%00000101,%00101000,%10100000,%00000000 9 | .byte %00000000,%00100100,%11011000,%11001000,%10011000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Resume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_OK_Button_Resume.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Resume_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_OK_Button_Resume_Highlighted: 2 | .byte 48, 8 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%01111111,%11111111,%11111111,%11111100,%00000000 5 | .byte %00000000,%01000111,%11111111,%11111111,%11111100,%00000000 6 | .byte %00000000,%01011011,%01110010,%11011010,%11101100,%00000000 7 | .byte %00000000,%01000110,%00100110,%11010101,%01000100,%00000000 8 | .byte %00000000,%01011010,%11111010,%11010111,%01011100,%00000000 9 | .byte %00000000,%01011011,%00100111,%00110111,%01100100,%00000000 10 | .byte %00000000,%01111111,%11111111,%11111111,%11111100,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Resume_Highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_OK_Button_Resume_Highlighted.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Start.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_OK_Button_Start: 2 | .byte 48, 8 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000011,%00100000,%00000000,%10000000,%00000000 6 | .byte %00000000,%00000100,%01110011,%00010101,%11000000,%00000000 7 | .byte %00000000,%00000010,%00100100,%10011000,%10000000,%00000000 8 | .byte %00000000,%00000001,%00100100,%10010000,%10000000,%00000000 9 | .byte %00000000,%00000110,%00100011,%01010000,%10000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_OK_Button_Start.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Start_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_OK_Button_Start_Highlighted: 2 | .byte 48, 8 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00001111,%11111111,%11111111,%11100000,%00000000 5 | .byte %00000000,%00001100,%11011111,%11111111,%01100000,%00000000 6 | .byte %00000000,%00001011,%10001100,%11101010,%00100000,%00000000 7 | .byte %00000000,%00001101,%11011011,%01100111,%01100000,%00000000 8 | .byte %00000000,%00001110,%11011011,%01101111,%01100000,%00000000 9 | .byte %00000000,%00001001,%11011100,%10101111,%01100000,%00000000 10 | .byte %00000000,%00001111,%11111111,%11111111,%11100000,%00000000 -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_OK_Button_Start_Highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_OK_Button_Start_Highlighted.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Player_Option.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Player_Option: 2 | .byte 24, 8 3 | .byte %11100100,%00000000,%00000001 4 | .byte %10010100,%00000000,%00000000 5 | .byte %10010100,%10010100,%10010100 6 | .byte %11100101,%01010101,%11011000 7 | .byte %10000101,%01001101,%00010000 8 | .byte %10000100,%11100100,%11010001 9 | .byte %00000000,%00000100,%00000000 10 | .byte %00000000,%00011000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Player_Option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Player_Option.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_1_City.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Stage_1_City: 2 | .byte 24, 8 3 | .byte %00000000,%00000000,%00000000 4 | .byte %00000111,%01001000,%00000000 5 | .byte %00001000,%00011100,%00000000 6 | .byte %00001000,%01001001,%00100000 7 | .byte %00001000,%01001001,%00100000 8 | .byte %00000111,%01001000,%11100000 9 | .byte %00000000,%00000000,%00100000 10 | .byte %00000000,%00000000,%11000000 11 | 12 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_1_City.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Stage_1_City.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_1_City_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Stage_1_City_Highlighted: 2 | .byte 24, 8 3 | .byte %11111111,%11111111,%11111111 4 | .byte %11111000,%10110111,%11111111 5 | .byte %11110111,%11100010,%11011111 6 | .byte %11110111,%10110110,%11011111 7 | .byte %11110111,%10110111,%00011111 8 | .byte %11111000,%10110111,%11011111 9 | .byte %11111111,%11111110,%00111111 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_1_City_Highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Stage_1_City_Highlighted.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_2_Jungle.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Stage_2_Jungle: 2 | .byte 24, 8 3 | .byte %00000000,%00000000,%00000000 4 | .byte %00001000,%00000000,%00100000 5 | .byte %00001010,%10110001,%10100100 6 | .byte %00001010,%10101010,%10101110 7 | .byte %00001010,%10101001,%10101000 8 | .byte %00110001,%10101000,%10100110 9 | .byte %00000000,%00000011,%00000000 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_2_Jungle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Stage_2_Jungle.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_2_Jungle_Highlighted.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Stage_2_Jungle_Highlighted: 2 | .byte 24, 8 3 | .byte %01111111,%11111111,%11111111 4 | .byte %01110111,%11111111,%11011111 5 | .byte %01110101,%01001110,%01011011 6 | .byte %01110101,%01010101,%01010001 7 | .byte %01110101,%01010110,%01010111 8 | .byte %01001110,%01010111,%01011001 9 | .byte %01111111,%11111100,%11111111 10 | .byte %00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_Option.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Stage_Option: 2 | .byte 24, 8 3 | .byte %00000110,%00000000,%00000001 4 | .byte %00001000,%10000000,%00000000 5 | .byte %00000101,%11010001,%00010000 6 | .byte %00000010,%10101010,%10111000 7 | .byte %00000010,%10101010,%10100000 8 | .byte %00001100,%10011101,%10011001 9 | .byte %00000000,%00000000,%10000000 10 | .byte %00000000,%00000011,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Stage_Option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Stage_Option.png -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Welcome_Message.asm: -------------------------------------------------------------------------------- 1 | Menu_Text_Welcome_Message: 2 | .byte 48, 8 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %10001000,%10000000,%00000000,%10000010,%00000000,%00000101 5 | .byte %10001010,%10010101,%01001001,%11010010,%01010101,%01100101 6 | .byte %10101111,%10101011,%11111100,%10101010,%11101010,%11010111 7 | .byte %01010100,%10101011,%00110000,%10101010,%10010110,%11010001 8 | .byte %01010011,%10010101,%00101100,%10010011,%01101001,%01010001 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | -------------------------------------------------------------------------------- /Lesson_4/img/Menu_Text_Welcome_Message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_4/img/Menu_Text_Welcome_Message.png -------------------------------------------------------------------------------- /Lesson_4/lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Kresna Susila 2 | 3 | This software is provided 'as-is', without any express or implied warranty. 4 | In no event will the authors be held liable for any damages arising from 5 | the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software in 13 | a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not 17 | be misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /Lesson_4/lib/libkcommon.asm: -------------------------------------------------------------------------------- 1 | ;****************************************************************************** 2 | ; libkcommon 3 | ;****************************************************************************** 4 | ; Some common functions I use all the time 5 | ;****************************************************************************** 6 | ; Nicer names for button masks 7 | Button_Up equ %00000001 8 | Button_Down equ %00000010 9 | Button_Left equ %00000100 10 | Button_Right equ %00001000 11 | Button_A equ %00010000 12 | Button_B equ %00100000 13 | Button_Mode equ %01000000 14 | Button_Sleep equ %10000000 15 | 16 | Get_Input: 17 | ;---------------------------------------------------------------------- 18 | ; Get input from P3, compare input to previous P3 input to get buttons 19 | ; pressed this cycle. 20 | ;---------------------------------------------------------------------- 21 | ld p3_last_input 22 | st c 23 | ld p3 24 | bn acc, 6, .quit 25 | bn acc, 7, .sleep 26 | st p3_last_input 27 | xor #%11111111 28 | and c 29 | xor #%11111111 30 | st p3_pressed 31 | ret 32 | .quit 33 | jmpf goodbye 34 | .sleep 35 | mov #0, t1cnt ; Disable audio 36 | set1 pcon, 0 ; Activate HALT mode (saves power) 37 | bn p3, 7, .sleep ; wait until Sleep Key is released 38 | mov #0,vccr ; turn off LCD 39 | .sleepmore 40 | set1 pcon,0 ; activate HALT mode (saves power) 41 | bp p7, 0, .quit ; Docked? 42 | bp p3, 7, .sleepmore ; no Sleep Key pressed yet 43 | mov #$80, vccr ; turn on LCD again 44 | .waitsleepup: 45 | set1 pcon,0 ; activate HALT modus (saves power) 46 | bn p3,7,.waitsleepup 47 | ret 48 | 49 | Check_Button_Pressed: 50 | ;---------------------------------------------------------------------- 51 | ; Check if a button is pressed, not held, this cycle 52 | ;---------------------------------------------------------------------- 53 | ; acc = button to check 54 | ;---------------------------------------------------------------------- 55 | st c 56 | ld p3_pressed 57 | xor #%11111111 58 | and c 59 | ret 60 | -------------------------------------------------------------------------------- /Lesson_4/lib/sfr.i: -------------------------------------------------------------------------------- 1 | 2 | * 3 | * Special Function Register addresses 4 | * 5 | 6 | ACC EQU $100 7 | PSW EQU $101 8 | B EQU $102 9 | C EQU $103 10 | TRL EQU $104 11 | TRH EQU $105 12 | SP EQU $106 13 | PCON EQU $107 14 | IE EQU $108 15 | IP EQU $109 16 | EXT EQU $10D 17 | OCR EQU $10E 18 | T0CON EQU $110 19 | T0PRR EQU $111 20 | T0L EQU $112 21 | T0LR EQU $113 22 | T0H EQU $114 23 | T0HR EQU $115 24 | T1CNT EQU $118 25 | T1LC EQU $11A 26 | T1L EQU $11B 27 | T1LR EQU $11B 28 | T1HC EQU $11C 29 | T1H EQU $11D 30 | T1HR EQU $11D 31 | MCR EQU $120 32 | STAD EQU $122 33 | CNR EQU $123 34 | TDR EQU $124 35 | XBNK EQU $125 36 | VCCR EQU $127 37 | SCON0 EQU $130 38 | SBUF0 EQU $131 39 | SBR EQU $132 40 | SCON1 EQU $134 41 | SBUF1 EQU $135 42 | P1 EQU $144 43 | P1DDR EQU $145 44 | P1FCR EQU $146 45 | P3 EQU $14C 46 | P3DDR EQU $14D 47 | P3INT EQU $14E 48 | P7 EQU $15C 49 | I01CR EQU $15D 50 | I23CR EQU $15E 51 | ISL EQU $15F 52 | VSEL EQU $163 53 | VRMAD1 EQU $164 54 | VRMAD2 EQU $165 55 | VTRBF EQU $166 56 | VLREG EQU $167 57 | BTCR EQU $17F 58 | XRAM EQU $180 59 | 60 | 61 | * 62 | * PSW bits 63 | * 64 | 65 | CY EQU 7 66 | AC EQU 6 67 | IRBK1 EQU 4 68 | IRBK0 EQU 3 69 | OV EQU 2 70 | RAMBK0 EQU 1 71 | P EQU 0 72 | 73 | -------------------------------------------------------------------------------- /Lesson_4/main.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ;Beginners' VMU Tutorial; 3 | ; Lesson 4 ; 4 | ;=======================; 5 | 6 | ;=======================; 7 | ;VMU Application Header ; 8 | ;=======================; 9 | .include "GameHeader.i" 10 | 11 | ;=======================; 12 | ; Include Libraries ; 13 | ;=======================; 14 | .include "./lib/libperspective.asm" 15 | .include "./lib/libkcommon.asm" 16 | .include "./lib/sfr.i" 17 | 18 | ;=======================; 19 | ; Include Images ; 20 | ;=======================; 21 | .include "./img/Hello_World_BackGround.asm" 22 | .include "./img/Example_Sprite.asm" 23 | .include "./img/Example_Sprite_Mask.asm" 24 | .include "./img/Example_Sprite_HeroChao_Mask.asm" 25 | .include "./img/ExampleBG_City.asm" 26 | .include "./img/Main_Menu_BG.asm" 27 | .include "./img/Menu_Text_Character_1.asm" 28 | .include "./img/Menu_Text_Character_1_Highlighted.asm" 29 | .include "./img/Menu_Text_Character_2.asm" 30 | .include "./img/Menu_Text_Character_2_Smiley.asm" 31 | .include "./img/Menu_Text_Character_2_Smiley_Highlighted.asm" 32 | .include "./img/Menu_Text_Character_3.asm" 33 | .include "./img/Menu_Text_Character_3_Highlighted.asm" 34 | ;.include "./img/Menu_Text_Stage_1.asm" 35 | .include "./img/Menu_Text_Stage_1_City.asm" 36 | ;.include "./img/Menu_Text_Stage_1_Highlighted.asm" 37 | .include "./img/Menu_Text_Stage_1_City_Highlighted.asm" 38 | ;.include "./img/Menu_Text_Stage_2_Jungle.asm" 39 | ;.include "./img/Menu_Text_Stage_2_Jungle_Highlighted.asm" 40 | ;.include "./img/Menu_Text_Stage_3.asm" 41 | ;.include "./img/Menu_Text_Stage_3_Highlighted.asm" 42 | .include "./img/Menu_Text_OK_Button_Start.asm" 43 | .include "./img/Menu_Text_OK_Button_Start_Highlighted.asm" 44 | .include "./img/Menu_Text_OK_Button_Resume.asm" 45 | .include "./img/Menu_Text_OK_Button_Resume_Highlighted.asm" 46 | .include "./img/Menu_Text_Welcome_Message.asm" 47 | .include "./img/Digit_0.asm" 48 | .include "./img/Digit_1.asm" 49 | .include "./img/Digit_2.asm" 50 | .include "./img/Digit_3.asm" 51 | .include "./img/Digit_4.asm" 52 | .include "./img/Digit_5.asm" 53 | .include "./img/Digit_6.asm" 54 | .include "./img/Digit_7.asm" 55 | .include "./img/Digit_8.asm" 56 | .include "./img/Digit_9.asm" 57 | 58 | ;=======================; 59 | ; Include Code Files ; 60 | ;=======================; 61 | .include "./Cursor_Gameplay.asm" 62 | .include "./Main_Menu.asm" 63 | 64 | ;=======================; 65 | ; Define Variables: ; 66 | ;=======================; 67 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 68 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 69 | character_flags = $17 ; 1 Byte 70 | stage_flags = $18 ; 1 Byte 71 | 72 | ;=======================; 73 | ; Initialize Variables: ; 74 | ;=======================; 75 | mov #0, character_flags 76 | mov #0, stage_flags 77 | 78 | ;=======================; 79 | ; Constants ; 80 | ;=======================; 81 | T_BTN_SLEEP equ 7 82 | T_BTN_MODE equ 6 83 | T_BTN_B1 equ 5 84 | T_BTN_A1 equ 4 85 | T_BTN_RIGHT1 equ 3 86 | T_BTN_LEFT1 equ 2 87 | T_BTN_DOWN1 equ 1 88 | T_BTN_UP1 equ 0 89 | 90 | ;=======================; 91 | ; Prepare Application ; 92 | ;=======================; 93 | .org $00 94 | jmpf start 95 | 96 | .org $03 97 | reti 98 | 99 | .org $0b 100 | reti 101 | 102 | .org $13 103 | reti 104 | 105 | .org $1b 106 | jmpf t1int 107 | 108 | .org $23 109 | reti 110 | 111 | .org $2b 112 | reti 113 | 114 | .org $33 115 | reti 116 | 117 | .org $3b 118 | reti 119 | 120 | .org $43 121 | reti 122 | 123 | .org $4b 124 | clr1 p3int,0 125 | clr1 p3int,1 126 | reti 127 | 128 | .org $130 129 | t1int: 130 | push ie 131 | clr1 ie,7 132 | not1 ext,0 133 | jmpf t1int 134 | pop ie 135 | reti 136 | 137 | .org $1f0 138 | 139 | goodbye: 140 | not1 ext,0 141 | jmpf goodbye 142 | 143 | ;=======================; 144 | ; Main Program ; 145 | ;=======================; 146 | start: 147 | clr1 ie,7 148 | mov #$a1,ocr 149 | mov #$09,mcr 150 | mov #$80,vccr 151 | clr1 p3int,0 152 | clr1 p1,7 153 | mov #$ff,p3 154 | set1 ie,7 155 | 156 | Main_Loop: 157 | callf Main_Menu 158 | callf Cursor_Gameplay 159 | jmpf Main_Loop 160 | 161 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 162 | -------------------------------------------------------------------------------- /Lesson_5/GameHeader.i: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------------------- 2 | ; ROM info 3 | ;------------------------------------------------------------------------------- 4 | .org $200 5 | 6 | .byte "VMU Dev Lesson 5 " ; 16 bytes 7 | .byte "VMU Beginners' Tutorial #5." ; 32 byte 8 | ; Thanks To Marcus, Sebastian, And Tyro For Header Format! 9 | 10 | .org $240 11 | 12 | .word 1 ; number of icons (max = 3) 13 | .word 14 ; animation speed 14 | 15 | ;------------------------------------------------------------------------------- 16 | ; Game Icon Palette Table 17 | ; 18 | ; Each entry is 16-bit, as such AAAARRRR GGGGBBBB 19 | ; where a value of 0xF for alpha means opaque 20 | ;------------------------------------------------------------------------------- 21 | .org $260 22 | 23 | .word $fffe, $f114, $ffff, $f8df, $fa0f, $f02f, $ffae, $f000 24 | .word $f60a, $ff8d, $f406, $f051, $f081, $fd7b, $fd00, $f900 25 | 26 | ;------------------------------------------------------------------------------- 27 | ; Game Icon Data 28 | ;------------------------------------------------------------------------------- 29 | 30 | ; This is where the game icons are placed. Each icon is 512 byte long, 31 | ; 32 * 32 pixel, each pixel being represented by 4 bit (one nybble) that 32 | ; serve as a pointer into the color palette table. 33 | 34 | .org $280 35 | ; 0 5 10 15 20 25 30 36 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 37 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 38 | .byte $00,$10,$00,$10,$00,$00,$00,$01,$11,$01,$00,$00,$00,$00,$00,$00 39 | .byte $00,$11,$01,$10,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$10,$00 40 | .byte $00,$10,$10,$10,$10,$01,$00,$01,$10,$01,$01,$10,$11,$01,$11,$00 41 | .byte $00,$10,$00,$10,$10,$01,$00,$01,$00,$01,$01,$00,$10,$00,$10,$00 42 | .byte $00,$10,$00,$10,$01,$11,$00,$01,$00,$01,$01,$01,$10,$00,$10,$00 43 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 44 | .byte $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 45 | .byte $00,$00,$00,$00,$01,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 46 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 47 | .byte $10,$00,$10,$10,$00,$10,$10,$00,$10,$00,$01,$10,$00,$00,$00,$00 48 | .byte $10,$00,$10,$11,$01,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 49 | .byte $10,$00,$10,$10,$10,$10,$10,$00,$10,$00,$10,$01,$00,$00,$00,$00 50 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$11,$11,$01,$10,$01,$10 51 | .byte $01,$01,$00,$10,$00,$10,$10,$00,$10,$00,$10,$01,$01,$01,$01,$01 52 | .byte $00,$10,$00,$10,$00,$10,$01,$11,$00,$00,$10,$01,$01,$10,$01,$10 53 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00 54 | .byte $00,$00,$00,$00,$00,$00,$00,$01,$11,$00,$00,$00,$01,$00,$01,$00 55 | .byte $00,$00,$00,$00,$00,$00,$01,$10,$00,$11,$00,$00,$00,$00,$00,$00 56 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 57 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 58 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 59 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 60 | .byte $00,$00,$00,$00,$00,$00,$10,$11,$11,$10,$10,$00,$00,$00,$00,$00 61 | .byte $00,$00,$00,$00,$00,$00,$10,$00,$00,$00,$10,$00,$00,$00,$00,$00 62 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$00,$00,$10,$00,$00,$00,$00,$00 63 | .byte $00,$00,$00,$00,$00,$00,$11,$11,$00,$01,$10,$00,$00,$00,$00,$00 64 | .byte $00,$00,$00,$00,$00,$00,$10,$10,$01,$00,$10,$00,$00,$00,$00,$00 65 | .byte $00,$00,$00,$00,$00,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00 66 | .byte $00,$00,$00,$00,$00,$00,$00,$11,$11,$10,$00,$00,$00,$00,$00,$00 67 | .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 68 | 69 | -------------------------------------------------------------------------------- /Lesson_5/README.MD: -------------------------------------------------------------------------------- 1 | # Lesson 5: Putting It All Together: Let's Make A Game! 2 | 3 | Now, let's try adding up everything we've learned so far, and upgrade our Program from "Dragging A Cursor Around" to something more akin to a Full Game. In the vein of the phenomenal [MegaRunner](https://www.ohsat.com/tutorial/megarunner/megarunner-1/) by Andrej Preradovic (A.K.A. [Ohsat](https://www.ohsat.com/).), let's try making it a Side-Scrolling, Infinite Runner type of Game! 4 | 5 | ## Collision Calculation Within A Range 6 | 7 | We can start off by editing our movable "Cursor" from the last lesson into our playable "Character" in this one. Rather than colliding with just the edges of the screen, we'll want to check collision with both the floor and our obstacles; the former will be calculated similarly, and the latter will be a new thing for us to learn. Rather than cycling between the .ASM Files on every press as last time, we'll swap our Face Buttons to Jump now, so that the player can avoid the Obstacle Object. We'll also "Animate" our Character Sprite later, with Different Graphics For Different Actions. To start out, we'll Comment Out our Menu, and Jump straight into our Gameplay while we Code it Up. 8 | 9 | Inside our Gameplay Loop, we'll refactor the bottom of the screen's collision detection to now be the "Floor" of our Infinite Runner. Our "Jump" Button can increase the Y-Position (or technically decrease it, since 0 is at the top), like pressing "Up" did before, but in a larger increment initially. Then, "Gravity" can pull the Sprite back down to the Floor, by subtracting an "Accelerated" Value from the Y-Position. 10 | 11 | player_sprite_y = $19 ; 1 Byte 12 | player_y_velocity = $1a ; 1 Byte 13 | ... 14 | Runner_Gameplay_Loop: 15 | ; Check Input 16 | callf Get_Input ; This Function Is In LibKCommon.ASM 17 | ld p3 18 | .Check_Up 19 | ; bp acc, T_BTN_UP1, .Check_Down ; Commenting the Up and Down Buttons out for now. 20 | .Check_Down 21 | ;ld p3 22 | ;bp acc, T_BTN_DOWN1, .Check_Left 23 | .Check_Left 24 | ld p3 25 | bp acc, T_BTN_LEFT1, .Check_Right 26 | ld test_sprite_x 27 | sub #2 28 | bp acc, 7, .Check_Right 29 | dec test_sprite_x 30 | .Check_Right 31 | ld p3 32 | bp acc, T_BTN_RIGHT1, .Check_Buttons 33 | ld test_sprite_x 34 | sub #40 35 | bn acc, 7, .Draw_Screen 36 | inc test_sprite_x 37 | .Check_Buttons 38 | ld p3 39 | bp acc, T_BTN_A1, .Skip_Jump 40 | ld test_sprite_y 41 | sub #24 42 | bnz .Skip_Jump 43 | mov #5, runner_jump_acceleration 44 | .Skip_Jump 45 | ld test_sprite_y 46 | sub runner_jump_acceleration 47 | st test_sprite_y 48 | dec runner_jump_acceleration 49 | ld runner_jump_acceleration 50 | .Check_Ground 51 | ld test_sprite_y 52 | sub #24 53 | bp acc, 7, .Skip_Grounded 54 | mov #24, test_sprite_y 55 | mov #0, runner_jump_acceleration 56 | .Skip_Grounded 57 | .Skip_Floor_Collision 58 | jmpf .Main_GamePlay_Loop 59 | 60 | Next, let's make an "Obstacle" object for our Player Character to collide with and jump over. As mentioned before, Collision Detection with Obstacles will be a little different. This is because with boundaries such as the Walls and Floor, we're only worried about One Direction. Here, though, we need to worry about All 4 Cardinal Directions. In other words, before we had something like "is X < 48?" For the Right Wall, whereas now we'll have "Is 21 < X < 23 &AND& Is 14 < Y 16?" instead, with the range being determined by the height or width of the object and what it's being collided with. In Assembly, that'll look like this: 61 | 62 | obstacle_sprite_x = $10 63 | ... 64 | .Check_Obstacle_Collision 65 | .Check_Up 66 | ld player_sprite_y 67 | sub obstacle_sprite_y 68 | sub obstacle_size_y 69 | bp acc, 7, .Check_Bottom 70 | .Check_Bottom 71 | ld player_sprite_y 72 | sub obstacle_sprite_y 73 | bp acc, 7, .Check_Left ; .Check_Sides 74 | ; Set The Collision Flag 75 | .Check_Left 76 | ld player_sprite_x 77 | sub obstacle_sprite_x 78 | sub obstacle_size_x 79 | bp acc, 7, .Check_Right 80 | .Check_Right 81 | ld player_sprite_x 82 | sub obstacle_sprite_x 83 | bn acc, 7, .Collision_Done 84 | ; Set The Collision Flag 85 | .Collision_Done 86 | 87 | While for collision before, we would simply move the Player Object back in bounds, now we will be setting a Flag and then deciding what to do when it's set. Since collision is a Binary "On" or "Off" Value right now, we could use All 8 Bits of a Variable for Different Flags, but for now we'll simply have a Value Assigned as "0" or "1" and compute from there. 88 | 89 | collision_flags = $1b ; 1 Byte 90 | ... 91 | mov #0, collision_flags 92 | ... 93 | ld collision_flags 94 | bn acc, 7, .Collision_Done 95 | mov #1, collision_flags ; Set The Collision Flag 96 | 97 | Then, with that Collision Flag Set, we can decide what to do with it, or continue on like nothing happened (because nothing _did_ happen!) if it's Not Set. It basically works the same as checking for button presses did earlier: 98 | 99 | ld collision_flags 100 | bnz .Collison_Flag_Not_Set 101 | ; Do whatever you'd like upon collision here! 102 | .Collision_Flag_Not_Set 103 | 104 | Then, we can have the obstacle move sideways across the screen for us to interact with: 105 | 106 | dec obstacle_sprite_x ; Single Speed 107 | ; dec obstacle_sprite_x ; Uncomment For Double Speed 108 | 109 | It's tough to jump over the obstacle if it's moving a 1 Pixel Per Second, so we can mess around with its speed value. For example, we can move it at single or double speed in the Code Block Above. 110 | 111 | There are several things we can do when Collision is Detected for this Auto Runner. For example, we could decrement a Health Bar or Lives Counter, or Display an Animation, or do all of the above. 112 | 113 | num_lives = $1c 114 | ... 115 | ld num_lives 116 | bz .Continue_Playing 117 | mov #Obstacle_Sprite_Mask, test_sprite_sprite_address+1 133 | jmpf .Draw_Screen 134 | .Collision_No 135 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 137 | .Draw_Screen 138 | P_Draw_Sprite test_sprite_x, test_sprite_y, test_sprite_address ; This Address Will Be Filled In By The Above Code! 139 | ... 140 | 141 | ## Animating Sprites 142 | 143 | Next, we can up this set of two images to a larger number, and think of them as the first two frames. Animating the Sprites will be a fun process. While we won't have animation files, we will be using a "State Machine" similarly to how the many excellent tutorials for Unity and other Engines often handle it. Then, we can `#mov` each Frame for the Distinct Animations based on which State we're in, and that requisite image will be drawn when we blit the screen and call LibPerspective. 144 | 145 | run_frame = $1d 146 | ... 147 | inc run_frame 148 | bp run_frame, 2, .Reset_Run_Frame 149 | jmpf .Continue_Running 150 | .Rest_Run_Frame 151 | mov #0, run_frame 152 | .Continue_Running 153 | ... 154 | .Run_Frame_0 155 | ld run_frame 156 | bnz .Run_Frame_1 157 | mov #Run_Frame_0, Player_Sprite_Address 159 | .Run_Frame_1 160 | ld run_frame 161 | sub #1 162 | bnz .Run_Frame_2 163 | mov #Run_Frame_1, Player_Sprite_Address 165 | .Run_Frame_2 ; And So On... 166 | ... 167 | P_Draw_Sprite_Mask Player_Sprite_Address, player_Sprite_x, player_sprite_y 168 | 169 | Then, we can add assign this animation to a new "State #" Variable as the "Running" state, and add another state on top of it, a "Jumping" one! 170 | 171 | player_state = $22 ; 1 Byte. 0 = Default Value (Running.). 172 | ... 173 | .Check_Buttons 174 | ld p3 175 | bp acc, T_BTN_A1, .Skip_Jump 176 | ld test_sprite_y 177 | sub #24 178 | bnz .Skip_Jump 179 | mov #5, runner_jump_acceleration 180 | mov #1, player_state 181 | ... 182 | .Check_Ground 183 | ld test_sprite_y 184 | sub #24 185 | bp acc, 7, .Skip_Grounded 186 | mov #24, test_sprite_y 187 | mov #0, runner_jump_acceleration 188 | mov #0, player_state 189 | 190 | With that State set, we can update those "Animation" Loops and Branches to Call it and decide which Animation will show when we Draw the Player Sprite: 191 | 192 | .Draw_Player_Running 193 | ld player_state 194 | bnz .Draw_Player_Jumping 195 | .Run_Frame_1 196 | .Run_Frame_2 197 | ... 198 | .Draw_Player_Jumping 199 | ld player_state 200 | sub #1 201 | bnz .Draw_Third_State ; (If we have one) 202 | .Jump_Frame_1 203 | .Jump_Frame_2 204 | ... 205 | 206 | Then, the Final P_Draw_Sprite will have the "Frame" of Animation. 207 | -------------------------------------------------------------------------------- /Lesson_5/bin/Lesson_5.vms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Candle-Electric/VMU_Development_Beginners-Tutorial/8cb29b5f621d89bb10c3d7826017b90c2f572e97/Lesson_5/bin/Lesson_5.vms -------------------------------------------------------------------------------- /Lesson_5/img/Digit_1.ASM: -------------------------------------------------------------------------------- 1 | Digit_1: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00001000 5 | .byte %00011000 6 | .byte %00001000 7 | .byte %00001000 8 | .byte %00001000 9 | .byte %00001000 10 | .byte %00111110 11 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_2.asm: -------------------------------------------------------------------------------- 1 | Digit_2: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00000100 7 | .byte %00011000 8 | .byte %00100000 9 | .byte %01000000 10 | .byte %01111100 11 | 12 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_3.ASM: -------------------------------------------------------------------------------- 1 | Digit_3: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00000100 7 | .byte %00011000 8 | .byte %00000100 9 | .byte %01000100 10 | .byte %00111000 11 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_4.ASM: -------------------------------------------------------------------------------- 1 | Digit_4: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %01000100 5 | .byte %01000100 6 | .byte %01111100 7 | .byte %00000100 8 | .byte %00000100 9 | .byte %00000100 10 | .byte %00000000 11 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_5.ASM: -------------------------------------------------------------------------------- 1 | Digit_5: 2 | .byte 8,8 3 | .byte %00000000 4 | .byte %00111100 5 | .byte %00100000 6 | .byte %00011000 7 | .byte %00000100 8 | .byte %01000100 9 | .byte %00111000 10 | .byte %00000000 11 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_6.ASM: -------------------------------------------------------------------------------- 1 | Digit_6: 2 | .byte 8,8 3 | .byte %00000000 4 | .byte %00011100 5 | .byte %00100000 6 | .byte %01011000 7 | .byte %01100100 8 | .byte %01000010 9 | .byte %00100100 10 | .byte %00011000 11 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_7.asm: -------------------------------------------------------------------------------- 1 | Digit_7: 2 | .byte 8, 8 3 | .byte %00000000 4 | .byte %01111100 5 | .byte %00000100 6 | .byte %00001000 7 | .byte %00010000 8 | .byte %00010000 9 | .byte %00100000 10 | .byte %00100000 -------------------------------------------------------------------------------- /Lesson_5/img/Digit_8.ASM: -------------------------------------------------------------------------------- 1 | Digit_8: 2 | .byte %00000000 3 | .byte %00011000 4 | .byte %00100100 5 | .byte %00011000 6 | .byte %00100100 7 | .byte %00100100 8 | .byte %00011000 9 | .byte %00000000 10 | -------------------------------------------------------------------------------- /Lesson_5/img/Digit_9.ASM: -------------------------------------------------------------------------------- 1 | Digit_9: 2 | .byte 8,8 3 | .byte %00000000 4 | .byte %00111000 5 | .byte %01000100 6 | .byte %00111100 7 | .byte %00000100 8 | .byte %00000100 9 | .byte %00011000 10 | .byte %00000000 11 | -------------------------------------------------------------------------------- /Lesson_5/img/ExampleBG_City.asm: -------------------------------------------------------------------------------- 1 | ExampleBG_City: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%01010000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%01010000 5 | .byte %00000000,%01110000,%00000000,%00000000,%00000000,%01010000 6 | .byte %00000000,%10001000,%00000000,%00000000,%00000000,%11111000 7 | .byte %00000001,%00000100,%00000000,%00000000,%00000000,%10001000 8 | .byte %00000001,%00000100,%00000000,%00000000,%00000000,%10101000 9 | .byte %00000001,%00000100,%00001111,%11100000,%00000000,%10001000 10 | .byte %00000000,%10001000,%00001000,%00100000,%00000000,%10101000 11 | .byte %00000000,%01110000,%00001010,%10100000,%00000000,%10001110 12 | .byte %10100000,%00000000,%00001000,%00100000,%10000000,%10101010 13 | .byte %10100000,%00000000,%00001010,%10100001,%11000000,%10001010 14 | .byte %10100000,%00000000,%00001000,%00100000,%10000011,%10101010 15 | .byte %11110000,%00000000,%00001010,%10100000,%10000010,%10001010 16 | .byte %00010000,%00000000,%00001000,%00100000,%10000010,%10100010 17 | .byte %11010000,%00000000,%00001010,%10100001,%01000010,%10000010 18 | .byte %00010011,%11111111,%11101000,%00100010,%00100010,%10101010 19 | .byte %11010010,%00000000,%00101010,%10100010,%00100010,%00000010 20 | .byte %00010010,%00000000,%00101000,%00100100,%10010010,%10101010 21 | .byte %11010011,%10110110,%11101010,%10100101,%11010010,%00000010 22 | .byte %00010011,%10110110,%11101000,%00100100,%10010010,%10101010 23 | .byte %11010010,%00000000,%00101010,%10100100,%00010010,%00000010 24 | .byte %00010010,%00111110,%00101000,%00100100,%00010010,%10101010 25 | .byte %10010010,%00101010,%00101001,%00100100,%10010010,%00100010 26 | .byte %10010010,%00101010,%00101001,%00100100,%10010010,%00100010 27 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 28 | .byte %00011111,%10000111,%11100001,%11111000,%01111110,%00011111 29 | .byte %01111111,%00001111,%11100001,%11111000,%01111111,%00001111 30 | .byte %11111110,%00001111,%11000001,%11111000,%00111111,%10000011 31 | .byte %11111100,%00011111,%11000011,%11111100,%00111111,%11000001 32 | .byte %11111000,%00111111,%10000011,%11111100,%00011111,%11100000 33 | .byte %11110000,%00111111,%10000011,%11111100,%00011111,%11110000 34 | .byte %11100000,%01111111,%00000011,%11111100,%00001111,%11111000 35 | -------------------------------------------------------------------------------- /Lesson_5/img/Example_Sprite_Jump.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite_Jump_Mask: 2 | -------------------------------------------------------------------------------- /Lesson_5/img/Example_Sprite_Mask.asm: -------------------------------------------------------------------------------- 1 | Example_Sprite_Mask: 2 | .byte 10,8 3 | .byte %11000001,%11111111 4 | .byte %10000000,%11111111 5 | .byte %00000000,%01111111 6 | .byte %00000000,%01111111 7 | .byte %00000000,%01111111 8 | .byte %00000000,%01111111 9 | .byte %10000000,%11111111 10 | .byte %11000001,%11111111 11 | .byte %00000000,%00000000 12 | .byte %00111110,%00000000 13 | .byte %01010101,%00000000 14 | .byte %01000001,%00000000 15 | .byte %01010101,%00000000 16 | .byte %01001001,%00000000 17 | .byte %00111110,%00000000 18 | .byte %00000000,%00000000 -------------------------------------------------------------------------------- /Lesson_5/img/Obstacle_Sprite_Mask.asm: -------------------------------------------------------------------------------- 1 | Obstacle_Sprite_Mask: 2 | .byte 13,7 3 | .byte %11101111,%01011111 4 | .byte %11000110,%00001111 5 | .byte %10000000,%00011111 6 | .byte %00000000,%00111111 7 | .byte %10000000,%00011111 8 | .byte %11000110,%00001111 9 | .byte %11101111,%01011111 10 | .byte %00000000,%00000000 11 | .byte %00010000,%10100000 12 | .byte %00110001,%01000000 13 | .byte %01111111,%10000000 14 | .byte %00110001,%01000000 15 | .byte %00010000,%10100000 16 | .byte %00000000,%00000000 17 | -------------------------------------------------------------------------------- /Lesson_5/img/Player_Running_1_Mask.asm: -------------------------------------------------------------------------------- 1 | Player_Running_1: 2 | .byte 14, 11 3 | .byte %11111111,%10011111 4 | .byte %11111111,%11101111 5 | .byte %11111000,%11101111 6 | .byte %11110000,%10011111 7 | .byte %11100000,%10001111 8 | .byte %11110000,%00000111 9 | .byte %11100011,%10001111 10 | .byte %10000111,%11111111 11 | .byte %11110111,%11111111 12 | .byte %11001111,%11111111 13 | .byte %11111111,%11111111 14 | .byte %00000000,%00000000 15 | .byte %00000000,%01100000 16 | .byte %00000000,%01100000 17 | .byte %00000111,%10000000 18 | .byte %00001001,%01110000 19 | .byte %00000010,%00000000 20 | .byte %00000111,%00000000 21 | .byte %00001000,%11001000 22 | .byte %01110000,%01110000 23 | .byte %01000000,%00100000 24 | .byte %00000000,%00000000 25 | -------------------------------------------------------------------------------- /Lesson_5/img/Player_Running_3_Mask.asm: -------------------------------------------------------------------------------- 1 | Player_Running_3_Mask: 2 | .byte 14, 11 3 | .byte %11111111,%10011111 4 | .byte %11111111,%11101111 5 | .byte %11111111,%11101111 6 | .byte %11111111,%10011111 7 | .byte %11111111,%01111111 8 | .byte %11111111,%11111111 9 | .byte %11111111,%11111111 10 | .byte %11111111,%11111111 11 | .byte %11111111,%11111111 12 | .byte %11111111,%11111111 13 | .byte %11111111,%11111111 14 | .byte %00000000,%00000000 15 | .byte %00000000,%01100000 16 | .byte %00000000,%01100000 17 | .byte %00000000,%10000000 18 | .byte %00000000,%11000000 19 | .byte %00000000,%00000000 20 | .byte %00000000,%00000000 21 | .byte %00000000,%00000000 22 | .byte %00000000,%00000000 23 | .byte %00000000,%00000000 24 | .byte %00000000,%00000000 25 | -------------------------------------------------------------------------------- /Lesson_5/img/Player_Running_Mask_2.asm: -------------------------------------------------------------------------------- 1 | Player_Running_Mask_2: 2 | .byte 15,13 3 | .byte %11100111 4 | .byte %11000011 5 | .byte %11000011 6 | .byte %11000011 7 | .byte %11000111 8 | .byte %11000011 9 | .byte %10000111 10 | .byte %11000111 11 | .byte %11101111 12 | .byte %11111111 13 | .byte %11111111 14 | .byte %11111111 15 | .byte %00000000 16 | .byte %00011000 17 | .byte %00011000 18 | .byte %00010000 19 | .byte %00011000 20 | .byte %00110000 21 | .byte %00010000 22 | .byte %00000000 23 | .byte %00000000 24 | .byte %00000000 25 | .byte %00000000 26 | .byte %00000000 27 | -------------------------------------------------------------------------------- /Lesson_5/img/Runner_BackGround_1.asm: -------------------------------------------------------------------------------- 1 | Runner_BackGround_1: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 7 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 8 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 13 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 14 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 15 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 16 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 17 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 18 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 19 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 26 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 27 | .byte %00011111,%10000111,%11100001,%11111000,%01111110,%00011111 28 | .byte %01111111,%00001111,%11100001,%11111000,%01111111,%00001111 29 | .byte %11111110,%00001111,%11000001,%11111000,%00111111,%10000011 30 | .byte %11111100,%00011111,%11000011,%11111100,%00111111,%11000001 31 | .byte %11111000,%00111111,%10000011,%11111100,%00011111,%11100000 32 | .byte %11110000,%00111111,%10000011,%11111100,%00011111,%11110000 33 | .byte %11100000,%01111111,%00000011,%11111100,%00001111,%11111000 34 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 35 | -------------------------------------------------------------------------------- /Lesson_5/img/Runner_BackGround_2.asm: -------------------------------------------------------------------------------- 1 | Runner_BackGround_2: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 7 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 8 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 13 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 14 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 15 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 16 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 17 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 18 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 19 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 26 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 27 | .byte %01111100,%00011111,%00000111,%11000001,%11110000,%01111100 28 | .byte %11110000,%00111110,%00000111,%11000001,%11111000,%00111111 29 | .byte %11100000,%11111100,%00001111,%11000001,%11111000,%00011111 30 | .byte %10000001,%11111000,%00001111,%11000000,%11111100,%00001111 31 | .byte %00000011,%11111000,%00011111,%10000000,%11111100,%00000111 32 | .byte %00000111,%11110000,%00011111,%10000000,%01111110,%00000011 33 | .byte %00001111,%11100000,%00111111,%10000000,%01111111,%00000001 34 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 35 | -------------------------------------------------------------------------------- /Lesson_5/img/Runner_BackGround_3.asm: -------------------------------------------------------------------------------- 1 | Runner_BackGround_3: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 7 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 8 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 13 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 14 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 15 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 16 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 17 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 18 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 19 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 26 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 27 | .byte %10000001,%11110000,%01111100,%00011111,%00000111,%10000011 28 | .byte %00000111,%11000000,%11111100,%00011111,%00000011,%11000000 29 | .byte %00001111,%10000001,%11111000,%00011111,%00000011,%11100000 30 | .byte %00011111,%00000011,%11111000,%00011111,%10000001,%11110000 31 | .byte %01111100,%00000011,%11110000,%00111111,%10000001,%11111000 32 | .byte %11111000,%00000111,%11110000,%00111111,%11000000,%11111100 33 | .byte %11110000,%00001111,%11100000,%00111111,%11000000,%01111110 34 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 35 | -------------------------------------------------------------------------------- /Lesson_5/img/Runner_BackGround_4.asm: -------------------------------------------------------------------------------- 1 | Runner_BackGround_4: 2 | .byte 48,32 3 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 4 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 5 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 6 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 7 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 8 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 9 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 10 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 11 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 12 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 13 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 14 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 15 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 16 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 17 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 18 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 19 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 20 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 21 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 22 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 23 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 24 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 25 | .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 26 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 27 | .byte %00011111,%10000111,%11100001,%11111000,%01111110,%00011111 28 | .byte %01111111,%00001111,%11100001,%11111000,%01111111,%00001111 29 | .byte %11111110,%00001111,%11000001,%11111000,%00111111,%10000011 30 | .byte %11111100,%00011111,%11000011,%11111100,%00111111,%11000001 31 | .byte %11111000,%00111111,%10000011,%11111100,%00011111,%11100000 32 | .byte %11110000,%00111111,%10000011,%11111100,%00011111,%11110000 33 | .byte %11100000,%01111111,%00000011,%11111100,%00001111,%11111000 34 | .byte %11111111,%11111111,%11111111,%11111111,%11111111,%11111111 35 | -------------------------------------------------------------------------------- /Lesson_5/lib/libkcommon.asm: -------------------------------------------------------------------------------- 1 | ;****************************************************************************** 2 | ; libkcommon 3 | ;****************************************************************************** 4 | ; Some common functions I use all the time 5 | ;****************************************************************************** 6 | ; Nicer names for button masks 7 | Button_Up equ %00000001 8 | Button_Down equ %00000010 9 | Button_Left equ %00000100 10 | Button_Right equ %00001000 11 | Button_A equ %00010000 12 | Button_B equ %00100000 13 | Button_Mode equ %01000000 14 | Button_Sleep equ %10000000 15 | 16 | Get_Input: 17 | ;---------------------------------------------------------------------- 18 | ; Get input from P3, compare input to previous P3 input to get buttons 19 | ; pressed this cycle. 20 | ;---------------------------------------------------------------------- 21 | ld p3_last_input 22 | st c 23 | ld p3 24 | bn acc, 6, .quit 25 | bn acc, 7, .sleep 26 | st p3_last_input 27 | xor #%11111111 28 | and c 29 | xor #%11111111 30 | st p3_pressed 31 | ret 32 | .quit 33 | jmpf goodbye 34 | .sleep 35 | mov #0, t1cnt ; Disable audio 36 | set1 pcon, 0 ; Activate HALT mode (saves power) 37 | bn p3, 7, .sleep ; wait until Sleep Key is released 38 | mov #0,vccr ; turn off LCD 39 | .sleepmore 40 | set1 pcon,0 ; activate HALT mode (saves power) 41 | bp p7, 0, .quit ; Docked? 42 | bp p3, 7, .sleepmore ; no Sleep Key pressed yet 43 | mov #$80, vccr ; turn on LCD again 44 | .waitsleepup: 45 | set1 pcon,0 ; activate HALT modus (saves power) 46 | bn p3,7,.waitsleepup 47 | ret 48 | 49 | Check_Button_Pressed: 50 | ;---------------------------------------------------------------------- 51 | ; Check if a button is pressed, not held, this cycle 52 | ;---------------------------------------------------------------------- 53 | ; acc = button to check 54 | ;---------------------------------------------------------------------- 55 | st c 56 | ld p3_pressed 57 | xor #%11111111 58 | and c 59 | ret 60 | -------------------------------------------------------------------------------- /Lesson_5/main.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ;Beginners' VMU Tutorial; 3 | ; Lesson 5 ; 4 | ;=======================; 5 | 6 | ;=======================; 7 | ; Prepare Application ; 8 | ;=======================; 9 | .org $00 10 | jmpf start 11 | 12 | .org $03 13 | reti 14 | 15 | .org $0b 16 | reti 17 | 18 | .org $13 19 | reti 20 | 21 | .org $1b 22 | jmpf t1int 23 | 24 | .org $23 25 | reti 26 | 27 | .org $2b 28 | reti 29 | 30 | .org $33 31 | reti 32 | 33 | .org $3b 34 | reti 35 | 36 | .org $43 37 | reti 38 | 39 | .org $4b 40 | clr1 p3int,0 41 | clr1 p3int,1 42 | reti 43 | 44 | .org $130 45 | t1int: 46 | push ie 47 | clr1 ie,7 48 | not1 ext,0 49 | jmpf t1int 50 | pop ie 51 | reti 52 | 53 | .org $1f0 54 | 55 | goodbye: 56 | not1 ext,0 57 | jmpf goodbye 58 | 59 | ;=======================; 60 | ;VMU Application Header ; 61 | ;=======================; 62 | .include "GameHeader.i" 63 | 64 | ;=======================; 65 | ; Include Libraries ; 66 | ;=======================; 67 | .include "./lib/libperspective.asm" 68 | .include "./lib/libkcommon.asm" 69 | .include "./lib/sfr.i" 70 | 71 | ;=======================; 72 | ; Include Images ; 73 | ;=======================; 74 | .include "./img/Hello_World_BackGround.asm" 75 | ; .include "./img/Example_Sprite.asm" 76 | .include "./img/Example_Sprite_Mask.asm" 77 | ; .include "./img/Example_Sprite_HeroChao_Mask.asm" 78 | .include "./img/ExampleBG_City.asm" 79 | .include "./img/Obstacle_Sprite_Mask.asm" 80 | ; .include "./img/Main_Menu_BG.asm" 81 | ; .include "./img/Menu_Text_Character_1.asm" 82 | ; .include "./img/Menu_Text_Character_1_Highlighted.asm" 83 | ; .include "./img/Menu_Text_Character_2_Smiley.asm" 84 | ; .include "./img/Menu_Text_Character_2_Smiley_Highlighted.asm" 85 | ; .include "./img/Menu_Text_Character_3.asm" 86 | ; .include "./img/Menu_Text_Character_3_Highlighted.asm" 87 | ; .include "./img/Menu_Text_Stage_1.asm" 88 | ; .include "./img/Menu_Text_Stage_1_Highlighted.asm" 89 | ; .include "./img/Menu_Text_Stage_2.asm" 90 | ; .include "./img/Menu_Text_Stage_2_Highlighted.asm" 91 | ; .include "./img/Menu_Text_Stage_3.asm" 92 | ; .include "./img/Menu_Text_Stage_3_Highlighted.asm" 93 | ; .include "./img/Menu_Text_OK_Button_Start.asm" 94 | ; .include "./img/Menu_Text_OK_Button_Start_Highlighted.asm" 95 | ; .include "./img/Menu_Text_OK_Button_Resume.asm" 96 | ; .include "./img/Menu_Text_OK_Button_Resume_Highlighted.asm" 97 | ; .include "./img/Menu_Text_Welcome_Message.asm" 98 | ; .include "./img/Menu_Text_Stage_1_City.asm" 99 | ; .include "./img/Menu_Text_Stage_1_City_Highlighted.asm" 100 | ; .include "./img/Menu_Text_Stage_2_Jungle.asm" 101 | ; .include "./img/Menu_Text_Stage_2_Jungle_Highlighted.asm" 102 | ; .include "./img/Digit_0.asm" 103 | .include "./img/Digit_1.asm" 104 | .include "./img/Digit_2.asm" 105 | .include "./img/Digit_3.asm" 106 | .include "./img/Digit_4.asm" 107 | .include "./img/Digit_5.asm" 108 | ; .include "./img/Digit_6.asm" 109 | .include "./img/Digit_7.asm" 110 | ; .include "./img/Digit_8.asm" 111 | ; .include "./img/Digit_9.asm" 112 | .include "./img/Runner_BackGround_1.asm" 113 | .include "./img/Runner_BackGround_2.asm" 114 | .include "./img/Runner_BackGround_3.asm" 115 | .include "./img/Runner_BackGround_4.asm" 116 | 117 | ;=======================; 118 | ; Include Code Files ; 119 | ;=======================; 120 | .include "./src/Runner_Gameplay.asm" 121 | ; .include "./Main_Menu.asm" 122 | 123 | ;=======================; 124 | ; Define Variables: ; 125 | ;=======================; 126 | p3_pressed = $4 ; 1 Byte (For LibKCommon) 127 | p3_last_input = $5 ; 1 Byte (For LibKCommon) 128 | ; character_flags = $17 ; 1 Byte 129 | ; stage_flags = $18 ; 1 Byte 130 | 131 | ;=======================; 132 | ; Initialize Variables: ; 133 | ;=======================; 134 | ; mov #0, character_flags 135 | ; mov #0, stage_flags 136 | 137 | ;=======================; 138 | ; Constants ; 139 | ;=======================; 140 | T_BTN_SLEEP equ 7 141 | T_BTN_MODE equ 6 142 | T_BTN_B1 equ 5 143 | T_BTN_A1 equ 4 144 | T_BTN_RIGHT1 equ 3 145 | T_BTN_LEFT1 equ 2 146 | T_BTN_DOWN1 equ 1 147 | T_BTN_UP1 equ 0 148 | 149 | ;=======================; 150 | ; Main Program ; 151 | ;=======================; 152 | start: 153 | clr1 ie,7 154 | mov #$a1,ocr 155 | mov #$09,mcr 156 | mov #$80,vccr 157 | clr1 p3int,0 158 | clr1 p1,7 159 | mov #$ff,p3 160 | set1 ie,7 161 | 162 | Main_Loop: 163 | ; callf Main_Menu 164 | callf Runner_Gameplay 165 | jmpf Main_Loop 166 | 167 | .cnop 0,$200 ; Pad To An Even Number Of Blocks 168 | -------------------------------------------------------------------------------- /Lesson_5/src/Runner_Gameplay.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ; Gameplay ; 3 | ;=======================; 4 | Runner_Gameplay: 5 | player_sprite_x = $6 ; 1 Byte ; Moving These Three To "Cursor_Gameplay." 6 | playerer_sprite_y = $7 ; 1 Byte 7 | player_sprite_sprite_address = $8 ; 2 Bytes 8 | ones_digit = $1a 9 | tens_digit = $1b 10 | hundreds_digit = $1c 11 | thousands_digit = $1d 12 | score = $1e 13 | digit_sprite_address = $1f 14 | runner_jump_acceleration = $21 15 | jump_accel_positive = $22 16 | obstacle_sprite_address = $23 17 | obstacle_sprite_x = $25 18 | obstacle_sprite_y = $26 19 | frame_counter = $27 20 | collision_flags = $28 21 | dropping_obstacle_active = $29 22 | obstacle_timer = $30 23 | dropping_obstacle_x = $31 24 | dropping_obstacle_y = $32 25 | player_animation_state = $33 26 | dropping_obstacle_sprite_address = $34 27 | 28 | ; Populate Character And Stage Flags 29 | ; ld cursor_flags 30 | ; ld stage_flags 31 | ; Set Sprite Addresses 32 | mov #20, runner_sprite_x 33 | mov #12, runner_sprite_y 34 | mov #32, obstacle_sprite_x 35 | mov #12, obstacle_sprite_y 36 | mov #0, runner_jump_acceleration 37 | mov #0, jump_accel_positive 38 | mov #0, frame_counter 39 | mov #0, dropping_obstacle_x 40 | mov #0, dropping_obstacle_y 41 | .Draw_Example_Character 42 | ; ld character_flags 43 | ; bnz .Draw_Example_Character_2 44 | mov #Example_Sprite_Mask, test_sprite_sprite_address+1 46 | ; jmpf Runner_Gameplay_Loop 47 | mov #obstacle_sprite_mask, obstacle_sprite_address+1 49 | mov #dropping_obstacle_sprite_mask, dropping_obstacle_sprite_address+1 51 | 52 | Runner_Gameplay_Loop: 53 | ; Check Input 54 | callf Get_Input ; This Function Is In LibKCommon.ASM 55 | ld p3 56 | .Check_Up 57 | ; bp acc, T_BTN_UP1, .Check_Down 58 | ; ld test_sprite_y 59 | ; sub #1 60 | ; bp acc, 7, .Check_Down 61 | ; dec test_sprite_y 62 | .Check_Down 63 | ;callf Get_Input 64 | ;ld p3 65 | ;bp acc, T_BTN_DOWN1, .Check_Left 66 | ;ld test_sprite_y 67 | ;sub #24 68 | ; bn acc, 7, .Check_Left 69 | ; inc test_sprite_y 70 | .Check_Left 71 | ; callf Get_Input 72 | ld p3 73 | bp acc, T_BTN_LEFT1, .Check_Right 74 | ld test_sprite_x 75 | sub #2 76 | bp acc, 7, .Check_Right 77 | dec runner_sprite_x 78 | .Check_Right 79 | ; callf Get_Input 80 | ld p3 81 | bp acc, T_BTN_RIGHT1, .Check_Buttons 82 | ld runner_sprite_x 83 | sub #40 84 | bp acc, 7, .Build_Error_1; bn.Draw_Screen 85 | jmpf .Draw_Screen 86 | .Build_Error_1 87 | inc runner_sprite_x 88 | .Check_Buttons 89 | ; callf Get_Input 90 | ld p3 91 | bp acc, T_BTN_A1, .Skip_Jump 92 | ; bn acc, T_BTN_B1, .Return_To_Menu 93 | ld runner_sprite_y 94 | sub #24 95 | bnz .Skip_Jump 96 | mov #5, runner_jump_acceleration 97 | ; jmpf .Draw_Screen 98 | .Skip_Jump ; .Return_To_Menu 99 | ld runner_sprite_y 100 | sub runner_jump_acceleration 101 | st runner_sprite_y 102 | ; ld runner_jump_acceleration 103 | dec runner_jump_acceleration 104 | ld runner_jump_acceleration 105 | 106 | ; bp acc, 7, .Check_Ground 107 | ; sub #1 108 | ; st runner_jump_acceleration 109 | .Check_Ground 110 | ld runner_sprite_y 111 | sub #24 112 | bp acc, 7, .Skip_Grounded 113 | mov #24, runner_sprite_y 114 | mov #0, runner_jump_acceleration 115 | .Skip_Grounded 116 | ; ld test_sprite_y 117 | mov #22, obstacle_sprite_y ; st obstacle_sprite_y 118 | ; mov #20, obstacle_sprite_x 119 | ; jmpf .Skip_Arrow_Reset 120 | inc frame_counter 121 | ; mov #22, obstacle_sprite_y 122 | dec obstacle_sprite_x; 123 | dec obstacle_sprite_x 124 | bp obstacle_sprite_x, 7, .Do_Arrow_Reset 125 | jmpf .Skip_Arrow_Reset 126 | .Do_Arrow_Reset 127 | mov #48, obstacle_sprite_x 128 | jmpf .Skip_Arrow_Reset 129 | bn obstacle_sprite_x, 7, .Skip_Arrow_Reset 130 | mov #47, obstacle_sprite_x 131 | ld frame_counter 132 | st c 133 | mov #0, acc 134 | mov #7, b 135 | div 136 | ld c 137 | add #20 138 | st obstacle_sprite_y 139 | .Skip_Arrow_Reset 140 | .Check_Obstacle_Collision 141 | mov #0, collision_flags 142 | .Check_Up_Collision 143 | ld runner_sprite_y 144 | sub obstacle_sprite_y 145 | add #7 ; obstacle_size_y 146 | bp acc, 7, .Check_Left_Collision 147 | .Check_Bottom_Collision 148 | ld runner_sprite_y 149 | add #8 150 | sub obstacle_sprite_y 151 | bp acc, 7, .Check_Left_Collision ; .Check_Sides 152 | set1 collision_flags, 0 ; Set The Collision Flag 153 | .Check_Left_Collision 154 | ld runner_sprite_x 155 | sub obstacle_sprite_x 156 | add #5 ; obstacle_size_x 157 | bp acc, 7, .Collision_Done 158 | .Check_Right_Collision 159 | ld obstacle_sprite_x 160 | add #8 161 | sub runner_sprite_x 162 | bp acc, 7, .Collision_Done 163 | set1 collision_flags, 1 ; Set The Collision Flag 164 | .Collision_Done 165 | ld collision_flags 166 | sub #3 167 | bnz .Collision_No 168 | .Collision_Yes 169 | mov #Obstacle_Sprite_Mask, runner_sprite_address+1 171 | jmpf .Draw_Screen 172 | .Collision_No 173 | mov #Example_Sprite_Mask, runner_sprite_address+1 175 | .Draw_Screen 176 | bn dropping_obstacle_active, 0, .Drop_Bomb 177 | mov #0, dropping_obstacle_y 178 | ; bn frame_counter, 4, .Draw_Example_Stage_1 179 | callf random 180 | mov #0, frame_counter 181 | jmpf .Draw_BG_Frame_1 ; Example_Stage_1 182 | .Drop_Bomb 183 | ; bn frame_counter, 4, .Draw_Example_Stage_1 184 | mov #1, dropping_obstacle_active 185 | .Draw_BG_Frame_1 186 | bp frame_counter, 1, .Draw_BG_Frame_3 ; ld stage_flags 187 | bp frame_counter, 0, .Draw_BG_Frame_2 188 | ; bnz .Draw_Example_Stage_2 189 | P_Draw_Background_Constant Runner_BackGround_1 190 | jmpf .Draw_Character 191 | .Draw_BG_Frame_2 192 | bp frame_counter, 1, .Draw_BG_Frame_3 ; ld stage_flags 193 | bn frame_counter, 0, .Draw_BG_Frame_3 ; Might Comment This One 194 | P_Draw_Background_Constant Runner_BackGround_2 195 | ; sub #1 196 | ; bnz .Draw_Example_Stage_3 197 | ; P_Draw_Background_Constant ExampleBG_Jungle 198 | jmpf .Draw_Character 199 | .Draw_BG_Frame_3 200 | bn frame_counter, 1, .Draw_BG_Frame_4 ; ld stage_flags 201 | bp frame_counter, 0, .Draw_BG_Frame_4 202 | P_Draw_Background_Constant Runner_BackGround_3 203 | jmpf .Draw_Character ; sub #2 204 | ; bnz .Draw_Character 205 | ; P_Draw_Background_Constant Hello_World_BackGround 206 | .Draw_BG_Frame_4 207 | bn frame_counter, 1, .Draw_Character ; ld stage_flags 208 | bn frame_counter, 0, .Draw_Character 209 | P_Draw_Background_Constant Runner_BackGround_4 210 | .Draw_Character 211 | P_Draw_Sprite_Mask runner_sprite_address, runner_sprite_x, runner_sprite_y 212 | .Draw_Obstacle 213 | P_Draw_Sprite_Mask obstacle_sprite_address, obstacle_sprite_x, obstacle_sprite_y 214 | P_Draw_Sprite_Mask obstacle_sprite_address, dropping_obstacle_x, dropping_obstacle_y 215 | P_Blit_Screen 216 | jmpf Runner_Gameplay_Loop 217 | 218 | random: 219 | ld test_sprite_x 220 | XOR frame_counter 221 | st dropping_obstacle_x ; obstacle_sprite_x 222 | ret 223 | 224 | Draw_Score: 225 | ;LD Score, Then Div, Then Call Draw_Digit On Each Time? Saves On RAM. 226 | ; ld ones_digit ; mov the X-Position + Store As B Before The Draw? 227 | ld score 228 | mov #10, b 229 | div 230 | ld c 231 | st c 232 | mov #16, b 233 | callf Draw_Digit 234 | ld score 235 | mov #10, b 236 | div 237 | div 238 | mov #24, b 239 | callf Draw_Digit 240 | ld score 241 | mov #10, b 242 | div 243 | div 244 | div 245 | mov #32, b 246 | callf Draw_Digit 247 | ret 248 | 249 | Draw_Digit: 250 | ; b = the X-Position, c = the Number 251 | mov #16, b 252 | mov #0, c 253 | ; P_Draw_Sprite digit_sprite_address, b, c 254 | ; mov #8, b 255 | .Digit_0 256 | ld c 257 | bnz .Digit_1 258 | mov #Digit_0, digit_sprite_address+1 260 | jmpf .Digit_Decided 261 | .Digit_1 262 | ld c 263 | sub #1 264 | bnz .Digit_2 265 | mov #Digit_1, digit_sprite_address+1 267 | jmpf .Digit_Decided 268 | .Digit_2 269 | ld c 270 | sub #2 271 | bnz .Digit_3 272 | mov #Digit_2, digit_sprite_address+1 274 | jmpf .Digit_Decided 275 | .Digit_3 276 | ld c 277 | sub #3 278 | bnz .Digit_4 279 | mov #Digit_3, digit_sprite_address+1 281 | jmpf .Digit_Decided 282 | .Digit_4 283 | ld c 284 | sub #4 285 | bnz .Digit_5 286 | mov #Digit_4, digit_sprite_address+1 288 | jmpf .Digit_Decided 289 | Digit_5 290 | ld c 291 | sub #5 292 | bnz .Digit_6 293 | mov #Digit_5, digit_sprite_address+1 295 | jmpf .Digit_Decided 296 | .Digit_6 297 | ld c 298 | sub #6 299 | bnz .Digit_7 300 | mov #Digit_6, digit_sprite_address+1 302 | jmpf .Digit_Decided 303 | .Digit_7 304 | ld c 305 | sub #7 306 | bnz .Digit_8 307 | mov #Digit_7, digit_sprite_address+1 309 | jmpf .Digit_Decided 310 | .Digit_8 311 | ld c 312 | sub #8 313 | bnz .Digit_9 314 | mov #Digit_8, digit_sprite_address+1 316 | jmpf .Digit_Decided 317 | .Digit_9 318 | ld c 319 | sub #9 320 | bnz .Digit_Decided 321 | mov #Digit_9, digit_sprite_address+1 323 | .Digit_Decided 324 | mov #0, c ; Every Digit will be at the top of the screen. ; To-Do: Store, Read, & Call B. 325 | P_Draw_Sprite digit_sprite_address, b, c 326 | ; ret 327 | ; 328 | ; %macro Draw_Score 329 | ; mov #16, b 330 | ; ld ones_digit 331 | ; st c 332 | ; callf Draw_Digit 333 | ; mov #24, b 334 | ; ld tens_digit 335 | ; st c 336 | ; callf Draw_Digit 337 | ; mov #32, b 338 | ; ld hundreds_digit 339 | ; st c 340 | ; callf Draw_Digit 341 | ; mov #40, b 342 | ; ld thousands_digit 343 | ; st c 344 | ; callf Draw_Digit 345 | ; %end 346 | -------------------------------------------------------------------------------- /Lesson_5/src/Runner_Menu.asm: -------------------------------------------------------------------------------- 1 | ;=======================; 2 | ; Menu ; 3 | ;=======================; 4 | Runner_Menu: 5 | cursor_1_val = $6 6 | cursor_2_val = $7 7 | cursor_y_pos = $8 8 | option_1_sprite_address = $9 9 | option_2_sprite_address = $a 10 | Confirm_Button_Sprite_Address = $c 11 | Menu_Loop: 12 | callf Get_Input 13 | .Check_Up 14 | ld p3 15 | mov #Button_Up, acc ; bp acc, 7, ... 16 | callf Check_Button_Pressed 17 | bn acc, 0, .Check_Down 18 | dec cursor_y_pos 19 | ; jmpf .Input_DPad_Done 20 | .Check_Down 21 | ld p3 22 | mov #Button_Down, acc 23 | callf Check_Button_Pressed 24 | bn acc, 1, .Check_Left 25 | inc cursor_y_pos 26 | .Check_Left 27 | ld p3 28 | mov #Button_Left, acc 29 | callf Check_Button_Pressed 30 | bn acc, 2, .Check_Right 31 | .Check_Right 32 | ld p3 33 | mov #Button_Right, acc 34 | callf Check_Button_Pressed 35 | bn acc, 3, .Draw_Screen 36 | .Check_Buttons 37 | .Check_B ; 38 | ld p3 39 | mov #Button_B1, acc 40 | callf Check_Button_Pressed 41 | bn acc, 6, .Check_A 42 | ld cursor_y_pos 43 | sub #2 44 | bnz .Check_A 45 | ret 46 | .Check_A 47 | mov #Button_A1, acc 48 | callf Check_Button_Pressed 49 | ld cursor_y_pos 50 | sub #2 51 | bnz .Draw_Screen 52 | ret 53 | jmpf .Draw_Screen 54 | ; sub #3 55 | ; bnz .Draw_Screen ; bp/jmpf Options + Draw Screen 56 | ; ret 57 | .Draw_Screen 58 | P_Draw_BackGround_Constant Menu_BG 59 | ; .Option_2_1 60 | ; mov #8, b ; Option #2'll Always Be At The Same Height On The Screen. 61 | ; ld option_2 62 | ; bnz ; .Option_2_2 ; Could Also Make A Variable If we Have The R.A.M. (Should.). 63 | ; mov #8, c 64 | P_Draw_Sprite option1_sprite_address, b, c ; Move These To A Separate Line/The End Of Their Respective Functions, Since The X-Coordinates Will Change? 65 | ; .Option_2_2 66 | ; mov #8, b 67 | ; mov #16, c 68 | ; P_Draw_Sprite "" "" 69 | P_Draw_Sprite option2_sprite_address, b, c 70 | P_Draw_Sprite cursor_sprite_address, b, c 71 | P_Draw_Sprite Confirm_Button_Sprite_Address, b, c ; Mov The "Highlighted" Or "Normal" Button To The Address. 72 | ret 73 | 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VMU Development Beginners' Tutorial 2 | A Guide For VMU Development For Beginners . 3 | --------------------------------------------------------------------------------