├── .gitattributes ├── N64 ├── BadInstructionTest │ ├── BadInstructionTest.N64 │ ├── BadInstructionTest.asm │ ├── N64_Header.asm │ └── make.cmd ├── Color16 │ ├── Color16.N64 │ ├── Color16.asm │ ├── Color16_Test.N64 │ ├── Color16_Test.asm │ ├── N64_Header.asm │ └── make.cmd ├── Color32 │ ├── Color32_Test.N64 │ ├── Color32_Test.asm │ ├── N64_Header.asm │ └── make.cmd ├── Exception │ ├── Exception.N64 │ ├── Exception.asm │ ├── ExceptionTest.N64 │ ├── Main.asm │ ├── N64_Header.asm │ ├── cfg │ │ ├── default.cfg │ │ └── n64.cfg │ ├── error.log │ ├── make.cmd │ └── nvram │ │ └── n64 │ │ └── Lesson2.nv ├── Exception2 │ ├── Exception.N64 │ ├── Exception.asm │ ├── Main.asm │ ├── N64_Header.asm │ └── make.cmd ├── ExceptionTest │ ├── ExceptionTest.N64 │ ├── ExceptionTest.asm │ ├── N64_Header.asm │ └── make.cmd ├── GDB │ ├── GDB_Test.N64 │ ├── GDB_Test.asm │ ├── N64_Header.asm │ └── make.cmd ├── IPL_FONT │ ├── IPL_FONT.N64 │ ├── IPL_FONT.asm │ ├── IPL_FONT.png │ ├── N64_Header.asm │ └── make.cmd ├── InterruptTest │ ├── InterruptTest.N64 │ ├── InterruptTest.asm │ ├── N64_Header.asm │ └── make.cmd ├── LIB │ ├── COLORS16.INC │ ├── COLORS32.INC │ ├── N64.INC │ ├── N64_BOOTCODE.BIN │ ├── N64_DRIVE.INC │ ├── N64_DRIVE.S │ ├── N64_EVER.INC │ ├── N64_EVER.S │ ├── N64_EXCEPTION.INC │ ├── N64_EXCEPTION.S │ ├── N64_GDB.INC │ ├── N64_GDB.S │ ├── N64_GFX.INC │ ├── N64_INTERRUPT.INC │ ├── N64_INTERRUPT.S │ ├── N64_INTERRUPT_HANDLER.S │ ├── N64_INTERRUPT_TEMPLATE.S │ ├── N64_IPL_FONT.INC │ ├── N64_IPL_FONT.S │ ├── N64_RSP.INC │ ├── N64_SYS.INC │ ├── N64_SYS.S │ ├── N64_SYSCALL_MARS.S │ └── README.md ├── Lesson1 │ └── bass-win.zip ├── Lesson2 │ ├── Lesson2.N64 │ ├── Lesson2.asm │ ├── N64_Header.asm │ └── make.cmd └── Template │ ├── N64_Header.asm │ ├── Template.N64 │ ├── make.cmd │ └── template.asm ├── README.md └── gobass.cmd /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /N64/BadInstructionTest/BadInstructionTest.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/BadInstructionTest/BadInstructionTest.N64 -------------------------------------------------------------------------------- /N64/BadInstructionTest/BadInstructionTest.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/N64_GFX.INC" 9 | include "../LIB/COLORS32.INC" 10 | include "./N64_HEADER.ASM" // Include 64 Byte Header & Vector Table 11 | insert "../LIB/N64_BOOTCODE.BIN" // Include 4032 Byte Boot Code 12 | force_pc($80001000) 13 | Start: 14 | align(8) 15 | variable vi_buffer(t7) 16 | li vi_buffer, $A0100000 17 | N64_INIT() 18 | ScreenNTSC(320, 240, BPP32, $A0100000) // Screen NTSC: 320x240, 32BPP, DRAM Origin $A0100000 19 | nop 20 | nop 21 | variable backColor(s0) 22 | li backColor, BLUE_VIOLET 23 | variable source(t0) 24 | variable destination(t1) 25 | variable length(t2) 26 | variable count(t3) 27 | 28 | la source, GeneralHandler 29 | la destination, 0x80000180 30 | li length, 128 31 | li count, r0 32 | loop_mem_cpy: 33 | lw s2, 0x0(source) 34 | lw s3, 0x4(source) 35 | lw s4, 0x8(source) 36 | lw s5, 0xC(source) 37 | sw s2, 0x0(destination) 38 | sw s3, 0x4(destination) 39 | sw s4, 0x8(destination) 40 | sw s5, 0xC(destination) 41 | bne length,count, loop_mem_cpy 42 | addi count, count, 16 43 | 44 | 45 | nop 46 | nop 47 | dw 0x40806800 48 | nop 49 | nop 50 | 51 | Loop: 52 | // Insert Looping Code Here 53 | li s6, vi_buffer+0x4B000 54 | loop_color: 55 | sw backColor, 0x0(source) 56 | sw backColor, 0x4(source) 57 | sw backColor, 0x8(source) 58 | sw backColor, 0xC(source) 59 | bne source, s6, loop_color 60 | addi source, source, 16 61 | j Loop 62 | nop // Delay Slot 63 | 64 | GeneralHandler: 65 | li backColor, DARK_ORANGE 66 | eret -------------------------------------------------------------------------------- /N64/BadInstructionTest/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Template " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/BadInstructionTest/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=BadInstructionTest.N64 3 | REM Space seperated list of source files 4 | set source_files=BadInstructionTest.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Color16/Color16.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Color16/Color16.N64 -------------------------------------------------------------------------------- /N64/Color16/Color16.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/COLORS16.INC" 9 | include "../LIB/N64_GFX.INC" 10 | 11 | include "N64_HEADER.ASM" 12 | insert "../LIB/N64_BOOTCODE.BIN" 13 | 14 | Start: 15 | N64_INIT() 16 | ScreenNTSC(320, 240, BPP16, $A0100000) 17 | DPC(RDPBuffer, RDPBufferEnd) 18 | WaitScanline($200) 19 | nop // Marker NOP's 20 | Loop: 21 | j Loop 22 | nop // Delay Slot 23 | macro square16(col, row, color) { 24 | Set_Fill_Color ({color} << 16) | {color} // Set Fill Color: PACKED COLOR 32B R8G8B8A8 Pixel 25 | Fill_Rectangle (({row} * 20) + (({col} + 1) * 20)) << 2, ({row} * 20) << 2, (({row} * 20) + ({col} * 20)) << 2, ({row} * 20) << 2 26 | } 27 | 28 | align(8) // Align 64-Bit 29 | RDPBuffer: 30 | arch n64.rdp 31 | 32 | Set_Scissor 0<<2,0<<2, 0,0, 320<<2,240<<2 33 | Set_Other_Modes CYCLE_TYPE_FILL // | Z_MODE_OPAQUE 34 | Set_Color_Image IMAGE_DATA_FORMAT_RGBA,SIZE_OF_PIXEL_16B,320-1, $00100000 35 | 36 | // Bottom Right X, Bottom Right Y, Top Left X, Top Left Y 37 | 38 | Set_Fill_Color (BLACK << 16) | BLACK // Set Fill Color: PACKED COLOR 32B R8G8B8A8 Pixel 39 | Fill_Rectangle 319<<2,239<<2, 0<<2,0<<2 // Fill Rectangle: XL 319.0,YL 239.0, XH 0.0,YH 0.0 40 | No_Op 41 | No_Op 42 | square16(0, 0, STEEL_BLUE) 43 | Set_Fill_Color (STEEL_BLUE << 16) | STEEL_BLUE 44 | Fill_Rectangle 20<<2,20<<2, 0<<2,0<<2 45 | No_Op 46 | No_Op 47 | 48 | square16(0, 1, PALE_TURQUOISE) 49 | Set_Fill_Color (PALE_TURQUOISE << 16) | PALE_TURQUOISE 50 | Fill_Rectangle 40<<2,20<<2,0<<2,20<<2 51 | No_Op 52 | No_Op 53 | 54 | //Set_Fill_Color (AQUA << 16) | AQUA 55 | //Fill_Rectangle 319<<2,18<<2, 301<<2,0<<2 //Fill_Rectangle 20<<2,20<<2,5<<2,5<<2 56 | //No_Op 57 | 58 | Sync_Full // Ensure Entire Scene Is Fully Drawn 59 | align(8) 60 | RDPBufferEnd: 61 | dw 0x0 62 | dw 0x0 63 | dw 0x0 64 | dw 0x0 65 | Set_Fill_Color (LIGHT_CYAN <<16) | LIGHT_CYAN 66 | Fill_Rectangle 80<<2,20<<2,100<<2,1<<2 67 | 68 | 69 | Set_Fill_Color (AQUAMARINE <<16) | AQUAMARINE 70 | Fill_Rectangle 260<<2,100<<2,241<<2,81<<2 71 | Set_Fill_Color (TURQUOISE <<16) | TURQUOISE 72 | Fill_Rectangle 280<<2,100<<2,261<<2,81<<2 73 | Set_Fill_Color (MEDIUM_TURQUOISE <<16) | MEDIUM_TURQUOISE 74 | Fill_Rectangle 300<<2,100<<2,281<<2,81<<2 75 | //Set_Fill_Color (DARK_TURQUOISE <<16) | DARK_TURQUOISE 76 | //Fill_Rectangle 320<<2,100<<2,301<<2,81<<2 77 | //Set_Fill_Color (CADET_BLUE <<16) | CADET_BLUE 78 | //Fill_Rectangle 340<<2,100<<2,321<<2,81<<2 79 | 80 | Set_Fill_Color (CYAN <<16) | CYAN 81 | Fill_Rectangle 20<<2,120<<2,1<<2,101<<2 82 | Set_Fill_Color (LIGHT_STEEL_BLUE <<16) | LIGHT_STEEL_BLUE 83 | Fill_Rectangle 40<<2,120<<2,21<<2,101<<2 84 | Set_Fill_Color (POWDER_BLUE <<16) | POWDER_BLUE 85 | Fill_Rectangle 60<<2,120<<2,41<<2,101<<2 86 | Set_Fill_Color (LIGHT_BLUE <<16) | LIGHT_BLUE 87 | Fill_Rectangle 80<<2,120<<2,61<<2,101<<2 88 | Set_Fill_Color (SKY_BLUE <<16) | SKY_BLUE 89 | Fill_Rectangle 100<<2,120<<2,81<<2,101<<2 90 | Set_Fill_Color (LIGHT_SKY_BLUE <<16) | LIGHT_SKY_BLUE 91 | Fill_Rectangle 120<<2,120<<2,101<<2,101<<2 92 | Set_Fill_Color (DEEP_SKY_BLUE <<16) | DEEP_SKY_BLUE 93 | Fill_Rectangle 140<<2,120<<2,121<<2,101<<2 94 | Set_Fill_Color (DODGER_BLUE <<16) | DODGER_BLUE 95 | Fill_Rectangle 160<<2,120<<2,141<<2,101<<2 96 | Set_Fill_Color (CORN_FLOWER_BLUE <<16) | CORN_FLOWER_BLUE 97 | Fill_Rectangle 180<<2,120<<2,161<<2,101<<2 98 | Set_Fill_Color (MEDIUM_SLATE_BLUE <<16) | MEDIUM_SLATE_BLUE 99 | Fill_Rectangle 200<<2,120<<2,181<<2,101<<2 100 | Set_Fill_Color (ROYAL_BLUE <<16) | ROYAL_BLUE 101 | Fill_Rectangle 220<<2,120<<2,201<<2,101<<2 102 | Set_Fill_Color (MEDIUM_BLUE <<16) | MEDIUM_BLUE 103 | Fill_Rectangle 240<<2,120<<2,221<<2,101<<2 104 | Set_Fill_Color (BLUE <<16) | BLUE 105 | Fill_Rectangle 260<<2,120<<2,241<<2,101<<2 106 | Set_Fill_Color (DARK_BLUE <<16) | DARK_BLUE 107 | Fill_Rectangle 280<<2,120<<2,261<<2,101<<2 108 | Set_Fill_Color (NAVY <<16) | NAVY 109 | Fill_Rectangle 300<<2,120<<2,281<<2,101<<2 110 | //Set_Fill_Color (MIDNIGHT_BLUE <<16) | MIDNIGHT_BLUE 111 | //Fill_Rectangle 320<<2,120<<2,301<<2,101<<2 112 | //Set_Fill_Color (BLACK <<16) | BLACK 113 | //Fill_Rectangle 340<<2,120<<2,321<<2,101<<2 114 | 115 | 116 | 117 | Set_Fill_Color (INDIAN_RED <<16) | INDIAN_RED 118 | Fill_Rectangle 20<<2,20<<2, 1<<2,1<<2 119 | 120 | Set_Fill_Color (LIGHT_CORAL <<16) | LIGHT_CORAL 121 | Fill_Rectangle 80<<2,40<<2, 21<<2,1<<2 122 | 123 | Set_Fill_Color (SALMON <<16) | SALMON 124 | Fill_Rectangle 60<<2,20<<2, 41<<2,1<<2 125 | 126 | Set_Fill_Color (DARK_SALMON <<16) | DARK_SALMON 127 | Fill_Rectangle 80<<2,20<<2, 61<<2,1<<2 128 | Set_Fill_Color (CRIMSON <<16) | CRIMSON 129 | Fill_Rectangle 100<<2,20<<2, 81<<2,1<<2 130 | 131 | Set_Fill_Color (RED <<16) | RED 132 | Fill_Rectangle 120<<2,20<<2, 101<<2,1<<2 133 | Set_Fill_Color (FIRE_BRICK <<16) | FIRE_BRICK 134 | Fill_Rectangle 140<<2,20<<2, 121<<2,1<<2 135 | Set_Fill_Color (DARK_RED <<16) | DARK_RED 136 | Fill_Rectangle 160<<2,20<<2, 141<<2,1<<2 137 | Set_Fill_Color (BLACK <<16) | BLACK 138 | Fill_Rectangle 180<<2,20<<2, 161<<2,1<<2 139 | 140 | Set_Fill_Color (PINK <<16) | PINK 141 | Fill_Rectangle 200<<2,20<<2, 181<<2,1<<2 142 | Set_Fill_Color (LIGHT_PINK <<16) | LIGHT_PINK 143 | Fill_Rectangle 220<<2,20<<2, 201<<2,1<<2 144 | Set_Fill_Color (HOT_PINK <<16) | HOT_PINK 145 | Fill_Rectangle 240<<2,20<<2, 221<<2,1<<2 146 | Set_Fill_Color (DEEP_PINK <<16) | DEEP_PINK 147 | Fill_Rectangle 260<<2,20<<2, 241<<2,1<<2 148 | Set_Fill_Color (MEDIUM_VIOLET_RED <<16) | MEDIUM_VIOLET_RED 149 | Fill_Rectangle 280<<2,20<<2, 261<<2,1<<2 150 | Set_Fill_Color (PALE_VIOLET_RED <<16) | PALE_VIOLET_RED 151 | Fill_Rectangle 300<<2,20<<2, 281<<2,1<<2 152 | //Set_Fill_Color (BLACK <<16) | BLACK 153 | //Fill_Rectangle 320<<2,20<<2, 301<<2,1<<2 154 | 155 | // Bottom Right X, Bottom Right Y, Top Left X, Top Left Y 156 | Set_Fill_Color (LIGHT_SALMON <<16) | LIGHT_SALMON 157 | Fill_Rectangle 20<<2,40<<2, 1<<2,21<<2 158 | Set_Fill_Color (CORAL <<16) | CORAL 159 | Fill_Rectangle 40<<2,40<<2, 21<<2,21<<2 160 | Set_Fill_Color (TOMATO <<16) | TOMATO 161 | Fill_Rectangle 60<<2,40<<2, 41<<2,21<<2 162 | Set_Fill_Color (ORANGE_RED <<16) | ORANGE_RED 163 | Fill_Rectangle 80<<2,40<<2, 61<<2,21<<2 164 | Set_Fill_Color (DARK_ORANGE <<16) | DARK_ORANGE 165 | Fill_Rectangle 100<<2,40<<2, 81<<2,21<<2 166 | Set_Fill_Color (ORANGE <<16) | ORANGE 167 | Fill_Rectangle 120<<2,40<<2, 101<<2,21<<2 168 | Set_Fill_Color (BLACK <<16) | BLACK 169 | Fill_Rectangle 140<<2,40<<2, 121<<2,21<<2 170 | 171 | Set_Fill_Color (GOLD <<16) | GOLD 172 | Fill_Rectangle 160<<2,40<<2, 141<<2, 21<<2 173 | Set_Fill_Color (YELLOW <<16) | YELLOW 174 | Fill_Rectangle 180<<2,40<<2, 161<<2,21<<2 175 | Set_Fill_Color (LIGHT_YELLOW <<16) | LIGHT_YELLOW 176 | Fill_Rectangle 200<<2,40<<2, 181<<2,21<<2 177 | Set_Fill_Color (LEMON_CHIFFON <<16) | LEMON_CHIFFON 178 | Fill_Rectangle 220<<2,40<<2, 201<<2,21<<2 179 | Set_Fill_Color (LIGHT_GOLDENROD_YELLOW <<16) | LIGHT_GOLDENROD_YELLOW 180 | Fill_Rectangle 240<<2,40<<2, 221<<2,21<<2 181 | Set_Fill_Color (PAPAYA_WHIP <<16) | PAPAYA_WHIP 182 | Fill_Rectangle 260<<2,40<<2, 241<<2,21<<2 183 | Set_Fill_Color (MOCCASIN <<16) | MOCCASIN 184 | Fill_Rectangle 280<<2,40<<2, 261<<2,21<<2 185 | Set_Fill_Color (PEACH_PUFF <<16) | PEACH_PUFF 186 | Fill_Rectangle 300<<2,40<<2, 281<<2,21<<2 187 | //Set_Fill_Color (PALE_GOLDENROD <<16) | PALE_GOLDENROD 188 | //Fill_Rectangle 320<<2,40<<2, 301<<2,21<<2 189 | //Set_Fill_Color (KHAKI <<16) | KHAKI 190 | //Fill_Rectangle 340<<2,40<<2, 321<<2,21<<2 191 | 192 | Set_Fill_Color (DARK_KHAKI <<16) | DARK_KHAKI 193 | Fill_Rectangle 20<<2,60<<2,1<<2,41<<2 194 | Set_Fill_Color (BLACK <<16) | BLACK 195 | Fill_Rectangle 40<<2,60<<2,21<<2,41<<2 196 | 197 | Set_Fill_Color (LAVENDER <<16) | LAVENDER 198 | Fill_Rectangle 60<<2,60<<2,41<<2,41<<2 199 | Set_Fill_Color (THISTLE <<16) | THISTLE 200 | Fill_Rectangle 80<<2,60<<2,61<<2,41<<2 201 | Set_Fill_Color (PLUM <<16) | PLUM 202 | Fill_Rectangle 100<<2,60<<2,81<<2,41<<2 203 | Set_Fill_Color (VIOLET <<16) | VIOLET 204 | Fill_Rectangle 120<<2,60<<2,101<<2,41<<2 205 | Set_Fill_Color (ORCHID <<16) | ORCHID 206 | Fill_Rectangle 140<<2,60<<2,121<<2,41<<2 207 | Set_Fill_Color (FUCHSIA <<16) | FUCHSIA 208 | Fill_Rectangle 160<<2,60<<2,141<<2,41<<2 209 | Set_Fill_Color (MAGENTA <<16) | MAGENTA 210 | Fill_Rectangle 180<<2,60<<2,161<<2,41<<2 211 | Set_Fill_Color (MEDIUM_ORCHID <<16) | MEDIUM_ORCHID 212 | Fill_Rectangle 200<<2,60<<2,181<<2,41<<2 213 | Set_Fill_Color (BLUE_VIOLET <<16) | BLUE_VIOLET 214 | Fill_Rectangle 220<<2,60<<2,201<<2,41<<2 215 | Set_Fill_Color (DARK_ORCHID <<16) | DARK_ORCHID 216 | Fill_Rectangle 240<<2,60<<2,221<<2,41<<2 217 | Set_Fill_Color (DARK_MAGENTA <<16) | DARK_MAGENTA 218 | Fill_Rectangle 260<<2,60<<2,241<<2,41<<2 219 | Set_Fill_Color (PURPLE <<16) | PURPLE 220 | Fill_Rectangle 280<<2,60<<2,261<<2,41<<2 221 | Set_Fill_Color (INDIGO <<16) | INDIGO 222 | Fill_Rectangle 300<<2,60<<2,281<<2,41<<2 223 | //Set_Fill_Color (SLATE_BLUE <<16) | SLATE_BLUE 224 | //Fill_Rectangle 320<<2,60<<2,301<<2,41<<2 225 | //Set_Fill_Color (DARK_SLATE_BLUE <<16) | DARK_SLATE_BLUE 226 | //Fill_Rectangle 340<<2,60<<2,321<<2,41<<2 227 | 228 | Set_Fill_Color (BLACK <<16) | BLACK 229 | Fill_Rectangle 20<<2,80<<2,1<<2,61<<2 230 | Set_Fill_Color (GREEN_YELLOW <<16) | GREEN_YELLOW 231 | Fill_Rectangle 40<<2,80<<2,21<<2,61<<2 232 | Set_Fill_Color (CHARTREUSE <<16) | CHARTREUSE 233 | Fill_Rectangle 60<<2,80<<2,41<<2,61<<2 234 | Set_Fill_Color (LAWN_GREEN <<16) | LAWN_GREEN 235 | Fill_Rectangle 80<<2,80<<2,61<<2,61<<2 236 | Set_Fill_Color (LIME <<16) | LIME 237 | Fill_Rectangle 100<<2,80<<2,81<<2,61<<2 238 | Set_Fill_Color (LIME_GREEN <<16) | LIME_GREEN 239 | Fill_Rectangle 120<<2,80<<2,101<<2,61<<2 240 | Set_Fill_Color (PALE_GREEN <<16) | PALE_GREEN 241 | Fill_Rectangle 140<<2,80<<2,121<<2,61<<2 242 | Set_Fill_Color (LIGHT_GREEN <<16) | LIGHT_GREEN 243 | Fill_Rectangle 160<<2,80<<2,141<<2,61<<2 244 | Set_Fill_Color (MEDIUM_SPRING_GREEN <<16) | MEDIUM_SPRING_GREEN 245 | Fill_Rectangle 180<<2,80<<2,161<<2,61<<2 246 | Set_Fill_Color (SPRING_GREEN <<16) | SPRING_GREEN 247 | Fill_Rectangle 200<<2,80<<2,181<<2,61<<2 248 | Set_Fill_Color (MEDIUM_SEA_GREEN <<16) | MEDIUM_SEA_GREEN 249 | Fill_Rectangle 220<<2,80<<2,201<<2,61<<2 250 | Set_Fill_Color (SEA_GREEN <<16) | SEA_GREEN 251 | Fill_Rectangle 240<<2,80<<2,221<<2,61<<2 252 | Set_Fill_Color (FOREST_GREEN <<16) | FOREST_GREEN 253 | Fill_Rectangle 260<<2,80<<2,241<<2,61<<2 254 | Set_Fill_Color (GREEN <<16) | GREEN 255 | Fill_Rectangle 280<<2,80<<2,261<<2,61<<2 256 | Set_Fill_Color (DARK_GREEN <<16) | DARK_GREEN 257 | Fill_Rectangle 300<<2,80<<2,281<<2,61<<2 258 | //Set_Fill_Color (YELLOW_GREEN <<16) | YELLOW_GREEN 259 | //Fill_Rectangle 320<<2,80<<2,301<<2,61<<2 260 | //Set_Fill_Color (OLIVE_DRAB <<16) | OLIVE_DRAB 261 | //Fill_Rectangle 340<<2,80<<2,321<<2,61<<2 262 | 263 | Set_Fill_Color (OLIVE <<16) | OLIVE 264 | Fill_Rectangle 20<<2,100<<2,1<<2,81<<2 265 | Set_Fill_Color (DARK_OLIVE_GREEN <<16) | DARK_OLIVE_GREEN 266 | Fill_Rectangle 40<<2,100<<2,21<<2,81<<2 267 | Set_Fill_Color (MEDIUM_AQUAMARINE <<16) | MEDIUM_AQUAMARINE 268 | Fill_Rectangle 60<<2,100<<2,41<<2,81<<2 269 | Set_Fill_Color (DARK_SEA_GREEN <<16) | DARK_SEA_GREEN 270 | Fill_Rectangle 80<<2,100<<2,61<<2,81<<2 271 | Set_Fill_Color (LIGHT_SEA_GREEN <<16) | LIGHT_SEA_GREEN 272 | Fill_Rectangle 100<<2,100<<2,81<<2,81<<2 273 | Set_Fill_Color (DARK_CYAN <<16) | DARK_CYAN 274 | Fill_Rectangle 120<<2,100<<2,101<<2,81<<2 275 | Set_Fill_Color (TEAL <<16) | TEAL 276 | Fill_Rectangle 140<<2,100<<2,121<<2,81<<2 277 | Set_Fill_Color (BLACK <<16) | BLACK 278 | Fill_Rectangle 160<<2,100<<2,141<<2,81<<2 279 | 280 | 281 | 282 | Set_Fill_Color (CORNSILK <<16) | CORNSILK 283 | Fill_Rectangle 20<<2,140<<2,1<<2,121<<2 284 | Set_Fill_Color (BLANCHED_ALMOND <<16) | BLANCHED_ALMOND 285 | Fill_Rectangle 40<<2,140<<2,21<<2,121<<2 286 | Set_Fill_Color (BISQUE <<16) | BISQUE 287 | Fill_Rectangle 60<<2,140<<2,41<<2,121<<2 288 | Set_Fill_Color (NAVAJO_WHITE <<16) | NAVAJO_WHITE 289 | Fill_Rectangle 80<<2,140<<2,61<<2,121<<2 290 | Set_Fill_Color (WHEAT <<16) | WHEAT 291 | Fill_Rectangle 100<<2,140<<2,81<<2,121<<2 292 | Set_Fill_Color (BURLY_WOOD <<16) | BURLY_WOOD 293 | Fill_Rectangle 120<<2,140<<2,101<<2,121<<2 294 | Set_Fill_Color (TAN <<16) | TAN 295 | Fill_Rectangle 140<<2,140<<2,121<<2,121<<2 296 | Set_Fill_Color (ROSY_BROWN <<16) | ROSY_BROWN 297 | Fill_Rectangle 160<<2,140<<2,141<<2,121<<2 298 | Set_Fill_Color (SANDY_BROWN <<16) | SANDY_BROWN 299 | Fill_Rectangle 180<<2,140<<2,161<<2,121<<2 300 | Set_Fill_Color (GOLDENROD <<16) | GOLDENROD 301 | Fill_Rectangle 200<<2,140<<2,181<<2,121<<2 302 | Set_Fill_Color (DARK_GOLDENROD <<16) | DARK_GOLDENROD 303 | Fill_Rectangle 220<<2,140<<2,201<<2,121<<2 304 | Set_Fill_Color (PERU <<16) | PERU 305 | Fill_Rectangle 240<<2,140<<2,221<<2,121<<2 306 | Set_Fill_Color (CHOCOLATE <<16) | CHOCOLATE 307 | Fill_Rectangle 260<<2,140<<2,241<<2,121<<2 308 | Set_Fill_Color (SADDLE_BROWN <<16) | SADDLE_BROWN 309 | Fill_Rectangle 280<<2,140<<2,261<<2,121<<2 310 | Set_Fill_Color (SIENNA <<16) | SIENNA 311 | Fill_Rectangle 300<<2,140<<2,281<<2,121<<2 312 | //Set_Fill_Color (BROWN <<16) | BROWN 313 | //Fill_Rectangle 320<<2,140<<2,301<<2,121<<2 314 | //Set_Fill_Color (MAROON <<16) | MAROON 315 | //Fill_Rectangle 340<<2,140<<2,321<<2,121<<2 316 | 317 | Set_Fill_Color (BLACK <<16) | BLACK 318 | Fill_Rectangle 20<<2,160<<2,1<<2,141<<2 319 | Set_Fill_Color (WHITE <<16) | WHITE 320 | Fill_Rectangle 40<<2,160<<2,21<<2,141<<2 321 | Set_Fill_Color (SNOW <<16) | SNOW 322 | Fill_Rectangle 60<<2,160<<2,41<<2,141<<2 323 | Set_Fill_Color (HONEYDEW <<16) | HONEYDEW 324 | Fill_Rectangle 80<<2,160<<2,61<<2,141<<2 325 | Set_Fill_Color (MINT_CREAM <<16) | MINT_CREAM 326 | Fill_Rectangle 100<<2,160<<2,81<<2,141<<2 327 | Set_Fill_Color (AZURE <<16) | AZURE 328 | Fill_Rectangle 120<<2,160<<2,101<<2,141<<2 329 | Set_Fill_Color (ALICE_BLUE <<16) | ALICE_BLUE 330 | Fill_Rectangle 140<<2,160<<2,121<<2,141<<2 331 | Set_Fill_Color (GHOST_WHITE <<16) | GHOST_WHITE 332 | Fill_Rectangle 160<<2,160<<2,141<<2,141<<2 333 | Set_Fill_Color (WHITE_SMOKE <<16) | WHITE_SMOKE 334 | Fill_Rectangle 180<<2,160<<2,161<<2,141<<2 335 | Set_Fill_Color (SEA_SHELL <<16) | SEA_SHELL 336 | Fill_Rectangle 200<<2,160<<2,181<<2,141<<2 337 | Set_Fill_Color (BEIGE <<16) | BEIGE 338 | Fill_Rectangle 220<<2,160<<2,201<<2,141<<2 339 | Set_Fill_Color (OLD_LACE <<16) | OLD_LACE 340 | Fill_Rectangle 240<<2,160<<2,221<<2,141<<2 341 | Set_Fill_Color (FLORAL_WHITE <<16) | FLORAL_WHITE 342 | Fill_Rectangle 260<<2,160<<2,241<<2,141<<2 343 | Set_Fill_Color (IVORY <<16) | IVORY 344 | Fill_Rectangle 280<<2,160<<2,261<<2,141<<2 345 | Set_Fill_Color (ANTIQUE_WHITE <<16) | ANTIQUE_WHITE 346 | Fill_Rectangle 300<<2,160<<2,281<<2,141<<2 347 | //Set_Fill_Color (LINEN <<16) | LINEN 348 | //Fill_Rectangle 320<<2,160<<2,301<<2,141<<2 349 | //Set_Fill_Color (LAVENDER_BLUSH <<16) | LAVENDER_BLUSH 350 | //Fill_Rectangle 340<<2,160<<2,321<<2,141<<2 351 | 352 | Set_Fill_Color (MISTY_ROSE <<16) | MISTY_ROSE 353 | Fill_Rectangle 20<<2,180<<2,1<<2,161<<2 354 | Set_Fill_Color (BLACK <<16) | BLACK 355 | Fill_Rectangle 40<<2,180<<2,21<<2,161<<2 356 | Set_Fill_Color (GAINSBORO <<16) | GAINSBORO 357 | Fill_Rectangle 60<<2,180<<2,41<<2,161<<2 358 | Set_Fill_Color (LIGHT_GREY <<16) | LIGHT_GREY 359 | Fill_Rectangle 80<<2,180<<2,61<<2,161<<2 360 | Set_Fill_Color (SILVER <<16) | SILVER 361 | Fill_Rectangle 100<<2,180<<2,81<<2,161<<2 362 | Set_Fill_Color (DARK_GREY <<16) | DARK_GREY 363 | Fill_Rectangle 120<<2,180<<2,101<<2,161<<2 364 | Set_Fill_Color (GREY <<16) | GREY 365 | Fill_Rectangle 140<<2,180<<2,121<<2,161<<2 366 | Set_Fill_Color (DIM_GREY <<16) | DIM_GREY 367 | Fill_Rectangle 160<<2,180<<2,141<<2,161<<2 368 | Set_Fill_Color (LIGHT_SLATE_GREY <<16) | LIGHT_SLATE_GREY 369 | Fill_Rectangle 180<<2,180<<2,161<<2,161<<2 370 | Set_Fill_Color (SLATE_GREY <<16) | SLATE_GREY 371 | Fill_Rectangle 200<<2,180<<2,181<<2,161<<2 372 | // Set_Fill_Color (BLACK <<16) | BLACK 373 | // Fill_Rectangle 220<<2,180<<2,201<<2,161<<2 374 | // Set_Fill_Color (BLACK <<16) | BLACK 375 | // Fill_Rectangle 240<<2,180<<2,221<<2,161<<2 376 | // Set_Fill_Color (BLACK <<16) | BLACK 377 | // Fill_Rectangle 260<<2,180<<2,241<<2,161<<2 378 | // Set_Fill_Color (BLACK <<16) | BLACK 379 | // Fill_Rectangle 280<<2,180<<2,261<<2,161<<2 380 | // Set_Fill_Color (BLACK <<16) | BLACK 381 | // Fill_Rectangle 300<<2,180<<2,281<<2,161<<2 382 | // Set_Fill_Color (BLACK <<16) | BLACK 383 | // Fill_Rectangle 320<<2,180<<2,301<<2,161<<2 384 | // Set_Fill_Color (BLACK <<16) | BLACK 385 | // Fill_Rectangle 340<<2,180<<2,321<<2,161<<2 386 | 387 | Sync_Full // Ensure Entire Scene Is Fully Drawn 388 | -------------------------------------------------------------------------------- /N64/Color16/Color16_Test.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Color16/Color16_Test.N64 -------------------------------------------------------------------------------- /N64/Color16/Color16_Test.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/COLORS16.INC" 9 | include "../LIB/N64_GFX.INC" 10 | 11 | include "N64_HEADER.ASM" 12 | insert "../LIB/N64_BOOTCODE.BIN" 13 | 14 | Start: 15 | N64_INIT() 16 | ScreenNTSC(320, 240, BPP16, $A0100000) 17 | DPC(RDPBuffer, RDPBufferEnd) 18 | WaitScanline($200) 19 | nop // Marker NOP's 20 | Loop: 21 | j Loop 22 | nop // Delay Slot 23 | 24 | 25 | macro square16(col, row, color) { 26 | Set_Fill_Color ({color} << 16) | {color} 27 | // Bottom Right X, Bottom Right Y, Top Left X, Top Left Y 28 | Fill_Rectangle (({row} * 16) + (({col} + 1) * 16)) << 2, ({row} * 16) + 16 << 2, (({row} * 16) + ({col} * 16)) << 2, ({row} * 16) << 2 29 | } 30 | 31 | 32 | align(8) // Align 64-Bit 33 | RDPBuffer: 34 | arch n64.rdp 35 | Set_Scissor 0<<2,0<<2, 0,0, 320<<2,240<<2 36 | Set_Other_Modes CYCLE_TYPE_FILL // | Z_MODE_OPAQUE 37 | Set_Color_Image IMAGE_DATA_FORMAT_RGBA,SIZE_OF_PIXEL_16B,320-1, $00100000 38 | 39 | Set_Fill_Color (BLACK << 16) | BLACK // Set Fill Color: PACKED COLOR 32B R8G8B8A8 Pixel 40 | Fill_Rectangle 319<<2,239<<2, 0<<2,0<<2 // Fill Rectangle: XL 319.0,YL 239.0, XH 0.0,YH 0.0 41 | 42 | square16(0, 0, STEEL_BLUE) 43 | square16(1, 0, PALE_TURQUOISE) 44 | square16(0, 1, MEDIUM_TURQUOISE) 45 | square16(1, 1, CADET_BLUE) 46 | RDPBufferEnd: -------------------------------------------------------------------------------- /N64/Color16/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Color 16 bit " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Color16/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Color16_Test.N64 3 | REM Space seperated list of source files 4 | set source_files=Color16_Test.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Color32/Color32_Test.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Color32/Color32_Test.N64 -------------------------------------------------------------------------------- /N64/Color32/Color32_Test.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/COLORS32.INC" 9 | include "../LIB/N64_GFX.INC" 10 | 11 | include "N64_HEADER.ASM" 12 | insert "../LIB/N64_BOOTCODE.BIN" 13 | 14 | Start: 15 | N64_INIT() 16 | ScreenNTSC(320, 240, BPP32, $A0100000) 17 | nop // Marker NOP's 18 | WaitScanline($200) 19 | DPC(RDPBuffer, RDPBufferEnd) 20 | nop // Marker NOP's 21 | Loop: 22 | j Loop 23 | nop // Delay Slot 24 | 25 | align(8) // Align 64-Bit 26 | RDPBuffer: 27 | arch n64.rdp 28 | Set_Scissor 0<<2,0<<2, 0,0, 320<<2,240<<2 29 | Set_Other_Modes CYCLE_TYPE_FILL 30 | Set_Color_Image IMAGE_DATA_FORMAT_RGBA,SIZE_OF_PIXEL_32B,320-1, $00100000 31 | 32 | Set_Fill_Color $000000FF // Set Fill Color: PACKED COLOR 32B R8G8B8A8 Pixel 33 | Fill_Rectangle 319<<2,239<<2, 0<<2,0<<2 // Fill Rectangle: XL 319.0,YL 239.0, XH 0.0,YH 0.0 34 | 35 | Set_Fill_Color INDIAN_RED 36 | // Bottom Right X, Bottom Right Y, Top Left X, Top Left Y 37 | Fill_Rectangle 20<<2,20<<2, 1<<2,1<<2 38 | 39 | Set_Fill_Color LIGHT_CORAL 40 | Fill_Rectangle 40<<2,20<<2, 21<<2,1<<2 41 | Set_Fill_Color SALMON 42 | Fill_Rectangle 60<<2,20<<2, 41<<2,1<<2 43 | Set_Fill_Color DARK_SALMON 44 | Fill_Rectangle 80<<2,20<<2, 61<<2,1<<2 45 | Set_Fill_Color CRIMSON 46 | Fill_Rectangle 100<<2,20<<2, 81<<2,1<<2 47 | Set_Fill_Color RED 48 | Fill_Rectangle 120<<2,20<<2, 101<<2,1<<2 49 | Set_Fill_Color FIRE_BRICK 50 | Fill_Rectangle 140<<2,20<<2, 121<<2,1<<2 51 | Set_Fill_Color DARK_RED 52 | Fill_Rectangle 160<<2,20<<2, 141<<2,1<<2 53 | Set_Fill_Color BLACK 54 | Fill_Rectangle 180<<2,20<<2, 161<<2,1<<2 55 | 56 | Set_Fill_Color PINK 57 | Fill_Rectangle 200<<2,20<<2, 181<<2,1<<2 58 | Set_Fill_Color LIGHT_PINK 59 | Fill_Rectangle 220<<2,20<<2, 201<<2,1<<2 60 | Set_Fill_Color HOT_PINK 61 | Fill_Rectangle 240<<2,20<<2, 221<<2,1<<2 62 | Set_Fill_Color DEEP_PINK 63 | Fill_Rectangle 260<<2,20<<2, 241<<2,1<<2 64 | Set_Fill_Color MEDIUM_VIOLET_RED 65 | Fill_Rectangle 280<<2,20<<2, 261<<2,1<<2 66 | Set_Fill_Color PALE_VIOLET_RED 67 | Fill_Rectangle 300<<2,20<<2, 281<<2,1<<2 68 | Set_Fill_Color BLACK 69 | Fill_Rectangle 320<<2,20<<2, 301<<2,1<<2 70 | 71 | // Bottom Right X, Bottom Right Y, Top Left X, Top Left Y 72 | Set_Fill_Color LIGHT_SALMON 73 | Fill_Rectangle 20<<2,40<<2, 1<<2,21<<2 74 | Set_Fill_Color CORAL 75 | Fill_Rectangle 40<<2,40<<2, 21<<2,21<<2 76 | Set_Fill_Color TOMATO 77 | Fill_Rectangle 60<<2,40<<2, 41<<2,21<<2 78 | Set_Fill_Color ORANGE_RED 79 | Fill_Rectangle 80<<2,40<<2, 61<<2,21<<2 80 | Set_Fill_Color DARK_ORANGE 81 | Fill_Rectangle 100<<2,40<<2, 81<<2,21<<2 82 | Set_Fill_Color ORANGE 83 | Fill_Rectangle 120<<2,40<<2, 101<<2,21<<2 84 | Set_Fill_Color BLACK 85 | Fill_Rectangle 140<<2,40<<2, 121<<2,21<<2 86 | 87 | Set_Fill_Color GOLD 88 | Fill_Rectangle 160<<2,40<<2, 141<<2, 21<<2 89 | Set_Fill_Color YELLOW 90 | Fill_Rectangle 180<<2,40<<2, 161<<2,21<<2 91 | Set_Fill_Color LIGHT_YELLOW 92 | Fill_Rectangle 200<<2,40<<2, 181<<2,21<<2 93 | Set_Fill_Color LEMON_CHIFFON 94 | Fill_Rectangle 220<<2,40<<2, 201<<2,21<<2 95 | Set_Fill_Color LIGHT_GOLDENROD_YELLOW 96 | Fill_Rectangle 240<<2,40<<2, 221<<2,21<<2 97 | Set_Fill_Color PAPAYA_WHIP 98 | Fill_Rectangle 260<<2,40<<2, 241<<2,21<<2 99 | Set_Fill_Color MOCCASIN 100 | Fill_Rectangle 280<<2,40<<2, 261<<2,21<<2 101 | Set_Fill_Color PEACH_PUFF 102 | Fill_Rectangle 300<<2,40<<2, 281<<2,21<<2 103 | Set_Fill_Color PALE_GOLDENROD 104 | Fill_Rectangle 320<<2,40<<2, 301<<2,21<<2 105 | Set_Fill_Color KHAKI 106 | Fill_Rectangle 340<<2,40<<2, 321<<2,21<<2 107 | 108 | Set_Fill_Color DARK_KHAKI 109 | Fill_Rectangle 20<<2,60<<2,1<<2,41<<2 110 | Set_Fill_Color BLACK 111 | Fill_Rectangle 40<<2,60<<2,21<<2,41<<2 112 | 113 | Set_Fill_Color LAVENDER 114 | Fill_Rectangle 60<<2,60<<2,41<<2,41<<2 115 | Set_Fill_Color THISTLE 116 | Fill_Rectangle 80<<2,60<<2,61<<2,41<<2 117 | Set_Fill_Color PLUM 118 | Fill_Rectangle 100<<2,60<<2,81<<2,41<<2 119 | Set_Fill_Color VIOLET 120 | Fill_Rectangle 120<<2,60<<2,101<<2,41<<2 121 | Set_Fill_Color ORCHID 122 | Fill_Rectangle 140<<2,60<<2,121<<2,41<<2 123 | Set_Fill_Color FUCHSIA 124 | Fill_Rectangle 160<<2,60<<2,141<<2,41<<2 125 | Set_Fill_Color MAGENTA 126 | Fill_Rectangle 180<<2,60<<2,161<<2,41<<2 127 | Set_Fill_Color MEDIUM_ORCHID 128 | Fill_Rectangle 200<<2,60<<2,181<<2,41<<2 129 | Set_Fill_Color BLUE_VIOLET 130 | Fill_Rectangle 220<<2,60<<2,201<<2,41<<2 131 | Set_Fill_Color DARK_ORCHID 132 | Fill_Rectangle 240<<2,60<<2,221<<2,41<<2 133 | Set_Fill_Color DARK_MAGENTA 134 | Fill_Rectangle 260<<2,60<<2,241<<2,41<<2 135 | Set_Fill_Color PURPLE 136 | Fill_Rectangle 280<<2,60<<2,261<<2,41<<2 137 | Set_Fill_Color INDIGO 138 | Fill_Rectangle 300<<2,60<<2,281<<2,41<<2 139 | Set_Fill_Color SLATE_BLUE 140 | Fill_Rectangle 320<<2,60<<2,301<<2,41<<2 141 | Set_Fill_Color DARK_SLATE_BLUE 142 | Fill_Rectangle 340<<2,60<<2,321<<2,41<<2 143 | 144 | Set_Fill_Color BLACK 145 | Fill_Rectangle 20<<2,80<<2,1<<2,61<<2 146 | Set_Fill_Color GREEN_YELLOW 147 | Fill_Rectangle 40<<2,80<<2,21<<2,61<<2 148 | Set_Fill_Color CHARTREUSE 149 | Fill_Rectangle 60<<2,80<<2,41<<2,61<<2 150 | Set_Fill_Color LAWN_GREEN 151 | Fill_Rectangle 80<<2,80<<2,61<<2,61<<2 152 | Set_Fill_Color LIME 153 | Fill_Rectangle 100<<2,80<<2,81<<2,61<<2 154 | Set_Fill_Color LIME_GREEN 155 | Fill_Rectangle 120<<2,80<<2,101<<2,61<<2 156 | Set_Fill_Color PALE_GREEN 157 | Fill_Rectangle 140<<2,80<<2,121<<2,61<<2 158 | Set_Fill_Color LIGHT_GREEN 159 | Fill_Rectangle 160<<2,80<<2,141<<2,61<<2 160 | Set_Fill_Color MEDIUM_SPRING_GREEN 161 | Fill_Rectangle 180<<2,80<<2,161<<2,61<<2 162 | Set_Fill_Color SPRING_GREEN 163 | Fill_Rectangle 200<<2,80<<2,181<<2,61<<2 164 | Set_Fill_Color MEDIUM_SEA_GREEN 165 | Fill_Rectangle 220<<2,80<<2,201<<2,61<<2 166 | Set_Fill_Color SEA_GREEN 167 | Fill_Rectangle 240<<2,80<<2,221<<2,61<<2 168 | Set_Fill_Color FOREST_GREEN 169 | Fill_Rectangle 260<<2,80<<2,241<<2,61<<2 170 | Set_Fill_Color GREEN 171 | Fill_Rectangle 280<<2,80<<2,261<<2,61<<2 172 | Set_Fill_Color DARK_GREEN 173 | Fill_Rectangle 300<<2,80<<2,281<<2,61<<2 174 | Set_Fill_Color YELLOW_GREEN 175 | Fill_Rectangle 320<<2,80<<2,301<<2,61<<2 176 | Set_Fill_Color OLIVE_DRAB 177 | Fill_Rectangle 340<<2,80<<2,321<<2,61<<2 178 | 179 | Set_Fill_Color OLIVE 180 | Fill_Rectangle 20<<2,100<<2,1<<2,81<<2 181 | Set_Fill_Color DARK_OLIVE_GREEN 182 | Fill_Rectangle 40<<2,100<<2,21<<2,81<<2 183 | Set_Fill_Color MEDIUM_AQUAMARINE 184 | Fill_Rectangle 60<<2,100<<2,41<<2,81<<2 185 | Set_Fill_Color DARK_SEA_GREEN 186 | Fill_Rectangle 80<<2,100<<2,61<<2,81<<2 187 | Set_Fill_Color LIGHT_SEA_GREEN 188 | Fill_Rectangle 100<<2,100<<2,81<<2,81<<2 189 | Set_Fill_Color DARK_CYAN 190 | Fill_Rectangle 120<<2,100<<2,101<<2,81<<2 191 | Set_Fill_Color TEAL 192 | Fill_Rectangle 140<<2,100<<2,121<<2,81<<2 193 | Set_Fill_Color BLACK 194 | Fill_Rectangle 160<<2,100<<2,141<<2,81<<2 195 | 196 | Set_Fill_Color AQUA 197 | Fill_Rectangle 180<<2,100<<2,161<<2,81<<2 198 | Set_Fill_Color CYAN 199 | Fill_Rectangle 200<<2,100<<2,181<<2,81<<2 200 | Set_Fill_Color LIGHT_CYAN 201 | Fill_Rectangle 220<<2,100<<2,201<<2,81<<2 202 | Set_Fill_Color PALE_TURQUOISE 203 | Fill_Rectangle 240<<2,100<<2,221<<2,81<<2 204 | Set_Fill_Color AQUAMARINE 205 | Fill_Rectangle 260<<2,100<<2,241<<2,81<<2 206 | Set_Fill_Color TURQUOISE 207 | Fill_Rectangle 280<<2,100<<2,261<<2,81<<2 208 | Set_Fill_Color MEDIUM_TURQUOISE 209 | Fill_Rectangle 300<<2,100<<2,281<<2,81<<2 210 | Set_Fill_Color DARK_TURQUOISE 211 | Fill_Rectangle 320<<2,100<<2,301<<2,81<<2 212 | Set_Fill_Color CADET_BLUE 213 | Fill_Rectangle 340<<2,100<<2,321<<2,81<<2 214 | 215 | Set_Fill_Color STEEL_BLUE 216 | Fill_Rectangle 20<<2,120<<2,1<<2,101<<2 217 | Set_Fill_Color LIGHT_STEEL_BLUE 218 | Fill_Rectangle 40<<2,120<<2,21<<2,101<<2 219 | Set_Fill_Color POWDER_BLUE 220 | Fill_Rectangle 60<<2,120<<2,41<<2,101<<2 221 | Set_Fill_Color LIGHT_BLUE 222 | Fill_Rectangle 80<<2,120<<2,61<<2,101<<2 223 | Set_Fill_Color SKY_BLUE 224 | Fill_Rectangle 100<<2,120<<2,81<<2,101<<2 225 | Set_Fill_Color LIGHT_SKY_BLUE 226 | Fill_Rectangle 120<<2,120<<2,101<<2,101<<2 227 | Set_Fill_Color DEEP_SKY_BLUE 228 | Fill_Rectangle 140<<2,120<<2,121<<2,101<<2 229 | Set_Fill_Color DODGER_BLUE 230 | Fill_Rectangle 160<<2,120<<2,141<<2,101<<2 231 | Set_Fill_Color CORN_FLOWER_BLUE 232 | Fill_Rectangle 180<<2,120<<2,161<<2,101<<2 233 | Set_Fill_Color MEDIUM_SLATE_BLUE 234 | Fill_Rectangle 200<<2,120<<2,181<<2,101<<2 235 | Set_Fill_Color ROYAL_BLUE 236 | Fill_Rectangle 220<<2,120<<2,201<<2,101<<2 237 | Set_Fill_Color MEDIUM_BLUE 238 | Fill_Rectangle 240<<2,120<<2,221<<2,101<<2 239 | Set_Fill_Color BLUE 240 | Fill_Rectangle 260<<2,120<<2,241<<2,101<<2 241 | Set_Fill_Color DARK_BLUE 242 | Fill_Rectangle 280<<2,120<<2,261<<2,101<<2 243 | Set_Fill_Color NAVY 244 | Fill_Rectangle 300<<2,120<<2,281<<2,101<<2 245 | Set_Fill_Color MIDNIGHT_BLUE 246 | Fill_Rectangle 320<<2,120<<2,301<<2,101<<2 247 | Set_Fill_Color BLACK 248 | Fill_Rectangle 340<<2,120<<2,321<<2,101<<2 249 | 250 | Set_Fill_Color CORNSILK 251 | Fill_Rectangle 20<<2,140<<2,1<<2,121<<2 252 | Set_Fill_Color BLANCHED_ALMOND 253 | Fill_Rectangle 40<<2,140<<2,21<<2,121<<2 254 | Set_Fill_Color BISQUE 255 | Fill_Rectangle 60<<2,140<<2,41<<2,121<<2 256 | Set_Fill_Color NAVAJO_WHITE 257 | Fill_Rectangle 80<<2,140<<2,61<<2,121<<2 258 | Set_Fill_Color WHEAT 259 | Fill_Rectangle 100<<2,140<<2,81<<2,121<<2 260 | Set_Fill_Color BURLY_WOOD 261 | Fill_Rectangle 120<<2,140<<2,101<<2,121<<2 262 | Set_Fill_Color TAN 263 | Fill_Rectangle 140<<2,140<<2,121<<2,121<<2 264 | Set_Fill_Color ROSY_BROWN 265 | Fill_Rectangle 160<<2,140<<2,141<<2,121<<2 266 | Set_Fill_Color SANDY_BROWN 267 | Fill_Rectangle 180<<2,140<<2,161<<2,121<<2 268 | Set_Fill_Color GOLDENROD 269 | Fill_Rectangle 200<<2,140<<2,181<<2,121<<2 270 | Set_Fill_Color DARK_GOLDENROD 271 | Fill_Rectangle 220<<2,140<<2,201<<2,121<<2 272 | Set_Fill_Color PERU 273 | Fill_Rectangle 240<<2,140<<2,221<<2,121<<2 274 | Set_Fill_Color CHOCOLATE 275 | Fill_Rectangle 260<<2,140<<2,241<<2,121<<2 276 | Set_Fill_Color SADDLE_BROWN 277 | Fill_Rectangle 280<<2,140<<2,261<<2,121<<2 278 | Set_Fill_Color SIENNA 279 | Fill_Rectangle 300<<2,140<<2,281<<2,121<<2 280 | Set_Fill_Color BROWN 281 | Fill_Rectangle 320<<2,140<<2,301<<2,121<<2 282 | Set_Fill_Color MAROON 283 | Fill_Rectangle 340<<2,140<<2,321<<2,121<<2 284 | 285 | Set_Fill_Color BLACK 286 | Fill_Rectangle 20<<2,160<<2,1<<2,141<<2 287 | Set_Fill_Color WHITE 288 | Fill_Rectangle 40<<2,160<<2,21<<2,141<<2 289 | Set_Fill_Color SNOW 290 | Fill_Rectangle 60<<2,160<<2,41<<2,141<<2 291 | Set_Fill_Color HONEYDEW 292 | Fill_Rectangle 80<<2,160<<2,61<<2,141<<2 293 | Set_Fill_Color MINT_CREAM 294 | Fill_Rectangle 100<<2,160<<2,81<<2,141<<2 295 | Set_Fill_Color AZURE 296 | Fill_Rectangle 120<<2,160<<2,101<<2,141<<2 297 | Set_Fill_Color ALICE_BLUE 298 | Fill_Rectangle 140<<2,160<<2,121<<2,141<<2 299 | Set_Fill_Color GHOST_WHITE 300 | Fill_Rectangle 160<<2,160<<2,141<<2,141<<2 301 | Set_Fill_Color WHITE_SMOKE 302 | Fill_Rectangle 180<<2,160<<2,161<<2,141<<2 303 | Set_Fill_Color SEA_SHELL 304 | Fill_Rectangle 200<<2,160<<2,181<<2,141<<2 305 | Set_Fill_Color BEIGE 306 | Fill_Rectangle 220<<2,160<<2,201<<2,141<<2 307 | Set_Fill_Color OLD_LACE 308 | Fill_Rectangle 240<<2,160<<2,221<<2,141<<2 309 | Set_Fill_Color FLORAL_WHITE 310 | Fill_Rectangle 260<<2,160<<2,241<<2,141<<2 311 | Set_Fill_Color IVORY 312 | Fill_Rectangle 280<<2,160<<2,261<<2,141<<2 313 | Set_Fill_Color ANTIQUE_WHITE 314 | Fill_Rectangle 300<<2,160<<2,281<<2,141<<2 315 | Set_Fill_Color LINEN 316 | Fill_Rectangle 320<<2,160<<2,301<<2,141<<2 317 | Set_Fill_Color LAVENDER_BLUSH 318 | Fill_Rectangle 340<<2,160<<2,321<<2,141<<2 319 | 320 | Set_Fill_Color MISTY_ROSE 321 | Fill_Rectangle 20<<2,180<<2,1<<2,161<<2 322 | Set_Fill_Color BLACK 323 | Fill_Rectangle 40<<2,180<<2,21<<2,161<<2 324 | Set_Fill_Color GAINSBORO 325 | Fill_Rectangle 60<<2,180<<2,41<<2,161<<2 326 | Set_Fill_Color LIGHT_GREY 327 | Fill_Rectangle 80<<2,180<<2,61<<2,161<<2 328 | Set_Fill_Color SILVER 329 | Fill_Rectangle 100<<2,180<<2,81<<2,161<<2 330 | Set_Fill_Color DARK_GREY 331 | Fill_Rectangle 120<<2,180<<2,101<<2,161<<2 332 | Set_Fill_Color GREY 333 | Fill_Rectangle 140<<2,180<<2,121<<2,161<<2 334 | Set_Fill_Color DIM_GREY 335 | Fill_Rectangle 160<<2,180<<2,141<<2,161<<2 336 | Set_Fill_Color LIGHT_SLATE_GREY 337 | Fill_Rectangle 180<<2,180<<2,161<<2,161<<2 338 | Set_Fill_Color SLATE_GREY 339 | Fill_Rectangle 200<<2,180<<2,181<<2,161<<2 340 | Set_Fill_Color BLACK 341 | Fill_Rectangle 220<<2,180<<2,201<<2,161<<2 342 | Set_Fill_Color BLACK 343 | Fill_Rectangle 240<<2,180<<2,221<<2,161<<2 344 | Set_Fill_Color BLACK 345 | Fill_Rectangle 260<<2,180<<2,241<<2,161<<2 346 | Set_Fill_Color BLACK 347 | Fill_Rectangle 280<<2,180<<2,261<<2,161<<2 348 | Set_Fill_Color BLACK 349 | Fill_Rectangle 300<<2,180<<2,281<<2,161<<2 350 | Set_Fill_Color BLACK 351 | Fill_Rectangle 320<<2,180<<2,301<<2,161<<2 352 | Set_Fill_Color BLACK 353 | Fill_Rectangle 340<<2,180<<2,321<<2,161<<2 354 | 355 | Sync_Full // Ensure Entire Scene Is Fully Drawn 356 | RDPBufferEnd: -------------------------------------------------------------------------------- /N64/Color32/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Color 32 bit " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Color32/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Color32_Test.N64 3 | REM Space seperated list of source files 4 | set source_files=Color32_Test.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Exception/Exception.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Exception/Exception.N64 -------------------------------------------------------------------------------- /N64/Exception/Exception.asm: -------------------------------------------------------------------------------- 1 | libn64_tlb_exception_handler: 2 | base $80000000 3 | mtc0 ra, $30 4 | lui ra, 0x8000 5 | fixed_gap(libn64_tlb_exception_handler, 0x080) 6 | libn64_xtlb_exception_handler: 7 | fixed_gap(libn64_xtlb_exception_handler, 0x100) 8 | libn64_cache_exception_handler: 9 | fixed_gap(libn64_cache_exception_handler, 0x180) 10 | libn64_general_exception_handler: 11 | 12 | fixed_gap(libn64_tlb_exception_handler, 0x300) 13 | libn64_exception_jump_table: 14 | 15 | libn64_exception_register_store: 16 | // Scaler Registers 17 | dd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 18 | dd 0, 0, 0, 0, 0, 0, 0, 0 19 | dd 0, 0, 0, 0, 0, 0, 0, 0 20 | dd 0, 0, 0, 0, 0, 0, 0, 0 21 | db "End of Scaler" 22 | // COP0 23 | dd 0, 0, 0, 0, 0, 0, 0, 0 24 | db "End of Ctrl" 25 | // COP1 Floating Point 26 | dd 0, 0, 0, 0, 0, 0, 0, 0 27 | dd 0, 0, 0, 0, 0, 0, 0, 0 28 | dd 0, 0, 0, 0, 0, 0, 0, 0 29 | dd 0, 0, 0, 0, 0, 0, 0, 0 30 | db "End of Data" -------------------------------------------------------------------------------- /N64/Exception/ExceptionTest.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Exception/ExceptionTest.N64 -------------------------------------------------------------------------------- /N64/Exception/Main.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | output "Exception.N64", create 4 | fill 1052672 5 | 6 | origin $00000000 7 | base $80000000 8 | include "../LIB/N64.INC" 9 | include "N64_HEADER.ASM" 10 | insert "../LIB/N64_BOOTCODE.BIN" 11 | 12 | Start: 13 | lui t0,$BFC0 14 | addi t1,r0,8 15 | sw t1,$7FC(t0) 16 | 17 | // DMA interrupt handler on top of the vector. 18 | // First, write the DRAM (destination) register. 19 | lui at, 0xA460 20 | lui v0, 0x8000 21 | sw v0, 0(at) // RDRAM Location 22 | la v1, 0x10000000 + (libn64_tlb_exception_handler - 0x80000000) 23 | sw v1, 0x4(at) // Cart Location 24 | addiu v0, r0, 0x300 - 0x1 25 | sw v0, 0xC(at) // Start DMA from CART -> RDRAM 26 | Loop: 27 | j Loop 28 | nop 29 | include "./Exception.asm" -------------------------------------------------------------------------------- /N64/Exception/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Exception Jump Table " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Exception/cfg/default.cfg: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /N64/Exception/cfg/n64.cfg: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /N64/Exception/error.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Exception/error.log -------------------------------------------------------------------------------- /N64/Exception/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Exception.N64 3 | REM Space seperated list of source files 4 | set source_files=Main.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Exception/nvram/n64/Lesson2.nv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Exception/nvram/n64/Lesson2.nv -------------------------------------------------------------------------------- /N64/Exception2/Exception.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Exception2/Exception.N64 -------------------------------------------------------------------------------- /N64/Exception2/Exception.asm: -------------------------------------------------------------------------------- 1 | // Notes: 2 | // There can be only one Exception. 3 | // If the Exception is "Interrupt" then there can be multiple Interrupts. 4 | // Should the Exception handler be able to throw exceptions? 5 | libn64_tlb_exception_handler: 6 | variable old_base(base()) 7 | base $80000000 8 | // ra when used correctly is 32bits, COP0$30 is 32 bits 9 | // This frees up ra for anything, including Jumps 10 | mtc0 ra, $30 11 | la ra, libn64_tlb_exception_handler 12 | sw k0, k0(ra) 13 | mfc0 k0, Cause // Get Cause 14 | sw k1, k1(ra) 15 | andi k1, k0, 0x0F // mask 16 | beql k1, r0, Interrupt 17 | nop 18 | // Process Exceptions 19 | // TODO Call Individual handler 20 | j int_x_continue 21 | nop 22 | align(128) 23 | libn64_xtlb_exception_handler: 24 | j $80000001 25 | nop 26 | int_x_continue: 27 | // TODO More Code HERE 28 | Interrupt: 29 | mfc0 k1, SR // Get Status 30 | andi k1, k1, $FF00 // mask 31 | and k0, k0, k1 32 | addi k0, k0, 0x60 // 0x60 = 24 * 4 33 | li k1, libn64_exception_jump_table 34 | add k1, k0, k1 35 | lw k0, 0(k1) 36 | // FIX: Don't have the right memory address yet. 37 | // TODO Call Individual handler 38 | j int_cache_continue 39 | nop 40 | align(128) 41 | libn64_cache_exception_handler: 42 | j $80000002 43 | nop 44 | int_cache_continue: 45 | // TODO More Code HERE 46 | j int_general_continue 47 | nop 48 | align(128) 49 | libn64_general_exception_handler: 50 | j $80000003 51 | nop 52 | int_general_continue: 53 | mfc0 k0, EPC 54 | // Restore the 'ra' register 55 | // TODO: Process Branch Delay Bit, 4 instructions 56 | mfc0 ra, PErr 57 | addiu k0, k0, 4 58 | mtc0 k0, EPC 59 | eret 60 | align(128) 61 | libn64_tlb_exception_handler_end: 62 | base old_base 63 | db "JTBL" 64 | libn64_exception_jump_table: 65 | dw 0 // Interrupt type Exception 66 | dw 0 // TLB Modification 67 | dw 0 // TLB Miss (load or fetch) 68 | dw 0 // TLB Miss (store) 69 | dw 0 // Address Error (load or fetch) 70 | dw 0 // Address Error (store) 71 | dw 0 // Bus Error (instruction fetch) 72 | dw 0 // Bus Error (load or store) 73 | dw 0 // Syscall 74 | dw 0 // Breakpoint 75 | dw 0 // Reserved Instruction 76 | dw 0 // Coprocessor Unusable 77 | dw 0 // Arithmetic Overflow 78 | dw 0 // Trap 79 | db "RFU " // Unused - RFU 80 | dw 0 // Floating Point 81 | dw 0 // 16 MI-SP 82 | dw 0 // 17 MI-SI 83 | dw 0 // 18 MI-AI 84 | dw 0 // 19 MI-VI 85 | dw 0 // 20 MI-PI 86 | dw 0 // 21 MI-DP 87 | dw 0 // 22 88 | dw 0 // Watch 89 | dw 0 // 24 INT0 - Software 0 90 | dw 0 // 25 INT1 - Software 1 91 | dw 0 // 26 INT2 (PIN-INT0) - RCP 92 | dw 0 // 27 INT3 (PIN-INT1) - Unused 93 | dw 0 // 28 INT4 (PIN-INT2) - PIF 94 | dw 0 // 29 INT5 (PIN-INT3) - Unused 95 | dw 0 // 30 INT6 (PIN-INT4) - Unused 96 | dw 0 // 31 INT7 - Timer 97 | db "register" 98 | libn64_exception_register_store: 99 | // Scaler Registers 100 | dd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 101 | dd 0, 0, 0, 0, 0, 0, 0, 0 102 | dd 0, 0, 0, 0, 0, 0, 0, 0 103 | dd 0, 0, 0, 0, 0, 0, 0, 0 104 | db "End of Scaler" 105 | // COP0 106 | dd 0, 0, 0, 0, 0, 0, 0, 0 107 | db "End of Ctrl" 108 | // COP1 Floating Point 109 | dd 0, 0, 0, 0, 0, 0, 0, 0 110 | dd 0, 0, 0, 0, 0, 0, 0, 0 111 | dd 0, 0, 0, 0, 0, 0, 0, 0 112 | dd 0, 0, 0, 0, 0, 0, 0, 0 113 | db "End of Float" -------------------------------------------------------------------------------- /N64/Exception2/Main.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | output "Exception.N64", create 4 | fill 1052672 5 | 6 | origin $00000000 7 | base $80000000 8 | include "../LIB/N64.INC" 9 | include "N64_HEADER.ASM" 10 | insert "../LIB/N64_BOOTCODE.BIN" 11 | 12 | // constant exp_interrupt(0) //Not applicable 13 | constant exp_tlb_modification(1) 14 | constant exp_tlb_miss_misc(2) 15 | constant exp_tlb_miss_store(3) 16 | constant exp_addr_misc(4) 17 | constant exp_addr_store(5) 18 | constant exp_bus_fetch(6) 19 | constant exp_bus_misc(7) 20 | constant exp_syscall(8) 21 | constant exp_breakpoint(9) 22 | constant exp_reserved_instruction(10) 23 | constant exp_coprocessor_unusable(11) 24 | constant exp_arithmetic_overflow(12) 25 | constant exp_trap(13) 26 | //constant unused(14) 27 | constant exp_floating_point(15) 28 | constant int_MI_SP_entry(16) 29 | constant int_MI_SI_entry(17) 30 | constant int_MI_AI_entry(18) 31 | constant int_MI_VI_entry(19) 32 | constant int_MI_PI_entry(20) 33 | constant int_MI_DP_entry(21) 34 | // constant unused(22) 35 | constant exp_watch(23) 36 | constant int_software0_entry(24) 37 | constant int_software1_entry(25) 38 | constant int_RCP_entry(26) 39 | //constant int_unused_entry(27) 40 | constant int_PIF_entry(28) 41 | //constant int_unused_entry(29) 42 | //constant int_unused_entry(30) 43 | constant int_timer_entry(31) 44 | 45 | macro setHandler(handler_name, handler_label) { 46 | nop // Marker NOP's 47 | la t0, libn64_exception_jump_table 48 | li t1, {handler_label} 49 | sw t1, {handler_name}<<2(t0) 50 | nop // Marker NOP's 51 | } 52 | 53 | macro setInterrupt(enable_mask) { 54 | nop // Marker NOP's 55 | mfc0 t0, SR 56 | ori t0, t0, {enable_mask} 57 | mtc0 t0, SR 58 | nop // Marker NOP's 59 | } 60 | 61 | macro fireSoftwareInterrupt0() { 62 | mfc0 t0, Cause 63 | ori t0, t0, 0x0100 64 | mtc0 t0, Cause 65 | } 66 | 67 | macro fireSoftwareInterrupt1() { 68 | mfc0 t0, Cause 69 | ori t0, t0, 0x0200 70 | mtc0 t0, Cause 71 | } 72 | 73 | Start: 74 | N64_INIT() 75 | 76 | setInterrupt(0x0) 77 | 78 | DMA(libn64_tlb_exception_handler, libn64_tlb_exception_handler_end, 0x8000000) 79 | 80 | nop // Marker NOP's 81 | nop // Marker NOP's 82 | 83 | lui t1, PI_BASE 84 | dma_incomplete: 85 | lw t2, PI_STATUS(t1) 86 | bne t2, r0, dma_incomplete 87 | nop 88 | nop // Marker NOP's 89 | nop // Marker NOP's 90 | 91 | setHandler(exp_tlb_modification, software0) 92 | // Test Cases 93 | // Software Interrupts 94 | setHandler(int_software0_entry, software0) 95 | setInterrupt(0x0101) 96 | fireSoftwareInterrupt0() 97 | 98 | nop // Marker NOP's 99 | nop // Marker NOP's 100 | 101 | setHandler(int_software1_entry, software1) 102 | setInterrupt(0x0201) 103 | fireSoftwareInterrupt1() 104 | 105 | setInterrupt(0x0) 106 | nop // Marker NOP's 107 | nop // Marker NOP's 108 | 109 | // Timer Interrupts 110 | setHandler(int_timer_entry, timer) 111 | mfc0 t0, Compare 112 | addi t0, t0, 0x1000 113 | mtc0 t0, Compare 114 | setInterrupt(0x0801) 115 | 116 | 117 | nop // Marker NOP's 118 | setInterrupt(0x0) 119 | nop // Marker NOP's 120 | 121 | Loop: 122 | j Loop 123 | nop 124 | 125 | software0: 126 | ori t4, r0, 123 127 | jr ra 128 | nop 129 | 130 | software1: 131 | ori t4, r0, 234 132 | jr ra 133 | nop 134 | timer: 135 | ori t4, r0, 345 136 | jr ra 137 | nop 138 | 139 | include "./Exception.asm" -------------------------------------------------------------------------------- /N64/Exception2/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Exception Jump Table " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Exception2/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Exception.N64 3 | REM Space seperated list of source files 4 | set source_files=Main.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/ExceptionTest/ExceptionTest.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/ExceptionTest/ExceptionTest.N64 -------------------------------------------------------------------------------- /N64/ExceptionTest/ExceptionTest.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/N64_GFX.INC" 9 | include "./N64_HEADER.ASM" // Include 64 Byte Header & Vector Table 10 | insert "../LIB/N64_BOOTCODE.BIN" // Include 4032 Byte Boot Code 11 | constant Status_All_Exceptions(0xFF10) 12 | // CU RP FR RE DS IM KX SX UX KSU ERL EXL IE 13 | // 0011 0 1 0 000'000'000 0000'0000 0 0 0 00 0 0 0 14 | // 0000 0 0 0 000'000'000 1111'1111 0 0 0 10 0 0 1 15 | 16 | force_pc($80001000) 17 | Start: 18 | align(8) 19 | N64_INIT() 20 | ScreenNTSC(320, 240, BPP32, $A0100000) // Screen NTSC: 320x240, 32BPP, DRAM Origin $A0100000 21 | // Insert Initialization Code 22 | 23 | mfc0 s0, SR 24 | // Copy Exception Handler code 25 | la t0, $8000'0000 26 | la t1, ExceptionHandlerBlock 27 | la t2, ExceptionHandlerBlockEnd 28 | repeat_load_exception: 29 | lw t3, 0(t1) 30 | lw t4, 4(t1) 31 | lw t5, 8(t1) 32 | lw t6, 12(t1) 33 | sw t3, 0(t0) 34 | sw t4, 4(t0) 35 | sw t5, 8(t0) 36 | sw t6, 12(t0) 37 | addi t1, t1, 16 38 | bne t1, t2, repeat_load_exception 39 | addi t0, t0, 16 40 | nop 41 | nop 42 | // Copy Exception Handler code to Cache area 43 | la t0, $A000'0000 44 | la t1, ExceptionHandlerBlock 45 | la t2, ExceptionHandlerBlockEnd 46 | repeat_load_exception_cache: 47 | lw t3, 0(t1) 48 | lw t4, 4(t1) 49 | lw t5, 8(t1) 50 | lw t6, 12(t1) 51 | sw t3, 0(t0) 52 | sw t4, 4(t0) 53 | sw t5, 8(t0) 54 | sw t6, 12(t0) 55 | addi t1, t1, 16 56 | bne t1, t2, repeat_load_exception_cache 57 | addi t0, t0, 16 58 | nop 59 | nop 60 | 61 | la t8, savedCP0 62 | jal save_cop0 63 | nop 64 | // Throws TLB Exception 65 | lui t2, r0; 66 | sw t3, 0(t2) 67 | nop 68 | nop 69 | nop 70 | 71 | 72 | 73 | 74 | // Throw XTLB Exception 75 | mfc0 t7, SR 76 | li t8, 0x20 77 | not t8, t8 78 | and t7, t7, t8 79 | mtc0 t7, SR 80 | ori t7, t7, 1 81 | mtc0 t7, SR 82 | // Try to access Memory above 4 GB 83 | addi t2, r0, -1; 84 | sw t3, 0(t2) // TODO: Doesn't work yet 85 | nop 86 | nop 87 | nop 88 | 89 | // Throw Cache Exception - Not Applicable on VR4300 90 | 91 | // Break Instruction 92 | break // TODO: Doesn't work yet 93 | 94 | // Syscall Instruction 95 | // syscall // TODO: Doesn't work yet 96 | 97 | // CP0 Disable - Control Processor 98 | mfc0 t7, SR 99 | li t8, 0x10000000 100 | not t8, t8 101 | and t7, t7, t8 102 | ori t7, t7, 0x10 103 | mtc0 t7, SR 104 | ori t7, t7, 1 105 | mtc0 t7, SR 106 | nop 107 | // Try to use CP0 108 | mtc0 t7, SR // TODO: Doesn't work yet 109 | nop 110 | nop 111 | nop 112 | 113 | // Set CP1 Disable - Floating Point Unit 114 | mfc0 t7, SR 115 | li t8, 0x20000000 116 | not t8, t8 117 | and t7, t7, t8 118 | mtc0 t7, SR 119 | ori t7, t7, 1 120 | mtc0 t7, SR 121 | nop 122 | // Try to use Floating Point Unit 123 | la t0, VALUEDOUBLEA 124 | ldc1 f0, 0(t0) 125 | nop 126 | nop 127 | nop 128 | 129 | 130 | 131 | Loop: 132 | // Insert Looping Code Here 133 | j Loop 134 | nop // Delay Slot 135 | 136 | save_cop0: 137 | dmfc0 t0, Index 138 | dmfc0 t1, Random 139 | dmfc0 t2, EntryLo0 140 | dmfc0 t3, EntryLo1 141 | dmfc0 t4, Context 142 | dmfc0 t5, PageMask 143 | dmfc0 t6, Wired 144 | sw t0, 0x00(k0) 145 | sw t1, 0x08(k0) 146 | sw t2, 0x0F(k0) 147 | sw t3, 0x17(k0) 148 | sw t4, 0x1F(k0) 149 | sw t5, 0x27(k0) 150 | sw t6, 0x2F(k0) 151 | 152 | // dmfc0 t3, EntryLo1 153 | // sw t3, 0x37(k0) 154 | 155 | dmfc0 t0, BadVAddr 156 | dmfc0 t1, Count 157 | dmfc0 t2, EntryHi 158 | dmfc0 t3, Compare 159 | dmfc0 t4, Status 160 | dmfc0 t5, Cause 161 | dmfc0 t6, EPC 162 | 163 | sw t0, 0x3F(k0) 164 | sw t1, 0x47(k0) 165 | sw t2, 0x4F(k0) 166 | sw t3, 0x57(k0) 167 | sw t4, 0x5F(k0) 168 | sw t5, 0x67(k0) 169 | sw t6, 0x6F(k0) 170 | 171 | dmfc0 t0, PRevID 172 | dmfc0 t1, Config 173 | dmfc0 t2, LLAddr 174 | dmfc0 t3, WatchLo 175 | dmfc0 t4, WatchHi 176 | dmfc0 t5, XContext 177 | 178 | sw t0, 0x77(k0) 179 | sw t1, 0x7F(k0) 180 | sw t2, 0x87(k0) 181 | sw t3, 0x8F(k0) 182 | sw t4, 0x97(k0) 183 | sw t5, 0x9F(k0) 184 | 185 | dmfc0 t0, PErr 186 | dmfc0 t1, CacheErr 187 | dmfc0 t2, TagLo 188 | dmfc0 t3, TagHi 189 | dmfc0 t4, ErrorEPC 190 | 191 | sw t0, 0xCF(k0) 192 | sw t1, 0xD7(k0) 193 | sw t2, 0xDF(k0) 194 | sw t3, 0xE7(k0) 195 | sw t4, 0xEF(k0) 196 | 197 | align(128) 198 | savedCP0: 199 | fill 256, 0x55 200 | rIndex: // 0 201 | rRandom: // 1 202 | rEntryLo0: // 2 203 | rEntryLo1: // 3 204 | rContext: // 4 205 | rPageMask: // 5 206 | rWired: // 6 207 | // 7 208 | rBadVAddr: // 8 209 | rCount: // 9 210 | rEntryHi: // 10 211 | rCompare: // 11 212 | rStatus: // SR, 12 213 | rCause: // 13 214 | rEPC: // 14 215 | rPRId: // 15 216 | rConfig: // 16 217 | rLLAddr: // 17 218 | rWatchLo: // 18 219 | rWatchHi: // 19 220 | rXContext: // 20 221 | // 21 222 | // 22 223 | // 23 224 | // 24 225 | // 25 226 | rPErr: // 26 227 | rCacheErr: // 27 228 | rTagLo: // 28 229 | rTagHi: // 29 230 | rErrorEPC: // 30 231 | // 31 232 | saved_cp0_end: 233 | 234 | align(128) 235 | screen_char: 236 | // 49 columns 637 of 640 pixels 237 | // 34 rows 476 of 480 pixels 238 | // 1,666 total characters on screen 239 | fill 49, 0x00 240 | fill 49, 0x01 241 | fill 49, 0x02 242 | fill 49, 0x03 243 | fill 49, 0x04 244 | fill 49, 0x05 245 | fill 49, 0x06 246 | fill 49, 0x07 247 | fill 49, 0x08 248 | fill 49, 0x09 249 | fill 49, 0x0A 250 | fill 49, 0x0B 251 | fill 49, 0x0C 252 | fill 49, 0x0D 253 | fill 49, 0x0E 254 | fill 49, 0x0F 255 | fill 49, 0x10 256 | fill 49, 0x11 257 | fill 49, 0x12 258 | fill 49, 0x13 259 | fill 49, 0x14 260 | fill 49, 0x15 261 | fill 49, 0x16 262 | fill 49, 0x17 263 | fill 49, 0x18 264 | fill 49, 0x19 265 | fill 49, 0x1A 266 | fill 49, 0x1B 267 | fill 49, 0x1C 268 | fill 49, 0x1D 269 | fill 49, 0x1E 270 | fill 49, 0x1F 271 | fill 49, 0x20 272 | fill 49, 0x21 273 | fill 49, 0x22 274 | screen_char_end: 275 | 276 | align(128) 277 | exception_cp0: 278 | fill 256, 0x55 279 | exception_cp0_end: 280 | 281 | align(128) 282 | ExceptionHandlerBlock: 283 | // TLB Handler 284 | la k0, exception_cp0 285 | jal save_cop0 286 | nop 287 | mfc0 k0, EPC 288 | mtc0 s0, SR 289 | addi k0, k0, 4 290 | mtc0 k0, EPC 291 | nop 292 | eret 293 | nop 294 | fill 100, 0xAA 295 | align(128) 296 | // XTLB Handler 297 | mfc0 k0, EPC 298 | mtc0 s0, SR 299 | addi k0, k0, 4 300 | mtc0 k0, EPC 301 | nop 302 | eret 303 | nop 304 | fill 100, 0xBB 305 | align(128) 306 | // Cache Handler 307 | mfc0 k0, EPC 308 | mtc0 s0, SR 309 | addi k0, k0, 4 310 | mtc0 k0, EPC 311 | nop 312 | eret 313 | nop 314 | fill 100, 0xCC 315 | align(128) 316 | // General Handler 317 | mfc0 k0, EPC 318 | mtc0 s0, SR 319 | addi k0, k0, 4 320 | mtc0 k0, EPC 321 | nop 322 | eret 323 | nop 324 | fill 100, 0xDD 325 | ExceptionHandlerBlockEnd: 326 | db 0xff 327 | align(8) // Align 64-Bit 328 | VALUEDOUBLEA: 329 | float64 0.0 -------------------------------------------------------------------------------- /N64/ExceptionTest/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Exception Test " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/ExceptionTest/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=ExceptionTest.N64 3 | REM Space seperated list of source files 4 | set source_files=ExceptionTest.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/GDB/GDB_Test.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/GDB/GDB_Test.N64 -------------------------------------------------------------------------------- /N64/GDB/GDB_Test.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | // Useful for identifying where a value is in the output ROM file 8 | // Commented = Zeros in Gaps + Interrupt Zeros 9 | // Defined(1) = Filled Gaps + Interrupt Names 10 | // Defined(0) = Filled Gaps + Interrupt Names 11 | define DEBUG_SHOW_STATIC_VALUE(comment_out) 12 | include "../LIB/COLORS16.INC" 13 | include "../LIB/N64.INC" 14 | include "../LIB/N64_DRIVE.INC" 15 | include "../LIB/N64_GDB.INC" 16 | include "../LIB/N64_GFX.INC" 17 | include "../LIB/N64_INTERRUPT.INC" 18 | include "N64_HEADER.ASM" 19 | insert "../LIB/N64_BOOTCODE.BIN" 20 | 21 | Start: 22 | N64_INIT() 23 | ScreenNTSC(320, 240, BPP32, $A0100000) // Screen NTSC: 320x240, 32BPP, DRAM $A0100000 24 | nop // Marker NOP's 25 | nop // Marker NOP's 26 | interrupt_init() 27 | nop // Marker NOP's 28 | nop // Marker NOP's 29 | interrupt_tlb(gdb_serial_tlb_handler) 30 | nop // Marker NOP's 31 | nop // Marker NOP's 32 | gdb_communication_test() 33 | // Clear tlb handler so the debug handler will assign 34 | interrupt_tlb(0x00) 35 | nop // Marker NOP's 36 | nop // Marker NOP's 37 | interrupt_set_debug(gdb_interrupt_handler) 38 | nop // Marker NOP's 39 | nop // Marker NOP's 40 | interrupt_vblank($200,interrupt_vblank_handler) 41 | nop // Marker NOP's 42 | nop // Marker NOP's 43 | 44 | // Force GDB Sync 45 | gdb_sync() 46 | 47 | nop // Marker NOP's 48 | nop // Marker NOP's 49 | // Force TLB Interrupt 50 | lui v0,$7000 51 | lw v1,0000 (v0) 52 | nop // Marker NOP's 53 | nop // Marker NOP's 54 | Loop: 55 | j Loop 56 | nop // Delay Slot 57 | 58 | interrupt_default_handler: 59 | jr ra 60 | nop 61 | interrupt_vblank_handler: 62 | jr ra 63 | nop 64 | 65 | include "../LIB/N64_INTERRUPT.S" 66 | include "../LIB/N64_SYS.S" 67 | include "../LIB/N64_GDB.S" 68 | include "../LIB/N64_INTERRUPT_TEMPLATE.S" -------------------------------------------------------------------------------- /N64/GDB/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "GDB Test " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/GDB/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=GDB_Test.N64 3 | REM Space seperated list of source files 4 | set source_files=GDB_Test.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/IPL_FONT/IPL_FONT.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/IPL_FONT/IPL_FONT.N64 -------------------------------------------------------------------------------- /N64/IPL_FONT/IPL_FONT.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | define SHOW_EXCEPTIONS(1) 6 | 7 | origin $00000000 8 | base $80000000 9 | include "../LIB/N64.INC" 10 | include "../LIB/N64_GFX.INC" 11 | include "../LIB/COLORS16.INC" 12 | include "../LIB/N64_IPL_FONT.INC" 13 | include "../LIB/N64_EXCEPTION.INC" 14 | include "./N64_HEADER.ASM" // Include 64 Byte Header & Vector Table 15 | insert "../LIB/N64_BOOTCODE.BIN" // Include 4032 Byte Boot Code 16 | force_pc($80001000) 17 | Start: 18 | align(8) 19 | variable video_buffer($A0100000) 20 | N64_INIT() 21 | ScreenNTSC(640, 480, BPP16, video_buffer) // Screen NTSC: 640x480, 16BPP, DRAM Origin $A0100000 22 | nop 23 | nop 24 | exception_load_handler() 25 | //DMA(libn64_tlb_exception_handler, libn64_tlb_exception_handler_end, $80000000) 26 | nop 27 | nop 28 | variable font_good($8008'A000) 29 | font_init16(WHITE, SEA_GREEN, font_good) 30 | 31 | variable font_fail($8008'F000) 32 | font_init16(WHITE, RED, font_fail) 33 | 34 | variable font_white($8008'0000) 35 | font_init16(WHITE, 0x01, font_white) 36 | 37 | variable font_blue($8008'5000) 38 | font_init16(STEEL_BLUE, 0x01, font_blue) 39 | 40 | nop 41 | nop 42 | font_print_line16(font_white, video_buffer, 10, 10, testtext, 31) 43 | font_print_line16(font_blue, video_buffer, 100, 30, myname, 20) 44 | 45 | font_print_line16(font_good, video_buffer, 50, 50, pass, 4) 46 | font_print_line16(font_fail, video_buffer, 75, 70, fail, 4) 47 | Loop: 48 | 49 | j Loop 50 | nop // Delay Slot 51 | 52 | include "../LIB/N64_IPL_FONT.S" 53 | include "../LIB/N64_EXCEPTION.S" 54 | 55 | map 'A',0,26 // A-Z 56 | map 'a',0,26 // a-z 57 | map '0',26,10 // 0-9 58 | map '!',36,3 // ! " # 59 | //map '\'', 39, 1 // ' 60 | map '*', 40, 6 // * + , - . / 61 | map ':', 46, 1 // : 62 | map '=', 47, 1 // = 63 | map '?',48, 2 // ? @ 64 | map ' ',51, 1 // space 65 | testtext: 66 | db "the quick brown fox jumped over" 67 | myname: 68 | db "my name is fraser125" 69 | pass: 70 | db "pass" 71 | fail: 72 | db "fail" 73 | map 0, 0, 256 -------------------------------------------------------------------------------- /N64/IPL_FONT/IPL_FONT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/IPL_FONT/IPL_FONT.png -------------------------------------------------------------------------------- /N64/IPL_FONT/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "IPL FONT DEMO " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/IPL_FONT/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=IPL_FONT.N64 3 | REM Space seperated list of source files 4 | set source_files=IPL_FONT.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/InterruptTest/InterruptTest.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/InterruptTest/InterruptTest.N64 -------------------------------------------------------------------------------- /N64/InterruptTest/InterruptTest.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "../LIB/N64_GFX.INC" 9 | include "../LIB/N64_INTERRUPT.INC" 10 | include "./N64_HEADER.ASM" // Include 64 Byte Header & Vector Table 11 | insert "../LIB/N64_BOOTCODE.BIN" // Include 4032 Byte Boot Code 12 | force_pc($80001000) 13 | Start: 14 | align(8) 15 | //N64_INIT() 16 | interrupt_init() 17 | interrupt_set_default(ExceptionHandler) // Interrupts Active by Default 18 | ScreenNTSC(320, 240, BPP32, $A0100000) // Screen NTSC: 320x240, 32BPP, DRAM Origin $A0100000 19 | // Insert Initialization Code 20 | nop // Marker NOP's 21 | nop // Marker NOP's 22 | 23 | // TLB Exception - Handled by the Handler, no developer action 24 | la t0, 0x00000000 25 | lw t0, 0(t0) 26 | nop // Marker NOP's 27 | nop // Marker NOP's 28 | 29 | // BREAK Instruction 30 | interrupt_set_break(ExceptionHandler) 31 | break 32 | nop // Marker NOP's 33 | nop // Marker NOP's 34 | 35 | // SYSCALL Instruction 36 | interrupt_set_syscall(syscall_mars) 37 | //lui a0, r0 38 | //ori a0, 10 39 | //syscall 40 | 41 | // Timer Exception - Just before Inifinite loop 42 | interrupt_set_timer(ExceptionHandler) 43 | nop 44 | mfc0 t0, Count 45 | li t1, 0x1FFFFF // 2 Million 46 | add t0, t1, t0 47 | mtc0 t0, Compare 48 | interrupt_timer_enable() 49 | Loop: 50 | // Insert Looping Code Here 51 | j Loop 52 | nop // Delay Slot 53 | 54 | nop // Marker NOP's 55 | nop // Marker NOP's 56 | 57 | ExceptionHandler: 58 | // interrupt_register_* macros allow the use of any register 59 | // Otherwise only k0, k1, ra can be used. 60 | interrupt_register_save() 61 | // 62 | // Your Code Here 63 | // 64 | interrupt_register_restore() 65 | 66 | jr ra 67 | nop 68 | 69 | // Shared Function Libraries 70 | include "../LIB/N64_SYS.S" 71 | include "../LIB/N64_INTERRUPT.S" 72 | include "../LIB/N64_INTERRUPT_HANDLER.S" 73 | include "../LIB/N64_SYSCALL_MARS.S" -------------------------------------------------------------------------------- /N64/InterruptTest/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Interrupt Test " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/InterruptTest/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=InterruptTest.N64 3 | REM Space seperated list of source files 4 | set source_files=InterruptTest.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if ERRORLEVEL 0 ECHO Compile Success! 11 | if exist %rom_name% ( 12 | @chksum64 %rom_name% 13 | ) -------------------------------------------------------------------------------- /N64/LIB/COLORS16.INC: -------------------------------------------------------------------------------- 1 | // COLOR names used from 2 | // http://etetoolkit.org/docs/2.3/reference/reference_treeview.html 3 | // Red Colors 4 | constant INDIAN_RED($CAD6 ) 5 | constant LIGHT_CORAL($F420) 6 | constant SALMON($FC1C) 7 | constant DARK_SALMON($EC9E) 8 | constant CRIMSON($D88E) 9 | constant RED($F800) 10 | constant FIRE_BRICK($B108) 11 | constant DARK_RED($8800) 12 | // Pink Colors 13 | constant PINK($FE32) 14 | constant LIGHT_PINK($FDB0) 15 | constant HOT_PINK($FB6C) 16 | constant DEEP_PINK($F8A4) 17 | constant MEDIUM_VIOLET_RED($C0A0) 18 | constant PALE_VIOLET_RED($DBA4) 19 | // Orange Colors 20 | constant LIGHT_SALMON($FD1E) 21 | constant CORAL($FBD4) 22 | constant TOMATO($FB10) 23 | constant ORANGE_RED($FA00) 24 | constant DARK_ORANGE($FC40) 25 | constant ORANGE($FD00) 26 | // YELLOW Colors 27 | constant GOLD($FA80) 28 | constant YELLOW($FFC0) 29 | constant LIGHT_YELLOW($FFF8) 30 | constant LEMON_CHIFFON($FFF2) 31 | constant LIGHT_GOLDENROD_YELLOW($FFF4) 32 | constant PAPAYA_WHIP($FF74) 33 | constant MOCCASIN($FF2C) 34 | constant PEACH_PUFF($FEEE) 35 | constant PALE_GOLDENROD($EF6A) 36 | constant KHAKI($F722) 37 | constant DARK_KHAKI($BD9A) 38 | // Purple Colors 39 | constant LAVENDER($E73E) 40 | constant THISTLE($DDF6) 41 | constant PLUM($DD36) 42 | constant VIOLET($EC3A) 43 | constant ORCHID($DBB4) 44 | constant FUCHSIA($F83E) 45 | constant MAGENTA($F83E) 46 | constant MEDIUM_ORCHID($BAB4) 47 | constant BLUE_VIOLET($8978) 48 | constant DARK_VIOLET($9034) 49 | constant DARK_ORCHID($99B2) 50 | constant DARK_MAGENTA($8822) 51 | constant PURPLE($8020) 52 | constant INDIGO($4820) 53 | constant SLATE_BLUE($6AF2) 54 | constant DARK_SLATE_BLUE($49E2) 55 | // Green Colors 56 | constant GREEN_YELLOW($AFCA) 57 | constant CHARTREUSE($7FC0) 58 | constant LAWN_GREEN($7FC0) 59 | constant LIME($07C0) 60 | constant LIME_GREEN($364C) 61 | constant PALE_GREEN($9FE6) 62 | constant LIGHT_GREEN($9764) 63 | constant MEDIUM_SPRING_GREEN($07E6) 64 | constant SPRING_GREEN($07DE) 65 | constant MEDIUM_SEA_GREEN($3D9C) 66 | constant SEA_GREEN($2C54) 67 | constant FOREST_GREEN($2448) 68 | constant GREEN($0400) 69 | constant DARK_GREEN($0300) 70 | constant YELLOW_GREEN($9E4C) 71 | constant OLIVE_DRAB($6C48) 72 | constant OLIVE($8400) 73 | constant DARK_OLIVE_GREEN($534A) 74 | constant MEDIUM_AQUAMARINE($666A) 75 | constant DARK_SEA_GREEN($8DE2) 76 | constant LIGHT_SEA_GREEN($25AA) 77 | constant DARK_CYAN($0462) 78 | constant TEAL($0420) 79 | // Blue/Cyan Colors 80 | constant AQUA($00C6) 81 | constant CYAN($00C6) 82 | constant LIGHT_CYAN($E0C6) 83 | constant PALE_TURQUOISE($C842) 84 | constant AQUAMARINE($7FF4) 85 | constant TURQUOISE($4734) 86 | constant MEDIUM_TURQUOISE($4EB2) 87 | constant DARK_TURQUOISE($0674) 88 | constant CADET_BLUE($5CE8) 89 | constant STEEL_BLUE($442C) 90 | constant LIGHT_STEEL_BLUE($B636) 91 | constant POWDER_BLUE($B738) 92 | constant LIGHT_BLUE($AEF8) 93 | constant SKY_BLUE($867A) 94 | constant LIGHT_SKY_BLUE($867E) 95 | constant DEEP_SKY_BLUE($05FE) 96 | constant DODGER_BLUE($1CBE) 97 | constant CORN_FLOWER_BLUE($64BA) 98 | constant MEDIUM_SLATE_BLUE($7B7A) 99 | constant ROYAL_BLUE($4378) 100 | constant MEDIUM_BLUE($0032) 101 | constant BLUE($0032) 102 | constant DARK_BLUE($0022) 103 | constant NAVY($0020) 104 | constant MIDNIGHT_BLUE($18DC) 105 | // Brown Colors 106 | constant CORNSILK($FFF6) 107 | constant BLANCHED_ALMOND($FF72) 108 | constant BISQUE($FF30) 109 | constant NAVAJO_WHITE($FEEA) 110 | constant WHEAT($F6EC) 111 | constant BURLY_WOOD($DDE0) 112 | constant TAN($D5A2) 113 | constant ROSY_BROWN($BC62) 114 | constant SANDY_BROWN($F518) 115 | constant GOLDENROD($DD08) 116 | constant DARK_GOLDENROD($BC02) 117 | constant PERU($CC0E) 118 | constant CHOCOLATE($D346) 119 | constant SADDLE_BROWN($8A04) 120 | constant SIENNA($A28A) 121 | constant BROWN($A14A) 122 | constant MAROON($8000) 123 | 124 | // White Colors 125 | constant WHITE($FFFE) 126 | constant SNOW($FFFE) 127 | constant HONEYDEW($F7FC) 128 | constant MINT_CREAM($F7FE) 129 | constant AZURE($F7FE) 130 | constant ALICE_BLUE($F7FE) 131 | constant GHOST_WHITE($FFFE) 132 | constant WHITE_SMOKE($F7BC) // Dark Grey??? 133 | constant SEA_SHELL($FFBA) 134 | constant BEIGE($F7B6) 135 | constant OLD_LACE($FFB8) 136 | constant FLORAL_WHITE($FFFC) 137 | constant IVORY($FFFC) 138 | constant ANTIQUE_WHITE($FF74) 139 | constant LINEN($FFB8) 140 | constant LAVENDER_BLUSH($FFBC) 141 | constant MISTY_ROSE($FF38) 142 | 143 | // Gray Colors 144 | constant GAINSBORO($DEF6) 145 | constant LIGHT_GREY($D6B4) 146 | constant SILVER($C630) 147 | constant DARK_GREY($AD6A) 148 | constant GREY($8420) 149 | constant DIM_GREY($6B5A) 150 | constant LIGHT_SLATE_GREY($7466) 151 | constant SLATE_GREY($7424) 152 | constant BLACK($0001) 153 | -------------------------------------------------------------------------------- /N64/LIB/COLORS32.INC: -------------------------------------------------------------------------------- 1 | // COLOR names used from 2 | // http://etetoolkit.org/docs/2.3/reference/reference_treeview.html 3 | // Red Colors 4 | constant INDIAN_RED($CD5C5C00 ) 5 | constant LIGHT_CORAL($F0808000) 6 | constant SALMON($FA807200) 7 | constant DARK_SALMON($E9967A00) 8 | constant CRIMSON($DC143C00) 9 | constant RED($FF000000) 10 | constant FIRE_BRICK($B2222200) 11 | constant DARK_RED($8B000000) 12 | // Pink Colors 13 | constant PINK($FFC0CB00) 14 | constant LIGHT_PINK($FFB6C100) 15 | constant HOT_PINK($FF69B400) 16 | constant DEEP_PINK($FF149300) 17 | constant MEDIUM_VIOLET_RED($C7158500) 18 | constant PALE_VIOLET_RED($DB709300) 19 | // Orange Colors 20 | constant LIGHT_SALMON($FFA07A00) 21 | constant CORAL($FF7F5000) 22 | constant TOMATO($FF634700) 23 | constant ORANGE_RED($FF450000) 24 | constant DARK_ORANGE($FF8C0000) 25 | constant ORANGE($FFA50000) 26 | // YELLOW Colors 27 | constant GOLD($FF570000) 28 | constant YELLOW($FFFF0000) 29 | constant LIGHT_YELLOW($FFFFE000) 30 | constant LEMON_CHIFFON($FFFACD00) 31 | constant LIGHT_GOLDENROD_YELLOW($FAFAD200) 32 | constant PAPAYA_WHIP($FFEFD500) 33 | constant MOCCASIN($FFE4B500) 34 | constant PEACH_PUFF($FFDAB900) 35 | constant PALE_GOLDENROD($EEE8AA00) 36 | constant KHAKI($F0E68C00) 37 | constant DARK_KHAKI($BDB76B00) 38 | // Purple Colors 39 | constant LAVENDER($E6E6FA00) 40 | constant THISTLE($D8BFD800) 41 | constant PLUM($DDA0DD00) 42 | constant VIOLET($EE82EE00) 43 | constant ORCHID($DA70D600) 44 | constant FUCHSIA($FF00FF00) 45 | constant MAGENTA($FF00FF00) 46 | constant MEDIUM_ORCHID($BA55D300) 47 | constant BLUE_VIOLET($8A2BE200) 48 | constant DARK_VIOLET($9400D300) 49 | constant DARK_ORCHID($9932CC00) 50 | constant DARK_MAGENTA($8B008B00) 51 | constant PURPLE($80008000) 52 | constant INDIGO($4B008200) 53 | constant SLATE_BLUE($6A5ACD00) 54 | constant DARK_SLATE_BLUE($483D8B00) 55 | // Green Colors 56 | constant GREEN_YELLOW($ADFF2F00) 57 | constant CHARTREUSE($7FFF0000) 58 | constant LAWN_GREEN($7CFC0000) 59 | constant LIME($00FF0000) 60 | constant LIME_GREEN($32CD3200) 61 | constant PALE_GREEN($98FB9800) 62 | constant LIGHT_GREEN($90EE9000) 63 | constant MEDIUM_SPRING_GREEN($00FA9A00) 64 | constant SPRING_GREEN($00FF7F00) 65 | constant MEDIUM_SEA_GREEN($3CB37100) 66 | constant SEA_GREEN($2E8B5700) 67 | constant FOREST_GREEN($228B2200) 68 | constant GREEN($00800000) 69 | constant DARK_GREEN($00640000) 70 | constant YELLOW_GREEN($9ACD3200) 71 | constant OLIVE_DRAB($6B8E2300) 72 | constant OLIVE($80800000) 73 | constant DARK_OLIVE_GREEN($556B2F00) 74 | constant MEDIUM_AQUAMARINE($66CDAA00) 75 | constant DARK_SEA_GREEN($8FBC8F00) 76 | constant LIGHT_SEA_GREEN($20B2AA00) 77 | constant DARK_CYAN($008B8B00) 78 | constant TEAL($00808000) 79 | // Blue/Cyan Colors 80 | constant AQUA($00ffff00) 81 | constant CYAN($00ffff00) 82 | constant LIGHT_CYAN($e0ffff00) 83 | constant PALE_TURQUOISE($afeeee00) 84 | constant AQUAMARINE($7FFFD400) 85 | constant TURQUOISE($40E0D000) 86 | constant MEDIUM_TURQUOISE($48D1CC00) 87 | constant DARK_TURQUOISE($00CED100) 88 | constant CADET_BLUE($5F9EA000) 89 | constant STEEL_BLUE($4682B400) 90 | constant LIGHT_STEEL_BLUE($B0C4DE00) 91 | constant POWDER_BLUE($B0E0E600) 92 | constant LIGHT_BLUE($ADD8E600) 93 | constant SKY_BLUE($87CEEB00) 94 | constant LIGHT_SKY_BLUE($87CEFA00) 95 | constant DEEP_SKY_BLUE($00BFFF00) 96 | constant DODGER_BLUE($1E90FF00) 97 | constant CORN_FLOWER_BLUE($6495ED00) 98 | constant MEDIUM_SLATE_BLUE($7B68EE00) 99 | constant ROYAL_BLUE($4169E100) 100 | constant MEDIUM_BLUE($0000CD00) 101 | constant BLUE($0000CD00) 102 | constant DARK_BLUE($00008B00) 103 | constant NAVY($00008000) 104 | constant MIDNIGHT_BLUE($19197000) 105 | // Brown Colors 106 | constant CORNSILK($FFF8DC00) 107 | constant BLANCHED_ALMOND($FFEBCD00) 108 | constant BISQUE($FFE4C400) 109 | constant NAVAJO_WHITE($FFDEAD00) 110 | constant WHEAT($F5DEB300) 111 | constant BURLY_WOOD($DEB88700) 112 | constant TAN($D2B48C00) 113 | constant ROSY_BROWN($BC8F8F00) 114 | constant SANDY_BROWN($F4A46000) 115 | constant GOLDENROD($DAA52000) 116 | constant DARK_GOLDENROD($B8860B00) 117 | constant PERU($CD853F00) 118 | constant CHOCOLATE($D2691E00) 119 | constant SADDLE_BROWN($8B451300) 120 | constant SIENNA($A0522D00) 121 | constant BROWN($A52A2A00) 122 | constant MAROON($80000000) 123 | 124 | // White Colors 125 | constant WHITE($FFFFFF00) 126 | constant SNOW($FFFAFA00) 127 | constant HONEYDEW($F0FFF000) 128 | constant MINT_CREAM($F5FFFA00) 129 | constant AZURE($F0FFFF00) 130 | constant ALICE_BLUE($F0F8FF00) 131 | constant GHOST_WHITE($F8F8FF00) 132 | constant WHITE_SMOKE($F5F5F500) 133 | constant SEA_SHELL($FFF5EE00) 134 | constant BEIGE($F5F5DC00) 135 | constant OLD_LACE($FDF5E600) 136 | constant FLORAL_WHITE($FFFAF000) 137 | constant IVORY($FFFFF000) 138 | constant ANTIQUE_WHITE($FAEBD700) 139 | constant LINEN($FAF0E600) 140 | constant LAVENDER_BLUSH($FFF0F500) 141 | constant MISTY_ROSE($FFE4E100) 142 | 143 | // Gray Colors 144 | constant GAINSBORO($DCDCDC00) 145 | constant LIGHT_GREY($D3D3D300) 146 | constant SILVER($C0C0C000) 147 | constant DARK_GREY($A9A9A900) 148 | constant GREY($80808000) 149 | constant DIM_GREY($69696900) 150 | constant LIGHT_SLATE_GREY($77889900) 151 | constant SLATE_GREY($70809000) 152 | constant BLACK($00000000) 153 | -------------------------------------------------------------------------------- /N64/LIB/N64.INC: -------------------------------------------------------------------------------- 1 | //============= 2 | // N64 Include 3 | //============= 4 | // N64 MIPS 4300 CPU Registers 5 | constant r0(0) 6 | constant r1(1) 7 | constant r2(2) 8 | constant r3(3) 9 | constant r4(4) 10 | constant r5(5) 11 | constant r6(6) 12 | constant r7(7) 13 | constant r8(8) 14 | constant r9(9) 15 | constant r10(10) 16 | constant r11(11) 17 | constant r12(12) 18 | constant r13(13) 19 | constant r14(14) 20 | constant r15(15) 21 | constant r16(16) 22 | constant r17(17) 23 | constant r18(18) 24 | constant r19(19) 25 | constant r20(20) 26 | constant r21(21) 27 | constant r22(22) 28 | constant r23(23) 29 | constant r24(24) 30 | constant r25(25) 31 | constant r26(26) 32 | constant r27(27) 33 | constant r28(28) 34 | constant r29(29) 35 | constant r30(30) 36 | constant r31(31) 37 | 38 | constant at(1) 39 | constant v0(2) 40 | constant v1(3) 41 | constant a0(4) 42 | constant a1(5) 43 | constant a2(6) 44 | constant a3(7) 45 | constant t0(8) 46 | constant t1(9) 47 | constant t2(10) 48 | constant t3(11) 49 | constant t4(12) 50 | constant t5(13) 51 | constant t6(14) 52 | constant t7(15) 53 | constant s0(16) 54 | constant s1(17) 55 | constant s2(18) 56 | constant s3(19) 57 | constant s4(20) 58 | constant s5(21) 59 | constant s6(22) 60 | constant s7(23) 61 | constant t8(24) 62 | constant t9(25) 63 | constant k0(26) 64 | constant k1(27) 65 | constant gp(28) 66 | constant sp(29) 67 | constant s8(30) 68 | constant ra(31) 69 | 70 | // N64 MIPS 4300 CP1 Floating Point Unit (FPU) Registers (COP1) 71 | constant f0(0) 72 | constant f1(1) 73 | constant f2(2) 74 | constant f3(3) 75 | constant f4(4) 76 | constant f5(5) 77 | constant f6(6) 78 | constant f7(7) 79 | constant f8(8) 80 | constant f9(9) 81 | constant f10(10) 82 | constant f11(11) 83 | constant f12(12) 84 | constant f13(13) 85 | constant f14(14) 86 | constant f15(15) 87 | constant f16(16) 88 | constant f17(17) 89 | constant f18(18) 90 | constant f19(19) 91 | constant f20(20) 92 | constant f21(21) 93 | constant f22(22) 94 | constant f23(23) 95 | constant f24(24) 96 | constant f25(25) 97 | constant f26(26) 98 | constant f27(27) 99 | constant f28(28) 100 | constant f29(29) 101 | constant f30(30) 102 | constant f31(31) 103 | 104 | // COP0 registers: 105 | constant Index($00) 106 | constant Random($01) 107 | constant EntryLo0($02) 108 | constant EntryLo1($03) 109 | constant Context($04) 110 | constant PageMask($05) 111 | constant Wired($06) 112 | //constant *RESERVED*($07) 113 | constant BadVAddr($08) 114 | constant Count($09) 115 | constant EntryHi($0A) 116 | constant Compare($0B) 117 | constant Status($0C) 118 | constant SR($0C) 119 | constant Cause($0D) 120 | constant EPC($0E) 121 | constant PRevID($0F) 122 | constant Config($10) 123 | constant LLAddr($11) 124 | constant WatchLo($12) 125 | constant WatchHi($13) 126 | constant XContext($14) 127 | //constant *RESERVED*($15) 128 | //constant *RESERVED*($16) 129 | //constant *RESERVED*($17) 130 | //constant *RESERVED*($18) 131 | //constant *RESERVED*($19) 132 | constant PErr($1A) 133 | constant CacheErr($1B) 134 | constant TagLo($1C) 135 | constant TagHi($1D) 136 | constant ErrorEPC($1E) 137 | //constant *RESERVED*($1F) 138 | 139 | // Memory Map 140 | constant RDRAM($A000) // $00000000..$003FFFFF RDRAM Memory 4MB ($00000000..$007FFFFF 8MB With Expansion Pak) 141 | 142 | constant RDRAM_BASE($A3F0) // $03F00000..$03F00027 RDRAM Base Register 143 | constant RDRAM_DEVICE_TYPE($00) // $03F00000..$03F00003 RDRAM: Device Type Register 144 | constant RDRAM_DEVICE_ID($04) // $03F00004..$03F00007 RDRAM: Device ID Register 145 | constant RDRAM_DELAY($08) // $03F00008..$03F0000B RDRAM: Delay Register 146 | constant RDRAM_MODE($0C) // $03F0000C..$03F0000F RDRAM: Mode Register 147 | constant RDRAM_REF_INTERVAL($10) // $03F00010..$03F00013 RDRAM: Ref Interval Register 148 | constant RDRAM_REF_ROW($14) // $03F00014..$03F00017 RDRAM: Ref Row Register 149 | constant RDRAM_RAS_INTERVAL($18) // $03F00018..$03F0001B RDRAM: Ras Interval Register 150 | constant RDRAM_MIN_INTERVAL($1C) // $03F0001C..$03F0001F RDRAM: Minimum Interval Register 151 | constant RDRAM_ADDR_SELECT($20) // $03F00020..$03F00023 RDRAM: Address Select Register 152 | constant RDRAM_DEVICE_MANUF($24) // $03F00024..$03F00027 RDRAM: Device Manufacturer Register 153 | 154 | constant SP_MEM_BASE($A400) // $04000000..$04000FFF SP MEM Base Register 155 | constant SP_DMEM($0000) // $04000000..$04000FFF SP: RSP DMEM (4096 Bytes) 156 | constant SP_IMEM($1000) // $04001000..$04001FFF SP: RSP IMEM (4096 Bytes) 157 | 158 | constant SP_BASE($A404) // $04040000..$0404001F SP Base Register 159 | constant SP_MEM_ADDR($00) // $04040000..$04040003 SP: Master, SP Memory Address Register 160 | constant SP_DRAM_ADDR($04) // $04040004..$04040007 SP: Slave, SP DRAM DMA Address Register 161 | constant SP_RD_LEN($08) // $04040008..$0404000B SP: Read DMA Length Register 162 | constant SP_WR_LEN($0C) // $0404000C..$0404000F SP: Write DMA Length Register 163 | constant SP_STATUS($10) // $04040010..$04040013 SP: Status Register 164 | constant SP_DMA_FULL($14) // $04040014..$04040017 SP: DMA Full Register 165 | constant SP_DMA_BUSY($18) // $04040018..$0404001B SP: DMA Busy Register 166 | constant SP_SEMAPHORE($1C) // $0404001C..$0404001F SP: Semaphore Register 167 | 168 | constant SP_PC_BASE($A408) // $04080000..$04080007 SP PC Base Register 169 | constant SP_PC($00) // $04080000..$04080003 SP: PC Register 170 | constant SP_IBIST_REG($04) // $04080004..$04080007 SP: IMEM BIST Register 171 | 172 | constant DPC_BASE($A410) // $04100000..$0410001F DP Command (DPC) Base Register 173 | constant DPC_START($00) // $04100000..$04100003 DPC: CMD DMA Start Register 174 | constant DPC_END($04) // $04100004..$04100007 DPC: CMD DMA End Register 175 | constant DPC_CURRENT($08) // $04100008..$0410000B DPC: CMD DMA Current Register 176 | constant DPC_STATUS($0C) // $0410000C..$0410000F DPC: CMD Status Register 177 | constant DPC_CLOCK($10) // $04100010..$04100013 DPC: Clock Counter Register 178 | constant DPC_BUFBUSY($14) // $04100014..$04100017 DPC: Buffer Busy Counter Register 179 | constant DPC_PIPEBUSY($18) // $04100018..$0410001B DPC: Pipe Busy Counter Register 180 | constant DPC_TMEM($1C) // $0410001C..$0410001F DPC: TMEM Load Counter Register 181 | 182 | constant DPS_BASE($A420) // $04200000..$0420000F DP Span (DPS) Base Register 183 | constant DPS_TBIST($00) // $04200000..$04200003 DPS: Tmem Bist Register 184 | constant DPS_TEST_MODE($04) // $04200004..$04200007 DPS: Span Test Mode Register 185 | constant DPS_BUFTEST_ADDR($08) // $04200008..$0420000B DPS: Span Buffer Test Address Register 186 | constant DPS_BUFTEST_DATA($0C) // $0420000C..$0420000F DPS: Span Buffer Test Data Register 187 | 188 | constant MI_BASE($A430) // $04300000..$0430000F MIPS Interface (MI) Base Register 189 | constant MI_INIT_MODE($00) // $04300000..$04300003 MI: Init Mode Register 190 | constant MI_VERSION($04) // $04300004..$04300007 MI: Version Register 191 | constant MI_INTR($08) // $04300008..$0430000B MI: Interrupt Register 192 | constant MI_INTR_MASK($0C) // $0430000C..$0430000F MI: Interrupt Mask Register 193 | constant mi_mask_clear_all($0555) // Value to Clear/Reset all Interrupts 194 | 195 | constant VI_BASE($A440) // $04400000..$04400037 Video Interface (VI) Base Register 196 | constant VI_STATUS($00) // $04400000..$04400003 VI: Status/Control Register 197 | constant VI_ORIGIN($04) // $04400004..$04400007 VI: Origin Register 198 | constant VI_WIDTH($08) // $04400008..$0440000B VI: Width Register 199 | constant VI_V_INTR($0C) // $0440000C..$0440000F VI: Vertical Interrupt Register 200 | constant VI_V_CURRENT_LINE($10) // $04400010..$04400013 VI: Current Vertical Line Register 201 | constant VI_TIMING($14) // $04400014..$04400017 VI: Video Timing Register 202 | constant VI_V_SYNC($18) // $04400018..$0440001B VI: Vertical Sync Register 203 | constant VI_H_SYNC($1C) // $0440001C..$0440001F VI: Horizontal Sync Register 204 | constant VI_H_SYNC_LEAP($20) // $04400020..$04400023 VI: Horizontal Sync Leap Register 205 | constant VI_H_VIDEO($24) // $04400024..$04400027 VI: Horizontal Video Register 206 | constant VI_V_VIDEO($28) // $04400028..$0440002B VI: Vertical Video Register 207 | constant VI_V_BURST($2C) // $0440002C..$0440002F VI: Vertical Burst Register 208 | constant VI_X_SCALE($30) // $04400030..$04400033 VI: X-Scale Register 209 | constant VI_Y_SCALE($34) // $04400034..$04400037 VI: Y-Scale Register 210 | 211 | constant AI_BASE($A450) // $04500000..$04500017 Audio Interface (AI) Base Register 212 | constant AI_DRAM_ADDR($00) // $04500000..$04500003 AI: DRAM Address Register 213 | constant AI_LEN($04) // $04500004..$04500007 AI: Length Register 214 | constant AI_CONTROL($08) // $04500008..$0450000B AI: Control Register 215 | constant AI_STATUS($0C) // $0450000C..$0450000F AI: Status Register 216 | constant AI_DACRATE($10) // $04500010..$04500013 AI: DAC Sample Period Register 217 | constant AI_BITRATE($14) // $04500014..$04500017 AI: Bit Rate Register 218 | 219 | constant PI_BASE($A460) // $04600000..$04600033 Peripheral Interface (PI) Base Register 220 | constant PI_DRAM_ADDR($00) // $04600000..$04600003 PI: DRAM Address Register 221 | constant PI_CART_ADDR($04) // $04600004..$04600007 PI: Pbus (Cartridge) Address Register 222 | constant PI_RD_LEN($08) // $04600008..$0460000B PI: Read Length Register 223 | constant PI_WR_LEN($0C) // $0460000C..$0460000F PI: Write length register 224 | constant PI_STATUS($10) // $04600010..$04600013 PI: Status Register 225 | constant PI_BSD_DOM1_LAT($14) // $04600014..$04600017 PI: Domain 1 Latency Register 226 | constant PI_BSD_DOM1_PWD($18) // $04600018..$0460001B PI: Domain 1 Pulse Width Register 227 | constant PI_BSD_DOM1_PGS($1C) // $0460001C..$0460001F PI: Domain 1 Page Size Register 228 | constant PI_BSD_DOM1_RLS($20) // $04600020..$04600023 PI: Domain 1 Release Register 229 | constant PI_BSD_DOM2_LAT($24) // $04600024..$04600027 PI: Domain 2 Latency Register 230 | constant PI_BSD_DOM2_PWD($28) // $04600028..$0460002B PI: Domain 2 Pulse Width Register 231 | constant PI_BSD_DOM2_PGS($2C) // $0460002C..$0460002F PI: Domain 2 Page Size Register 232 | constant PI_BSD_DOM2_RLS($30) // $04600030..$04600033 PI: Domain 2 Release Register 233 | 234 | constant RI_BASE($A470) // $04700000..$0470001F RDRAM Interface (RI) Base Register 235 | constant RI_MODE($00) // $04700000..$04700003 RI: Mode Register 236 | constant RI_CONFIG($04) // $04700004..$04700007 RI: Config Register 237 | constant RI_CURRENT_LOAD($08) // $04700008..$0470000B RI: Current Load Register 238 | constant RI_SELECT($0C) // $0470000C..$0470000F RI: Select Register 239 | constant RI_REFRESH($10) // $04700010..$04700013 RI: Refresh Register 240 | constant RI_LATENCY($14) // $04700014..$04700017 RI: Latency Register 241 | constant RI_RERROR($18) // $04700018..$0470001B RI: Read Error Register 242 | constant RI_WERROR($1C) // $0470001C..$0470001F RI: Write Error Register 243 | 244 | constant SI_BASE($A480) // $04800000..$0480001B Serial Interface (SI) Base Register 245 | constant SI_DRAM_ADDR($00) // $04800000..$04800003 SI: DRAM Address Register 246 | constant SI_PIF_ADDR_RD64B($04) // $04800004..$04800007 SI: Address Read 64B Register 247 | //*RESERVED*($08) // $04800008..$0480000B SI: Reserved Register 248 | //*RESERVED*($0C) // $0480000C..$0480000F SI: Reserved Register 249 | constant SI_PIF_ADDR_WR64B($10) // $04800010..$04800013 SI: Address Write 64B Register 250 | //*RESERVED*($14) // $04800014..$04800017 SI: Reserved Register 251 | constant SI_STATUS($18) // $04800018..$0480001B SI: Status Register 252 | 253 | constant CART_DOM2_ADDR1($A500) // $05000000..$0507FFFF Cartridge Domain 2(Address 1) SRAM 254 | constant CART_DOM1_ADDR1($A600) // $06000000..$07FFFFFF Cartridge Domain 1(Address 1) 64DD 255 | constant CART_DOM2_ADDR2($A800) // $08000000..$0FFFFFFF Cartridge Domain 2(Address 2) SRAM 256 | constant CART_DOM1_ADDR2($B000) // $10000000..$18000803 Cartridge Domain 1(Address 2) ROM 257 | 258 | constant PIF_BASE($BFC0) // $1FC00000..$1FC007BF PIF Base Register 259 | constant PIF_ROM($000) // $1FC00000..$1FC007BF PIF: Boot ROM 260 | constant PIF_RAM($7C0) // $1FC007C0..$1FC007FF PIF: RAM (JoyChannel) 261 | constant PIF_HWORD($7C4) // $1FC007C4..$1FC007C5 PIF: HWORD 262 | constant PIF_XBYTE($7C6) // $1FC007C6 PIF: Analog X Byte 263 | constant PIF_YBYTE($7C7) // $1FC007C7 PIF: Analog Y Byte 264 | 265 | constant CART_DOM1_ADDR3($BFD0) // $1FD00000..$7FFFFFFF Cartridge Domain 1 (Address 3) 266 | 267 | constant EXT_SYS_AD($8000) // $80000000..$FFFFFFFF External SysAD Device 268 | 269 | constant VI_NTSC_CLOCK(48681812) // NTSC: Hz = 48.681812 MHz 270 | constant VI_PAL_CLOCK(49656530) // PAL: Hz = 49.656530 MHz 271 | constant VI_MPAL_CLOCK(48628316) // MPAL: Hz = 48.628316 MHz 272 | 273 | constant NTSC_Interlaced_HighRes_32bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 274 | constant NTSC_Interlaced_HighRes_16bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 275 | constant NTSC_Interlaced_LowRes_32bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 276 | constant NTSC_Interlaced_LowRes_16bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 277 | 278 | constant NTSC_NonInterlaced_HighRes_32bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 279 | constant NTSC_NonInterlaced_HighRes_16bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 280 | constant NTSC_NonInterlaced_LowRes_32bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 281 | constant NTSC_NonInterlaced_LowRes_16bitPixel(0b0000'0001'0000'0001'0000'0001'0000'0011) 282 | 283 | macro force_pc(size) { 284 | if (pc() > {size}) { 285 | error "Program Counter is greater than specified size" 286 | } 287 | while (pc() < {size}) { 288 | db 0 289 | } 290 | } 291 | 292 | macro fixed_gap(base, gap) { 293 | if (pc() > {base} + {gap}) { 294 | error "Gap is greater than specified size." 295 | } 296 | while (pc() < {base} + {gap}) { 297 | if {defined DEBUG_SHOW_STATIC_VALUE} { 298 | db 0xAB 299 | } else { 300 | db 0x0 301 | } 302 | } 303 | } 304 | 305 | // static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TEST") 306 | macro static_value(conditional, default, alternative) { 307 | if {defined {conditional}} { 308 | {alternative} 309 | } else { 310 | {default} 311 | } 312 | } 313 | 314 | macro align(size) { // Align Byte Amount 315 | while (pc() % {size}) { 316 | db 0 317 | } 318 | } 319 | 320 | macro N64_INIT() { // Initialise N64 (Stop N64 From Crashing 5 Seconds After Boot) 321 | lui a0,PIF_BASE // A0 = PIF Base Register ($BFC00000) 322 | lli t0,8 323 | sw t0,PIF_RAM+$3C(a0) 324 | // Stack is configured by Cartridge BootCode 325 | //addiu sp, r0, $FFF // 4K of Stack Space 326 | } 327 | 328 | macro STACK_PUSH(register) { 329 | addiu sp, sp, -4 330 | sw {register}, 0(sp) 331 | } 332 | 333 | macro STACK_POP(register) { 334 | lw {register}, 0(sp) 335 | addiu sp, sp, 4 336 | } 337 | macro STACK_ARGS_ENTRY() { 338 | } 339 | 340 | macro STACK_ENTRY() { 341 | addiu sp, sp, -56 342 | sw ra, 0(sp) 343 | sw a0, 4(sp) 344 | sw a1, 8(sp) 345 | sw a2, 12(sp) 346 | sw a3, 16(sp) 347 | sw s0, 20(sp) 348 | sw s1, 24(sp) 349 | sw s2, 28(sp) 350 | sw s3, 32(sp) 351 | sw s4, 36(sp) 352 | sw s5, 40(sp) 353 | sw s6, 44(sp) 354 | sw s7, 48(sp) 355 | sw s8, 52(sp) 356 | } 357 | 358 | macro STACK_RETURN() { 359 | sw ra, 0(sp) 360 | sw a0, 4(sp) 361 | sw a1, 8(sp) 362 | sw a2, 12(sp) 363 | sw a3, 16(sp) 364 | sw s0, 20(sp) 365 | sw s1, 24(sp) 366 | sw s2, 28(sp) 367 | sw s3, 32(sp) 368 | sw s4, 36(sp) 369 | sw s5, 40(sp) 370 | sw s6, 44(sp) 371 | sw s7, 48(sp) 372 | sw s8, 52(sp) 373 | addiu sp, sp, 56 374 | } 375 | 376 | macro DMA(start, end, dest) { // DMA Data Copy Cart->DRAM: Start Cart Address, End Cart Address, Destination DRAM Address 377 | lui a0,PI_BASE // A0 = PI Base Register ($A4600000) 378 | - 379 | lw t0,PI_STATUS(a0) // T0 = Word From PI Status Register ($A4600010) 380 | andi t0,3 // AND PI Status With 3 381 | bnez t0,- // IF TRUE DMA Is Busy 382 | nop // Delay Slot 383 | 384 | la t0,{dest}&$7FFFFF // T0 = Aligned DRAM Physical RAM Offset ($00000000..$007FFFFF 8MB) 385 | sw t0,PI_DRAM_ADDR(a0) // Store RAM Offset To PI DRAM Address Register ($A4600000) 386 | la t0,$10000000|({start}&$3FFFFFF) // T0 = Aligned Cart Physical ROM Offset ($10000000..$13FFFFFF 64MB) 387 | sw t0,PI_CART_ADDR(a0) // Store ROM Offset To PI Cart Address Register ($A4600004) 388 | la t0,({end}-{start})-1 // T0 = Length Of DMA Transfer In Bytes - 1 389 | sw t0,PI_WR_LEN(a0) // Store DMA Length To PI Write Length Register ($A460000C) 390 | } -------------------------------------------------------------------------------- /N64/LIB/N64_BOOTCODE.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/LIB/N64_BOOTCODE.BIN -------------------------------------------------------------------------------- /N64/LIB/N64_DRIVE.INC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/LIB/N64_DRIVE.INC -------------------------------------------------------------------------------- /N64/LIB/N64_DRIVE.S: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/LIB/N64_DRIVE.S -------------------------------------------------------------------------------- /N64/LIB/N64_EVER.INC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/LIB/N64_EVER.INC -------------------------------------------------------------------------------- /N64/LIB/N64_EVER.S: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/LIB/N64_EVER.S -------------------------------------------------------------------------------- /N64/LIB/N64_EXCEPTION.INC: -------------------------------------------------------------------------------- 1 | macro exception_load_handler() { 2 | jal exception_handler_init 3 | nop 4 | } -------------------------------------------------------------------------------- /N64/LIB/N64_EXCEPTION.S: -------------------------------------------------------------------------------- 1 | align(8) 2 | //B0001500 3 | //10110000000000000001010100000000 4 | //00010000000000000001010100000000 5 | // Additional code outside the Exception Handler 6 | // 7 | exception_handler_init: 8 | lui t0, PI_BASE 9 | // DMA sees DRAM starting @ 0x00000000 10 | // VR4300 sees it at 0x80000000 11 | la t1, 0x0 // libn64_tlb_exception_handler - 0x80000000 12 | sw t1, 0(t0) 13 | lui t2, 0xE000 14 | la t1, libn64_tlb_exception_handler - 0x80000000 15 | //xor t1, t1, t2 16 | sw t1, 4(t0) 17 | addiu t1, r0, $300 - 1 18 | sw t1, 0xC(t0) 19 | jr ra 20 | nop 21 | nop 22 | nop 23 | exception_handler_show: 24 | lui k1, VI_BASE 25 | lw k1, VI_ORIGIN(k1) 26 | addiu k0, $FFFF -2 27 | _loopFrameBuffer: 28 | sw r0, 0(k1) 29 | addi k1,k1,4 30 | bne k0,r0,_loopFrameBuffer 31 | addi k0, k0, -1 32 | li k0,0x3FFFFFF 33 | delay: 34 | bnel k0, r0, delay 35 | addi k0, k0, -1 36 | jr ra 37 | nop 38 | 39 | 40 | exception_handler_cart: 41 | variable old_base(base()) 42 | db "exct" 43 | align(128) 44 | libn64_tlb_exception_handler: 45 | base $80000000 46 | dmfc0 k1, Context 47 | nop 48 | lw k0, 0(k1) 49 | lw k1, 8(k1) 50 | mtc0 k0, EntryLo0 51 | mtc0 k1, EntryLo1 52 | nop 53 | tlbwr 54 | if {defined SHOW_EXCEPTIONS} { 55 | jal exception_handler_show 56 | nop 57 | } 58 | eret 59 | exception_default_step1: 60 | 61 | mtc0 ra, $30 62 | la ra, N64_SCALER 63 | sw k0, k0(ra) 64 | mfc0 k0, Cause // Get Cause 65 | sw k1, k1(ra) 66 | mfc0 k1, $30 67 | sw at, at(ra) 68 | sw k1, k1(ra) 69 | mfc0 k1, Status 70 | and k0, k0, k1 71 | j exception_default_step2 72 | nop 73 | align(128) 74 | // N64 can but does not run in User/Supervisor mode 75 | // libn64_xtlb_exception_handler: 76 | dmfc0 k1, XContext 77 | nop 78 | lw k0, 0(k1) 79 | lw k1, 8(k1) 80 | mtc0 k0, EntryLo0 81 | mtc0 k1, EntryLo1 82 | nop 83 | tlbwr 84 | if {defined SHOW_EXCEPTIONS} { 85 | jal exception_handler_show 86 | nop 87 | } 88 | eret 89 | exception_default_step2: 90 | // TODO: Code Here 91 | j exception_default_step3 92 | nop 93 | align(128) 94 | // Not Applicable 95 | //libn64_cache_exception_handler: 96 | exception_default_step3: 97 | // TODO: Code Here 98 | j exception_default_step4 99 | nop 100 | align(128) 101 | libn64_default_exception_handler: 102 | j exception_default_step1 103 | nop 104 | exception_default_step4: 105 | // TODO: Code Here 106 | 107 | if {defined SHOW_EXCEPTIONS} { 108 | jal exception_handler_show 109 | nop 110 | } 111 | eret 112 | // Get this less than 0x300 in size 113 | libn64_tlb_exception_handler_end: 114 | base old_base 115 | 116 | align(8) 117 | db "Exeption registers" 118 | libn64_exception_register_store: 119 | // Scaler Registers 120 | N64_SCALER: 121 | dd 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 122 | dd 0, 0, 0, 0, 0, 0, 0, 0 123 | dd 0, 0, 0, 0, 0, 0, 0, 0 124 | dd 0, 0, 0, 0, 0, 0, 0, 0 125 | db "End of Scaler" 126 | N64_COP0: 127 | dd 0, 0, 0, 0, 0, 0, 0, 0 128 | db "End of Ctrl" 129 | N64_COP1: // Floating Point 130 | dd 0, 0, 0, 0, 0, 0, 0, 0 131 | dd 0, 0, 0, 0, 0, 0, 0, 0 132 | dd 0, 0, 0, 0, 0, 0, 0, 0 133 | dd 0, 0, 0, 0, 0, 0, 0, 0 134 | db "End of Float" -------------------------------------------------------------------------------- /N64/LIB/N64_GDB.INC: -------------------------------------------------------------------------------- 1 | macro gdb_sync() { 2 | break 3 | } 4 | // has to be called after the Interrupt handler has been put in place 5 | // but before there are any handlers assigned. 6 | // This way it will fall through the handlers and return, 7 | // Also possible to determine if hander was executed. 8 | macro gdb_communication_test() { 9 | jal gdb_serial_test 10 | nop 11 | } -------------------------------------------------------------------------------- /N64/LIB/N64_GDB.S: -------------------------------------------------------------------------------- 1 | // COP0 Config - EP Register 2 | // COP0 Status FR bit to enable 64-bit Floating point Registers? 3 | // Might be 16 x 64 bit or 32 x 32 bit 4 | // COP0 Status DS Self Diagnostic Status Area 5 | // COP0 Status DS is 8 bits 6 | // ITS - Instruction Trace Support 7 | // BEV - TLB & General Exception Vector 8 | // TS - TLB shutd down 9 | // SR - Soft Reset Exception 10 | // CH - Condition bit of the CP0 11 | // CE - Cache Check bit use ECC register (Not used always 0) 12 | // DE - Cache Parity Error (Not used always 1) 13 | // Packet Size: 448 + Overhead = 512? 14 | // General Purpose Registers: 128 15 | // Miscellaneous Registers: 64 16 | // Floating Point Registers: 256 17 | align(4) 18 | gdb_receive_buffer: 19 | fixed_gap(gdb_receive_buffer, 0x200) 20 | 21 | gdb_transmit_buffer: 22 | fixed_gap(gdb_transmit_buffer, 0x200) 23 | 24 | // 0xFFFF'FFFF = Error 25 | // 0x0 = Untested 26 | // 0x1 = Exists 27 | gdb_serial_status: 28 | dw 0x0 29 | 30 | // Code 31 | align(8) 32 | gdb_interrupt_handler: 33 | la t0, gdb_serial_status 34 | lw t0, 0(t0) 35 | nop 36 | blez t0, _gdb_display_HUD 37 | nop 38 | bgtz t0, _gdb_serial_rxtx 39 | nop 40 | _gdb_serial_rxtx: 41 | _gdb_display_HUD: 42 | _gdb_exit: 43 | jr ra 44 | nop 45 | gdb_serial_test: 46 | // Save current TLB handler 47 | la t0, tlb_handler_ptr 48 | lw t1, 0(t0) // Save old pointer to t1 49 | // Insert our own Handler 50 | la t2, gdb_serial_tlb_handler 51 | sw t2, 0(t0) 52 | // Run our Test and Initialization 53 | // 54 | 55 | // Restore the original Handler 56 | la t0, tlb_handler_ptr 57 | sw t1, 0(t0) 58 | jr ra 59 | nop 60 | gdb_serial_tlb_handler: 61 | la k0, gdb_serial_status 62 | addi k1, r0, -1 63 | sw k1, 0(k0) 64 | jr ra 65 | nop -------------------------------------------------------------------------------- /N64/LIB/N64_INTERRUPT.INC: -------------------------------------------------------------------------------- 1 | macro interrupt_init() { 2 | jal _interrupt_init 3 | nop 4 | } 5 | 6 | macro interrupt_set_tlb(functionPointer) { 7 | la t0, tlb_handler_ptr 8 | la t1, {functionPointer} 9 | sw t1, 0(t0) 10 | } 11 | 12 | macro interrupt_set_xtlb(functionPointer) { 13 | if ({functionPointer} > 0) 14 | error "XTLB only used in 64 bit mode" 15 | } 16 | 17 | //macro interrupt_set_cache(functionPointer) { 18 | // la t0, cache_handler_ptr 19 | // la t1, {functionPointer} 20 | // sw t1, 0(t0) 21 | //} 22 | 23 | macro interrupt_set_default(functionPointer) { 24 | la t0, default_handler_ptr 25 | la t1, {functionPointer} 26 | sw t1, 0(t0) 27 | } 28 | 29 | macro interrupt_set_vblank(line, functionPointer) { 30 | lui t0,VI_BASE 31 | lli t1,{line} 32 | sw t1,VI_V_INTR(t0) 33 | 34 | la t0, vblank_handler_ptr 35 | la t1, {functionPointer} 36 | sw t1, 0(t0) 37 | jal interrupt_vi_enable 38 | nop 39 | } 40 | 41 | macro interrupt_set_syscall(functionPointer) { 42 | la t0, exc8_Sys_handler_ptr 43 | la t1, {functionPointer} 44 | sw t1, 0(t0) 45 | } 46 | 47 | macro interrupt_set_break(functionPointer) { 48 | la t0, exc9_Bp_handler_ptr 49 | la t1, {functionPointer} 50 | sw t1, 0(t0) 51 | } 52 | 53 | macro interrupt_set_watch(functionPointer) { 54 | la t0, exc23_WATCH_handler_ptr 55 | la t1, {functionPointer} 56 | sw t1, 0(t0) 57 | } 58 | 59 | macro interrupt_watch(address, read, write) { 60 | la t0, {address} 61 | li t1, {read} 62 | li t2, {write} 63 | sll t1, t1, 1 64 | and t0, t0, t1 65 | and t0, t0, t2 66 | mtc0 t0, WatchLo 67 | } 68 | 69 | // Sets all "blank" 0x00 handlers to the Debug Handler 70 | macro interrupt_set_debug(functionPointer) { 71 | la a0, {functionPointer} 72 | jal interrupt_set_debug 73 | nop 74 | } 75 | 76 | macro interrupt_set_timer(functionPointer) { 77 | la t0, int7_handler_ptr 78 | la t1, {functionPointer} 79 | sw t1, 0(t0) 80 | } 81 | 82 | macro interrupt_set_audio(functionPointer) { 83 | la t0, _interrupt_AI 84 | la t1, {functionPointer} 85 | sw t1, 0(t0) 86 | } 87 | 88 | macro interrupt_register_scalar_load() { 89 | la k1, interrupt_saved_registers_std 90 | // Save Registers 91 | lw at, at*4(k1) 92 | lw v0, v0*4(k1) 93 | lw v1, v1*4(k1) 94 | 95 | lw a0, a0*4(k1) 96 | lw a1, a1*4(k1) 97 | lw a2, a2*4(k1) 98 | lw a3, a3*4(k1) 99 | 100 | lw s0, s0*4(k1) 101 | lw s1, s1*4(k1) 102 | lw s2, s2*4(k1) 103 | lw s3, s3*4(k1) 104 | lw s4, s4*4(k1) 105 | lw s5, s5*4(k1) 106 | lw s6, s6*4(k1) 107 | lw s7, s7*4(k1) 108 | lw s8, s8*4(k1) 109 | 110 | lw gp, gp*4(k1) 111 | lw sp, sp*4(k1) 112 | 113 | lw t0, t0*4(k1) 114 | lw t1, t1*4(k1) 115 | lw t2, t2*4(k1) 116 | lw t3, t3*4(k1) 117 | lw t4, t4*4(k1) 118 | lw t5, t5*4(k1) 119 | lw t6, t6*4(k1) 120 | lw t7, t7*4(k1) 121 | lw t8, t8*4(k1) 122 | lw t9, t9*4(k1) 123 | } 124 | 125 | macro interrupt_register_scalar_store() { 126 | la k1, interrupt_saved_registers_std 127 | // Save Registers 128 | sw at, at*4(k1) 129 | sw v0, v0*4(k1) 130 | sw v1, v1*4(k1) 131 | 132 | sw a0, a0*4(k1) 133 | sw a1, a1*4(k1) 134 | sw a2, a2*4(k1) 135 | sw a3, a3*4(k1) 136 | 137 | sw s0, s0*4(k1) 138 | sw s1, s1*4(k1) 139 | sw s2, s2*4(k1) 140 | sw s3, s3*4(k1) 141 | sw s4, s4*4(k1) 142 | sw s5, s5*4(k1) 143 | sw s6, s6*4(k1) 144 | sw s7, s7*4(k1) 145 | sw s8, s8*4(k1) 146 | 147 | sw gp, gp*4(k1) 148 | sw sp, sp*4(k1) 149 | 150 | sw t0, t0*4(k1) 151 | sw t1, t1*4(k1) 152 | sw t2, t2*4(k1) 153 | sw t3, t3*4(k1) 154 | sw t4, t4*4(k1) 155 | sw t5, t5*4(k1) 156 | sw t6, t6*4(k1) 157 | sw t7, t7*4(k1) 158 | sw t8, t8*4(k1) 159 | sw t9, t9*4(k1) 160 | } 161 | 162 | macro interrupt_register_float_load() { 163 | la k1, interrupt_saved_registers_float 164 | ldc1 f0, f0*8(k1) 165 | ldc1 f1, f1*8(k1) 166 | ldc1 f2, f2*8(k1) 167 | ldc1 f3, f3*8(k1) 168 | ldc1 f4, f4*8(k1) 169 | ldc1 f5, f5*8(k1) 170 | ldc1 f6, f6*8(k1) 171 | ldc1 f7, f7*8(k1) 172 | ldc1 f8, f8*8(k1) 173 | ldc1 f9, f9*8(k1) 174 | ldc1 f10, f10*8(k1) 175 | ldc1 f11, f11*8(k1) 176 | ldc1 f12, f12*8(k1) 177 | ldc1 f13, f13*8(k1) 178 | ldc1 f14, f14*8(k1) 179 | ldc1 f15, f15*8(k1) 180 | ldc1 f16, f16*8(k1) 181 | ldc1 f17, f17*8(k1) 182 | ldc1 f18, f18*8(k1) 183 | ldc1 f19, f19*8(k1) 184 | ldc1 f20, f20*8(k1) 185 | ldc1 f21, f21*8(k1) 186 | ldc1 f22, f22*8(k1) 187 | ldc1 f23, f23*8(k1) 188 | ldc1 f24, f24*8(k1) 189 | ldc1 f25, f25*8(k1) 190 | ldc1 f26, f26*8(k1) 191 | ldc1 f27, f27*8(k1) 192 | ldc1 f28, f28*8(k1) 193 | ldc1 f29, f29*8(k1) 194 | ldc1 f30, f30*8(k1) 195 | ldc1 f31, f31*8(k1) 196 | } 197 | macro interrupt_register_float_store() { 198 | la k1, interrupt_saved_registers_float 199 | swc1 f0, f0*8(k1) 200 | swc1 f1, f1*8(k1) 201 | swc1 f2, f2*8(k1) 202 | swc1 f3, f3*8(k1) 203 | swc1 f4, f4*8(k1) 204 | swc1 f5, f5*8(k1) 205 | swc1 f6, f6*8(k1) 206 | swc1 f7, f7*8(k1) 207 | swc1 f8, f8*8(k1) 208 | swc1 f9, f9*8(k1) 209 | swc1 f10, f10*8(k1) 210 | swc1 f11, f11*8(k1) 211 | swc1 f12, f12*8(k1) 212 | swc1 f13, f13*8(k1) 213 | swc1 f14, f14*8(k1) 214 | swc1 f15, f15*8(k1) 215 | swc1 f16, f16*8(k1) 216 | swc1 f17, f17*8(k1) 217 | swc1 f18, f18*8(k1) 218 | swc1 f19, f19*8(k1) 219 | swc1 f20, f20*8(k1) 220 | swc1 f21, f21*8(k1) 221 | swc1 f22, f22*8(k1) 222 | swc1 f23, f23*8(k1) 223 | swc1 f24, f24*8(k1) 224 | swc1 f25, f25*8(k1) 225 | swc1 f26, f26*8(k1) 226 | swc1 f27, f27*8(k1) 227 | swc1 f28, f28*8(k1) 228 | swc1 f29, f29*8(k1) 229 | swc1 f30, f30*8(k1) 230 | swc1 f31, f31*8(k1) 231 | } 232 | 233 | macro interrupt_register_COP0_load() { 234 | la k1, interrupt_saved_COP0_misc 235 | lw t0, Index*4(k1) 236 | lw t1, Random*4(k1) 237 | lw t2, EntryLo0*4(k1) 238 | lw t3, EntryLo1*4(k1) 239 | lw t4, Context*4(k1) 240 | lw t5, PageMask*4(k1) 241 | lw t6, Wired*4(k1) 242 | lw t7, BadVAddr*4(k1) 243 | lw t8, Count*4(k1) 244 | lw t9, EntryHi*4(k1) 245 | mtc0 t0, Index 246 | mtc0 t1, Random 247 | mtc0 t2, EntryLo0 248 | mtc0 t3, EntryLo1 249 | mtc0 t4, Context 250 | mtc0 t5, PageMask 251 | mtc0 t6, Wired 252 | mtc0 t7, BadVAddr 253 | mtc0 t8, Count 254 | mtc0 t9, EntryHi 255 | 256 | lw t0, Compare*4(k1) 257 | lw t1, Status*4(k1) 258 | lw t2, SR*4(k1) 259 | lw t3, Cause*4(k1) 260 | lw t4, EPC*4(k1) 261 | lw t5, PRevID*4(k1) 262 | lw t6, Config*4(k1) 263 | lw t7, LLAddr*4(k1) 264 | lw t8, WatchLo*4(k1) 265 | lw t9, WatchHi*4(k1) 266 | mtc0 t0, Compare 267 | mtc0 t1, Status 268 | mtc0 t2, SR 269 | mtc0 t3, Cause 270 | mtc0 t4, EPC 271 | mtc0 t5, PRevID 272 | mtc0 t6, Config 273 | mtc0 t7, LLAddr 274 | mtc0 t8, WatchLo 275 | mtc0 t9, WatchHi 276 | 277 | // PErr is used to store the 'ra' register 278 | lw t0, XContext*4(k1) 279 | //lw t1, PErr*4(k1) 280 | lw t2, CacheErr*4(k1) 281 | lw t3, TagLo*4(k1) 282 | lw t4, TagHi*4(k1) 283 | lw t5, ErrorEPC*4(k1) 284 | mtc0 t0, XContext 285 | //mfc0 t1, PErr 286 | mtc0 t2, CacheErr 287 | mtc0 t3, TagLo 288 | mtc0 t4, TagHi 289 | mtc0 t5, ErrorEPC 290 | } 291 | 292 | macro interrupt_register_COP0_store() { 293 | la k1, interrupt_saved_COP0_misc 294 | mfc0 t0, Index 295 | mfc0 t1, Random 296 | mfc0 t2, EntryLo0 297 | mfc0 t3, EntryLo1 298 | mfc0 t4, Context 299 | mfc0 t5, PageMask 300 | mfc0 t6, Wired 301 | mfc0 t7, BadVAddr 302 | mfc0 t8, Count 303 | mfc0 t9, EntryHi 304 | sw t0, Index*4(k1) 305 | sw t1, Random*4(k1) 306 | sw t2, EntryLo0*4(k1) 307 | sw t3, EntryLo1*4(k1) 308 | sw t4, Context*4(k1) 309 | sw t5, PageMask*4(k1) 310 | sw t6, Wired*4(k1) 311 | sw t7, BadVAddr*4(k1) 312 | sw t8, Count*4(k1) 313 | sw t9, EntryHi*4(k1) 314 | 315 | mfc0 t0, Compare 316 | mfc0 t1, Status 317 | mfc0 t2, SR 318 | mfc0 t3, Cause 319 | mfc0 t4, EPC 320 | mfc0 t5, PRevID 321 | mfc0 t6, Config 322 | mfc0 t7, LLAddr 323 | mfc0 t8, WatchLo 324 | mfc0 t9, WatchHi 325 | sw t0, Compare*4(k1) 326 | sw t1, Status*4(k1) 327 | sw t2, SR*4(k1) 328 | sw t3, Cause*4(k1) 329 | sw t4, EPC*4(k1) 330 | sw t5, PRevID*4(k1) 331 | sw t6, Config*4(k1) 332 | sw t7, LLAddr*4(k1) 333 | sw t8, WatchLo*4(k1) 334 | sw t9, WatchHi*4(k1) 335 | 336 | // PErr is used to store the 'ra' register 337 | mfc0 t0, XContext 338 | //mfc0 t1, PErr 339 | mfc0 t2, CacheErr 340 | mfc0 t3, TagLo 341 | mfc0 t4, TagHi 342 | mfc0 t5, ErrorEPC 343 | sw t0, XContext*4(k1) 344 | //sw t1, PErr*4(k1) 345 | sw t2, CacheErr*4(k1) 346 | sw t3, TagLo*4(k1) 347 | sw t4, TagHi*4(k1) 348 | sw t5, ErrorEPC*4(k1) 349 | } 350 | 351 | macro interrupt_register_misc_store() { 352 | la k1, interrupt_saved_registers_misc 353 | mfhi t0 354 | mflo t1 355 | sw t0, 0(k1) 356 | sw t1, 4(k1) 357 | } 358 | 359 | macro interrupt_register_misc_load() { 360 | la k1, interrupt_saved_registers_misc 361 | lw t0, 0(k1) 362 | lw t1, 4(k1) 363 | mthi t0 364 | mtlo t1 365 | } 366 | 367 | macro interrupt_register_store() { 368 | // 'ra' saved in the Handler code itself. 369 | // sw ra, ra*4(k1) 370 | // sw k0, *4(k1) Already wiped and re-used 371 | // sw k1, *4(k1) Already wiped and re-used 372 | 373 | // Store scaler registers first because they are used 374 | // for the misc and COP0 store macros 375 | interrupt_register_scalar_store() 376 | interrupt_register_misc_store() 377 | interrupt_register_COP0_store() 378 | interrupt_register_float_store() 379 | } 380 | 381 | macro interrupt_register_load() { 382 | // misc & COP0 load's use the t0-t9 registers 383 | interrupt_register_misc_load() 384 | interrupt_register_COP0_load() 385 | // Load t0-t9 after misc & COP0 386 | interrupt_register_scalar_load() 387 | interrupt_register_float_load() 388 | } 389 | 390 | macro interrupt_activate() { 391 | jal interrupt_activate 392 | nop 393 | } 394 | 395 | macro interrupt_deactivate() { 396 | jal interrupt_deactivate 397 | nop 398 | } 399 | 400 | macro interrupt_timer_enable() { 401 | mfc0 t0, Status 402 | nop 403 | ori t0, 0x8000 404 | mtc0 t0, Status 405 | } 406 | 407 | macro interrupt_timer_disable() { 408 | mfc0 t0, Status 409 | ori t0, 1 410 | mtc0 t0, Status 411 | } 412 | 413 | macro interrupt_timer_reset() { 414 | jal interrupt_timer_reset 415 | nop 416 | } 417 | 418 | macro interrupt_sp_enable() { 419 | jal interrupt_sp_enable 420 | nop 421 | jal _interrupt_mi_manage 422 | nop 423 | } 424 | 425 | macro interrupt_sp_reset() { 426 | jal interrupt_sp_reset 427 | nop 428 | } 429 | 430 | macro interrupt_sp_disable() { 431 | jal interrupt_sp_disable 432 | nop 433 | jal _interrupt_mi_manage 434 | nop 435 | } 436 | 437 | 438 | macro interrupt_si_enable() { 439 | jal interrupt_si_enable 440 | nop 441 | jal _interrupt_mi_manage 442 | nop 443 | } 444 | 445 | macro interrupt_si_reset() { 446 | jal interrupt_si_reset 447 | nop 448 | } 449 | 450 | macro interrupt_si_disable() { 451 | jal interrupt_si_disable 452 | nop 453 | jal _interrupt_mi_manage 454 | nop 455 | } 456 | 457 | 458 | macro interrupt_ai_enable() { 459 | jal interrupt_ai_enable 460 | nop 461 | jal _interrupt_mi_manage 462 | nop 463 | } 464 | 465 | macro interrupt_ai_reset() { 466 | jal interrupt_ai_reset 467 | nop 468 | } 469 | 470 | macro interrupt_ai_disable() { 471 | jal interrupt_ai_disable 472 | nop 473 | jal _interrupt_mi_manage 474 | nop 475 | } 476 | 477 | 478 | macro interrupt_vi_enable() { 479 | jal interrupt_vi_enable 480 | nop 481 | jal _interrupt_mi_manage 482 | nop 483 | } 484 | 485 | macro interrupt_vi_reset() { 486 | jal interrupt_vi_reset 487 | nop 488 | } 489 | 490 | macro interrupt_vi_disable() { 491 | jal interrupt_vi_disable 492 | nop 493 | jal _interrupt_mi_manage 494 | nop 495 | } 496 | 497 | 498 | macro interrupt_pi_enable() { 499 | jal interrupt_pi_enable 500 | nop 501 | jal _interrupt_mi_manage 502 | nop 503 | } 504 | 505 | macro interrupt_pi_reset() { 506 | jal interrupt_pi_reset 507 | nop 508 | } 509 | 510 | macro interrupt_pi_disable() { 511 | jal interrupt_pi_disable 512 | nop 513 | jal _interrupt_mi_manage 514 | nop 515 | } 516 | 517 | 518 | macro interrupt_dp_enable() { 519 | jal interrupt_dp_enable 520 | nop 521 | jal _interrupt_mi_manage 522 | nop 523 | } 524 | 525 | macro interrupt_dp_reset() { 526 | jal interrupt_dp_reset 527 | nop 528 | } 529 | 530 | macro interrupt_dp_disable() { 531 | jal interrupt_dp_disable 532 | nop 533 | jal _interrupt_mi_manage 534 | nop 535 | } 536 | -------------------------------------------------------------------------------- /N64/LIB/N64_INTERRUPT.S: -------------------------------------------------------------------------------- 1 | constant exception_destination($80000000) 2 | align(8) 3 | _interrupt_init: 4 | la t0, _inthandler_overlay 5 | li t1, exception_destination 6 | li t2, _interrupt_handler_length 7 | addi t2, t2, 15 8 | andi t2, t2, $FFF0 9 | _interrupt_init_loop: 10 | lw t4, 0(t0) 11 | lw t5, 4(t0) 12 | lw t6, 8(t0) 13 | lw t7, 12(t0) 14 | sw t4, 0(t1) 15 | sw t5, 4(t1) 16 | sw t6, 8(t1) 17 | sw t7, 12(t1) 18 | addi t2, t2, -16 19 | addi t0, t0, 16 20 | bnel t2, r0, _interrupt_init_loop 21 | addi t1, t1, 16 22 | 23 | // V4300i Interrupt_Init 24 | mfc0 t0, Status 25 | ori t0, 0x401 26 | mtc0 t0, Status 27 | // RCP Interrupt_Init 28 | la a0, (MI_BASE << 16) | MI_INTR_MASK 29 | li a1, mi_mask_clear_all 30 | sw a1, 0(a0) 31 | 32 | jr ra 33 | nop 34 | nop 35 | 36 | align(8) 37 | interrupt_set_debug: 38 | // Set all empty Jump Table Entries to the debug handler. 39 | li t0, 52 40 | la t1,InterruptHandlers 41 | add t3, t1, t0 42 | _interrupt_set_debug_int_loop: 43 | lw t2, 0(t1) 44 | nop 45 | nop 46 | beql t2, r0, _interrupt_set_debug_int_next 47 | add t2, r0, a0 48 | sw t2, 0(t1) 49 | _interrupt_set_debug_int_next: 50 | bnel t1, t3, _interrupt_set_debug_int_loop 51 | add t1, t1, 4 52 | 53 | _interrupt_set_debug_exceptions: 54 | li t0, 64 55 | la t1,ExceptionHandlers 56 | add t3, t1, t0 57 | 58 | 59 | jr ra 60 | nop 61 | 62 | interrupt_activate: 63 | mfc0 t0, Status 64 | ori t0, 1 65 | mtc0 t0, Status 66 | jr ra 67 | nop 68 | 69 | interrupt_deactivate: 70 | mfc0 t0, Status 71 | la t1, ~1 72 | and t0, t1 73 | mtc0 t0, Status 74 | jr ra 75 | nop 76 | 77 | interrupt_timer_reset: 78 | jr ra 79 | nop 80 | 81 | _interrupt_mi_manage: 82 | // Disable all Interrupts otherwise we might "trigger" one/all. 83 | mfc0 t0, Status 84 | addi t1, r0, -2 85 | and t1, t1, t0 86 | mtc0 t1, Status 87 | // Get MI Interrupts 88 | lui t1, MI_BASE 89 | lw t1, MI_INTR_MASK(t1) 90 | // Set the MI master interrupt if any of the other Interrupts are set. 91 | beq t1, r0, _exit 92 | ori t2, t0, 0x8000 93 | // Restore Global Interrupt State 94 | mtc0 t2, Status 95 | _exit: 96 | jr ra 97 | nop 98 | 99 | interrupt_sp_enable: 100 | la a0, (MI_BASE << 16) | MI_INTR_MASK 101 | lw a1, 0(a0) 102 | nop 103 | ori a1, a1, mi_mask_set_sp 104 | sw a1, 0(a0) 105 | jr ra 106 | nop 107 | interrupt_sp_reset: 108 | la a0, (SP_BASE << 16) | SP_STATUS 109 | lw a1, 0(a0) 110 | nop 111 | ori a1, a1, sp_clear_interrupt 112 | sw a1, 0(a0) 113 | jr ra 114 | nop 115 | interrupt_sp_disable: 116 | la a0, (MI_BASE << 16) | MI_INTR_MASK 117 | lw a1, 0(a0) 118 | nop 119 | ori a1, a1, mi_mask_clear_sp 120 | sw a1, 0(a0) 121 | jr ra 122 | nop 123 | 124 | interrupt_si_enable: 125 | la a0, (MI_BASE << 16) | MI_INTR_MASK 126 | lw a1, 0(a0) 127 | nop 128 | ori a1, a1, mi_mask_set_si 129 | sw a1, 0(a0) 130 | jr ra 131 | nop 132 | interrupt_si_reset: 133 | la a0, (SI_BASE << 16) | SI_STATUS 134 | lw a1, 0(a0) 135 | nop 136 | ori a1, a1, si_clear_interrupt 137 | sw a1, 0(a0) 138 | jr ra 139 | nop 140 | interrupt_si_disable: 141 | la a0, (MI_BASE << 16) | MI_INTR_MASK 142 | lw a1, 0(a0) 143 | nop 144 | ori a1, a1, mi_mask_clear_si 145 | sw a1, 0(a0) 146 | jr ra 147 | nop 148 | 149 | interrupt_ai_enable: 150 | la a0, (MI_BASE << 16) | MI_INTR_MASK 151 | lw a1, 0(a0) 152 | nop 153 | ori a1, a1, mi_mask_set_ai 154 | sw a1, 0(a0) 155 | jr ra 156 | nop 157 | interrupt_ai_reset: 158 | la a0, (AI_BASE << 16) | AI_STATUS 159 | lw a1, 0(a0) 160 | nop 161 | ori a1, a1, ai_clear_interrupt 162 | sw a1, 0(a0) 163 | jr ra 164 | nop 165 | interrupt_ai_disable: 166 | la a0, (MI_BASE << 16) | MI_INTR_MASK 167 | lw a1, 0(a0) 168 | nop 169 | ori a1, a1, mi_mask_clear_ai 170 | sw a1, 0(a0) 171 | jr ra 172 | nop 173 | 174 | interrupt_vi_enable: 175 | beq a0, r0, _interrupt_vi_enable2 // Trashes t0 if true 176 | la t0, (VI_BASE << 16) | VI_V_INTR 177 | sw a0, 0(t0) 178 | _interrupt_vi_enable2: 179 | la a0, (MI_BASE << 16) | MI_INTR_MASK 180 | lw a1, 0(a0) 181 | nop 182 | ori a1, a1, mi_mask_set_vi 183 | sw a1, 0(a0) 184 | jr ra 185 | nop 186 | interrupt_vi_reset: 187 | la a0, (VI_BASE << 16) | VI_V_CURRENT_LINE 188 | lw a1, 0(a0) 189 | nop 190 | nop 191 | sw a1, 0(a0) // Write same value back to reset Interrupt 192 | jr ra 193 | nop 194 | interrupt_vi_disable: 195 | la a0, (MI_BASE << 16) | MI_INTR_MASK 196 | lw a1, 0(a0) 197 | nop 198 | ori a1, a1, mi_mask_clear_vi 199 | sw a1, 0(a0) 200 | jr ra 201 | nop 202 | 203 | interrupt_pi_enable: 204 | la a0, (MI_BASE << 16) | MI_INTR_MASK 205 | lw a1, 0(a0) 206 | nop 207 | ori a1, a1, mi_mask_set_pi 208 | sw a1, 0(a0) 209 | jr ra 210 | nop 211 | interrupt_pi_reset: 212 | la a0, (PI_BASE << 16) | PI_STATUS 213 | lw a1, 0(a0) 214 | nop 215 | ori a1, a1, pi_clear_interrupt 216 | sw a1, 0(a0) 217 | jr ra 218 | nop 219 | interrupt_pi_disable: 220 | la a0, (MI_BASE << 16) | MI_INTR_MASK 221 | lw a1, 0(a0) 222 | nop 223 | ori a1, a1, mi_mask_clear_pi 224 | sw a1, 0(a0) 225 | jr ra 226 | nop 227 | 228 | interrupt_dp_enable: 229 | la a0, (MI_BASE << 16) | MI_INTR_MASK 230 | lw a1, 0(a0) 231 | nop 232 | ori a1, a1, mi_mask_set_dp 233 | sw a1, 0(a0) 234 | jr ra 235 | nop 236 | interrupt_dp_reset: 237 | la a0, (MI_BASE << 16) | MI_INIT_MODE 238 | lw a1, 0(a0) 239 | nop 240 | ori a1, a1, dp_clear_interrupt 241 | sw a1, 0(a0) 242 | jr ra 243 | nop 244 | interrupt_dp_disable: 245 | la a0, (MI_BASE << 16) | MI_INTR_MASK 246 | lw a1, 0(a0) 247 | nop 248 | ori a1, a1, mi_mask_clear_dp 249 | sw a1, 0(a0) 250 | jr ra 251 | nop 252 | align(8) 253 | interrupt_saved_registers_std: 254 | // Standard 32 Registers r0 - ra 255 | dw $0, $0, $0, $0, $0, $0, $0, $0 256 | dw $0, $0, $0, $0, $0, $0, $0, $0 257 | dw $0, $0, $0, $0, $0, $0, $0, $0 258 | dw $0, $0, $0, $0, $0, $0, $0, $0 259 | // Additional Hi, Lo, 260 | interrupt_saved_registers_misc: 261 | dw $0, $0, $0, $0 262 | interrupt_saved_COP0_misc: 263 | dw $0, $0, $0, $0, $0, $0, $0, $0 264 | dw $0, $0, $0, $0, $0, $0, $0, $0 265 | dw $0, $0, $0, $0, $0, $0, $0, $0 266 | dw $0, $0, $0, $0, $0, $0, $0, $0 267 | // Floating Point Registers 268 | interrupt_saved_registers_float: 269 | dl $0, $0, $0, $0, $0, $0, $0, $0 270 | dl $0, $0, $0, $0, $0, $0, $0, $0 271 | dl $0, $0, $0, $0, $0, $0, $0, $0 272 | dl $0, $0, $0, $0, $0, $0, $0, $0 -------------------------------------------------------------------------------- /N64/LIB/N64_INTERRUPT_HANDLER.S: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | include "../LIB/N64.INC" 4 | 5 | // Every Handler can safely assume that k0, k1, ra are usable registers 6 | 7 | define DEBUG_SHOW_STATIC_VALUE(yes) 8 | align(8) 9 | _inthandler_overlay: 10 | variable pc_save(pc()) 11 | 12 | base $80000000 13 | _tlb_handler: 14 | // Merge from 32 & 64 bit versions in See MIPS Run 15 | mfc0 k0, Status 16 | ori k1, r0, 0xE2 17 | and k0, k0, k1 18 | beql k0, r0, _tlb_32 19 | dmfc0 k1, XContext 20 | _tlb_32: 21 | dmfc0 k1, Context 22 | // MAME doesnt support Context & XContext 23 | beq k1, r0, _interrupt_return_handler 24 | nop 25 | lw k0, 0(k1) 26 | lw k1, 8(k1) 27 | mtc0 k0, EntryLo0 28 | mtc0 k1, EntryLo1 29 | nop 30 | tlbwr 31 | _tlb_end: 32 | eret 33 | 34 | fixed_gap(_tlb_handler, 0x40) 35 | ExceptionHandlers: 36 | // Interrupt 37 | exc0_Int_handler_ptr: 38 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "EInt") 39 | 40 | // TLB Change Exception 41 | exc1_Mod_handler_ptr: 42 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "EMod") 43 | 44 | // TLB Refill Exception (Load/Fetch) 45 | exc2_TLBL_handler_ptr: 46 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TLBL") 47 | 48 | // TLB Refill Exception (Store) 49 | exc3_TLBS_handler_ptr: 50 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TLBS") 51 | 52 | // Address Error (Load/Fetch) 53 | exc4_AdEL_handler_ptr: 54 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "AdEL") 55 | 56 | // Address Error (Store) 57 | exc5_AdES_handler_ptr: 58 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "AdES") 59 | 60 | // Bus Error (Fetch) 61 | exc6_IBE_handler_ptr: 62 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "IBE ") 63 | 64 | // Bus Error (Load/Store) 65 | exc7_DBE_handler_ptr: 66 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "DBE ") 67 | 68 | // System Exception Call 69 | exc8_Sys_handler_ptr: 70 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Sys ") 71 | 72 | // Breakpoint Exception 73 | exc9_Bp_handler_ptr: 74 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Bp ") 75 | 76 | // Reserved Instruction Exception 77 | exc10_RI_handler_ptr: 78 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "RI ") 79 | 80 | // Coprocessor Unusable 81 | exc11_CpU_handler_ptr: 82 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "CpU ") 83 | 84 | // Operation Overflow 85 | exc12_Ov_handler_ptr: 86 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Ov ") 87 | 88 | // Trap Exception 89 | exc13_Tr_handler_ptr: 90 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Tr ") 91 | 92 | // Reserved 93 | exc14_reserved_handler_ptr: 94 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Rsrv") 95 | 96 | // Floating Point Exception 97 | exc15_FPE_handler_ptr: 98 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "FPE ") 99 | 100 | 101 | fixed_gap(_tlb_handler, 0x80) 102 | _xtlb_handler: 103 | j _tlb_handler 104 | nop 105 | default_handler_ptr: 106 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "DEF ") 107 | fixed_gap(ExceptionHandlers, 0x5C) 108 | // Watch 109 | exc23_WATCH_handler_ptr: 110 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "WATH") 111 | 112 | fixed_gap(exc23_WATCH_handler_ptr, 0x20) 113 | _interrupt_MI: 114 | _interrupt_SP: 115 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " SP ") 116 | _interrupt_SI: 117 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " SI ") 118 | _interrupt_AI: 119 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " AI ") 120 | 121 | _interrupt_VI: 122 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " VI ") 123 | _interrupt_PI: 124 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " PI ") 125 | _interrupt_DP: 126 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db " DP ") 127 | 128 | 129 | fixed_gap(_xtlb_handler, 0x80) 130 | _cache_handler: 131 | j _interrupt_return_handler 132 | nop 133 | db "LEN " 134 | dw _interrupt_END - _tlb_handler 135 | 136 | InterruptHandlers: 137 | // The interrupt index is confusing! Since INT0 == bit 2, etc. 138 | // Cause Register -> Interrupt Pending bits are the following 139 | // 7. Timer 140 | // 6. Pin Interrupt INT4 Tied to VCC in Schematic 141 | // 5. Pin Interrupt INT3 Tied to VCC in Schematic 142 | // 4. Pin Interrupt INT2 Tied to PIF in Schematic Useful 143 | // 3. Pin Interrupt INT1 Tied to VCC in Schematic 144 | // 2. Pin Interrupt INT0 Tied to RCP in Schematic Useful 145 | // 1. Software 1 Interrupt 146 | // 0. Software 0 Interrupt 147 | // Software 148 | int0_handler_ptr: 149 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INS0") 150 | 151 | // Software 152 | int1_handler_ptr: 153 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INS1") 154 | 155 | // Ext: INT0 RCP 156 | int2_handler_ptr: 157 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT0") 158 | 159 | // Ext: INT1 Pulled High in Schematic 160 | int3_handler_ptr: 161 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT1") 162 | 163 | // Ext: INT2 PIF 164 | int4_handler_ptr: 165 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT2") 166 | 167 | // Ext: INT3 Pulled High in Schematic 168 | int5_handler_ptr: 169 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT3") 170 | 171 | // Ext: INT4 Pulled High in Schematic 172 | int6_handler_ptr: 173 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT4") 174 | 175 | // Timer Interrupt 176 | int7_handler_ptr: 177 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INTT") 178 | _interrupt_continue: 179 | 180 | ori k1, k0, $0100 // Software0 Interrupt 181 | bnel k1, r0, _interrupt_custom_handler 182 | // Compiler Side effect int0_handler_ptr is only the lsb 16bits 183 | addi k0, ra, int0_handler_ptr 184 | 185 | j _interrupt_return_handler 186 | nop 187 | 188 | _interrupt_custom_handler: 189 | // Only if k0 is not ZERO 190 | beq k0, r0, _interrupt_return_handler 191 | nop 192 | lw k0, 0(k0) 193 | nop 194 | jalr k0 195 | nop 196 | _interrupt_return_handler: 197 | mfc0 k0, EPC 198 | // Restore the 'ra' register 199 | // TODO: Process Branch Delay Bit, 4 instructions 200 | mfc0 ra, PErr 201 | addiu k0, k0, 4 202 | mtc0 k0, EPC 203 | eret 204 | 205 | fixed_gap(_cache_handler, 0x80) 206 | // Interrupts & Exception Handlers 207 | // BREAK Instruction 208 | // SYSCALL Instruction 209 | _default_handler: 210 | 211 | mfc0 k0, Cause // Happened 212 | // Save ra so it can behave as expected and 213 | // we then have 2 normal registers to use (k0,k1) 214 | // PErr register is available but unused on R4300i, 215 | // its for backwards compatibility with R4000/R4200 216 | mtc0 ra, PErr 217 | 218 | // (Ab)using the 'ra' Register! 219 | lui ra, $8000 220 | 221 | // Register Values 222 | // ra = $8000'0000 ' 223 | // k0 starts with the 'Cause' register then 224 | // ends up with the function pointer address to 225 | // load from and eventually the user interrupt 226 | // handler that is called. 227 | // k1 is our 'working' register 228 | 229 | // Look for exceptions first, Zero tell us its an interrupt 230 | andi k1, k0, $007C // Exceptions 231 | beql k1, r0, _default_interrupt 232 | mfc0 k1, SR // Watching 233 | 234 | // Load k0 with indexed Exception Handler Address 235 | // Compiler Side effect ExceptionHandlers is only the lsb 16bits 236 | andi k0, ra, ExceptionHandlers 237 | j _interrupt_custom_handler 238 | add k0, k1, k0 239 | 240 | _default_interrupt: 241 | nop // wait for SR register 242 | and k0, k0, k1 // Happened & Watching = Action to take 243 | 244 | ori k1, k0, $4000 // RCP Interrupt 245 | beq k1, r0, _interrupt_VR4300i 246 | // parse MI Interrupts 247 | lui k1, MI_BASE // wasted on branch but dont care. 248 | lw k0, MI_INTR(k1) // Happened 249 | lw k1, MI_INTR_MASK(k1) // Watching 250 | and k0, k0, k1 // Happened & Watching = Action to take 251 | sll k0, k0, 2 252 | // Compiler Side effect _interrupt_MI is only the lsb 16bits 253 | ori k1, ra, _interrupt_MI 254 | j _interrupt_custom_handler 255 | add k0, k0, k1 256 | 257 | _interrupt_VR4300i: 258 | ori k1, k0, $8000 // Timer Interrupt 7 259 | bnel k1, r0, _interrupt_custom_handler 260 | // Compiler Side effect int7_handler_ptr is only the lsb 16bits 261 | addi k0, ra, int7_handler_ptr 262 | 263 | ori k1, k0, $1000 // PIF Interrupt 5 264 | bnel k1, r0, _interrupt_custom_handler 265 | // Compiler Side effect int4_handler_ptr is only the lsb 16bits 266 | addi k0, ra, int4_handler_ptr 267 | 268 | // $0800 // Pulled High in Schematic 269 | ori k1, k0, $0200 // Software1 Interrupt 270 | bnel k1, r0, _interrupt_custom_handler 271 | // Compiler Side effect int1_handler_ptr is only the lsb 16bits 272 | addi k0, ra, int1_handler_ptr 273 | 274 | j _interrupt_continue 275 | nop 276 | 277 | _interrupt_END: 278 | 279 | fixed_gap(_tlb_handler, 0x200) 280 | //base pc_save 281 | //print(pc()) 282 | //output_pc(pc()) 283 | //putchar(pc_save) 284 | //putchar(pc()) 285 | //fixed_gap(_tlb_handler, 0x240) 286 | 287 | db "LENC" 288 | _interrupt_handler_length: 289 | dw _interrupt_END - _tlb_handler 290 | db "LEND" 291 | dw _interrupt_continue - _tlb_handler 292 | db "EInt" // Interrupt 293 | dw exc0_Int_handler_ptr 294 | db "EMod" // TLB Change Exception 295 | dw exc1_Mod_handler_ptr 296 | db "TLBL" // TLB Refill Exception (Load/Fetch) 297 | dw exc2_TLBL_handler_ptr 298 | db "TLBS" // TLB Refill Exception (Store) 299 | dw exc3_TLBS_handler_ptr 300 | db "AdEL" // Address Error (Load/Fetch) 301 | dw exc4_AdEL_handler_ptr 302 | db "AdES" // Address Error (Store) 303 | dw exc5_AdES_handler_ptr 304 | db "IBE " // Bus Error (Fetch) 305 | dw exc6_IBE_handler_ptr 306 | db "DBE " // Bus Error (Load/Store) 307 | dw exc7_DBE_handler_ptr 308 | db "Sys " // System Exception Call 309 | dw exc8_Sys_handler_ptr 310 | db "Bp " // Breakpoint Exception 311 | dw exc9_Bp_handler_ptr 312 | db "RI " // Reserved Instruction Exception 313 | dw exc10_RI_handler_ptr 314 | db "CpU " // Coprocessor Unusable 315 | dw exc11_CpU_handler_ptr 316 | db "Ov " // Operation Overflow 317 | dw exc12_Ov_handler_ptr 318 | db "Tr " // Trap Exception 319 | dw exc13_Tr_handler_ptr 320 | db "Rsrv" // Reserved 321 | dw exc14_reserved_handler_ptr 322 | db "FPE " // Floating Point Exception 323 | dw exc15_FPE_handler_ptr 324 | db "WATH" // Debug Watch 325 | dw exc23_WATCH_handler_ptr 326 | db "DEF " 327 | dw default_handler_ptr 328 | db " SP " 329 | dw _interrupt_SP 330 | db " SI " 331 | dw _interrupt_SI 332 | db " AI " 333 | dw _interrupt_AI 334 | db " VI " 335 | dw _interrupt_VI 336 | db " PI " 337 | dw _interrupt_PI 338 | db " DP " 339 | dw _interrupt_DP 340 | db "INT0" // Software 341 | dw int0_handler_ptr 342 | db "INT1" // Software 343 | dw int1_handler_ptr 344 | db "INT2" // Ext: INT0 RCP 345 | dw int2_handler_ptr 346 | db "INT3" // Ext: INT1 Pulled High in Schematic 347 | dw int3_handler_ptr 348 | db "INT4" // Ext: INT2 PIF 349 | dw int4_handler_ptr 350 | db "INT5" // Ext: INT3 Pulled High in Schematic 351 | dw int5_handler_ptr 352 | db "INT6" // Ext: INT4 Pulled High in Schematic 353 | dw int6_handler_ptr 354 | db "INT7" // Timer Interrupt 355 | dw int7_handler_ptr 356 | db "END " 357 | dw _END_Interrupt_Handler 358 | _END_Interrupt_Handler: -------------------------------------------------------------------------------- /N64/LIB/N64_INTERRUPT_TEMPLATE.S: -------------------------------------------------------------------------------- 1 | // This template lays over all of the Interrupt Handlers 2 | // TLB: 0x8000'0000 3 | // XTLB: 0x8000'0080 4 | // Cache: 0xA000'0100 5 | // Default: 0x8000'0180 6 | // End: 0x8000'0200 7 | // Unless the programmer defines a handler they all 8 | // jump through to the default: 9 | // Assumption: Trash k0, k1 10 | 11 | // libdragon notes: 12 | // Checks for Exceptions $0000 00FF 13 | // Checks for Reset Interrupt $0000 1000 14 | // Checks for Timer Interrupt $0000 8000 15 | // $0000 0400 RCP Assumed Type remaining MI has details 16 | // Software Interrupts are not checked 17 | 18 | // VR4300 Programming Guide notes: 19 | // 20 | 21 | db "Inter. Block" 22 | align(8) 23 | _interrupt_handler_template: 24 | variable code_pc(pc()) 25 | base $80000000 26 | _tlb_handler: 27 | la k0, tlb_handler_ptr 28 | lw k0, 0(k0) 29 | nop 30 | beq k0, r0, _default_handler 31 | nop 32 | // Jump to custom handler 33 | jalr k0 34 | nop 35 | j _return_handler 36 | nop 37 | 38 | fixed_gap(_tlb_handler, 0x40) 39 | ExceptionHandlers: 40 | exc0_Int_handler_ptr: // Interrupt 41 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "EInt") 42 | 43 | exc1_Mod_handler_ptr: // TLB Change Exception 44 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "EMod") 45 | 46 | exc2_TLBL_handler_ptr: // TLB Refill Exception (Load/Fetch) 47 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TLBL") 48 | 49 | exc3_TLBS_handler_ptr: // TLB Refill Exception (Store) 50 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TLBS") 51 | 52 | exc4_AdEL_handler_ptr: // Address Error (Load/Fetch) 53 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "AdEL") 54 | 55 | exc5_AdES_handler_ptr: // Address Error (Store) 56 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "AdES") 57 | 58 | exc6_IBE_handler_ptr: // Bus Error (Fetch) 59 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "IBE ") 60 | 61 | exc7_DBE_handler_ptr: // Bus Error (Load/Store) 62 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "DBE ") 63 | 64 | exc8_Sys_handler_ptr: // System Exception Call 65 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Sys ") 66 | 67 | exc9_Bp_handler_ptr: // Breakpoint Exception 68 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Bp ") 69 | 70 | exc10_RI_handler_ptr: // Reserved Instruction Exception 71 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "RI ") 72 | 73 | exc11_CpU_handler_ptr: // Coprocessor Unusable 74 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "CpU ") 75 | 76 | exc12_Ov_handler_ptr: // Operation Overflow 77 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Ov ") 78 | 79 | exc13_Tr_handler_ptr: // Trap Exception 80 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Tr ") 81 | 82 | exc14_reserved_handler_ptr: // Reserved 83 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "Rv ") 84 | 85 | exc15_FPE_handler_ptr: // Floating Point Exception 86 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "FPE ") 87 | 88 | fixed_gap(_tlb_handler, 0x80) 89 | 90 | _xtlb_handler: 91 | // Only applies to 64-bit code 92 | // Just in case something gets here, send backwards 93 | j _tlb_handler 94 | nop 95 | 96 | fixed_gap(ExceptionHandlers, 0x5C) 97 | exc23_WATCH_handler_ptr: // Watch 98 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "WATH") 99 | 100 | InterruptHandlers: 101 | // Software 102 | int0_handler_ptr: 103 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT0") 104 | 105 | // Software 106 | int1_handler_ptr: 107 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT1") 108 | 109 | // Ext: INT0 RCP 110 | int2_handler_ptr: 111 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT2") 112 | 113 | // Ext: INT1 Pulled High in Schematic 114 | nt3_handler_ptr: 115 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT3") 116 | 117 | // Ext: INT2 PIF 118 | int4_handler_ptr: 119 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT4") 120 | 121 | // Ext: INT3 Pulled High in Schematic 122 | int5_handler_ptr: 123 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT5") 124 | 125 | // Ext: INT4 Pulled High in Schematic 126 | int6_handler_ptr: 127 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT6") 128 | 129 | // Timer Interrupt 130 | int7_handler_ptr: 131 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "INT7") 132 | 133 | tlb_handler_ptr: 134 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "TLBH") 135 | 136 | cache_handler_ptr: 137 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "CACH") 138 | 139 | default_handler_ptr: 140 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "DEFT") 141 | 142 | vblank_handler_ptr: 143 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "VBLK") 144 | 145 | other_int_handler_ptr: 146 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "IOTR") 147 | 148 | other_exc_handler_ptr: 149 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "EOTR") 150 | 151 | _intterupt_save_ra: 152 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "ra ") 153 | 154 | fixed_gap(_xtlb_handler, 0x80) 155 | 156 | _cache_handler: 157 | la k0, cache_handler_ptr 158 | lw k0, 0(k0) 159 | nop 160 | beq k0, r0, _default_handler 161 | nop 162 | // Jump to custom handler 163 | jalr k0 164 | nop 165 | j _return_handler 166 | nop 167 | fixed_gap(_cache_handler, 0x80) 168 | 169 | // libdragon notes: 170 | // Checks for Exceptions $0000 00FF 171 | // Checks for Reset Interrupt $0000 1000 172 | // Checks for Timer Interrupt $0000 8000 173 | // $0000 0400 RCP Assumed Type remaining MI has details 174 | // Software Interrupts are not checked 175 | 176 | _default_handler: 177 | // Free up another register 178 | lui k1, $8000 179 | sw ra, _intterupt_save_ra(k1) 180 | 181 | mfc0 k0, SR // What we are watching for 182 | // Very careful use of 'ra' register 183 | mfc0 ra, Cause // What happened 184 | and k0, ra, k0 // Happened & Watching = Action to take 185 | andi ra, k0, $00FF 186 | 187 | // Process Interrupts first 188 | // Shift Right 8 then multiply by 4 to get an address 189 | srl k0, k0, 8 190 | beq k0, r0, _exception_check // k0 before or after are fine for this branch 191 | sll k0, k0, 1 192 | 193 | la k1, InterruptHandlers 194 | j _interrupt_custom_execute 195 | add k0, k0, k1 196 | 197 | _exception_check: 198 | blez ra, _interrupt_other_exception 199 | la k0, ExceptionHandlers // Intentionally in Delay Slot, gets overwritten if wrong. 200 | j _interrupt_custom_execute 201 | add k0, k0, ra 202 | 203 | _interrupt_other_exception: 204 | // Other Exception 205 | la k0, default_handler_ptr 206 | 207 | _interrupt_custom_execute: // Test custom handler 208 | lw k0, 0(k0) 209 | nop 210 | beq k0, r0, _return_handler 211 | nop 212 | _interrupt_custom_handler: 213 | // Jump to custom handler 214 | jalr k0 215 | nop 216 | 217 | //This is the return handler 218 | // Clean up and return 219 | _return_handler: 220 | // Restore the 'ra' register 221 | lui k1, $8000 222 | lw ra, _intterupt_save_ra(k1) 223 | 224 | mfc0 k0, EPC 225 | addiu k0, k0, 4 226 | mtc0 k0, EPC 227 | eret 228 | fixed_gap(_default_handler, 0x80) 229 | base code_pc 230 | db "EndBlock" -------------------------------------------------------------------------------- /N64/LIB/N64_IPL_FONT.INC: -------------------------------------------------------------------------------- 1 | macro font_init16(forecolor, backcolor, dest) { 2 | li a0, {forecolor} 3 | li a1, {backcolor} 4 | li a2, {dest} 5 | jal fontinit16 6 | nop 7 | } 8 | 9 | macro font_init32(forecolor, backcolor, dest) { 10 | li a0, {forecolor} 11 | li a1, {backcolor} 12 | li a2, {dest} 13 | jal fontinit32 14 | nop 15 | } 16 | 17 | macro font_print_line16(fontname, framebuffer, left, top, string_address, length) { 18 | li a0, {fontname} 19 | li a1, {framebuffer} 20 | li a2, {left} 21 | li a3, {top} 22 | li v0, {string_address} 23 | li v1, {length} 24 | jal fontprintline16 25 | nop 26 | } 27 | 28 | macro font_print_line32(fontname, framebuffer, left, top, string_address, length) { 29 | li a0, {fontname} 30 | li a1, {framebuffer} 31 | li a2, {left} 32 | li a3, {top} 33 | li v0, {string_address} 34 | li v1, {length} 35 | jal fontprintline32 36 | nop 37 | } 38 | 39 | macro font_conv_hex2dec(text_hex_address, text_hex_length, text_dec_address, text_dec_length) { 40 | li a0, {text_hex_address} 41 | li a1, {text_hex_length} 42 | li a2, {text_dec_address} 43 | li a3, {text_dec_length} 44 | jal fontconvhex2dec 45 | nop 46 | } -------------------------------------------------------------------------------- /N64/LIB/N64_IPL_FONT.S: -------------------------------------------------------------------------------- 1 | align(8) 2 | nop 3 | nop 4 | nop 5 | variable zero(r0) 6 | variable forecolor(a0) 7 | variable backcolor(a1) // (0x01 = transparent) 8 | variable destination(a2) 9 | 10 | variable ipl_font(t0) 11 | variable font_cur_word(t1) 12 | variable font_bits(t2) 13 | variable font_bit_count(t3) 14 | variable font_top_bit_mask(t4) 15 | variable ipl_font_end(t5) 16 | 17 | // 50 Characters @ 23 bytes + (18 0x00 bytes) = 1168 bytes 18 | // 1168 / 4 (word size) = 292 Ignore the last 16 bytes = 288 * 4 = 1152 19 | // 32 bits expand to 16 bit color for each bit = 64 bytes 20 | // Each Font will use 18.5 KB of RAM 21 | 22 | fontinit16: 23 | la ipl_font, $B0000B70 24 | addi ipl_font_end, ipl_font, 1168 25 | li font_top_bit_mask, 0x80000000 26 | 27 | font_next_word16: 28 | lw font_cur_word, 0(ipl_font) 29 | addi font_bit_count, zero, 31 30 | 31 | font_next_bits16: 32 | and font_bits, font_cur_word, font_top_bit_mask 33 | sll font_cur_word, font_cur_word, 1 34 | bnel font_bits, zero, font_forecolor16 35 | nop 36 | sh backcolor, 0(destination) 37 | j font_continue16 38 | nop 39 | font_forecolor16: 40 | sh forecolor, 0(destination) 41 | nop 42 | font_continue16: 43 | addi destination, destination, 2 44 | bne font_bit_count, zero, font_next_bits16 45 | addi font_bit_count, font_bit_count, -1 46 | 47 | bne ipl_font, ipl_font_end, font_next_word16 48 | addi ipl_font, ipl_font, 4 49 | jr ra 50 | addiu v0, zero, 18768 51 | nop 52 | nop 53 | 54 | nop 55 | nop 56 | fontinit32: 57 | la ipl_font, $B0000B70 58 | addi ipl_font_end, ipl_font, 1168 59 | li font_top_bit_mask, 0x80000000 60 | 61 | font_next_word32: 62 | lw font_cur_word, 0(ipl_font) 63 | addi font_bit_count, zero, 31 64 | 65 | font_next_bits32: 66 | and font_bits, font_cur_word, font_top_bit_mask 67 | sll font_cur_word, font_cur_word, 1 68 | bnel font_bits, zero, font_forecolor32 69 | nop 70 | sh backcolor, 0(destination) 71 | j font_continue32 72 | nop 73 | font_forecolor32: 74 | sh forecolor, 0(destination) 75 | nop 76 | font_continue32: 77 | addi destination, destination, 4 78 | bne font_bit_count, zero, font_next_bits32 79 | addi font_bit_count, font_bit_count, -1 80 | 81 | bne ipl_font, ipl_font_end, font_next_word32 82 | addi ipl_font, ipl_font, 4 83 | jr ra 84 | addiu v0, zero, 37536 85 | nop 86 | nop 87 | 88 | nop 89 | nop 90 | nop 91 | align(8) 92 | nop 93 | nop 94 | nop 95 | fontprintline16: 96 | // Constant Values 97 | constant font_addr(a0) 98 | constant fb_addr(a1) 99 | constant fb_left(a2) 100 | constant fb_top(a3) 101 | constant fb_base(fb_top) 102 | constant text_address(v0) 103 | constant text_length(v1) 104 | constant font_char_len(t2) 105 | constant line_byte_width(t4) 106 | 107 | // Variable - i.e. change for each line/char, etc 108 | constant text_curr_idx(t5) 109 | constant text_curr_char(t0) 110 | 111 | constant font_curr_addr(t1) 112 | constant fb_curr_addr(t3) 113 | 114 | // Totally Temp, so anything goes 115 | constant tmp_reg0(t7) 116 | constant tmp_reg1(t8) 117 | constant tmp_reg2(t9) 118 | 119 | addi text_curr_idx, zero, zero 120 | // Each character is 23 original bytes, 368 in expanded font 121 | addi font_char_len, zero, 368 122 | 123 | // Get the Video Pixel Width * 2 for 16 bit color 124 | lui tmp_reg0, VI_BASE 125 | lw tmp_reg0, VI_WIDTH(tmp_reg0) 126 | sll line_byte_width, tmp_reg0, 1 // *2 127 | 128 | // Set fb_curr_addr based on values we have 129 | add fb_curr_addr, zero, fb_addr 130 | // last line is only a partial for this calc, so remove it 131 | addi tmp_reg0, fb_top, -1 132 | // Multiply Video pixel width * number of lines from the top 133 | multu line_byte_width, tmp_reg0 134 | mflo fb_top 135 | // Add Line pixels 136 | add fb_curr_addr, fb_curr_addr, fb_top 137 | // Add partial line pixels 138 | sll tmp_reg0, fb_left, 1 // *2 16 bit color 139 | add fb_base, tmp_reg0, fb_curr_addr 140 | 141 | font_next_char: 142 | beql text_length, zero, font_finished 143 | nop 144 | // Add char offset to fb_base 145 | addi tmp_reg0, zero, 26 146 | multu text_curr_idx, tmp_reg0 147 | mflo tmp_reg0 148 | add fb_curr_addr, fb_base, tmp_reg0 149 | // Get selected char 150 | lb text_curr_char, 0(text_address) 151 | // Check for ' ' (space) 152 | addi tmp_reg0, zero, 0x33 153 | beql text_curr_char, tmp_reg0, font_space 154 | nop 155 | // Position font address 156 | multu font_char_len, text_curr_char 157 | mflo font_curr_addr 158 | add font_curr_addr, font_curr_addr, font_addr 159 | addi t6, zero, 13 160 | font_line_loop: 161 | ld tmp_reg0, 0(font_curr_addr) 162 | ld tmp_reg1, 8(font_curr_addr) 163 | ld tmp_reg2, 16(font_curr_addr) 164 | 165 | sd tmp_reg0, 0(fb_curr_addr) 166 | lh tmp_reg0, 24(font_curr_addr) 167 | sd tmp_reg1, 8(fb_curr_addr) 168 | sd tmp_reg2, 16(fb_curr_addr) 169 | sh tmp_reg0, 24(fb_curr_addr) 170 | 171 | add fb_curr_addr, fb_curr_addr, line_byte_width 172 | addi font_curr_addr, font_curr_addr, 26 173 | bne t6, zero, font_line_loop 174 | addi t6, t6, -1 175 | // Loop over 14 lines 176 | 177 | font_space: 178 | // Char Complete, setup for the next 179 | addi text_address, text_address, 1 180 | addi text_curr_idx, text_curr_idx, 1 181 | bnel text_length, zero, font_next_char 182 | addi text_length, text_length, -1 183 | font_finished: 184 | jr ra 185 | nop 186 | nop 187 | nop 188 | 189 | 190 | align(8) 191 | // https://stackoverflow.com/questions/5558492/divide-by-10-using-bit-shifts 192 | divide10: 193 | variable n(a0) 194 | variable q(v0) 195 | variable r(t0) 196 | variable t(t1) 197 | srl q, n, 1 198 | srl r, n, 2 199 | add q, q, r 200 | srl r, q, 4 201 | add q, q, r 202 | srl r, q, 8 203 | add q, q, r 204 | srl r, q, 16 205 | add q, q, r 206 | srl q, q, 3 207 | sll t, q, 2 208 | add t, t, q 209 | sll t, t, 1 210 | sub r, n, t 211 | addi t, zero, 10 212 | slt t, t, r 213 | jr ra 214 | add q, q, t 215 | 216 | nop 217 | nop 218 | nop 219 | nop 220 | nop 221 | nop 222 | 223 | align(8) 224 | fontconvhex2dec: 225 | variable text_hex_address(a0) 226 | variable text_hex_length(a1) 227 | variable text_dec_address(a2) 228 | variable text_dec_length(a3) 229 | // based on length load the value into a register (upto 64-bit values supported) 230 | // only populated the provided decimal length starting from the right LSB 231 | //jal divide10 232 | //addi a0, zero, -1 233 | // v0 = 0x19999999 234 | 235 | jr ra 236 | nop 237 | nop 238 | nop -------------------------------------------------------------------------------- /N64/LIB/N64_RSP.INC: -------------------------------------------------------------------------------- 1 | //============================== 2 | // N64 Reality Signal Processor 3 | //============================== 4 | // RSP MIPS 4000 CPU Registers R0..R31 5 | // RSP CP2 128-Bit Vector Registers: V0..V31 6 | // RSP CP2 Vector Elements (128-Bit Vector = 16 Elements): E0..E15 7 | 8 | // RSP CP0 Control Registers (MTF0/MTC0): 9 | constant c0(0) // RSP CP0 Control Register 00: I/DMEM Address For DMA (RW) ($04040000) 10 | constant c1(1) // RSP CP0 Control Register 01: DRAM Address For DMA (RW) ($04040004) 11 | constant c2(2) // RSP CP0 Control Register 02: DMA READ Length (DRAM -> I/DMEM) (RW) ($04040008) 12 | constant c3(3) // RSP CP0 Control Register 03: DMA WRITE Length (DRAM <- I/DMEM) (RW) ($0404000C) 13 | constant c4(4) // RSP CP0 Control Register 04: RSP Status (RW) ($04040010) 14 | constant c5(5) // RSP CP0 Control Register 05: DMA Full (R) ($04040014) 15 | constant c6(6) // RSP CP0 Control Register 06: DMA Busy (R) ($04040018) 16 | constant c7(7) // RSP CP0 Control Register 07: CPU-RSP Semaphore (RW) ($0404001C) 17 | constant c8(8) // RSP CP0 Control Register 08: RDP Command Buffer START (RW) ($04100000) 18 | constant c9(9) // RSP CP0 Control Register 09: RDP Command Buffer END (RW) ($04100004) 19 | constant c10(10) // RSP CP0 Control Register 10: RDP Command Buffer CURRENT (R) ($04100008) 20 | constant c11(11) // RSP CP0 Control Register 11: RDP Status (RW) ($0410000C) 21 | constant c12(12) // RSP CP0 Control Register 12: RDP Clock Counter (R) ($04100010) 22 | constant c13(13) // RSP CP0 Control Register 13: RDP Command Buffer BUSY (R) ($04100014) 23 | constant c14(14) // RSP CP0 Control Register 14: RDP Pipe BUSY (R) ($04100018) 24 | constant c15(15) // RSP CP0 Control Register 15: RDP TMEM BUSY (R) ($0410001C) 25 | 26 | // RSP CP2 Control Registers (CFC2/CTC2): 27 | constant vco(0) // RSP CP2 Control Register 0: Vector Carry Out 28 | constant vcc(1) // RSP CP2 Control Register 1: Vector Compare Code 29 | constant vce(2) // RSP CP2 Control Register 2: Vector Compare Extension 30 | 31 | // RSP Status Read Flags: 32 | constant RSP_HLT($0001) // SP_STATUS: Halt (Bit 0) 33 | constant RSP_BRK($0002) // SP_STATUS: Break (Bit 1) 34 | constant RSP_BSY($0004) // SP_STATUS: DMA Busy (Bit 2) 35 | constant RSP_FUL($0008) // SP_STATUS: DMA Full (Bit 3) 36 | constant RSP_IOF($0010) // SP_STATUS: IO Full (Bit 4) 37 | constant RSP_STP($0020) // SP_STATUS: Single Step (Bit 5) 38 | constant RSP_IOB($0040) // SP_STATUS: Interrupt On Break (Bit 6) 39 | constant RSP_SG0($0080) // SP_STATUS: Signal 0 Set (Bit 7) 40 | constant RSP_SG1($0100) // SP_STATUS: Signal 1 Set (Bit 8) 41 | constant RSP_SG2($0200) // SP_STATUS: Signal 2 Set (Bit 9) 42 | constant RSP_SG3($0400) // SP_STATUS: Signal 3 Set (Bit 10) 43 | constant RSP_SG4($0800) // SP_STATUS: Signal 4 Set (Bit 11) 44 | constant RSP_SG5($1000) // SP_STATUS: Signal 5 Set (Bit 12) 45 | constant RSP_SG6($2000) // SP_STATUS: Signal 6 Set (Bit 13) 46 | constant RSP_SG7($4000) // SP_STATUS: Signal 7 Set (Bit 14) 47 | 48 | // RSP Status Write Flags: 49 | constant CLR_HLT($0000001) // SP_STATUS: Clear Halt (Bit 0) 50 | constant SET_HLT($0000002) // SP_STATUS: Set Halt (Bit 1) 51 | constant CLR_BRK($0000004) // SP_STATUS: Clear Broke (Bit 2) 52 | constant CLR_INT($0000008) // SP_STATUS: Clear Interrupt (Bit 3) 53 | constant SET_INT($0000010) // SP_STATUS: Set Interrupt (Bit 4) 54 | constant CLR_STP($0000020) // SP_STATUS: Clear Single Step (Bit 5) 55 | constant SET_STP($0000040) // SP_STATUS: Set Single Step (Bit 6) 56 | constant CLR_IOB($0000080) // SP_STATUS: Clear Interrupt On Break (Bit 7) 57 | constant SET_IOB($0000100) // SP_STATUS: Set Interrupt On Break (Bit 8) 58 | constant CLR_SG0($0000200) // SP_STATUS: Clear Signal 0 (Bit 9) 59 | constant SET_SG0($0000400) // SP_STATUS: Set Signal 0 (Bit 10) 60 | constant CLR_SG1($0000800) // SP_STATUS: Clear Signal 1 (Bit 11) 61 | constant SET_SG1($0001000) // SP_STATUS: Set Signal 1 (Bit 12) 62 | constant CLR_SG2($0002000) // SP_STATUS: Clear Signal 2 (Bit 13) 63 | constant SET_SG2($0004000) // SP_STATUS: Set Signal 2 (Bit 14) 64 | constant CLR_SG3($0008000) // SP_STATUS: Clear Signal 3 (Bit 15) 65 | constant SET_SG3($0010000) // SP_STATUS: Set Signal 3 (Bit 16) 66 | constant CLR_SG4($0020000) // SP_STATUS: Clear Signal 4 (Bit 17) 67 | constant SET_SG4($0040000) // SP_STATUS: Set Signal 4 (Bit 18) 68 | constant CLR_SG5($0080000) // SP_STATUS: Clear Signal 5 (Bit 19) 69 | constant SET_SG5($0100000) // SP_STATUS: Set Signal 5 (Bit 20) 70 | constant CLR_SG6($0200000) // SP_STATUS: Clear Signal 6 (Bit 21) 71 | constant SET_SG6($0400000) // SP_STATUS: Set Signal 6 (Bit 22) 72 | constant CLR_SG7($0800000) // SP_STATUS: Clear Signal 7 (Bit 23) 73 | constant SET_SG7($1000000) // SP_STATUS: Set Signal 7 (Bit 24) 74 | 75 | // RDP Status Read Flags: 76 | constant RDP_XBS($0001) // DPC_STATUS: Use XBUS DMEM DMA Or DRAM DMA (Bit 0) 77 | constant RDP_FRZ($0002) // DPC_STATUS: RDP Frozen (Bit 1) 78 | constant RDP_FLS($0004) // DPC_STATUS: RDP Flushed (Bit 2) 79 | constant RDP_GCL($0008) // DPC_STATUS: GCLK Alive (Bit 3) 80 | constant RDP_TMB($0010) // DPC_STATUS: TMEM Busy (Bit 4) 81 | constant RDP_PLB($0020) // DPC_STATUS: RDP PIPELINE Busy (Bit 5) 82 | constant RDP_CMB($0040) // DPC_STATUS: RDP COMMAND Unit Busy (Bit 6) 83 | constant RDP_CMR($0080) // DPC_STATUS: RDP COMMAND Buffer Ready (Bit 7) 84 | constant RDP_DMA($0100) // DPC_STATUS: RDP DMA Busy (Bit 8) 85 | constant RDP_CME($0200) // DPC_STATUS: RDP COMMAND END Register Valid (Bit 9) 86 | constant RDP_CMS($0400) // DPC_STATUS: RDP COMMAND START Register Valid (Bit 10) 87 | 88 | // RDP Status Write Flags: 89 | constant CLR_XBS($001) // DPC_STATUS: Clear XBUS DMEM DMA (Bit 0) 90 | constant SET_XBS($002) // DPC_STATUS: Set XBUS DMEM DMA (Bit 1) 91 | constant CLR_FRZ($004) // DPC_STATUS: Clear FREEZE (Bit 2) 92 | constant SET_FRZ($008) // DPC_STATUS: Set FREEZE (Bit 3) 93 | constant CLR_FLS($010) // DPC_STATUS: Clear FLUSH (Bit 4) 94 | constant SET_FLS($020) // DPC_STATUS: Set FLUSH (Bit 5) 95 | constant CLR_TMC($040) // DPC_STATUS: Clear TMEM COUNTER (Bit 6) 96 | constant CLR_PLC($080) // DPC_STATUS: Clear PIPELINE COUNTER (Bit 7) 97 | constant CLR_CMC($100) // DPC_STATUS: Clear COMMAND COUNTER (Bit 8) 98 | constant CLR_CLK($200) // DPC_STATUS: Clear CLOCK COUNTER (Bit 9) 99 | 100 | // CPU DMA 101 | macro DMASPRD(start, end, dest) { // DMA Data Read DRAM->RSP MEM: Start Address, End Address, Destination RSP MEM Address 102 | lui a0,SP_BASE // A0 = SP Base Register ($A4040000) 103 | lui t0,SP_MEM_BASE // T0 = SP Memory Base Register ($A4000000) 104 | ori t0,{dest}&$1FFF // T0 = SP Memory Address Offset ($A4000000..$A4001FFF 8KB) 105 | sw t0,SP_MEM_ADDR(a0) // Store Memory Offset To SP Memory Address Register ($A4040000) 106 | la t0,{start}&$7FFFFFF // T0 = Aligned DRAM Physical RAM Offset ($00000000..$007FFFFF 8MB) 107 | sw t0,SP_DRAM_ADDR(a0) // Store RAM Offset To SP DRAM Address Register ($A4040004) 108 | la t0,({end}-{start})-1 // T0 = Length Of DMA Transfer In Bytes - 1 109 | sw t0,SP_RD_LEN(a0) // Store DMA Length To SP Read Length Register ($A4040008) 110 | } 111 | 112 | macro DMASPWR(start, end, source) { // DMA Data Write RSP MEM->DRAM: Start Address, End Address, Source RSP MEM Address 113 | lui a0,SP_BASE ; A0 = SP Base Register ($A4040000) 114 | lui t0,SP_MEM_BASE ; T0 = SP Memory Base Register ($A4000000) 115 | ori t0,{source}&$1FFF ; T0 = SP Memory Address Offset ($A4000000..$A4001FFF 8KB) 116 | sw t0,SP_MEM_ADDR(a0) ; Store Memory Offset To SP Memory Address Register ($A4040000) 117 | la t0,{start}&$7FFFFFF ; T0 = Aligned DRAM Physical RAM Offset ($00000000..$007FFFFF 8MB) 118 | sw t0,SP_DRAM_ADDR(a0) ; Store RAM Offset To SP DRAM Address Register ($A4040004) 119 | la t0,({end}-{start})-1 ; T0 = Length Of DMA Transfer In Bytes - 1 120 | sw t0,SP_WR_LEN(a0) ; Store DMA Length To SP Write Length Register ($A404000C) 121 | } 122 | 123 | // RSP DMA 124 | macro RSPDMASPRD(start, end, dest) { // DMA Data Read DRAM->RSP MEM: Start Address, End Address, Destination RSP MEM Address 125 | li a0,{dest}&$1FFF // A0 = SP Memory Address Offset ($A4000000..$A4001FFF 8KB) 126 | mtc0 a0,c0 // Store Memory Offset To SP Memory Address Register ($A4040000) 127 | la a0,{start}&$7FFFFFF // A0 = Aligned DRAM Physical RAM Offset ($00000000..$007FFFFF 8MB) 128 | mtc0 a0,c1 // Store RAM Offset To SP DRAM Address Register ($A4040004) 129 | la a0,({end}-{start})-1 // A0 = Length Of DMA Transfer In Bytes - 1 130 | mtc0 a0,c2 // Store DMA Length To SP Read Length Register ($A4040008) 131 | } 132 | 133 | macro RSPDMASPWR(start, end, source) { // DMA Data Write RSP MEM->DRAM: Start Address, End Address, Source RSP MEM Address 134 | li a0,{source}&$1FFF // A0 = SP Memory Address Offset ($A4000000..$A4001FFF 8KB) 135 | mtc0 a0,c0 // Store Memory Offset To SP Memory Address Register ($A4040000) 136 | la a0,{start}&$7FFFFFF // A0 = Aligned DRAM Physical RAM Offset ($00000000..$007FFFFF 8MB) 137 | mtc0 a0,c1 // Store RAM Offset To SP DRAM Address Register ($A4040004) 138 | la a0,({end}-{start})-1 // A0 = Length Of DMA Transfer In Bytes - 1 139 | mtc0 a0,c3 // Store DMA Length To SP Write Length Register ($A404000C) 140 | } 141 | 142 | macro RSPDPC(start, end) { // Run DPC Command Buffer: Start Address, End Address 143 | la a0,{start} // A0 = DPC Command Start Address 144 | mtc0 a0,c8 // Store DPC Command Start Address To DP Start Register ($A4100000) 145 | addi a0,{end}-{start} // A0 = DPC Command End Address 146 | mtc0 a0,c9 // Store DPC Command End Address To DP End Register ($A4100004) 147 | } 148 | 149 | // RSP CP2 Vector Operation Instructions (COP2): 150 | // vmulf vd, vs, vt[e] ; Vector Multiply Signed Fractions: VMULF VD,VS,VT[ELEMENT] 151 | // vmulu vd, vs, vt[e] ; Vector Multiply Unsigned Fractions: VMULU VD,VS,VT[ELEMENT] 152 | // vrndp vd, vs, vt[e] ; Vector DCT Round Positive: VRNDP VD,VS,VT[ELEMENT] (Reserved: MPEG DCT Rounding) 153 | // vmulq vd, vs, vt[e] ; Vector Multiply Integer: VMULQ VD,VS,VT[ELEMENT] (Reserved: MPEG Inverse Quantization) 154 | // vmudl vd, vs, vt[e] ; Vector Multiply Low Partial Products: VMUDL VD,VS,VT[ELEMENT] 155 | // vmudm vd, vs, vt[e] ; Vector Multiply Mid Partial Products: VMUDM VD,VS,VT[ELEMENT] 156 | // vmudn vd, vs, vt[e] ; Vector Multiply Mid Partial Products: VMUDN VD,VS,VT[ELEMENT] 157 | // vmudh vd, vs, vt[e] ; Vector Multiply High Partial Products: VMUDH VD,VS,VT[ELEMENT] 158 | // vmacf vd, vs, vt[e] ; Vector Multiply Accumulate Signed Fractions: VMACF VD,VS,VT[ELEMENT] 159 | // vmacu vd, vs, vt[e] ; Vector Multiply Accumulate Unsigned Fractions: VMACU VD,VS,VT[ELEMENT] 160 | // vrndn vd, vs, vt[e] ; Vector DCT Round Negative: VRNDN VD,VS,VT[ELEMENT] (Reserved: MPEG DCT Rounding) 161 | // vmacq vd, vs, vt[e] ; Vector Multiply Accumulate Integer: VMACQ VD,VS,VT[ELEMENT] (Reserved: MPEG Inverse Quantization) 162 | // vmadl vd, vs, vt[e] ; Vector Multiply Accumulate Low Partial Products: VMADL VD,VS,VT[ELEMENT] 163 | // vmadm vd, vs, vt[e] ; Vector Multiply Accumulate Mid Partial Products: VMADM VD,VS,VT[ELEMENT] 164 | // vmadn vd, vs, vt[e] ; Vector Multiply Accumulate Mid Partial Products: VMADN VD,VS,VT[ELEMENT] 165 | // vmadh vd, vs, vt[e] ; Vector Multiply Accumulate High Partial Products: VMADH VD,VS,VT[ELEMENT] 166 | // vadd vd, vs, vt[e] ; Vector Add Short Elements: VADD VD,VS,VT[ELEMENT] 167 | // vsub vd, vs, vt[e] ; Vector Subtract Short Elements: VSUB VD,VS,VT[ELEMENT] 168 | // vsut vd, vs, vt[e] ; Vector Subtract Short Elements (VT-VS): VSUT VD,VS,VT[ELEMENT] (Reserved) 169 | // vabs vd, vs, vt[e] ; Vector Absolute Value Of Short Elements: VABS VD,VS,VT[ELEMENT] 170 | // vaddc vd, vs, vt[e] ; Vector Add Short Elements With Carry: VADDC VD,VS,VT[ELEMENT] 171 | // vsubc vd, vs, vt[e] ; Vector Subtract Short Elements With Carry: VSUBC VD,VS,VT[ELEMENT] 172 | // vaddb vd, vs, vt[e] ; Vector Add Byte Elements: VADDB VD,VS,VT[ELEMENT] (Reserved) 173 | // vsubb vd, vs, vt[e] ; Vector Subtract Byte Elements: VSUBB VD,VS,VT[ELEMENT] (Reserved) 174 | // vaccb vd, vs, vt[e] ; Vector Add Byte Elements With Carry: VACCB VD,VS,VT[ELEMENT] (Reserved) 175 | // vsucb vd, vs, vt[e] ; Vector Subtract Byte Elements With Carry: VSUCB VD,VS,VT[ELEMENT] (Reserved) 176 | // vsad vd, vs, vt[e] ; Vector SAD: VSAD VD,VS,VT[ELEMENT] (Reserved) 177 | // vsac vd, vs, vt[e] ; Vector SAC: VSAC VD,VS,VT[ELEMENT] (Reserved) 178 | // vsum vd, vs, vt[e] ; Vector SUM: VSUM VD,VS,VT[ELEMENT] (Reserved) 179 | // vsar vd, vs, vt[e] ; Vector Accumulator Read: VSAR VD,VS,VT[ELEMENT] 180 | // vacc vd, vs, vt[e] ; Vector Add Elements With Carry: VACC VD,VS,VT[ELEMENT] (Reserved) 181 | // vsuc vd, vs, vt[e] ; Vector Subtract Elements With Carry: VSUC VD,VS,VT[ELEMENT] (Reserved) 182 | // vlt vd, vs, vt[e] ; Vector Select Less Than: VLT VD,VS,VT[ELEMENT] 183 | // veq vd, vs, vt[e] ; Vector Select Equal: VEQ VD,VS,VT[ELEMENT] 184 | // vne vd, vs, vt[e] ; Vector Select Not Equal: VNE VD,VS,VT[ELEMENT] 185 | // vge vd, vs, vt[e] ; Vector Select Greater Than Or Equal: VGE VD,VS,VT[ELEMENT] 186 | // vcl vd, vs, vt[e] ; Vector Select Clip Test Low: VCL VD,VS,VT[ELEMENT] 187 | // vch vd, vs, vt[e] ; Vector Select Clip Test High: VCH VD,VS,VT[ELEMENT] 188 | // vcr vd, vs, vt[e] ; Vector Select Crimp Test Low: VCR VD,VS,VT[ELEMENT] 189 | // vmrg vd, vs, vt[e] ; Vector Select Merge: VMRG VD,VS,VT[ELEMENT] 190 | // vand vd, vs, vt[e] ; Vector Logical AND Short Elements: VAND VD,VS,VT[ELEMENT] 191 | // vnand vd, vs, vt[e] ; Vector Logical NOT AND Short Elements: VNAND VD,VS,VT[ELEMENT] 192 | // vor vd, vs, vt[e] ; Vector Logical OR Short Elements: VOR VD,VS,VT[ELEMENT] 193 | // vnor vd, vs, vt[e] ; Vector Logical NOT OR Short Elements: VNOR VD,VS,VT[ELEMENT] 194 | // vxor vd, vs, vt[e] ; Vector Logical Exclusive OR Short Elements: VXOR VD,VS,VT[ELEMENT] 195 | // vnxor vd, vs, vt[e] ; Vector Logical NOT Exclusive OR Short Elements: VNXOR VD,VS,VT[ELEMENT] 196 | // v056 vd, vs, vt[e] ; Vector Row 5 Column 6: V056 VD,VS,VT[ELEMENT] (Reserved) 197 | // v057 vd, vs, vt[e] ; Vector Row 5 Column 7: V057 VD,VS,VT[ELEMENT] (Reserved) 198 | 199 | // vrcp vd[de], vt[e] ; Vector Element Scalar Reciprocal (Single Precision): VRCP VD[ELEMENT],VT[ELEMENT] 200 | // vrcpl vd[de], vt[e] ; Vector Element Scalar Reciprocal Low: VRCPL VD[ELEMENT],VT[ELEMENT] 201 | // vrcph vd[de], vt[e] ; Vector Element Scalar Reciprocal High: VRCPH VD[ELEMENT],VT[ELEMENT] 202 | // vmov vd[de], vt[e] ; Vector Element Scalar Move: VMOV VD[ELEMENT],VT[ELEMENT] 203 | // vrsq vd[de], vt[e] ; Vector Element Scalar SQRT Reciprocal (Single Precision): VRSQ VD[ELEMENT],VT[ELEMENT] 204 | // vrsql vd[de], vt[e] ; Vector Element Scalar SQRT Reciprocal Low: VRSQL VD[ELEMENT],VT[ELEMENT] 205 | // vrsqh vd[de], vt[e] ; Vector Element Scalar SQRT Reciprocal High: VRSQH VD[ELEMENT],VT[ELEMENT] 206 | 207 | // vnop ; Vector Null Instruction: VNOP 208 | 209 | // vextt vd, vs, vt[e] ; Vector Extract Triple (5/5/5/1): VEXTT VD,VS,VT[ELEMENT] (Reserved) 210 | // vextq vd, vs, vt[e] ; Vector Extract Quad (4/4/4/4): VEXTQ VD,VS,VT[ELEMENT] (Reserved) 211 | // vextn vd, vs, vt[e] ; Vector Extract Nibble (4/4/4/4) (Sign Extended): VEXTN VD,VS,VT[ELEMENT] (Reserved) 212 | // v073 vd, vs, vt[e] ; Vector Row 7 Column 3: V073 VD,VS,VT[ELEMENT] (Reserved) 213 | // vinst vd, vs, vt[e] ; Vector Insert Triple (5/5/5/1): VINST VD,VS,VT[ELEMENT] (Reserved) 214 | // vinsq vd, vs, vt[e] ; Vector Insert Quad (4/4/4/4): VINSQ VD,VS,VT[ELEMENT] (Reserved) 215 | // vinsn vd, vs, vt[e] ; Vector Insert Nibble (4/4/4/4) (Sign Extended): VINSN VD,VS,VT[ELEMENT] (Reserved) 216 | 217 | // vnull ; Vector Null Instruction: VNULL (Reserved) 218 | 219 | // RSP CP2 Vector Load Instructions (LWC2): 220 | // lbv vt[e], offset(base) ; Load Byte To Vector: LBV VT[ELEMENT],$OFFSET(BASE) 221 | // lsv vt[e], offset(base) ; Load Short To Vector: LSV VT[ELEMENT],$OFFSET(BASE) 222 | // llv vt[e], offset(base) ; Load Long To Vector: LLV VT[ELEMENT],$OFFSET(BASE) 223 | // ldv vt[e], offset(base) ; Load Double To Vector: LDV VT[ELEMENT],$OFFSET(BASE) 224 | // lqv vt[e], offset(base) ; Load Quad To Vector: LQV VT[ELEMENT],$OFFSET(BASE) 225 | // lrv vt[e], offset(base) ; Load Rest To Vector: LRV VT[ELEMENT],$OFFSET(BASE) 226 | // lpv vt[e], offset(base) ; Load Packed Signed To Vector: LPV VT[ELEMENT],$OFFSET(BASE) 227 | // luv vt[e], offset(base) ; Load Packed Unsigned To Vector: LUV VT[ELEMENT],$OFFSET(BASE) 228 | // lhv vt[e], offset(base) ; Load Half Bytes To Vector: LHV VT[ELEMENT],$OFFSET(BASE) 229 | // lfv vt[e], offset(base) ; Load Fourth Bytes To Vector: LFV VT[ELEMENT],$OFFSET(BASE) 230 | // lwv vt[e], offset(base) ; Load Transposed Wrapped Bytes To Vector: LWV VT[ELEMENT],$OFFSET(BASE) (Reserved) 231 | // ltv vt[e], offset(base) ; Load Transposed Bytes To Vector: LTV VT[ELEMENT],$OFFSET(BASE) 232 | 233 | // RSP CP2 Vector Store Instructions (SWC2): 234 | // sbv vt[e], offset(base) ; Store Byte From Vector: SBV VT[ELEMENT],$OFFSET(BASE) 235 | // ssv vt[e], offset(base) ; Store Short From Vector: SSV VT[ELEMENT],$OFFSET(BASE) 236 | // slv vt[e], offset(base) ; Store Long From Vector: SLV VT[ELEMENT],$OFFSET(BASE) 237 | // sdv vt[e], offset(base) ; Store Double From Vector: SDV VT[ELEMENT],$OFFSET(BASE) 238 | // sqv vt[e], offset(base) ; Store Quad From Vector: SQV VT[ELEMENT],$OFFSET(BASE) 239 | // srv vt[e], offset(base) ; Store Rest From Vector: SRV VT[ELEMENT],$OFFSET(BASE) 240 | // spv vt[e], offset(base) ; Store Packed Signed From Vector: SPV VT[ELEMENT],$OFFSET(BASE) 241 | // suv vt[e], offset(base) ; Store Packed Unsigned From Vector: SUV VT[ELEMENT],$OFFSET(BASE) 242 | // shv vt[e], offset(base) ; Store Half Bytes From Vector: SHV VT[ELEMENT],$OFFSET(BASE) 243 | // sfv vt[e], offset(base) ; Store Fourth Bytes From Vector: SFV VT[ELEMENT],$OFFSET(BASE) 244 | // swv vt[e], offset(base) ; Store Transposed Wrapped Bytes From Vector: SWV VT[ELEMENT],$OFFSET(BASE) 245 | // stv vt[e], offset(base) ; Store Transposed Bytes From Vector: STV VT[ELEMENT],$OFFSET(BASE) -------------------------------------------------------------------------------- /N64/LIB/N64_SYS.INC: -------------------------------------------------------------------------------- 1 | macro sys_get_clock() { 2 | jal sys_get_clock 3 | nop 4 | } 5 | 6 | macro sys_random(min, max) { 7 | li a0, {min} 8 | li a1, {max} 9 | jal sys_random 10 | nop 11 | } 12 | 13 | macro sys_zero_fill(start, length) { 14 | li a0, {start} 15 | li a1, {length} 16 | jal sys_zero_fill 17 | nop 18 | } 19 | 20 | macro sys_max_fill(start, length) { 21 | li a0, {start} 22 | li a1, {length} 23 | jal sys_max_fill 24 | nop 25 | } 26 | 27 | macro sys_count_start1() { 28 | jal sys_count_start1 29 | nop 30 | } 31 | 32 | macro sys_count_end1() { 33 | jal sys_count_end1 34 | nop 35 | } 36 | 37 | macro sys_count_diff1() { 38 | jal sys_count_diff1 39 | nop 40 | } 41 | 42 | macro sys_count_start2() { 43 | jal sys_count_start2 44 | nop 45 | } 46 | 47 | macro sys_count_end2() { 48 | jal sys_count_end2 49 | nop 50 | } 51 | 52 | macro sys_count_diff2() { 53 | jal sys_count_diff2 54 | nop 55 | } 56 | 57 | macro sys_count_start3() { 58 | jal sys_count_start3 59 | nop 60 | } 61 | 62 | macro sys_count_end3() { 63 | jal sys_count_end3 64 | nop 65 | } 66 | 67 | macro sys_count_diff3() { 68 | jal sys_count_diff3 69 | nop 70 | } 71 | 72 | macro sys_count_start4() { 73 | jal sys_count_start4 74 | nop 75 | } 76 | 77 | macro sys_count_end4() { 78 | jal sys_count_end4 79 | nop 80 | } 81 | 82 | macro sys_count_diff4() { 83 | jal sys_count_diff4 84 | nop 85 | } -------------------------------------------------------------------------------- /N64/LIB/N64_SYS.S: -------------------------------------------------------------------------------- 1 | // Some functions work some don't, Sorry 2 | constant mi_mask_clear_sp($0001) 3 | constant mi_mask_set_sp($0002) 4 | constant mi_mask_clear_si($0004) 5 | constant mi_mask_set_si($0008) 6 | constant mi_mask_clear_ai($0010) 7 | constant mi_mask_set_ai($0020) 8 | constant mi_mask_clear_vi($0040) 9 | constant mi_mask_set_vi($0080) 10 | constant mi_mask_clear_pi($0100) 11 | constant mi_mask_set_pi($0200) 12 | constant mi_mask_clear_dp($0400) 13 | constant mi_mask_set_dp($0800) 14 | 15 | constant pi_clear_interrupt($0002) 16 | constant si_clear_interrupt($0000) 17 | constant sp_clear_interrupt($0008) 18 | constant dp_clear_interrupt($0800) 19 | constant ai_clear_interrupt($0000) 20 | 21 | constant color_depth_mask($0100'0000) 22 | constant resolution_mask($0001'0000) 23 | constant interlacing_mask($0000'0100) 24 | constant tv_format_mask($0000'0003) 25 | 26 | align(8) 27 | // Calls Exit in the 'middle' 28 | sys_get_clock: 29 | la t0, $8000'0300 30 | lw t0, 0(t0) 31 | nop 32 | bnel t0, r0, _sys_get_clock_check_ntsc 33 | addiu t0, t0, -1 34 | li v0, VI_PAL_CLOCK 35 | jr ra 36 | nop 37 | _sys_get_clock_check_ntsc: 38 | bnel t0, r0, _sys_get_clock_check_mpal 39 | addiu t0, t0, -1 40 | li v0, VI_NTSC_CLOCK 41 | jr ra 42 | nop 43 | _sys_get_clock_check_mpal: 44 | li v0, VI_MPAL_CLOCK 45 | jr ra 46 | nop 47 | 48 | sys_random: 49 | // a0 = r0 ignored for now 50 | // a1 = maximum 51 | // v0 @ return = random number 52 | // t0 System Video Clock 53 | // t1 Current Video Line 54 | // t2 Current Counter Value 55 | STACK_PUSH(ra) 56 | jal sys_get_clock 57 | nop 58 | sll t0, v0, 5 59 | la t1, (VI_BASE << 16) | VI_V_CURRENT_LINE 60 | lw t1, 0(t1) 61 | mfc0 t2, Count 62 | // Make 1 value of our 3 Entropies 63 | // t0 shifted left is largest 64 | // quickly add all the others 65 | // Div by maximum is where it gets random 66 | addu t0, t0, t1 67 | addu t0, t0, t2 68 | //subu a0, a1, a0 // Removes the minimum? 69 | divu t0, a1 70 | STACK_POP(ra) 71 | mfhi v0 72 | subu v0, v0, a0 73 | jr ra 74 | nop 75 | // These could incorporate DMA to make all memory moves identical 76 | sys_memcopy: 77 | _sys_memcopy_loop: 78 | lw t4, 0(a0) 79 | lw t5, 4(a0) 80 | lw t6, 8(a0) 81 | lw t7, 12(a0) 82 | sw t4, 0(a1) 83 | sw t5, 4(a1) 84 | sw t6, 8(a1) 85 | sw t7, 12(a1) 86 | addi t2, t2, -16 87 | addi t0, t0, 16 88 | bnel t2, r0, _sys_memcopy_loop 89 | addi t1, t1, 16 90 | jr ra 91 | nop 92 | sys_memmove: 93 | jr ra 94 | nop 95 | sys_move_bytes: 96 | jr ra 97 | nop 98 | sys_mem_parm_check: 99 | jr ra 100 | nop 101 | // Call Example 102 | // la a0, $8000'0000 103 | // li a1, 64 104 | // jal sys_zero_fill 105 | // nop 106 | // 4 byte aligned 107 | // max 16bit range 108 | sys_zero_fill: 109 | add t0, r0, r0 110 | andi a1, a1, $FFFC 111 | add t1, a0, a1 112 | sw t0, 0(a0) 113 | _sys_zero_fill_loop: 114 | addi a0, a0, 4 115 | bnel a0, t1, _sys_zero_fill_loop 116 | sw t0, 0(a0) 117 | jr ra 118 | nop 119 | // Call Example 120 | // la a0, $8000'0000 121 | // li a1, 64 122 | // jal sys_max_fill 123 | // nop 124 | // 4 byte aligned 125 | // max 16bit range 126 | sys_max_fill: 127 | addiu t0, r0, -1 128 | andi a1, a1, $FFFC 129 | add t1, a0, a1 130 | sw t0, 0(a0) 131 | _sys_max_fill_loop: 132 | addi a0, a0, 4 133 | bnel a0, t1, _sys_max_fill_loop 134 | sw t0, 0(a0) 135 | jr ra 136 | nop 137 | // Assumed to spin cycles, i.e. nothing else happens 138 | // Example Logo Startup Screens 139 | sys_delay_ms: 140 | // a0 = ms 141 | STACK_PUSH(ra) 142 | jal sys_get_clock 143 | add t0, r0, v0 144 | multu a0, t0 145 | mfc0 t1, Count 146 | mflo t2 147 | add t2, t1, t2 148 | _sys_delay_ms_loop: 149 | mfc0 t1, Count 150 | // Not working yet 151 | STACK_POP(ra) 152 | jr ra 153 | nop 154 | 155 | // sys_count_* 156 | // Takes 187 Clock Cycles 157 | // Timing accuracy is far lower. 158 | // 0x5D = 93 Nothing 159 | // 0x71 = 113 ScreenNTSC Macro 160 | _sys_count_addr_start1: 161 | dw 0x0 162 | _sys_count_addr_end1: 163 | dw 0x0 164 | align(8) 165 | sys_count_start1: // 187 Count 166 | la v1, _sys_count_addr_start1 167 | mfc0 v0, Count // 93 Count 168 | jr ra 169 | sw v0, 0(v1) 170 | 171 | sys_count_end1: 172 | la v1, _sys_count_addr_end1 173 | mfc0 v0, Count 174 | jr ra 175 | sw v0, 0(v1) 176 | 177 | sys_count_diff1: 178 | la v0, _sys_count_addr_start1 179 | lw v0, 0(v0) 180 | la v1, _sys_count_addr_end1 181 | lw v1, 0(v1) 182 | addiu v0, v0, 93 // Remove 'overhead' 183 | jr ra 184 | subu v0, v1, v0 185 | 186 | _sys_count_addr_start2: 187 | dw 0x0 188 | _sys_count_addr_end2: 189 | dw 0x0 190 | align(8) 191 | sys_count_start2: 192 | la v1, _sys_count_addr_start2 193 | mfc0 v0, Count 194 | jr ra 195 | sw v0, 0(v1) 196 | 197 | sys_count_end2: 198 | la v1, _sys_count_addr_end2 199 | mfc0 v0, Count 200 | jr ra 201 | sw v0, 0(v1) 202 | sys_count_diff2: 203 | la v0, _sys_count_addr_start2 204 | lw v0, 0(v0) 205 | la v1, _sys_count_addr_end2 206 | lw v1, 0(v1) 207 | addiu v0, v0, 93 // Remove 'overhead' 208 | jr ra 209 | subu v0, v1, v0 210 | 211 | _sys_count_addr_start3: 212 | dw 0x0 213 | _sys_count_addr_end3: 214 | dw 0x0 215 | align(8) 216 | sys_count_start3: 217 | la v1, _sys_count_addr_start3 218 | mfc0 v0, Count 219 | jr ra 220 | sw v0, 0(v1) 221 | 222 | sys_count_end3: 223 | la v1, _sys_count_addr_end3 224 | mfc0 v0, Count 225 | jr ra 226 | sw v0, 0(v1) 227 | sys_count_diff3: 228 | la v0, _sys_count_addr_start3 229 | lw v0, 0(v0) 230 | la v1, _sys_count_addr_end3 231 | lw v1, 0(v1) 232 | addiu v0, v0, 93 // Remove 'overhead' 233 | jr ra 234 | subu v0, v1, v0 235 | 236 | _sys_count_addr_start4: 237 | dw 0x0 238 | _sys_count_addr_end4: 239 | dw 0x0 240 | align(8) 241 | sys_count_start4: 242 | la v1, _sys_count_addr_start4 243 | mfc0 v0, Count 244 | jr ra 245 | sw v0, 0(v1) 246 | 247 | sys_count_end4: 248 | la v1, _sys_count_addr_end4 249 | mfc0 v0, Count 250 | jr ra 251 | sw v0, 0(v1) 252 | sys_count_diff4: 253 | la v0, _sys_count_addr_start4 254 | lw v0, 0(v0) 255 | la v1, _sys_count_addr_end4 256 | lw v1, 0(v1) 257 | addiu v0, v0, 93 // Remove 'overhead' 258 | jr ra 259 | subu v0, v1, v0 260 | -------------------------------------------------------------------------------- /N64/LIB/N64_SYSCALL_MARS.S: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | 4 | //define DEBUG_SHOW_STATIC_VALUE(yes) 5 | 6 | // Based on http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html 7 | align(8) 8 | syscall_mars: 9 | interrupt_register_save() 10 | la t0, SYSCALL_Handlers 11 | sll t1, v0, 2 12 | lw t0, 0(t1) 13 | jr t0 14 | 15 | _syscall_1: 16 | // Printer Integer 17 | // $a0 = integer to print 18 | _syscall_2: 19 | // Printer Float 20 | // $f12 = float to print 21 | _syscall_3: 22 | // Printer Double 23 | // $f12 = double to print 24 | _syscall_4: 25 | // Printer String 26 | // $a0 = address of null-terminated string to print 27 | _syscall_5: 28 | // Read Integer 29 | // $v0 contains integer read 30 | _syscall_6: 31 | // Read Float 32 | // $f0 contains float read 33 | _syscall_7: 34 | // Read Double 35 | // $f0 contains double read 36 | _syscall_8: 37 | // Read String 38 | // $a0 = address of input buffer 39 | // $a1 = maximum number of characters to read 40 | // Service 8 - Follows semantics of UNIX 'fgets'. For specified length n, 41 | // string can be no longer than n-1. If less than that, adds newline to end. 42 | // In either case, then pads with null byte If n = 1, input is ignored and 43 | // null byte placed at buffer address. If n < 1, input is ignored and nothing 44 | // is written to the buffer. 45 | _syscall_9: 46 | // sbrk (allocate heap memory) 47 | // $a0 = number of bytes to allocate 48 | // $v0 contains address of allocated memory 49 | _syscall_10: 50 | // exit (terminate execution) 51 | _syscall_11: 52 | // $a0 = character to print 53 | // Service 11 - Prints ASCII character corresponding to contents of low-order byte. 54 | _syscall_12: 55 | // Read Character 56 | // $v0 contains character read 57 | _syscall_13: 58 | // open file 59 | // $a0 = address of null-terminated string containing filename 60 | // $a1 = flags 61 | // $a2 = mode 62 | // $v0 contains file descriptor (negative if error). See note below table 63 | _syscall_14: 64 | // read from file 65 | // $a0 = file descriptor 66 | // $a1 = address of input buffer 67 | // $a2 = maximum number of characters to read 68 | // $v0 contains number of characters read 69 | // (0 if end-of-file, negative if error). 70 | _syscall_15: 71 | // write to file 72 | // $a0 = file descriptor 73 | // $a1 = address of output buffer 74 | // $a2 = number of characters to write 75 | // $v0 contains number of characters written (negative if error). 76 | _syscall_16: 77 | // close file 78 | // $a0 = file descriptor 79 | _syscall_17: 80 | // exit2 (terminate with value) 81 | // $a0 = termination result 82 | interrupt_register_restore() 83 | jr ra 84 | nop 85 | 86 | //fixed_gap(_tlb_handler, 0x40) 87 | SYSCALL_Handlers: 88 | // Interrupt 89 | syscall_01_handler_ptr: 90 | static_value(DEBUG_SHOW_STATIC_VALUE, dw 0x0, db "PInt") 91 | -------------------------------------------------------------------------------- /N64/LIB/README.md: -------------------------------------------------------------------------------- 1 | # N64 LIB Conventions 2 | ## File Extensions 3 | * INC - Contain ONLY constants and macros 4 | * S - Code called with Jump or Branch instructions, may use global variables 5 | In some cases there is an INC and an S file, that have to be used together 6 | 7 | To use the files: 8 | The *.INC should always be at the top of the source file, similar to the #include statement in C. 9 | 10 | The *.S files should be included in the code near where it's used or before/after specific sections based on the desired ROM layout. 11 | 12 | Inside each file the following code patterns apply 13 | 14 | * The underscore _ prefixes labels and macros that are for internal use only. 15 | 16 | -------------------------------------------------------------------------------- /N64/Lesson1/bass-win.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Lesson1/bass-win.zip -------------------------------------------------------------------------------- /N64/Lesson2/Lesson2.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Lesson2/Lesson2.N64 -------------------------------------------------------------------------------- /N64/Lesson2/Lesson2.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | output "Lesson2.N64", create 4 | fill 1052672 5 | 6 | origin $00000000 7 | base $80000000 8 | include "../LIB/N64.INC" 9 | include "N64_HEADER.ASM" 10 | insert "../LIB/N64_BOOTCODE.BIN" 11 | 12 | Start: 13 | lui t0,$BFC0 14 | addi t1,r0,8 15 | sw t1,$7FC(t0) 16 | 17 | Loop: 18 | j Loop 19 | nop // Delay Slot -------------------------------------------------------------------------------- /N64/Lesson2/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Lesson 2 " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Lesson2/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Lesson2.N64 3 | REM Space seperated list of source files 4 | set source_files=Lesson2.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Template/N64_Header.asm: -------------------------------------------------------------------------------- 1 | //============ 2 | // N64 Header 3 | //============ 4 | // PI_BSB_DOM1 5 | db $80 // Initial PI_BSB_DOM1_LAT_REG Value 6 | db $37 // Initial PI_BSB_DOM1_PGS_REG Value 7 | db $12 // Initial PI_BSB_DOM1_PWD_REG Value 8 | db $40 // Initial PI_BSB_DOM1_PGS_REG Value 9 | 10 | // CLOCK RATE 11 | dw $000F // Initial Clock Rate 12 | 13 | // VECTOR 14 | dw Start // Boot Address Offset 15 | dw $1444 // Release Offset 16 | 17 | // COMPLEMENT CHECK & CHECKSUM 18 | db "CRC1" // CRC1: COMPLEMENT CHECK 19 | db "CRC2" // CRC2: CHECKSUM 20 | 21 | dd 0 // UNUSED 22 | 23 | // PROGRAM TITLE (27 Byte ASCII String, Use Spaces For Unused Bytes) 24 | db "Template " 25 | // "123456789012345678901234567" 26 | 27 | // DEVELOPER ID CODE 28 | db $00 // "N" = Nintendo 29 | 30 | // CARTRIDGE ID CODE 31 | db $00 32 | 33 | db 0 // UNUSED 34 | 35 | // COUNTRY CODE 36 | db $00 // "D" = Germany, "E" = USA, "J" = Japan, "P" = Europe, "U" = Australia 37 | 38 | db 0 // UNUSED -------------------------------------------------------------------------------- /N64/Template/Template.N64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fraser125/N64-ASM-Tutorial/90743405d5befe765c28ee8cb8df80f58dc67dd7/N64/Template/Template.N64 -------------------------------------------------------------------------------- /N64/Template/make.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | set rom_name=Template.N64 3 | REM Space seperated list of source files 4 | set source_files=Template.asm 5 | 6 | if exist %rom_name% ( 7 | del /q %rom_name% 8 | ) 9 | bass -strict -create %1 -o %rom_name% %source_files% 10 | if exist %rom_name% ( 11 | @chksum64 %rom_name% 12 | ) -------------------------------------------------------------------------------- /N64/Template/template.asm: -------------------------------------------------------------------------------- 1 | arch n64.cpu 2 | endian msb 3 | fill 1052672 4 | 5 | origin $00000000 6 | base $80000000 7 | include "../LIB/N64.INC" 8 | include "./N64_HEADER.ASM" // Include 64 Byte Header & Vector Table 9 | insert "../LIB/N64_BOOTCODE.BIN" // Include 4032 Byte Boot Code 10 | force_pc($80001000) 11 | Start: 12 | align(8) 13 | N64_INIT() 14 | ScreenNTSC(320, 240, BPP32, $A0100000) // Screen NTSC: 320x240, 32BPP, DRAM Origin $A0100000 15 | // Insert Initialization Code 16 | Loop: 17 | // Insert Looping Code Here 18 | j Loop 19 | nop // Delay Slot -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # N64-ASM-Tutorial 2 | The support files for N64 Assembly Language Tutorial that is hosted: https://sites.google.com/site/consoleprotocols/home/homebrew/n64-assembly-home 3 | 4 | * Lesson 1: [Environment](https://sites.google.com/site/consoleprotocols/home/homebrew/n64-assembly-home/Lesson01) 5 | * Lesson 2: [Minimum Code](https://sites.google.com/site/consoleprotocols/home/homebrew/n64-assembly-home/Lesson02) 6 | -------------------------------------------------------------------------------- /gobass.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | path=c:\bass\bin;c:\bass\include;c:\bass\lib;c:\mame;%path%; --------------------------------------------------------------------------------