Allgemeine Hex- und ASM-Fragen

geschrieben am 13.05.2011 12:58:37
( Link )
Hi ich hab mal eine Frage zu Better Boss Bass von smw central
Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Boss Bass
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; symbolic names for RAM addresses
RAM_SpriteDir = $157C
RAM_NoJumpTimer = $1504
RAM_StateTimer = $1540
RAM_SpriteState = $C2

ExecutePtr = $0086DF

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INIT and MAIN routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DCB "INIT"
LDA $D8,x
ORA #$08
STA $D8,x

STZ RAM_SpriteState,x
JSR SubHorzPos
TYA
STA RAM_SpriteDir,x
LDA TimeInState
STA RAM_StateTimer,x
RTL

DCB "MAIN"
PHB
PHK
PLB
JSR DecrementTimers
JSR BossBassMain
PLB
RTL

DecrementTimers:
LDA $14C8,x
CMP #$08
BNE DoneDec
LDA $9D
BNE DoneDec
LDA RAM_NoJumpTimer,x
BEQ DoneDec
DEC RAM_NoJumpTimer,x
DoneDec:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sprite Main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BossBassMain:
JSR SubGfx ; Draw sprite

LDA $1528,x ; If the eaten flag is set:
BEQ NotEaten
LDA #$03 ; Make Mario invisible
STA $78
NotEaten:

LDA $14C8,X ; \ Return if status != Normal
CMP #$08 ; |
BNE Return ; /
LDA $9D ; \ Return if sprites are locked
BNE Return ; /

;; JSR SubOffScreen ; Only process while on screen

JSR SetUpMovement
JSL $018022 ; Update x position, no gravity
JSL $01801A ; Update y position, no gravity

JSL $01A7DC ; Handle Mario/sprite contact
BCC Return ; Return if no contact

JSR HandleContact
Return:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Handle movement
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TimeInState:
dcb $11,$28

SwimSpeedX:
DCB $31,$CF
JumpProximity:
DCB $25,$DC

SetUpMovement:
LDA RAM_SpriteState,x
BNE Jumping
Swimming:
LDA RAM_SpriteDir,x
LDY RAM_StateTimer,x
BNE SkipFlipDireciton
EOR #$01
STA RAM_SpriteDir,x
LDA #$04
STA RAM_NoJumpTimer,x
LDA #$1C
STA RAM_StateTimer,x
SkipFlipDireciton:
LDY RAM_SpriteDir,x
LDA SwimSpeedX,y
STA $B6,x

JSR SubHorzPos ;0 if traveling towards mario
TYA
EOR RAM_SpriteDir,x
BNE SkipSetTimerMax

LDA RAM_NoJumpTimer,x ; Don't jump if timer is set
BNE NoIncState

JSR SubVertPos
CPY #$01 ; Doesn't jump if above Mario
BNE NoIncState
LDA $0F
CMP #$B0
BCC NoIncState

JSR SubHorzPos
CPY #$00
BEQ Less20
GreatE0:
LDA $0F
CMP #$F0
BCS NoIncState
CMP #$D0
BCC NoIncState
BRA IncState
Less20:
LDA $0F
CMP #$10
BCC NoIncState
CMP #$30
BCS NoIncState

IncState:
INC RAM_SpriteState,x
JSR SetStateTimer
LDA #$D9
STA $AA,x
RTS

NoIncState:
LDA #$20
STA RAM_StateTimer,x

SkipSetTimerMax:
STZ $AA,x
RTS


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


JumpAccelX:
dcb $01,$FF

Jumping:
LDA RAM_StateTimer,x ; Go back to swimming state if time
BEQ GotoSwim

LDA $AA,x ; Adjust Y speed
CLC
ADC #$02
STA $AA,x

LDA RAM_SpriteDir,x ; Get index for X acceleration
LDY $00AA,x
BPL NoAdjustIndex
EOR #$01
NoAdjustIndex:
TAY

LDA $B6,x ; Adjust X speed
CLC
ADC JumpAccelX,Y
STA $B6,x
Return2:
RTS

GotoSwim:
STZ RAM_SpriteState,x
JSR SetStateTimer
STZ $AA,x
LDA #$10
STA RAM_NoJumpTimer,x
RTS

HandleContact:
LDA RAM_SpriteState,x ; Only hurt Mario when jumping
BEQ Return2
LDA.B #$09 ; Set death animation
STA $71
STA $1DFB ; Set death music
LDA.B #$30 ; Set time until we return to the OW
STA $1496
STA $1528,x ; Set eaten flag
Return2:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetStateTimer:
LDY RAM_SpriteState,x
LDA TimeInState,Y
STA RAM_StateTimer,x
RTS


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Graphics Routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SpriteTiles: dcb $46,$47,$2B,$49,$59,$FF,$FF,$FF
dcb $46,$47,$2B,$4A,$5A,$FF,$FF,$FF
dcb $46,$47,$2B,$4D,$7F,$FF,$FF,$FF
dcb $46,$47,$04,$4D,$7F
SpriteTileSize: dcb $02,$02,$02,$00,$00
;; SpriteTileDispY: dcb $E8,$E8,$F8,$F8,$00
SpriteTileDispY: dcb $F0,$F0,$00,$00,$08
SpriteTileDispX: dcb $00,$08,$00,$10,$10
dcb $00,$F8,$00,$F8,$F8
SpriteGfxFlip: dcb $00,$40

SubGfx:
JSR GetDrawInfo

PHY
LDA $15F6,X ; $02 = Palette info
LDY RAM_SpriteDir,X
BNE NoFlip
ORA #$40
NoFlip:
STA $02

LDA #$03 ; $03 = Tilemap offset
LDY $C2,x
BNE StoreFrame
LDA $14
LSR
AND #$02
StoreFrame:
ASL
ASL
ASL
STA $03
PLY

PHX ; Push sprite index
LDX #$04 ; Draw 5 tiles
GfxLoopStart:
PHX ; Push tile number

PHX ; Push tile number
LDA $02
AND #$40
BEQ NoAdjust
TXA
CLC
ADC #$05
TAX
NoAdjust:
LDA $00
CLC
ADC SpriteTileDispX,X
STA $0300,Y
PLX ; Pull tile number

LDA $01
CLC
ADC SpriteTileDispY,X
STA $0301,Y

PHX ; Push tile number
TXA
CLC
ADC $03
TAX
LDA SpriteTiles,X
STA $0302,Y
PLX ; Pull tile number

LDA $02
ORA $64
STA $0303,Y

LDA SpriteTileSize,X
PHA
TYA
LSR
LSR
TAX
PLA
STA $0460,X
PLX ; Pull tile number

INY ; Adjust index into the OAM
INY
INY
INY
DEX
BPL GfxLoopStart

PLX ; Pull sprite index

LDY #$FF ; We already wrote to $0460,Y
LDA #$04 ; We wrote 5 tiles
JSL $01B7B3
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine. It sets off screen flags, and sets up
; variables. It will return with the following:
;
; Y = index to sprite OAM ($300)
; $00 = sprite x position relative to screen boarder
; $01 = sprite y position relative to screen boarder
;
; It is adapted from the subroutine at $03B760
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DATA_03B75C: dcb $0C,$1C
DATA_03B75E: dcb $01,$02

GetDrawInfo: STZ $186C,X ; Reset sprite offscreen flag, vertical
STZ $15A0,X ; Reset sprite offscreen flag, horizontal
LDA $E4,X ; \
CMP $1A ; | Set horizontal offscreen if necessary
LDA $14E0,X ; |
SBC $1B ; |
BEQ ADDR_03B774 ; |
INC $15A0,X ; /
ADDR_03B774: LDA $14E0,X ; \
XBA ; | Mark sprite invalid if far enough off screen
LDA $E4,X ; |
REP #$20 ; Accum (16 bit)
SEC ; |
SBC $1A ; |
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; Accum (8 bit)
ROL ; |
AND.B #$01 ; |
STA $15C4,X ; |
BNE ADDR_03B7CF ; /
LDY.B #$00 ; \ set up loop:
LDA $1662,X ; |
AND.B #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ADDR_03B79A ; | else, go through loop once
INY ; /
ADDR_03B79A: LDA $D8,X ; \
CLC ; | set vertical offscree
ADC DATA_03B75C,Y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,X ; |
ADC.B #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ADDR_03B7BA ; |
LDA $186C,X ; | (vert offscreen)
ORA DATA_03B75E,Y ; |
STA $186C,X ; |
ADDR_03B7BA: DEY ; |
BPL ADDR_03B79A ; /
LDY $15EA,X ; get offset to sprite OAM
LDA $E4,X ; \
SEC ; |
SBC $1A ; |
STA $00 ; / $00 = sprite x position relative to screen boarder
LDA $D8,X ; \
SEC ; |
SBC $1C ; |
STA $01 ; / $01 = sprite y position relative to screen boarder
RTS ; Return

ADDR_03B7CF: PLA ; \ Return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This routine determines which side of the sprite Mario is on. It sets the Y register
; to the direction such that the sprite would face Mario
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SubHorzPos:
LDY #$00
LDA $94
SEC
SBC $E4,x
STA $0F
LDA $95
SBC $14E0,x
BPL HorzIncY
INY
HorzIncY:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This routine determines if Mario is above or below the sprite. It sets the Y register
; to the direction such that the sprite would face Mario
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SubVertPos:
LDY #$00
LDA $96
SEC
SBC $D8,x
STA $0F
LDA $97
SBC $14D4,x
BPL VertIncY
INY
VertIncY:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DATA_01AC0D: dcb $40,$B0
DATA_01AC0F: dcb $01,$FF
DATA_01AC11: dcb $30,$C0
DATA_01AC19: dcb $01,$FF

SubOffScreen: STZ $03
JSR IsSprOnScreen ; \ if sprite is not off screen, return
BEQ Return01ACA4 ; /
LDA $5B ; \ vertical level
AND #$01 ; |
BNE VerticalLevel ; /
LDA $D8,X ; \
CLC ; |
ADC #$50 ; | if the sprite has gone off the bottom of the level...
LDA $14D4,X ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
ADC #$00 ; |
CMP #$02 ; |
BPL OffScrEraseSprite ; / ...erase the sprite
LDA $167A,X ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE Return01ACA4 ; /
LDA $13
AND #$01
STA $01
TAY
LDA $1A
CLC
ADC DATA_01AC11,Y
ROL $00
CMP $E4,X
PHP
LDA $1B
LSR $00
ADC DATA_01AC19,Y
PLP
SBC $14E0,X
STA $00
LSR $01
BCC ADDR_01AC7C
EOR #$80
STA $00
ADDR_01AC7C: LDA $00
BPL Return01ACA4
OffScrEraseSprite: LDA $14C8,X ; \ If sprite status < 8, permanently erase sprite
CMP #$08 ; |
BCC OffScrKillSprite ; /
LDY $161A,X
CPY #$FF
BEQ OffScrKillSprite
LDA #$00
STA $1938,Y
OffScrKillSprite: STZ $14C8,X ; Erase sprite
Return01ACA4: RTS

VerticalLevel: LDA $167A,X ; \ If "process offscreen" flag is set, return
AND #$04 ; |
BNE Return01ACA4 ; /
LDA $13 ; \
LSR ; |
BCS Return01ACA4 ; /
LDA $E4,X ; \
CMP #$00 ; | If the sprite has gone off the side of the level...
LDA $14E0,X ; |
SBC #$00 ; |
CMP #$02 ; |
BCS OffScrEraseSprite ; / ...erase the sprite
LDA $13
LSR
AND #$01
STA $01
TAY
LDA $1C
CLC
ADC DATA_01AC0D,Y
ROL $00
CMP $D8,X
PHP
LDA $001D
LSR $00
ADC DATA_01AC0F,Y
PLP
SBC $14D4,X
STA $00
LDY $01
BEQ ADDR_01ACF3
EOR #$80
STA $00
ADDR_01ACF3: LDA $00
BPL Return01ACA4
BMI OffScrEraseSprite

IsSprOnScreen: LDA $15A0,X ; \ A = Current sprite is offscreen
ORA $186C,X ; /
RTS ; Return


Ich wollt es so machen das er nach ein Paar Sekunden wieder erscheint wenn man ihn getötet hat egal wo man in dem Level ist. So wie in smb3.
Weil momentan macht er zwar alles was er soll, aber wenn man ihn am Anfang mit einer Feuerblume oder einem Panzer killt ist das restliche Level ganz schön einfach.
geschrieben am 13.05.2011 20:03:49
( Link )
Wie kann ich einem Sprite Layerpriorität geben ?
geschrieben am 13.05.2011 22:51:17
( Link )
Hast du schon bei der Sprite Map16 probiert?
Brutal Mario ist out.Spielt mal SMW FreedoMN,1Updudes-Hacks,The Devious Four Chronicles oder Chomps Attacke!
geschrieben am 14.05.2011 6:32:17
( Link )
Sprite Map 16 ?
geschrieben am 14.05.2011 10:44:24
( Link )
Druecke bei der Map16 ,an der du wahrscheinlich super geil kombinierst, Shift+Strg und dann PgDn(Ist wahrscheinlich bei dir Seite runter oder so)Dann scrollst du runter, bis du eine neue Map16 siehst, wo man Sprites sehen kann. Speichern tust du, glaube ich, mit Shift+Ctrl+F9.
Brutal Mario ist out.Spielt mal SMW FreedoMN,1Updudes-Hacks,The Devious Four Chronicles oder Chomps Attacke!
geschrieben am 14.05.2011 11:37:20
( Link )
Sprite-Map16 bringt gar nichts. Das ist nur zum Ansehen gedacht, im Spiel verändern tut es absolut nichts.

Um einem Sprite höchste Priorität zu geben, suche im Sprite-Code nach ORA $64 und füge darunter, in einer neuen Zeile, ORA #$30 ein. Mach das hinter jedem ORA $64, das du findest.
geschrieben am 14.05.2011 12:26:05
( Link )
Danke, WYE und danke Ricicir fürs versuchen.
geschrieben am 16.05.2011 17:40:42
( Link )
Ich hab mal ne ganz kleine Frage.

LDA #$DD ; \ start Custom music
STA $1DFB ; /

Eigentlich sollte das doch die Custom music starten, aber er bleibt bei No Music, aber wenn ich:

LDA #$05 ; \ start the boss music
STA $1DFB ; /

nehme funktioniert es. Wie kann ich machen , dass Custom Music abgespielt wird ?
geschrieben am 16.05.2011 18:59:47
( Link )
Du kannst nur Musik aus der selben Bank nehmen (1 Bank = 4 Lieder). Ich weiß jetzt nicht wie die Bank in der DD ist eingeteilt ist, also hilft nur testen oder hochrechnen, es muss im Level eben schon eine der Musiken aus der selben Bank spielen.
geschrieben am 16.05.2011 19:04:31
( Link )
Zitat von RealLink:
Du kannst nur Musik aus der selben Bank nehmen (1 Bank = 4 Lieder). Ich weiß jetzt nicht wie die Bank in der DD ist eingeteilt ist, also hilft nur testen oder hochrechnen, es muss im Level eben schon eine der Musiken aus der selben Bank spielen.

Was ist eine Bank. Wie meinst du das ?
geschrieben am 16.05.2011 19:08:06
( Link )
In diesem Falle ein Bund aus vier Liedern (20-23, 24-27, 28-2B etc.) Nur wenn zwei Lieder in derselben Bank sind, kann man sie so einfach hintereinander spielen lassen.
geschrieben am 16.05.2011 19:14:32
( Link )
Oder eine Sitzbank, (haha) auf die vier Leute passen. Alle Leute auf einer Bank können sich gegenseitig die Hand reichen, nicht jedoch die Leute auf verschiedenen Bänken.
-Das quadratische Rad neu erfinden-
Mit das quadratische Rad neu erfinden (englisch Reinventing the square wheel) bezeichnet man die Bereitstellung einer schlechten Lösung, wenn eine gute Lösung bereits existiert.

-Slowsort-
Slowsort (von engl. slow: langsam) ist ein langsamer, rekursiver Sortieralgorithmus, der nach dem Prinzip Vervielfache und kapituliere (engl. Multiply and surrender, eine Parodie auf Teile und herrsche) arbeitet.

geschrieben am 16.05.2011 19:43:24
( Link )
Also heißt das jetzt, dass ich wenn ich als Levelmusic DC hab kann der Boss DD abspielen ?
geschrieben am 16.05.2011 19:56:38
( Link )
Kommt ganz drauf an, wo die jeweilige Bank anfängt. Es könnte ja sein, dass die Banke bei D9 anfängt. Dann würde sie bei DC aufhören und DD wäre schon wieder eine neue Bank. Fängt die Bank aber bei DA, DB oder DC an, dann ja.
-Das quadratische Rad neu erfinden-
Mit das quadratische Rad neu erfinden (englisch Reinventing the square wheel) bezeichnet man die Bereitstellung einer schlechten Lösung, wenn eine gute Lösung bereits existiert.

-Slowsort-
Slowsort (von engl. slow: langsam) ist ein langsamer, rekursiver Sortieralgorithmus, der nach dem Prinzip Vervielfache und kapituliere (engl. Multiply and surrender, eine Parodie auf Teile und herrsche) arbeitet.

geschrieben am 22.05.2011 14:34:20
( Link )
Ich möchte gerne die Lebensanzahl in der Statusbar löschen aber wenn ich es mit Statuseffect probiere crasht meine Rom. Kann mir da wer helfen ?
geschrieben am 23.05.2011 16:28:10
( Link )
Ich habe mal eine Frage, was muss ich im Sprite machen, wenn temp.log das anzeigt:


Memory available: 2147483647
Starting address defined as $90B105

Pass 1

Pass 2
Error in 155.1/132: Branch out of range

Pass 3
Error in 155.1/132: Branch out of range

Source code assembled.

Although the source code was assembled, the program may not run
properly due to errors detected during the assembling process.

[$90B105-$90B54E]
Lines=607
Statements=528
Symbols=90
Errors=1
geschrieben am 23.05.2011 17:04:24
( Link )
Zitat von MetalJo:
was muss ich im Sprite machen

Den Code posten, dann bieg ich ihn dir vielleicht zurecht.

Der Fehler besteht darin, dass ein Label zu weit vom Branch-Befehl weg ist.
geschrieben am 23.05.2011 19:09:24
( Link )
Code
                    HITPOINTS = $02     	      ;Hit Points
TIME_TILL_THROW dcb $E8,$E8 ;Sprite spawn Timer

JUMP_TIMER = $163E
HAMMER_TIMER = $15AC
FIRE_TIMER = $1558
DIR_TIMER = $1540
SPRITE_DIR = $157C
SPRITE_IMG = $1602
SPRITE_STATUS = $14C8
SPRITE_STATE = $151C
TIME_TO_LOCK = $28
NEW_SPRITE_NUM = $7FAB9E ;08 bytes custom sprite number
EXTRA_BITS = $7FAB10
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcb "INIT"
JSR SUB_GET_DIR
TYA
STA $157C,x

TXA
AND #$03
ASL A
ASL A
ASL A
ASL A
ASL A
STA JUMP_TIMER,x
CLC
ADC #$22
STA FIRE_TIMER,x

RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main sprite JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcb "MAIN"
HAMMER_BRO_JSL PHB ; \
PHK ; | main sprite function, just calls local subroutine
PLB ; |
JSR START_HB_CODE ; |
PLB ; |
RTL ; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main sprite routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


TIME_TO_LOCK = $28
TIME_TO_JUMP = $88
TIME_TO_SHOW = $12 ;time to display the boomerang before it is thrown

SpriteSpeed:
dcb $08,$10,$18,$1D,$1D,$FF,$FF,$FF ;x speed - facing right
dcb $F8,$F0,$E8,$E3,$E3,$FF,$FF,$FF ;x speed - facing left
BounceSpeed:
dcb $C0,$30 ;x speed to give mario when he stomps the sprite
KILLED_X_SPEED dcb $F0,$10
TIME_IN_POS dcb $78,$14,$74,$14 ;moving up, rest at top, moving down, rest at bottom
TIME_TILL_HAMMER dcb $0C,$0C,$0C,$0C,$0C,$43,$0C,$0C
dcb $0C,$0C,$0C,$0C,$73,$0C,$0C,$0C
dcb $0C,$0C,$63,$0C,$0C,$0C,$0C,$0C
dcb $0C,$83,$0C,$0C,$0C,$0C,$0C,$53

STAR INC FIRE_TIMER,x
RETURN RTS
START_HB_CODE JSR SUB_GFX ; draw sprite gfx
LDA SPRITE_STATUS,x ; \ if sprite status != 8...
CMP #$02 ; } ... not (killed with spin jump [4] or star[2])
BEQ STAR
CMP #$08
BNE RETURN ; / ... return
LDA $9D ; \ if sprites locked...
BNE RETURN ; / ... return

JSR SUB_OFF_SCREEN_X3 ; only process sprite while on screen
INC $1570,x ; increment number of frames sprite has been on screen

LDA $1570,x ; \ calculate which frame to show:
LSR A ; |
LSR A ; |
AND #$01 ; | update every 16 cycles if normal
STA SPRITE_IMG,x ; / write frame to show

TO_ATTACK LDA FIRE_TIMER,x ; \ if time until spit >= $10
CMP #TIME_TO_SHOW ; | just go to normal walking code
BCS STATE_RUN ; /
INC SPRITE_IMG,x
INC SPRITE_IMG,x

LDA FIRE_TIMER,x ; throw fire if it's time
BNE NO_RESET
LDY $C2,x
LDA TIME_TILL_THROW,y
STA FIRE_TIMER,x
NO_RESET CMP #$01
BNE STATE_RUN

STATE_RUN LDA DIR_TIMER,x
CMP #$01
BNE WALK_SPRITE

JMP TO_ATTACK ; time to convert to pounding koopa
WALK_SPRITE LDA $1588,x ; \ if sprite is not on ground...
AND #$04 ; } ...(4 = on ground) ...
BEQ APPLY_SPEED ; / ...goto IN_AIR
LDA #$10 ; \ y speed = 10
STA $AA,x ; /
LDA $C2,x ; \ if hits on sprite == 0...
EOR #$01
BEQ NO_FAST_SPEED ; / ...goto DONT_ADJUST_SPEED
LDA $157C,x ; load, y = sprite direction, as index for speed
ASL
ASL
ASL
CLC
ADC $1528,x ; Speed depends on hit count
TAY
LDA SpriteSpeed,y ; \ load x speed from ROM...
NO_FAST_SPEED STA $B6,x ; / ...and store it


APPLY_SPEED JSL $01802A ; update position based on speed values


FREEZE_SPR LDA $1588,x ; \ if sprite is touching the side of an object...
AND #$03 ; |
BEQ DONT_CHANGE_DIR ; |
LDA $157C,x ; |
EOR #$01 ; | ... change sprite direction
STA $157C,x ; /
DONT_CHANGE_DIR JSL $018032 ; interact with other sprites
JSL $01A7DC ; check for mario/sprite contact

BCC RETURN1 ; (carry set = contact)
LDA $1490 ; \ if mario star timer > 0 ...
BNE HAS_STAR ; / ... goto HAS_STAR
LDA $7D ; \ if mario's y speed < 10 ...
CMP #$10 ; } ... sprite will hurt mario
BMI GOOB_WINS ; /

MARIO_WINS:

JSR SUB_STOMP_PTS ; give mario points
JSR SUB_GET_DIR ; \ set new sprite direction
JSL $01AB99 ; display contact graphic

LDA $15 ; Save controller state
PHA
ORA #$C0 ; Set holding X/Y and A/B
STA $15
JSL $01AA33 ; set mario speed
PLA
STA $15

JSR SUB_GET_DIR ; If there was contact,
LDY $157C,x
LDA BounceSpeed,y ; bounce away horizontally
STA $7B

INC $1528,x ; increment sprite hit counter
LDA $1528,x ; if sprite hit counter == 5
CMP #HITPOINTS
BNE RETURN1
LDA #$02 ; Kill the sprite
STA $14C8,x
STZ $B6,x
LDA #$F0
STA $AA,x
JMP Kill

RETURN1 RTS

GOOB_WINS LDA $1497 ; \ if mario is invincible...
ORA $187A ; } ... or mario on yoshi...
ORA $15D0,x ; | ...or sprite being eaten...
BNE RETURN2 ; / ... return
JSR SUB_GET_DIR ; \ set new sprite direction
TYA ; }
STA $157C,x ; /
JSL $00F5B7 ; hurt mario
RETURN2 RTS ; return

Kill

STZ $14C8,x ; die
LDA #$3C
STA $1DFC
JSR DrawSmoke
JSL $07FC3B
RTS

DrawSmoke: LDY #$03 ; \ find a free slot to display effect
FINDFREE: LDA $17C0,y ; |
BEQ FOUNDONE ; |
DEY ; |
BPL FINDFREE ; |
RTS ; / return if no slots open

FOUNDONE: LDA #$01 ; \ set effect graphic to smoke graphic
STA $17C0,y ; /
LDA #$1B ; \ set time to show smoke
STA $17CC,y ; /
LDA $D8,x ; \ smoke y position = generator y position
STA $17C4,y ; /
LDA $E4,x ; \ load generator x position and store it for later
STA $17C8,y ; /
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; spin and star kill (still part of above routine)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

STAR_SOUNDS dcb $00,$13,$14,$15,$16,$17,$18,$19

SPIN_KILL LDA #$04 ; \ status = 4 (being killed by spin jump)
STA $14C8,x ; /
LDA #$1F ; \ set spin jump animation timer
STA $1540,x ; /
JSL $07FC3B ; show star animation
LDA #$08 ; \ play sound effect
STA $1DF9 ; /
RTS ; return
HAS_STAR LDA #$02 ; \ status = 2 (being killed by star)
STA $14C8,x ; /
LDA #$D0 ; \ set y speed
STA $AA,x ; /
JSR SUB_GET_DIR ; get new direction
LDA KILLED_X_SPEED,y ; \ set x speed based on direction
STA $B6,x ; /
INC $18D2 ; increment number consecutive enemies killed
LDA $18D2 ; \
CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8
BCC NO_RESET2 ; |
LDA #$08 ; |
STA $18D2 ; /
NO_RESET2 JSL $02ACE5 ; give mario points
LDY $18D2 ; \
CPY #$08 ; | if consecutive enemies stomped < 8 ...
BCS NO_SOUND2 ; |
LDA STAR_SOUNDS,y ; | ... play sound effect
STA $1DF9 ; /
NO_SOUND2 RTS ; final return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine - unknown
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

STAR_SOUNDS dcb $00,$13,$14,$15,$16,$17,$18,$19

SUB_STOMP_PTS PHY ;
LDA $1697 ; \
CLC ; }
ADC $1626,x ; / some enemies give higher pts/1ups quicker??
INC $1697 ; increase consecutive enemies stomped
TAY ;
INY ;
CPY #$08 ; \ if consecutive enemies stomped >= 8 ...
BCS NO_SOUND ; / ... don't play sound
LDA #$47
STA $1DFC
NO_SOUND TYA ; \
CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8
BCC NO_RESET6 ; |
LDA #$08 ; /
NO_RESET6 JSL $02ACE5 ; give mario points
PLY ;
RET RTS ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; fire routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

XF_OFFSET dcb $13,$FC
XF_OFFSET2 dcb $00,$FF

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TILEMAP dcb $00,$02,$20,$22,$04,$06,$24,$26,$0C,$0E,$2C,$2E,$0C,$0E,$2C,$2E
dcb $00,$02,$20,$22,$04,$06,$24,$26,$0C,$0E,$2C,$2E,$0C,$0E,$2C,$2E
HORIZ_DISP dcb $00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10
dcb $10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00,$10,$00
VERT_DISP dcb $F0,$F0,$00,$00,$F0,$F0,$00,$00,$F0,$F0,$00,$00,$F0,$F0,$00,$00
dcb $F0,$F0,$00,$00,$F0,$F0,$00,$00,$F0,$F0,$00,$00,$F0,$F0,$00,$00
PROPERTIES dcb $40,$00 ;xyppccct format

HAMMER_TILE = $6D


SUB_GFX JSR GET_DRAW_INFO ; after: Y = index to sprite tile map ($300)
; $00 = sprite x position relative to screen boarder
; $01 = sprite y position relative to screen boarder
LDA SPRITE_IMG,x ; \
ASL A ; | $03 = index to frame start (frame to show * 2 tile per frame)
ASL A
STA $03 ; /
LDA SPRITE_DIR,x ; \ $02 = sprite direction
STA $02 ; /
BNE NO_ADD
LDA $03
CLC
ADC #$10
STA $03
NO_ADD PHX ; push sprite index

LDX #$03 ; loop counter = (number of tiles per frame) - 1
LOOP_START PHX ; push current tile number
TXA ; \ X = index to horizontal displacement
ORA $03 ; / get index of tile (index to first tile of frame + current tile number)
FACING_LEFT TAX ; \

LDA $00 ; \ tile x position = sprite x location ($00)
CLC ; |
ADC HORIZ_DISP,x ; |
STA $0300,y ; /

LDA $01 ; \ tile y position = sprite y location ($01) + tile displacement
CLC ; |
ADC VERT_DISP,x ; |
STA $0301,y ; /

LDA TILEMAP,x ; \ store tile
STA $0302,y ; /

LDX $02 ; \
LDA PROPERTIES,x ; | get tile properties using sprite direction
LDX $15E9 ; |
ORA $15F6,x ; | get palette info
ORA $64 ; | put in level properties
STA $0303,y ; / store tile properties

PLX ; \ pull, X = current tile of the frame we're drawing
INY ; | increase index to sprite tile map ($300)...
INY ; | ...we wrote 1 16x16 tile...
INY ; | ...sprite OAM is 8x8...
INY ; | ...so increment 4 times
DEX ; | go to next tile of frame and loop
BPL LOOP_START ; /

PLX ; pull, X = sprite index

LDA HAMMER_TIMER,x
CMP #$02
BCC NO_SHOW_HAMMER
CMP #30
BCS NO_SHOW_HAMMER
LDA SPRITE_IMG,x
CMP #$00

NO_SHOW_HAMMER LDY #$02 ; \ 02, because we didn't write to 460 yet
LDA #$03 ; | A = number of tiles drawn - 1
JSL $01B7B3 ; / don't draw if offscreen
RTS ; retur

SHOW_HAMMER_TOO PHX

LDA $00
LDX $02
CLC
ADC XF_OFFSET,x
STA $0300,y

LDA $01 ; \ tile y position = sprite y location ($01) + tile displacement
CLC ; |
ADC #$E8
STA $0301,y ; /

LDA #HAMMER_TILE ; \ store tile
STA $0302,y ; /

LDA #$03
CPX #$00
BNE NO_FLIP_HAMMER
ORA #$40
NO_FLIP_HAMMER ORA $64 ; | put in level properties
STA $0303,y ; / store tile properties

PLX
INY ; | increase index to sprite tile map ($300)...
INY ; | ...we wrote 1 16x16 tile...
INY ; | ...sprite OAM is 8x8...
INY ; | ...so increment 4 times

LDY #$02 ; \ 02, because we didn't write to 460 yet
LDA #$04 ; | A = number of tiles drawn - 1
JSL $01B7B3 ; / don't draw if offscreen
RTS ; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routines below can be shared by all sprites. they are ripped from original
; SMW and poorly documented
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B75C

TABLE1 dcb $0C,$1C
TABLE2 dcb $01,$02

GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC TABLE1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA TABLE2,y ; |
STA $186C,x ; |
ON_SCREEN_Y DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B817 - horizontal mario/sprite check - shared
; Y = 1 if mario left of sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B817 ; Y = 1 if contact

SUB_GET_DIR LDY #$00 ;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
LDA $94 ;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642
SEC ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642
SBC $E4,x ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1074 VC:097 00 FL:31642
STA $0F ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1104 VC:097 00 FL:31642
LDA $95 ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1128 VC:097 00 FL:31642
SBC $14E0,x ;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642
BPL LABEL16 ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1184 VC:097 00 FL:31642
INY ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1200 VC:097 00 FL:31642
LABEL16 RTS ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B85D - off screen processing code - shared
; sprites enter at different points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B83B

TABLE3 dcb $40,$B0
TABLE6 dcb $01,$FF
TABLE4 dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0
TABLE5 dcb $01,$FF,$01,$FF,$01,$00,$01,$FF

SUB_OFF_SCREEN_X0 LDA #$06 ; \ entry point of routine determines value of $03
BRA STORE_03 ; |
SUB_OFF_SCREEN_X1 LDA #$04 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X2 LDA #$02 ; |
STORE_03 STA $03 ; |
BRA START_SUB ; |
SUB_OFF_SCREEN_X3 STZ $03 ; /

START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return
BEQ RETURN_2 ; /
LDA $5B ; \ goto VERTICAL_LEVEL if vertical level
AND #$01 ; |
BNE VERTICAL_LEVEL ; /
LDA $D8,x ; \
CLC ; |
ADC #$50 ; | if the sprite has gone off the bottom of the level...
LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
ADC #$00 ; |
CMP #$02 ; |
BPL ERASE_SPRITE ; / ...erase the sprite
LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \
AND #$01 ; |
ORA $03 ; |
STA $01 ; |
TAY ; /
LDA $1A ;x boundry ;A:0101 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0256 VC:090 00 FL:16953
CLC ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0280 VC:090 00 FL:16953
ADC TABLE4,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0294 VC:090 00 FL:16953
ROL $00 ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0326 VC:090 00 FL:16953
CMP $E4,x ;x pos ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0364 VC:090 00 FL:16953
PHP ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0394 VC:090 00 FL:16953
LDA $1B ;x boundry hi ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizCHC:0416 VC:090 00 FL:16953
LSR $00 ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0440 VC:090 00 FL:16953
ADC TABLE5,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdizcHC:0478 VC:090 00 FL:16953
PLP ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0510 VC:090 00 FL:16953
SBC $14E0,x ;x pos high ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0538 VC:090 00 FL:16953
STA $00 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0570 VC:090 00 FL:16953
LSR $01 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0594 VC:090 00 FL:16953
BCC LABEL20 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0632 VC:090 00 FL:16953
EOR #$80 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0648 VC:090 00 FL:16953
STA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0664 VC:090 00 FL:16953
LABEL20 LDA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0688 VC:090 00 FL:16953
BPL RETURN_2 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0712 VC:090 00 FL:16953
ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite
CMP #$08 ; |
BCC KILL_SPRITE ; /
LDY $161A,x ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0140 VC:071 00 FL:21152
CPY #$FF ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0172 VC:071 00 FL:21152
BEQ KILL_SPRITE ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0188 VC:071 00 FL:21152
LDA #$00 ; \ mark sprite to come back A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0204 VC:071 00 FL:21152
STA $1938,y ; / A:FF00 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0220 VC:071 00 FL:21152
KILL_SPRITE STZ $14C8,x ; erase sprite
RETURN_2 RTS ; return

VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \ only handle every other frame??
LSR A ; |
BCS RETURN_2 ; /
AND #$01 ;A:0227 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0228 VC:112 00 FL:1142
STA $01 ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0244 VC:112 00 FL:1142
TAY ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0268 VC:112 00 FL:1142
LDA $1C ;A:0201 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0282 VC:112 00 FL:1142
CLC ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0306 VC:112 00 FL:1142
ADC TABLE3,y ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0320 VC:112 00 FL:1142
ROL $00 ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0352 VC:112 00 FL:1142
CMP $D8,x ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0390 VC:112 00 FL:1142
PHP ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0420 VC:112 00 FL:1142
LDA.W $001D ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNVMXdizcHC:0442 VC:112 00 FL:1142
LSR $00 ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdiZcHC:0474 VC:112 00 FL:1142
ADC TABLE6,y ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdizCHC:0512 VC:112 00 FL:1142
PLP ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0544 VC:112 00 FL:1142
SBC $14D4,x ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0572 VC:112 00 FL:1142
STA $00 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0604 VC:112 00 FL:1142
LDY $01 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0628 VC:112 00 FL:1142
BEQ LABEL22 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0652 VC:112 00 FL:1142
EOR #$80 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0668 VC:112 00 FL:1142
STA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0684 VC:112 00 FL:1142
LABEL22 LDA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0708 VC:112 00 FL:1142
BPL RETURN_2 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0732 VC:112 00 FL:1142
BMI ERASE_SPRITE ;A:0280 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0170 VC:064 00 FL:1195

SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0
ORA $186C,x ; |
RTS ; / return

geschrieben am 12.06.2011 22:13:57
( Link )
Nach langer Zeit habe ich ma wieder eine Frage die nicht zu den guten alten anfänger themen gehört
Okay, also wie wir alle wissen gibt es den Ground Pound Boss
Code:
Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Ground Pound Koopa, by mikeyk
;;
;; Description: This guy runs at Mario waving his fists in the air. He can pound the
;; ground, stopping Mario is his tracks.
;;
;; Uses first extra bit: NO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MarioSprInteract = $01A7DC

TimeInState = $1540
SpriteState = $C2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite initialization JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcb "INIT"
PHY
JSR SubHorzPos
TYA
STA $157C,x
PLY
LDA #40
STA TimeInState,x
RTL


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite main JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcb "MAIN"
PHB ; \
PHK ; | main sprite function, just calls local subroutine
PLB ; |
JSR START_SPRITE_CODE ; |
PLB ; |
RTL ; /


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sprite data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SpriteSpeed:
dcb $10,$14,$18,$1C,$20,$FF,$FF,$FF ;x speed - facing right
dcb $F0,$EC,$E8,$E4,$E0,$FF,$FF,$FF ;x speed - facing left
TimeToRun:
dcb $40,$3A,$34,$2E,$28,$FF,$FF,$FF
TimeToPound:
dcb $20,$20,$20,$20,$20,$FF,$FF,$FF
TimeToLock:
dcb $24,$24,$24,$24,$24,$FF,$FF,$FF
BounceSpeed:
dcb $E8,$18 ;x speed to give mario when he stomps the sprite

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main sprite sprite code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RETURN RTS

START_SPRITE_CODE JSR SUB_GFX ; draw sprite gfx
LDA $14C8,x ; \ if sprite status != 8...
CMP #$08 ; } ... not (killed with spin jump [4] or star[2])
BNE RETURN ; / ... return
LDA $9D ; \ if sprites locked...
BNE RETURN ; / ... return


ALIVE JSR SUB_OFF_SCREEN_SPR ; only process sprite while on screen

JSR CALC_FRAME

LDA SpriteState,x
BEQ STATE_RUN
JMP STATE_POUND ; in the pounding state

STATE_RUN LDA TimeInState,x
CMP #$01
BNE STILL_RUNNING
JMP TO_POUND ; time to convert to pounding koopa

STILL_RUNNING LDA $1588,x ; \ if sprite is not on ground...
AND #$04 ; } ...(4 = on ground) ...
BEQ IN_AIR ; / ...goto IN_AIR
LDA #$10 ; \ y speed = 10
STA $AA,x ; /
LDA SpriteState,x ; \ if hits on sprite == 0...
EOR #$01
BEQ NO_FAST_SPEED ; / ...goto DONT_ADJUST_SPEED
LDA $157C,x ; load, y = sprite direction, as index for speed
ASL
ASL
ASL
CLC
ADC $1528,x ; Speed depends on hit count
TAY
LDA SpriteSpeed,y ; \ load x speed from ROM...
NO_FAST_SPEED STA $B6,x ; / ...and store it
IN_AIR JSL $01802A ; update position based on speed values
FREEZE_SPR LDA $1588,x ; \ if sprite is touching the side of an object...
AND #$03 ; |
BEQ DONT_CHANGE_DIR ; |
LDA $157C,x ; |
EOR #$01 ; | ... change sprite direction
STA $157C,x ; /
DONT_CHANGE_DIR JSL $018032 ; interact with other sprites


LDA SpriteState,x ; Run interaction routine based on sprite
BNE Pounding
Running:
JSR RunningInteract
BRA DoneWithInteraction
Pounding:
JSR PoundingInteract
DoneWithInteraction:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RunningInteract:
JSL MarioSprInteract ; check for mario/sprite contact
BCC Return1 ; (carry set = mario/sprite contact)
LDA $1490 ; \ if mario star timer > 0 ...
BNE HAS_STAR ; / ... goto HAS_STAR
LDA $154C,x ; \ if sprite invincibility timer > 0 ...
BNE Return1 ; / ... goto NO_CONTACT
LDA #$08 ; \ sprite invincibility timer = $08
STA $154C,x ; /
LDA $7D ; \ if mario's y speed < 10 ...
CMP #$10 ; } ... sprite will hurt mario
BMI SPRITE_WINS ; /

MARIO_WINS:
JSR SUB_STOMP_PTS ; give mario points
JSL $01AB99 ; display contact graphic

LDA $15 ; Save controller state
PHA
ORA #$C0 ; Set holding X/Y and A/B
STA $15
JSL $01AA33 ; set mario speed
PLA
STA $15

JSR SubHorzPos ; If there was contact,
LDY $157C,x
LDA BounceSpeed,y ; bounce away horizontally
STA $7B



INC $1528,x ; increment sprite hit counter
LDA $1528,x ; if sprite hit counter == 5
CMP #$05
BNE Return1
LDA #$02 ; Kill the sprite
STA $14C8,x
STZ $B6,x
LDA #$F0
STA $AA,x
RTS ; return

SPRITE_WINS
LDA $1497 ; \ if mario is invincible...
ORA $187A ; } ... or mario on yoshi...
BNE Return1 ; / ... return
JSR SubHorzPos ; \ set new sprite direction
TYA ; }
STA $157C,x ; /
JSL $00F5B7 ; hurt mario
Return1:
RTS ; return

KILLED_X_SPEED dcb $F0,$10

HAS_STAR LDA #$02 ; \ sprite status = 2 (being killed by star)
STA $14C8,x ; /
LDA #$D0 ; \ set y speed
STA $AA,x ; /
JSR SubHorzPos ; get new sprite direction
LDA KILLED_X_SPEED,y ; \ set x speed based on sprite direction
STA $B6,x ; /
INC $18D2 ; increment number consecutive enemies killed
LDA $18D2 ; \
CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8
BCC NO_RESET2 ; |
LDA #$08 ; |
STA $18D2 ; /
NO_RESET2 JSL $02ACE5 ; give mario points
LDY $18D2 ; \
CPY #$08 ; | if consecutive enemies stomped < 8 ...
BCS NO_SOUND2 ; |
LDA STAR_SOUNDS,y ; | ... play sound effect
STA $1DF9 ; /
NO_SOUND2 RTS ; final return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine - unknown
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

STAR_SOUNDS dcb $00,$13,$14,$15,$16,$17,$18,$19

SUB_STOMP_PTS PHY ;
LDA $1697 ; \
CLC ; }
ADC $1626,x ; / some enemies give higher pts/1ups quicker??
INC $1697 ; increase consecutive enemies stomped
TAY ;
INY ;
CPY #$08 ; \ if consecutive enemies stomped >= 8 ...
BCS NO_SOUND ; / ... don't play sound
LDA STAR_SOUNDS,y ; \ play sound effect
STA $1DF9 ; /
NO_SOUND TYA ; \
CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8
BCC NO_RESET ; |
LDA #$08 ; /
NO_RESET JSL $02ACE5 ; give mario points
PLY ;
RTS ; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pounding interaction routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PoundingInteract:
LDA $140D ; Save spin jump flag
PHA
LDA #$01 ; Set Spin jump flag
STA $140D

LDA $15 ; Save controller state
PHA
ORA #$C0 ; Set holding X/Y and A/B
STA $15

LDA $167A,x ; Save property byte
PHA
AND #$7F ; Use default interaction
STA $167A,x

LDA $1656,x
PHA
AND #$EF
STA $1656,x

JSL MarioSprInteract ; Interact with Mario

PLA
STA $1656,x
PLA ; Restore property byte
STA $167A,x
PLA ; Restore controller state
STA $15
PLA ; Restore spin jump flag
STA $140D
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TO_RUN STZ SpriteState,x
LDY $1528,x
LDA TimeToRun,Y
STA TimeInState,x

JSR SubHorzPos
TYA
STA $157C,x

JSR CALC_FRAME

LDA $151C,x
BEQ NO_ADJ2
LDA $E4,x
SEC
SBC #$F0
STA $E4,x
LDA $14E0,x
SBC #$FF
STA $14E0,x
NO_ADJ2

LDA #$AA ;change sprite size
STA $1662,x

JMP STILL_RUNNING

DONT_POUND LDA #10
STA TimeInState,x
JMP STILL_RUNNING

TO_POUND LDA $1588,x ; \ if sprite is not on ground...
AND #$04 ; } ...(4 = on ground) ...
BEQ DONT_POUND ; / ...goto IN_AIR

LDA #$01
STA SpriteState,x
LDY $1528,x
LDA TimeToPound,Y
STA TimeInState,x

JSR CALC_FRAME

LDA $157C,x
STA $151C,x
BEQ NO_ADJ
LDA $E4,x
CLC
ADC #$F0
STA $E4,x
LDA $14E0,x
ADC #$FF
STA $14E0,x
NO_ADJ
LDA #$94 ;change sprite size
STA $1662,x

LDY $1528,x
LDA TimeToLock,Y
STA $1887 ; /

LDA #$09 ; \ play sound effect
STA $1DFC ; /

LDA $77
AND #$04
BEQ STILL_POUNDING

LDY $1528,x
LDA TimeToLock,Y
STA $18BD

BRA STILL_POUNDING

STATE_POUND LDA TimeInState,x
CMP #$01
BNE STILL_POUNDING
JMP TO_RUN

STILL_POUNDING JMP STILL_RUNNING
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

CALC_FRAME INC $1570,x ; increment number of frames sprite has been on screen
LDA $1570,x ; \ calculate which frame to show:
LSR A ; |
LSR A ; |
LDY SpriteState,x ; | number of hits determines if smushed
BEQ NOT_HIT ; |
LDA #$02 ; | show smushed frame
BRA LABEL3 ; |
NOT_HIT AND #$01 ; | update every 16 cycles if normal
LABEL3 STA $1602,x ; / write frame to show
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine - specific to sprite
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03964C

HORIZ_DISP dcb $00,$00,$00,$00,$00,$10
dcb $00,$00,$00,$00,$10,$00
VERT_DISP dcb $F0,$00,$F0,$00,$00,$00
TILEMAP dcb $CC,$EC,$CE,$EE,$AC,$AE
PROPERTIES dcb $40,$00 ;xyppccct format

SUB_GFX JSR GET_DRAW_INFO ; after: Y = index to sprite tile map ($300)
; $00 = sprite x position relative to screen boarder
; $01 = sprite y position relative to screen boarder
LDA $1602,x ; \
ASL A ; | $03 = index to frame start (frame to show * 2 tile per frame)
STA $03 ; /
LDA $157C,x ; \ $02 = sprite direction
STA $02 ; /
PHX ; push sprite index

LDX #$01 ; loop counter = (number of tiles per frame) - 1
LOOP_START PHX ; push current tile number
TXA ; \ X = index to horizontal displacement
ORA $03 ; / get index of tile (index to first tile of frame + current tile number)
PHA ; push index of current tile
LDX $02 ; \ if facing right...
BNE FACING_LEFT ; |
CLC ; |
ADC #$06 ; / ...use row 2 of horizontal tile displacement table
FACING_LEFT TAX ; \
LDA $00 ; | tile x position = sprite x location ($00) + tile displacement
CLC ; |
ADC HORIZ_DISP,x ; |
STA $0300,y ; /
PLX ; \ pull, X = index to vertical displacement and tilemap
LDA $01 ; | tile y position = sprite y location ($01) + tile displacement
CLC ; |
ADC VERT_DISP,x ; |
STA $0301,y ; /

LDA TILEMAP,x ; \ store tile
STA $0302,y ; /


LDX $02 ; \
LDA PROPERTIES,x ; | get tile properties using sprite direction
LDX $15E9
ORA $15F6,x
ORA $64 ; | ?? what is in 64, level properties... disable layer priority??
STA $0303,y ; / store tile properties
TYA ; \ get index to sprite property map ($460)...
LSR A ; | ...we use the sprite OAM index...
LSR A ; | ...and divide by 4 because a 16x16 tile is 4 8x8 tiles
LDX $03 ; | if index of frame start is > 0A
CPX #$0A ; |
TAX ; |
LDA #$00 ; | ...show only an 8x8 tile
BCS SMALL_TILE ; |
LDA #$02 ; | else show a full 16 x 16 tile
SMALL_TILE STA $0460,x ; /
PLX ; \ pull, X = current tile of the frame we're drawing
INY ; | increase index to sprite tile map ($300)...
INY ; | ...we wrote 1 16x16 tile...
INY ; | ...sprite OAM is 8x8...
INY ; | ...so increment 4 times
DEX ; | go to next tile of frame and loop
BPL LOOP_START ; /

PLX ; pull, X = sprite index
LDY #$FF ; \ why FF? (460 &= 2) 8x8 tiles maintained
LDA #$01 ; | A = number of tiles drawn - 1
JSL $01B7B3 ; / don't draw if offscreen
RTS ; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This routine determines which side of the sprite Mario is on. It sets the Y register
; to the direction such that the sprite would face Mario
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SubHorzPos:
LDY #$00
LDA $94
SEC
SBC $E4,x
STA $0F
LDA $95
SBC $14E0,x
BPL HorzIncY
INY
HorzIncY:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B75C

TABLE1 dcb $0C,$1C
TABLE2 dcb $01,$02

GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC TABLE1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA TABLE2,y ; |
STA $186C,x ; |
ON_SCREEN_Y DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; off screen processing code - shared
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B83B

TABLE3 dcb $40,$B0
TABLE6 dcb $01,$FF
TABLE4 dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0
TABLE5 dcb $01,$FF,$01,$FF,$01,$00,$01,$FF

SUB_OFF_SCREEN_MOLE LDA #$06 ; \ entry point of routine determines value of $03
BRA STORE_03 ; |
SUB_OFF_SCREEN_X1 LDA #$04 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X2 LDA #$02 ; |
STORE_03 STA $03 ; |
BRA START_SUB ; |
SUB_OFF_SCREEN_SPR STZ $03 ; /

START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return
BEQ RETURN_2 ; /
LDA $5B ; \ goto VERTICAL_LEVEL if vertical level
AND #$01 ; |
BNE VERTICAL_LEVEL ; /
LDA $D8,x ; \
CLC ; |
ADC #$50 ; | if the sprite has gone off the bottom of the level...
LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
ADC #$00 ; |
CMP #$02 ; |
BPL ERASE_SPRITE ; / ...erase the sprite
LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \
AND #$01 ; |
ORA $03 ; |
STA $01 ; |
TAY ; /
LDA $1A ;x boundry ;A:0101 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0256 VC:090 00 FL:16953
CLC ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0280 VC:090 00 FL:16953
ADC TABLE4,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0294 VC:090 00 FL:16953
ROL $00 ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0326 VC:090 00 FL:16953
CMP $E4,x ;x pos ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0364 VC:090 00 FL:16953
PHP ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0394 VC:090 00 FL:16953
LDA $1B ;x boundry hi ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizCHC:0416 VC:090 00 FL:16953
LSR $00 ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0440 VC:090 00 FL:16953
ADC TABLE5,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdizcHC:0478 VC:090 00 FL:16953
PLP ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0510 VC:090 00 FL:16953
SBC $14E0,x ;x pos high ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0538 VC:090 00 FL:16953
STA $00 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0570 VC:090 00 FL:16953
LSR $01 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0594 VC:090 00 FL:16953
BCC LABEL20 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0632 VC:090 00 FL:16953
EOR #$80 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0648 VC:090 00 FL:16953
STA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0664 VC:090 00 FL:16953
LABEL20 LDA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0688 VC:090 00 FL:16953
BPL RETURN_2 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0712 VC:090 00 FL:16953
ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite
CMP #$08 ; |
BCC KILL_SPRITE ; /
LDY $161A,x ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0140 VC:071 00 FL:21152
CPY #$FF ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0172 VC:071 00 FL:21152
BEQ KILL_SPRITE ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0188 VC:071 00 FL:21152
LDA #$00 ; \ mark sprite to come back A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0204 VC:071 00 FL:21152
STA $1938,y ; / A:FF00 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0220 VC:071 00 FL:21152
KILL_SPRITE STZ $14C8,x ; erase sprite
RETURN_2 RTS ; return

VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \ only handle every other frame??
LSR A ; |
BCS RETURN_2 ; /
AND #$01 ;A:0227 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0228 VC:112 00 FL:1142
STA $01 ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0244 VC:112 00 FL:1142
TAY ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0268 VC:112 00 FL:1142
LDA $1C ;A:0201 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0282 VC:112 00 FL:1142
CLC ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0306 VC:112 00 FL:1142
ADC TABLE3,y ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0320 VC:112 00 FL:1142
ROL $00 ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0352 VC:112 00 FL:1142
CMP $D8,x ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0390 VC:112 00 FL:1142
PHP ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0420 VC:112 00 FL:1142
LDA.W $001D ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNVMXdizcHC:0442 VC:112 00 FL:1142
LSR $00 ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdiZcHC:0474 VC:112 00 FL:1142
ADC TABLE6,y ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdizCHC:0512 VC:112 00 FL:1142
PLP ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0544 VC:112 00 FL:1142
SBC $14D4,x ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0572 VC:112 00 FL:1142
STA $00 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0604 VC:112 00 FL:1142
LDY $01 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0628 VC:112 00 FL:1142
BEQ LABEL22 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0652 VC:112 00 FL:1142
EOR #$80 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0668 VC:112 00 FL:1142
STA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0684 VC:112 00 FL:1142
LABEL22 LDA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0708 VC:112 00 FL:1142
BPL RETURN_2 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0732 VC:112 00 FL:1142
BMI ERASE_SPRITE ;A:0280 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0170 VC:064 00 FL:1195

SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0
ORA $186C,x ; |
RTS ; / return



Wenn ich schon eine Welt nach den Dingern Widme muss es auch verschiedene geben, also wären meine Fragen:
Was muss ich an dem Code verändern damit die mehr Hp hat?
Was muss ich verändern, damit einige von ihnen zwei Schläge hintereinander machen?
Was muss ich verändern, damit sie schneller laufen?
Und zu guter letzt warum brennt mein Pc?

The Lord of Monster Hunter, Auroros.


Projekt: SMWU
Status: Durchführung
News:
12.4.14: Was für ein Timing... zu Spikus Geburtstag komm ich zurück ^^ Und nebenbei beherrsche ich jetzt auch noch Ein wenig ASM
geschrieben am 24.08.2011 15:37:54
( Link )
HI (* freu das das forum wieder on is*)
Code
	print "INIT ",pc
JSR SUB_HORZ_POS
TYA
STA $157C,x
LDA #$19
STA $1528,x
RTL

print "MAIN ",pc
PHB ;\
PHK ; | Change the data bank to the one our code is running from.
PLB ; | This is a good practice.
JSR SpriteCode ; | Jump to the sprite's function.
PLB ; | Restore old data bank.
RTL ;/ And return.

;===================================
;Sprite Function
;===================================

RETURN: RTS

LeftSpd: db $00,$9D,$A0,$A3,$A5,$A8,$AA,$B0,$B4,$B8,$BB,$BD,$C0,$C7,$C8,$C9,$CA,$D0,$D1,$D8,$D9,$E0,$E1,$F6,$F7,$F8
RightSpd: db $00,$75,$72,$6F,$6C,$6A,$67,$5F,$58,$53,$4F,$4B,$49,$3F,$3D,$3B,$3A,$31,$30,$2F,$2E,$21,$20,$0E,$0D,$0C

NameTable: db $11,$19,$78 ;HP:
!NameSize = $02
!Position = $0F24

SpriteCode:
JSR SUB_GFX
PHX
JSR DrawTilemaps ; Draw the tilemaps.
PLX
LDA $1528,x
PHX
JSR HexDec
STX !Position+!NameSize+1
STA !Position+!NameSize+2
PLX
LDA $14C8,x ;\
CMP #$08 ; | If sprite dead,
BNE RETURN ;/ Return.
LDA $9D ;\
BNE RETURN ;/ If locked, return.

LDA $1588,x
AND #$03
BEQ NoFlip ; If touching an object ...
LDA $157C,x
EOR #$01 ; Flip direction.
STA $157C,x

NoFlip:
JSR SUB_OFF_SCREEN_X0 ; Handle offscreen.

LDY $1528,x
LDA $157C,x
BEQ Right
LDA LeftSpd,y
BRA DoSpeed
Right:
LDA RightSpd,y
DoSpeed:
STA $B6,x
LDA #$10
STA $AA,x
JSL $01802A

LDA $1594,x
CMP #$D5
BEQ TIME_TO_SHOOT
INC $1594,x
BRA SHARED

TIME_TO_SHOOT:
JSR DrawSmoke
JSR SUB_FIRE_THROW
STZ $1594,x

SHARED:
JSL $01802A
JSL $03B664
JSR GetSpriteClipping
JSL $03B72B
BCC NoContact

JSR SUB_VERT_POS
LDA $0E
CMP #$E6
BPL SpriteWins

JSL $01AB99
JSL $01AA33
LDA #$A0
STA $7D
DEC $1528,x
LDA $1528,x
BEQ KillSprite
LDA #$54
STA $1DFC ; SFX When jumping on the sprite.
RTS

SpriteWins:
LDA $1490
BNE NoContact ; NOTE: Don't kill the sprite when having a star.
JSL $00F5B7
NoContact:
RTS

KillSprite:
STZ $14C8,x ; die
LDA #$3C
STA $1DFC
JSR DrawSmoke
JSL $07FC3B
LDA #$80
STA $1DFB
LDA #$FF
STA $1493 ; activate "end level" flag
LDA #$00
STA $141C ; normal path
LDA #$0B
STA $71
RTS

;==================================================================
;Draw Tiles To Status Bar.
;==================================================================
DrawTilemaps:
LDX #!NameSize
DrawLoop:
LDA NameTable,x ; Load the tile data indexed by the size.
STA !Position,x ; .. and store to appriopriate tile.
DEX
BPL DrawLoop ; So far, it draws "AAAA"
RTS ; We draw the health routine later, after pulling X.
; ORLY
;==================================================================
;Hex/Dec Subroutine.
;==================================================================
HexDec:
LDX #$00
HexLoop:
CMP #$0A ; While (A == $0A) {
BCC NoConvo ; }
SBC #$0A ; Else { DrawLine.(A - 10); Fail C++ ftw.
INX ; (X + 1) }
BRA HexLoop ; Cout << ("C++ Fail ftw");
NoConvo: ; Oh wait where's the cin command?!
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; fire routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

XF_OFFSET: db $13,$FC
XF_OFFSET2: db $00,$FF

RETURN68: RTS
SUB_FIRE_THROW: ;LDA $15A0,x ; no fire if off screen
LDA $186C,x
ORA $15D0,x
BNE RETURN68

JSL $02A9DE ; \ get an index to an unused sprite slot, return if all slots full
BMI RETURN68 ; / after: Y has index of sprite being generated

LDA #$01 ; \ set sprite status for new sprite
STA $14C8,y ; /

LDA #$B6 ;sprite to fire
STA $009E,y

PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $E4,x
CLC
ADC XF_OFFSET,y
PLY
STA $00E4,y

PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $14E0,x
ADC XF_OFFSET2,y
PLY
STA $14E0,y

LDA $D8,x ; \ set y position for new sprite
SEC ; | (y position of generator - 1)
SBC #$03 ; |
STA $00D8,y ; |
LDA $14D4,x ; |
SBC #$00 ; |
STA $14D4,y ; /

PHX ; \ before: X must have index of sprite being generated
TYX ; | routine clears *all* old sprite values...
JSL $07F7D2 ; | ...and loads in new values for the 6 main sprite tables
PLX ; /


LDA #$09
STA $1DFC

RETURN67: RTS ; return

DrawSmoke: LDY #$03 ; \ find a free slot to display effect
FINDFREE: LDA $17C0,y ; |
BEQ FOUNDONE ; |
DEY ; |
BPL FINDFREE ; |
RTS ; / return if no slots open

FOUNDONE: LDA #$01 ; \ set effect graphic to smoke graphic
STA $17C0,y ; /
LDA #$1B ; \ set time to show smoke
STA $17CC,y ; /
LDA $D8,x ; \ smoke y position = generator y position
STA $17C4,y ; /
LDA $E4,x ; \ load generator x position and store it for later
STA $17C8,y ; /
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite clipping routine
; ripped and modified by Roy, then modified more by Sonikku
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetSpriteClipping:
PHY
PHX
TXY
LDA $00E4,y
CLC
ADC #$04 ; Starting X pos of sprite clipping = sprite center position - $0C ($0C pixels to the left)
STA $04
LDA $14E0,y
ADC #$00
STA $0A
LDA #$30 ; Width of sprite clipping
STA $06
LDA $00D8,y
SEC
SBC #$20 ; Starting Y pos of sprite clipping = sprite center position - $2C ($2C pixels above)
STA $05
LDA $14D4,y
SBC #$00
STA $0B
LDA #$30 ; Height of sprite clipping
STA $07
PLX
PLY
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TILEMAP: db $84,$82,$80 ; facing right
db $A4,$A2,$A0
db $C4,$C2,$C0

db $80,$82,$84 ; facing left
db $A0,$A2,$A4
db $C0,$C2,$C4

db $8A,$88,$86 ; facing right
db $AA,$A8,$A6
db $CA,$C8,$C6

db $86,$88,$8A ; facing left
db $A6,$A8,$AA
db $C6,$C8,$CA

X_OFFSET: db $00,$10,$20
db $00,$10,$20
db $00,$10,$20

Y_OFFSET: db $E0,$E0,$E0
db $F0,$F0,$F0
db $00,$00,$00

PROPERTIES: db $40,$40,$40
db $40,$40,$40
db $40,$40,$40

db $00,$00,$00
db $00,$00,$00
db $00,$00,$00

SUB_GFX: JSR GET_DRAW_INFO ; sets y = OAM offset
LDA $157C,x
STA $04
ASL A
ASL A
ASL A
CLC
ADC $04
STA $02

PHX
LDX #$08
LOOP_START: PHX
LDA X_OFFSET,x
CLC
ADC $00 ; \ tile x position = sprite y location ($01)
STA $0300,y ; /

LDA Y_OFFSET,x
CLC
ADC $01 ; \ tile y position = sprite x location ($00)
STA $0301,y ; /

TXA
CLC
ADC $02
TAX

PHX
LDA $14
LSR A
LSR A
LSR A
AND #$01
BNE SKIP
TXA
CLC
ADC #$12
TAX
SKIP: LDA TILEMAP,x
STA $0302,y
PLX

PHX
LDX $15E9
LDA $15F6,x ; tile properties xyppccct, format
PLX
ORA PROPERTIES,x
ORA $64 ; add in tile priority of level
STA $0303,y ; store tile properties
PLX

INY ; \ increase index to sprite tile map ($300)...
INY ; | ...we wrote 1 16x16 tile...
INY ; | ...sprite OAM is 8x8...
INY ; / ...so increment 4 times
DEX
BPL LOOP_START

PLX
LDY #$02 ; \ 460 = 2 (all 16x16 tiles)
LDA #$08 ; | A = (number of tiles drawn - 1)
JSL $01B7B3 ; / don't draw if offscreen
RTS ; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine. It sets off screen flags, and sets up
; variables. It will return with the following:
;
; Y = index to sprite OAM ($300)
; $00 = sprite x position relative to screen boarder
; $01 = sprite y position relative to screen boarder
;
; It is adapted from the subroutine at $03B760
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1: db $0C,$1C
SPR_T2: db $01,$02

GET_DRAW_INFO: STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X: LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.w #$0040 ; |
CMP.w #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP: LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC SPR_T1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA SPR_T2,y ; |
STA $186C,x ; |
ON_SCREEN_Y: DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID: PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T12: db $40,$B0
SPR_T13: db $01,$FF
SPR_T14: db $30,$C0,$A0,$C0,$A0,$F0,$60,$90 ;bank 1 sizes
db $30,$C0,$A0,$80,$A0,$40,$60,$B0 ;bank 3 sizes
SPR_T15: db $01,$FF,$01,$FF,$01,$FF,$01,$FF ;bank 1 sizes
db $01,$FF,$01,$FF,$01,$00,$01,$FF ;bank 3 sizes

SUB_OFF_SCREEN_X1: LDA #$02 ; \ entry point of routine determines value of $03
BRA STORE_03 ; | (table entry to use on horizontal levels)
SUB_OFF_SCREEN_X2: LDA #$04 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X3: LDA #$06 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X4: LDA #$08 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X5: LDA #$0A ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X6: LDA #$0C ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X7: LDA #$0E ; |
STORE_03: STA $03 ; |
BRA START_SUB ; |
SUB_OFF_SCREEN_X0: STZ $03 ; /

START_SUB: JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return
BEQ RETURN_35 ; /
LDA $5B ; \ goto VERTICAL_LEVEL if vertical level
AND #$01 ; |
BNE VERTICAL_LEVEL ; /
LDA $D8,x ; \
CLC ; |
ADC #$50 ; | if the sprite has gone off the bottom of the level...
LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
ADC #$00 ; |
CMP #$02 ; |
BPL ERASE_SPRITE ; / ...erase the sprite
LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_35 ; /
LDA $13 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0756 VC:176 00 FL:205
AND #$01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0780 VC:176 00 FL:205
ORA $03 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0796 VC:176 00 FL:205
STA $01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0820 VC:176 00 FL:205
TAY ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0844 VC:176 00 FL:205
LDA $1A ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0858 VC:176 00 FL:205
CLC ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0882 VC:176 00 FL:205
ADC SPR_T14,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0896 VC:176 00 FL:205
ROL $00 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizcHC:0928 VC:176 00 FL:205
CMP $E4,x ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:0966 VC:176 00 FL:205
PHP ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:0996 VC:176 00 FL:205
LDA $1B ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizCHC:1018 VC:176 00 FL:205
LSR $00 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdiZCHC:1042 VC:176 00 FL:205
ADC SPR_T15,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizcHC:1080 VC:176 00 FL:205
PLP ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F0 P:eNvMXdizcHC:1112 VC:176 00 FL:205
SBC $14E0,x ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1140 VC:176 00 FL:205
STA $00 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1172 VC:176 00 FL:205
LSR $01 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1196 VC:176 00 FL:205
BCC SPR_L31 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1234 VC:176 00 FL:205
EOR #$80 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1250 VC:176 00 FL:205
STA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1266 VC:176 00 FL:205
SPR_L31: LDA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1290 VC:176 00 FL:205
BPL RETURN_35 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1314 VC:176 00 FL:205
ERASE_SPRITE: LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite
CMP #$08 ; |
BCC KILL_SPRITE ; /
LDY $161A,x ;A:FF08 X:0007 Y:0001 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1108 VC:059 00 FL:2878
CPY #$FF ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1140 VC:059 00 FL:2878
BEQ KILL_SPRITE ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1156 VC:059 00 FL:2878
LDA #$00 ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1172 VC:059 00 FL:2878
STA $1938,y ;A:FF00 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZcHC:1188 VC:059 00 FL:2878
KILL_SPRITE: STZ $14C8,x ; erase sprite
RETURN_35: RTS ; return

VERTICAL_LEVEL: LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_35 ; /
LDA $13 ; \
LSR A ; |
BCS RETURN_35 ; /
LDA $E4,x ; \
CMP #$00 ; | if the sprite has gone off the side of the level...
LDA $14E0,x ; |
SBC #$00 ; |
CMP #$02 ; |
BCS ERASE_SPRITE ; / ...erase the sprite
LDA $13 ;A:0000 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:1218 VC:250 00 FL:5379
LSR A ;A:0016 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1242 VC:250 00 FL:5379
AND #$01 ;A:000B X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1256 VC:250 00 FL:5379
STA $01 ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1272 VC:250 00 FL:5379
TAY ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1296 VC:250 00 FL:5379
LDA $1C ;A:001A X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0052 VC:251 00 FL:5379
CLC ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0076 VC:251 00 FL:5379
ADC SPR_T12,y ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0090 VC:251 00 FL:5379
ROL $00 ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:enVMXdizCHC:0122 VC:251 00 FL:5379
CMP $D8,x ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0160 VC:251 00 FL:5379
PHP ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0190 VC:251 00 FL:5379
LDA $001D ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F2 P:eNVMXdizcHC:0212 VC:251 00 FL:5379
LSR $00 ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdiZcHC:0244 VC:251 00 FL:5379
ADC SPR_T13,y ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdizCHC:0282 VC:251 00 FL:5379
PLP ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:envMXdiZCHC:0314 VC:251 00 FL:5379
SBC $14D4,x ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0342 VC:251 00 FL:5379
STA $00 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0374 VC:251 00 FL:5379
LDY $01 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0398 VC:251 00 FL:5379
BEQ SPR_L38 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0422 VC:251 00 FL:5379
EOR #$80 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0438 VC:251 00 FL:5379
STA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0454 VC:251 00 FL:5379
SPR_L38: LDA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0478 VC:251 00 FL:5379
BPL RETURN_35 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0502 VC:251 00 FL:5379
BMI ERASE_SPRITE ;A:8AFF X:0002 Y:0000 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0704 VC:184 00 FL:5490

SUB_IS_OFF_SCREEN: LDA $15A0,x ; \ if sprite is on screen, accumulator = 0
ORA $186C,x ; |
RTS ; / return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_VERT_POS
; This routine determines if Mario is above or below the sprite. It sets the Y register
; to the direction such that the sprite would face Mario
; It is ripped from $03B829
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SUB_VERT_POS: LDY #$00 ;A:25A1 X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizCHC:0130 VC:085 00 FL:924
LDA $96 ;A:25A1 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdiZCHC:0146 VC:085 00 FL:924
SEC ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0170 VC:085 00 FL:924
SBC $D8,x ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0184 VC:085 00 FL:924
CLC
ADC #$20
STA $0E ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0214 VC:085 00 FL:924
LDA $97 ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0238 VC:085 00 FL:924
SBC $14D4,x ;A:2501 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizcHC:0262 VC:085 00 FL:924
BPL SPR_L11 ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0294 VC:085 00 FL:924
INY ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0310 VC:085 00 FL:924
SPR_L11: RTS ;A:25FF X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizcHC:0324 VC:085 00 FL:924

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB HORZ POS
;
; $B817 - horizontal mario/sprite check - shared
; Y = 1 if mario left of sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B817

SUB_HORZ_POS: LDY #$00 ;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
LDA $94 ;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642
SEC ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642
SBC $E4,x ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1074 VC:097 00 FL:31642
STA $0F ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1104 VC:097 00 FL:31642
LDA $95 ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1128 VC:097 00 FL:31642
SBC $14E0,x ;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642
BPL LABEL16 ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1184 VC:097 00 FL:31642
INY ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1200 VC:097 00 FL:31642
LABEL16: RTS ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642

print 'Insert size: ',bytes


kann mir jemand sagen was ich bei dem code dazu schreiben muss ,damit der gener für ca 3 sekunden unverwundbar ist ,nachdem ich ihn getroffen hab (ich sollte aber trotzdem nosch auf ihn springen können)
und kann man es machen ,dass wenn er nurnoch 5 hp oder so hat der bildschirm dunkler wird?

danke schonmal im forraus
WAS, WIE, WO???? Ne, Ne ich bin nicht die Signatur ...
Ich putze hier nur.

Mein Hack:
<!-- m --><a class="postlink" href="http://www.youtube.com/user/conankun88#p/a/u/0/8vdcyGylrg0">http://www.youtube.com/user/conankun88# ... vdcyGylrg0</a><!-- m -->