1
0
Disbranĉigi 0
Ĉi tiu deponejo arĥiviĝis je 2024-01-29. Vi povas vidi kaj elŝuti dosierojn, sed ne povas puŝi nek raporti problemojn nek tirpeti.
super_bread_pan/sbp.mfk

777 lines
21 KiB
Plaintext
Raw Normal View History

2020-07-29 13:24:00 -05:00
/// SUPER BREAD PAN
2020-07-20 04:01:38 -05:00
// SUPERPANSKATOL'
import nes_joy
segment(chrrom) const array graphics @ $0000 = file("tileset.chr")
// ============================================================================
// STRUCTS
// ============================================================================
// sprite layout in oam
struct Sprite {
byte y,
byte tile,
byte attrs,
byte x
}
2020-10-09 19:14:51 -05:00
2020-07-20 04:01:38 -05:00
// ============================================================================
// VARIABLES
// ============================================================================
byte i
byte score1
array oam_buffer [256] @$200 // sprite buffer
word framecounter
Entity sam @$204 // player character
2020-07-29 13:24:00 -05:00
Entity baby @$250 // baby character
2020-07-20 04:01:38 -05:00
volatile Gamestate gamestate // the current Gamestate
// ============================================================================
// CONSTANTS
// ============================================================================
const array fg_pallete = [
2020-07-29 13:24:00 -05:00
$22,$1C,$15,$14,
$0F,$18,$28,$0F, // sam
$0F,$28,$29,$0F, // enemies
$03,$07,$05,$03 // angry owo
2020-07-20 04:01:38 -05:00
]
enum Gamestate {
STATETITLE,
STATEPLAYING,
STATEGAMEOVER
}
const array scorebackground = "P1 Score- " ascii
const array gameover_msg = "G A M E O V E R" ascii
const array title_msg = "Press Start" ascii
// -------------------------------------
// LOCATIONS
// -------------------------------------
// vram locations declared as constants for readability/convenience
// *note that these do not correlate to CPU ram locations*
const word ppu_pallete_ram = $3F00
const word ppu_nametable_ram = $2000
const word ppu_nametable_0_attr_ram = $23C0
// -------------------------------------
// LEVEL
// -------------------------------------
const byte RIGHTWALL = $F4
const byte TOPWALL = $18
const byte BOTTOMWALL = $B0
const byte LEFTWALL = $04
// -------------------------------------
2020-07-29 13:24:00 -05:00
// ATTRIBUTES
2020-07-20 04:01:38 -05:00
// -------------------------------------
// i don't actually remember if the super crate box guy is named sam or not
// or if he even has a name?
const byte SAM_ATTR = %00000001
const byte SAM_ATTR_HFLIP = %01000001
const byte SAM_ATTR_VFLIP = %10000001
const byte SAM_ATTR_HVFLIP = %11000001
2020-07-29 13:24:00 -05:00
const byte BAD_ATTR = %00000010
const byte BAD_ATTR_HFLIP = %01000010
const byte BAD_ATTR_VFLIP = %10000010
const byte BAD_ATTR_HVFLIP = %11000010
const byte MAD_ATTR = %00000011
const byte MAD_ATTR_HFLIP = %01000011
const byte MAD_ATTR_VFLIP = %10000011
const byte MAD_ATTR_HVFLIP = %11000011
// -------------------------------------
// PHYSICS?
// -------------------------------------
const byte SAM_WALKSPEED = 2
const byte BABY_WALKSPEED = SAM_WALKSPEED / 2
const byte FALLSPEED = 4
2020-07-20 04:01:38 -05:00
// -------------------------------------
// ANIMATIONS
// -------------------------------------
// all Entity (16x16)'s animations are assumed by update_entity() to consist of
// 5 frames. An animation array just contains 20 locations in CHR, four per
// frame, in this totally logical order:
// top-left, bottom-left, top-right, bottom-right
2020-07-29 13:24:00 -05:00
const array SAM_IDLE = [ $01, $11, $02, $12,
$03, $13, $04, $14,
$05, $15, $06, $16,
$07, $17, $08, $18,
$09, $19, $0A, $1A ]
const array SAM_WALK = [ $21, $31, $22, $32,
$23, $33, $24, $34,
$25, $35, $26, $36,
$27, $37, $28, $38,
$29, $39, $2A, $3A ]
const array BABY_WALK = [ $00, $C0, $00, $00,
$00, $C1, $00, $C2,
$00, $C3, $00, $00,
$00, $C4, $00, $00,
$00, $C5, $00, $00 ]
2020-07-20 04:01:38 -05:00
2020-07-20 04:01:38 -05:00
// ============================================================================
// CORE
// ============================================================================
// quite important uwu
void main() {
2020-07-21 03:28:20 -05:00
sam.dircount = 0
2020-07-20 04:01:38 -05:00
gamestate = STATETITLE
title_init()
while(true){} // all work is done in nmi
// thnx nmi <3
}
// run at each non-maskable interrupt
// generated during each vertical blanking interval. cool
void nmi() {
// push all sprite info to the ppu (picture processing unit)
// through dma (direct memory access) transfer
ppu_oam_dma_write( oam_buffer.addr.hi )
main_game_logic()
}
// run at each interrupt request
// do I know when these are called on the nes? absolutely not
// at reset? maybe?
void irq() {
}
// pretty self-explanatory
inline void main_game_logic() {
// use a return dispatch here
// to use different logic for each screen/gamestate
return [gamestate] {
STATETITLE @ title_logic
STATEPLAYING @ ingame_logic
STATEGAMEOVER @ gameover_logic
}
}
// uwu owo uwu owo uwu owo
inline void init_graphics() {
init_sprites()
load_fg_pallete( fg_pallete )
2020-07-20 04:01:38 -05:00
}
// cleans up oam (object attribute memory)
// each sprite gets 4 bytes in oam:
// 1: ypos, 2: tile index, 3: attr table, 4: xpos
void init_sprites() {
byte i
for i,0,to,255 {
if (i & %00000011) == 0 {
//each sprite takes up 4 bytes, and we want to edit
//the y position of each sprite (0th byte)
//so we use the %00000011 mask to write every 4th byte
//(every 0th sprite byte)
oam_buffer[i] = $ef // move the sprite off screen
}
else {
oam_buffer[i] = 0
}
}
}
// ============================================================================
// TITLE-SCREEN
// ============================================================================
void title_init() {
byte i
//for now, turn off the screen and nmi
ppu_ctrl = 0
ppu_mask = 0
//initialize the sprites and palletes
init_graphics()
//write a full screen of background data
//write the title screen message
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$018B) // point the PPU to the message's start
for i,0,until,$0B {
ppu_write_data(title_msg[i])
}
//write the border
//top border
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$0020)
for i,0,until,$20 {
ppu_write_data($01)
}
//bottom border
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$0380)
for i,0,until,$20 {
ppu_write_data($01)
}
//set ppu address increment to 32 so we can draw the left and right borders
//(allows us to draw to the nametable in vertical strips rather than horizontal)
ppu_ctrl = %00000100
//left border
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram)
for i,0,until,$20 {
ppu_write_data($01)
}
//right border
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$1F)
for i,0,until,$20 {
ppu_write_data($01)
}
framecounter = 0
ppu_set_scroll(0,0)
ppu_wait_vblank() //wait for next vblank before re-enabling NMI
//so that we don't get messed up scroll registers
//re-enable the screen and nmi
ppu_ctrl = %10010000 // enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
ppu_mask = %00011110 // enable sprites, enable background, no clipping on left side
}
void title_logic() {
read_joy1()
if input_start != 0 {
gamestate = STATEPLAYING
ingame_init()
return
}
framecounter += 1
}
// ============================================================================
// IN-GAME
// ============================================================================
void ingame_init() {
//for now, turn off the screen and nmi
ppu_ctrl = 0
ppu_mask = 0
//write a full screen of data
init_map1_c()
// draw_score_text_background()
2020-10-09 19:14:51 -05:00
2020-07-20 04:01:38 -05:00
ppu_set_scroll(0,0)
ppu_wait_vblank() //wait for next vblank before re-enabling NMI
//so that we don't get messed up scroll registers
//re-enable the screen and nmi
ppu_ctrl = %10010000 // enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
ppu_mask = %00011110 // enable sprites, enable background, no clipping on left side
2020-07-21 03:28:20 -05:00
sam.top0.y = 40
sam.top0.x = 50
2020-07-29 13:24:00 -05:00
sam.walkspeed = SAM_WALKSPEED
baby.top0.y = 40
baby.top0.x = 100
baby.walkspeed = BABY_WALKSPEED
2020-07-20 04:01:38 -05:00
}
void ingame_logic() {
// draw_score()
2020-07-20 04:01:38 -05:00
//update scroll last because writes to vram also
//overwrite the scroll register
ppu_set_scroll(0,0) // tell the ppu there is no background scrolling
ingame_input()
update_ingame_sprites()
if score1 >= 15 {
//Someone's reached 15 points, the game is over,
//so set the state to game over and reset the
//framecounter
gamestate = STATEGAMEOVER
//move all the sprites off screen
//in preperation for the gameover screen
sam.top0.x = $ef
gameover_init()
}
}
void ingame_input ( ) {
// Player 1 controls
read_joy1()
sam.movement = 0
// left
2020-07-21 03:28:20 -05:00
if ( input_dx < 0 ) {
2020-07-20 04:01:38 -05:00
sam.direction = 0
2020-07-21 03:28:20 -05:00
sam.movement = 1
2020-07-20 04:01:38 -05:00
}
// right
2020-07-21 03:28:20 -05:00
else if ( input_dx > 0 ) {
2020-07-20 04:01:38 -05:00
sam.direction = 1
2020-07-21 03:28:20 -05:00
sam.movement = 1
}
// a button
if ( input_btn == 1 && sam.jump == 0 ) {
sam.jump = 1
sam.dircount = 0
2020-07-20 04:01:38 -05:00
}
}
void update_ingame_sprites ( )
{
// player. sam is the player.
2020-07-21 03:28:20 -05:00
update_entity( pointer.Entity( sam.addr ), SAM_IDLE, SAM_WALK )
2020-07-29 13:24:00 -05:00
update_entity( pointer.Entity( baby.addr ), BABY_WALK, BABY_WALK )
2020-07-20 04:01:38 -05:00
}
// ============================================================================
// GAME-OVER
// ============================================================================
void gameover_init() {
//for now, turn off nmi and sprites
ppu_ctrl = 0
ppu_mask = 0
draw_score() //draw the final score
draw_gameover() //draw the game over message
framecounter = 0
ppu_set_scroll(0,0) // tell the ppu there is no background scrolling
ppu_wait_vblank() //wait for next vblank before re-enabling NMI
//so that we don't get messed up scroll registers
//re-enable the screen and nmi
ppu_ctrl = %10010000 // enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
ppu_mask = %00011110 // enable sprites, enable background, no clipping on left side
}
void gameover_logic() {
if framecounter >= 240{
//3 seconds have passed,
//reset the game
simulate_reset()
}
framecounter += 1
}
void draw_gameover() {
byte i
//draw the static game over message
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$0107) // point the PPU to the message's start
for i,0,until,$12 {
ppu_write_data(gameover_msg[i])
}
//draw the win message
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram+$01AC) // point the PPU to the message's start
}
2020-07-20 04:01:38 -05:00
// ============================================================================
// MISC GRAPHICS
// ============================================================================
// -------------------------------------
// BACKGROUND
// -------------------------------------
inline void blank_bg() {
2020-07-20 04:01:38 -05:00
word xx
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_ram) // point the PPU to palette ram
for xx,0,until,$0300 {
ppu_write_data($00)
2020-07-20 04:01:38 -05:00
}
}
// -------------------------------------
// PALLETE MANAGEMENT
// -------------------------------------
// loads colours into the section of memory dedicated to background (sprite) colours.
// useful resource: https://wiki.nesdev.com/w/index.php/PPU_palettes
// (edits $3F00 to $3F0F)
void load_bg_pallete ( pointer pallete ) {
2020-07-20 04:01:38 -05:00
byte i
2020-10-09 19:14:51 -05:00
ppu_set_addr( ppu_pallete_ram )
for i,0,to,$F {
ppu_write_data( pallete[i] )
2020-07-20 04:01:38 -05:00
}
}
2020-07-20 04:01:38 -05:00
// loads colours into the section of memory dedicated to foreground (sprite) colours.
// unrelated, but heck do I feel like I'm spelling pallete wrong. doesn't it have 'double-t' vibes?
// like palette? or maybe pallette? hmm.
// (edits $3F10 to $3F1F)
void load_fg_pallete ( pointer pallete ) {
byte i
ppu_set_addr( ppu_pallete_ram + $10 )
for i,0,to,$F {
ppu_write_data( pallete[i] )
2020-07-20 04:01:38 -05:00
}
}
2020-10-09 19:14:51 -05:00
// load pallete selection for bg tiles to ppu
// useful resource: https://wiki.nesdev.com/w/index.php/PPU_palettes
macro void load_attr_table( pointer attributes ) {
byte i
read_ppu_status() // read PPU status to reset the high/low latch
ppu_set_addr(ppu_nametable_0_attr_ram) // point the PPU to nametable 0's attribute table
for i,0,to,64 {
ppu_write_data(attributes[i])
2020-10-09 19:14:51 -05:00
}
}
2020-10-09 19:14:51 -05:00
macro void draw_score_text_background() {
byte i
2020-07-20 04:01:38 -05:00
read_ppu_status() // read PPU status to reset the high/low latch
2020-10-09 19:14:51 -05:00
ppu_set_addr(ppu_nametable_ram+$20) // point the PPU to score text's start
for i,0,until,$1C {
ppu_write_data(scorebackground[i])
2020-07-20 04:01:38 -05:00
}
}
inline void draw_score() {
byte digit01
byte digit10
read_ppu_status() // read PPU status to reset the high/low latch
//display player1's score
digit01 = score1 %% 10 //get the ones digit
digit10 = score1 / 10 //get the tens digit
digit10 %%= 10
ppu_set_addr(ppu_nametable_ram+$29) // point the PPU to player1's score number
if digit10 > 0 {
ppu_write_data(digit10 + '0')
}
ppu_write_data(digit01 + '0')
}
// ============================================================================
// ENTITIES
// ============================================================================
// abstraction for 16x16 animated monstrosities
struct Entity {
Sprite top0, // left side, for the record
Sprite bottom0,
Sprite top1, // right side, please kill me
Sprite bottom1,
// all this can be crammed into a byte (if merge dircount w frame) `o`
// note to self: do that
byte movement, // 0-3; idle, walk, jump/fall
byte jump, // 0/1
byte direction, // 0/1
byte dircount, // counter for time-limited movement; i.e., jumping
byte frame, // internal count used for animation; max 5
byte walkspeed
}
2020-10-09 19:14:51 -05:00
2020-07-21 03:28:20 -05:00
void update_entity ( pointer.Entity ent, pointer idle, pointer walk ) {
entity_physics( ent )
2020-07-29 13:24:00 -05:00
if ( ent[0].bottom0.tile > $39 ) {
entity_destiny ( ent )
}
2020-07-21 03:28:20 -05:00
entity_sprite( ent, ent[0].top0.x, ent[0].top0.y, idle, walk )
}
2020-07-20 04:01:38 -05:00
// sets the current frame of ent's animation and determines which animation to use
2020-07-21 03:28:20 -05:00
void entity_sprite ( pointer.Entity ent, byte xx, byte yy, pointer idle, pointer walk ) {
2020-07-20 04:01:38 -05:00
if ( ent[0].direction == 0 ) {
2020-07-29 13:24:00 -05:00
if ( ent[0].bottom0.tile < $3A ) { // if player
ent[0].top0.attrs = SAM_ATTR_HFLIP
ent[0].bottom0.attrs = SAM_ATTR_HFLIP
ent[0].top1.attrs = SAM_ATTR_HFLIP
ent[0].bottom1.attrs = SAM_ATTR_HFLIP
} else {
ent[0].top0.attrs = BAD_ATTR_HFLIP
ent[0].bottom0.attrs = BAD_ATTR_HFLIP
ent[0].top1.attrs = BAD_ATTR_HFLIP
ent[0].bottom1.attrs = BAD_ATTR_HFLIP
}
2020-07-20 04:01:38 -05:00
ent[0].top1.x = xx - 8
ent[0].bottom1.x = xx - 8
}
else {
2020-07-29 13:24:00 -05:00
if ( ent[0].bottom0.tile < $3A ) { // if player
ent[0].top0.attrs = SAM_ATTR
ent[0].bottom0.attrs = SAM_ATTR
ent[0].top1.attrs = SAM_ATTR
ent[0].bottom1.attrs = SAM_ATTR
} else {
ent[0].top0.attrs = BAD_ATTR
ent[0].bottom0.attrs = BAD_ATTR
ent[0].top1.attrs = BAD_ATTR
ent[0].bottom1.attrs = BAD_ATTR
}
2020-07-20 04:01:38 -05:00
ent[0].top1.x = xx + 8
ent[0].bottom1.x = xx + 8
}
ent[0].top0.x = xx
ent[0].bottom0.x = xx
ent[0].top0.y = yy
ent[0].bottom0.y = yy + 8
ent[0].top1.y = yy
ent[0].bottom1.y = yy + 8
byte ani
ani = 0
if ( ent[0].frame < 4 ) {
ani = 0
} else if ( ent[0].frame < 8 ) {
ani = 4
} else if (ent[0].frame < 12 ) {
ani = 8
} else if (ent[0].frame < 16 ) {
ani = 12
} else if (ent[0].frame < 20 ) {
ani = 16
} else {
ent[0].frame = 0
ani = 0
}
2020-07-21 03:28:20 -05:00
if ( ent[0].jump == 1 ) {
ent[0].top0.tile = idle[0]
ent[0].bottom0.tile = idle[1]
ent[0].top1.tile = idle[2]
ent[0].bottom1.tile = idle[3]
} else if ( ent[0].movement == 1 ) {
2020-07-20 04:01:38 -05:00
ent[0].top0.tile = walk[ani + 0]
ent[0].bottom0.tile = walk[ani + 1]
ent[0].top1.tile = walk[ani + 2]
ent[0].bottom1.tile = walk[ani + 3]
} else {
ent[0].top0.tile = idle[ani + 0]
ent[0].bottom0.tile = idle[ani + 1]
ent[0].top1.tile = idle[ani + 2]
ent[0].bottom1.tile = idle[ani + 3]
}
ent[0].frame += 1
}
2020-07-21 03:28:20 -05:00
// -------------------------------------
// "PHYSICS"
// -------------------------------------
void entity_physics ( pointer.Entity ent ) {
2020-07-29 13:24:00 -05:00
// if player
if ( ent[0].bottom0.tile < $3A ) {
entity_jump_physics( ent )
}
if ( ent[0].bottom0.y < BOTTOMWALL - 10 && ent[0].jump == 0 ) {
ent[0].top0.y += FALLSPEED
}
if ( ent[0].movement == 1 ) {
if ( ent[0].direction == 0 ) {
ent[0].top0.x -= ent[0].walkspeed
} else if ( ent[0].direction == 1) {
ent[0].top0.x += ent[0].walkspeed
}
}
}
// frankly, this is just terrible. reeeee !!!!
// please replace this, please replace this, please replace this
// oh gods almightly please please please
2020-07-29 13:24:00 -05:00
void entity_jump_physics ( pointer.Entity ent ) {
2020-07-21 03:28:20 -05:00
if ( ent[0].bottom0.y < BOTTOMWALL - 10 && ent[0].jump == 1 && ent[0].dircount == 0 ) {
// if not on ground, don't start jumping
ent[0].jump = 0
} else if ( ent[0].jump == 1 )
{
// a meager attempt at replicating scb's jump arc
// a few deficiencies:
// * a bit too short
// * "float" is a bit too short
// it might work out gameplay-wise, though, so idk we'll see
if ( ent[0].dircount < 3) {
ent[0].top0.y -= 6
} else if ( ent[0].dircount == 3 ) {
ent[0].top0.y -= 2
} else if ( ent[0].dircount == 4 ) {
ent[0].top0.y -= 6
} else if ( ent[0].dircount < 9 ) {
ent[0].top0.y -= 3
} else if ( 9 <= ent[0].dircount <= 10 ) {
ent[0].top0.y -= 1
} else if ( ent[0].dircount == 13 ) {
ent[0].top0.y += 2
} else if ( 13 < ent[0].dircount < 20 ) {
ent[0].top0.y += 2
} else if ( 20 < ent[0].dircount ) {
ent[0].dircount = -1
ent[0].jump = 0
}
ent[0].dircount += 1
}
2020-07-29 13:24:00 -05:00
}
2020-07-21 03:28:20 -05:00
2020-07-29 13:24:00 -05:00
// enemy pathfinding, blah blah.
// determines an npc's destiny
void entity_destiny ( pointer.Entity ent ) {
ent[0].movement = 1
2020-07-21 03:28:20 -05:00
}
// ============================================================================
// MAPS
// ============================================================================
// load a map onto the ppu
void init_map ( pointer.word locations, pointer location_tiles,
pointer.word horiz_ranges, pointer horiz_tiles,
pointer.word vert_ranges, pointer vert_tiles,
pointer pallete, pointer attrs ) {
byte i
word j
byte last_range
last_range = 0
2020-07-20 04:01:38 -05:00
read_ppu_status() // read PPU status to reset the high/low latch
load_bg_pallete( pallete )
load_attr_table( attrs )
blank_bg()
read_ppu_status()
init_map_horiz_ranges( horiz_ranges, horiz_tiles )
init_map_vert_ranges ( vert_ranges, vert_tiles )
init_map_locations( locations, location_tiles )
}
// init_map helpers
// -----------------
macro void init_map_horiz_ranges ( pointer.word horiz_ranges, pointer horiz_tiles ) {
const byte horiz_inc = $1
ppu_load_range( horiz_ranges, horiz_tiles, horiz_inc )
}
macro void init_map_vert_ranges ( pointer.word vert_ranges, pointer vert_tiles ) {
const byte vert_inc = $20
ppu_load_range( vert_ranges, vert_tiles, vert_inc )
}
macro void init_map_locations ( pointer.word locations, pointer location_tiles ) {
i = 0
while ( locations[i] != nullchar ) {
ppu_set_addr(ppu_nametable_ram + locations[i])
ppu_write_data(location_tiles[i])
i += 1
2020-07-20 04:01:38 -05:00
}
}
macro void ppu_load_range ( pointer.word ranges, pointer tiles, byte increment ) {
i = 0
last_range = 0
while ( ranges[i] != nullchar ) {
if last_range != 0 {
j = ranges[i-1]
while ( j <= ranges[i] ) {
ppu_set_addr( ppu_nametable_ram + j )
ppu_write_data(tiles[i/2]) // bug when i==1?
j += increment
}
last_range = 0
} else {
last_range = 1
}
i += 1
}
}
2020-07-20 04:01:38 -05:00
// -------------------------------------
// MAP DATA
// -------------------------------------
// map1: construction site
void init_map1_c () {
init_map( pointer.word( MAP1_C_LOCATIONS ), MAP1_C_LOCATION_TILES,
pointer.word( MAP1_C_HORIZ ), MAP1_C_HORIZ_TILES,
pointer.word( MAP1_C_VERT ), MAP1_C_VERT_TILES,
MAP1_C_PALLETE, MAP1_C_ATTRS )
}
const array(word) MAP1_C_LOCATIONS = [
$22,$3D, $1A2,$1BD, $2E2,$2FD, // bolted parts of arena border
$EA,$F5, $26A,$275, // holding up bottom/top platforms w connecting metal
nullchar ]
const array(byte) MAP1_C_LOCATION_TILES = [
$81,$81, $81,$81, $81,$81,
$89,$8A, $87,$88 ]
const array(word) MAP1_C_VERT = [
$22,$2E2, $3D,$2FD, // arena border (far left & right)
$4A,$EA, $55,$F5, // lift up top platform
$26A,$30A, $275,$315, // hold up bottom platform
nullchar ]
const array(byte) MAP1_C_VERT_TILES = [ $82,$82, $85,$86, $85,$86 ]
const array(word) MAP1_C_HORIZ = [
$340,$3A0, // sandstone subterrain
$300,$308, $317,$31F, // brick floor (top)
$320,$32E, $331,$33F, // brick floor (second)
$23,$2E, $31,$3C, // ceiling
$109,$116, // top platform
$1A3,$1A8, $1B7,$1BC, // middle platforms
$249,$256, // bottom platform
nullchar ]
const array(byte) MAP1_C_HORIZ_TILES = [ $84, $83,$83, $83,$83, $80,$80, $80, $80,$80, $80 ]
const array(byte) MAP1_C_PALLETE = [ $21, // bg color
$29,$1A,$0F, $00,
// construction-blocks
$06,$07,$16, $00,
// construction-bricks
$06,$07,$00, $01,
// sandstone
$2B,$2B,$1A ]
const word MAP1_C_SPAWN = $2F
const word MAP1_C_FIRE = $34E
// palette selections for the ppu tiles
// also not the most efficient way to store this data. (... clearly) !!!!
// %DownRight DownLeft TopRight TopLeft
const array(byte) MAP1_C_ATTRS = [
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%01010101, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %01010101,
%11111010, %11111010, %11111010, %11111010, %11111010, %11111010, %11111010, %11111010,
%11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 ]
2020-07-20 04:01:38 -05:00
// ============================================================================
// UTIL
// ============================================================================
inline asm void ppu_wait_vblank() {
vblankwait:
BIT $2002
! BPL vblankwait
? RTS
}