comprehensive SMB1 disassembly

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Roth
Posts: 400
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Post by Roth »

tepples wrote:MMC3 IRQ routine
Hamtaro126 wrote:YES! It worked!
Now I'm really confused. What just happened, and/or did I miss or forget something from earlier in the thread?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

As far as I can tell, Hamtaro126 was trying to convert SMB1 from NROM to T*ROM, and one of the steps apparently included changing from a sprite 0 based screen split to an MMC3 IRQ based screen split. So I explained how to make the MMC3 IRQ simulate a sprite 0 hit.
DarkCode
Posts: 3
Joined: Thu Jan 08, 2009 5:01 pm

Post by DarkCode »

(a man steps out of the shadows and enters the room)

Where were all you guys when I first started the SMB Hacking Project????

I must say, doppelganger, I don't why you wouldn't use my code as a base (well I do....), but I'm impressed and glad that somebody final figured everything out. Although I wish your code would explain how certain sections worked in depth or made some narration as to the going on's in the code instead of having every stinking line commented. :) Really, I'm just a wee bit jealous. But hey, thanks for giving me credit!

I just recently started looking at my project just a few days ago after years of being buried on my hard drive, and was amazed how easy it was to pick up right where I left off... A couple of years ago, I did a bunch of work on it, but never got around to uploading it.

A little background for those who are curious:

The project was first started back in '99. There were a bunch of reasons for starting it. I had recently gotten into reverse engineering and wanted a reasonably sized project to work with. I was also into game development both of the PC and the NES. Mario became the prime choice for in-depth study. I stumbled across a disassembler which would trace through the code exposing as much as it could which worked perfectly for this project. It took about 4 or 5 iterations before I had enough of a symbol table to expose and separate all the code and data. I tried to get some community help, but only three people ever ended up taking interest in the project. I got tired hit a small stumbling block and gave up mainly because of all the little side projects I had started along the way :) (Mario for the Apple ][, Mario for the PC, a better disassembler, a better assembler, my own NES game, several PC games, etc... typical ADD) that and it was time for college! I only touched the code a little during college in which I made it able to compile in NESasm, and then again only recently.

And that is the story... *coming soon to a theater near you*

It is probably one of the most interesting pieces of code ever written.

It's good to see the project reincarnated.
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

I don't deny that I could have done certain things better (commenting every line seems to be a common pet peeve) and explained things a bit more in-depth...but what you have to realize is that this was my first ever reverse-engineering work, and it was written back when I was still somewhat wet behind the ears concerning coding techniques in games. I've gotten a little older and wiser since then. If and when time permits, I might consider updating it...
Be whatever the situation demands.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Changing the RAM mapping from EQU-style (specifying each RAM label's address individually) to RES-style (allocating most stuff out of a BSS segment) might help. That way, people could rearrange the RAM to keep related data together or change the size of some buffers.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: comprehensive SMB1 disassembly

Post by Movax12 »

ca65 style .res memory layout:

Code: Select all

.segment "ZEROPAGE"

temp_byte:                      .res  8 ; local  temp pointers and vars
ObjectOffset:                   .res  1
FrameCounter:                   .res  1
A_B_Buttons:                    .res  1
Up_Down_Buttons:                .res  1
Left_Right_Buttons:             .res  1
PreviousA_B_Buttons:            .res  1
GameEngineSubroutine:           .res  1
Enemy_Flag:                     .res  7
Enemy_ID :                      .res  7
Player_State:                   .res  1
Enemy_State:                    .res  6
Fireball_State:                 .res  2
Block_State:                    .res  4
Misc_State:                     .res  9
PlayerFacingDir:                .res  1
FirebarSpinDirection:
DestinationPageLoc:             .res  1
VictoryWalkControl:             .res  4
PowerUpType:                    .res  1
FireballBouncingFlag:           .res  2
HammerBroJumpTimer:             .res  9
Player_MovingDir:               .res  1
Enemy_MovingDir:                .res  17

SprObject_X_Speed:
Player_X_Speed:                 .res  1

Enemy_X_Speed:
LakituMoveSpeed:
PiranhaPlant_Y_Speed:
ExplosionGfxCounter:
Jumpspring_FixedYPos:
RedPTroopaCenterYPos:
BlooperMoveSpeed:
XMoveSecondaryCounter:
CheepCheepMoveMFlag:
FirebarSpinState_Low:
YPlatformCenterYPos:            .res 6

Fireball_X_Speed:               .res 2
Block_X_Speed:                  .res 4
Misc_X_Speed:                   .res 9

SprObject_PageLoc:
Player_PageLoc:                 .res  1

Enemy_PageLoc:                  .res  6
Fireball_PageLoc:               .res  2
Block_PageLoc:                  .res  4
Misc_PageLoc:                   .res  9
Bubble_PageLoc:                 .res  3

SprObject_X_Position:
Player_X_Position:              .res  1

Enemy_X_Position:               .res  6
Fireball_X_Position:            .res  2
Block_X_Position:               .res  4
Misc_X_Position:                .res  9
Bubble_X_Position:              .res  3

Player_Y_Speed:
SprObject_Y_Speed:              .res  1

FirebarSpinState_High:
XMovePrimaryCounter:
BlooperMoveCounter:
Enemy_Y_Speed:
LakituMoveDirection:
ExplosionTimerCounter:
PiranhaPlant_MoveFlag:          .res  6

Fireball_Y_Speed:               .res  2
Block_Y_Speed:                  .res  4
Misc_Y_Speed:                   .res  9

SprObject_Y_HighPos:
Player_Y_HighPos:               .res  1

Enemy_Y_HighPos:                .res  6
Fireball_Y_HighPos:             .res  2
Block_Y_HighPos:                .res  4
Misc_Y_HighPos:                 .res  9
Bubble_Y_HighPos:               .res  3

Player_Y_Position:
SprObject_Y_Position:           .res  1

Enemy_Y_Position:               .res  6
Fireball_Y_Position:            .res  2
Block_Y_Position:               .res  4
Misc_Y_Position:                .res  9
Bubble_Y_Position:              .res  3

AreaData:
AreaDataLow:                    .res  1

AreaDataHigh:                   .res  1

EnemyData:
EnemyDataLow:                   .res  1

EnemyDataHigh:                  .res  6
NoteLenLookupTblOfs:            .res  1
Square1SoundBuffer:             .res  1
Square2SoundBuffer:             .res  1
NoiseSoundBuffer:               .res  1
AreaMusicBuffer:                .res  1

MusicData:
MusicDataLow:                   .res  1

MusicDataHigh:                  .res  1
MusicOffset_Square2:            .res  1
MusicOffset_Square1:            .res  1
MusicOffset_Triangle:           .res  1
PauseSoundQueue:                .res  1
AreaMusicQueue:                 .res  1
EventMusicQueue:                .res  1
NoiseSoundQueue:                .res  1
Square2SoundQueue:              .res  1
Square1SoundQueue:              .res  1



.segment "STACK"
; start $0100

blank_stack:                    .res  9 ; not used
VerticalFlipFlag:               .res  4
FlagpoleFNum_Y_Pos:             .res  1
FlagpoleFNum_YMFDummy:          .res  1
FlagpoleScore:                  .res  1
FloateyNum_Control:             .res  7
FloateyNum_X_Pos:               .res  7
FloateyNum_Y_Pos:               .res  7
ShellChainCounter:              .res  7
FloateyNum_Timer:               .res  8
DigitModifier:                  .res  6


.segment "OAMRAM"
; start $0200

Sprite_Data:
Sprite_Y_Position:              .res  1
Sprite_Tilenumber:              .res  1
Sprite_Attributes:              .res  1
Sprite_X_Position:              .res  1

.segment "BSS"
; start $0300

VRAM_Buffer1_Offset:            .res  1
VRAM_Buffer1:                   .res  63
VRAM_Buffer2_Offset:            .res  1
VRAM_Buffer2:                   .res  34

BowserBodyControls:             .res  1
BowserFeetCounter:              .res  1
BowserMovementSpeed:            .res  1
BowserOrigXPos:                 .res  1
BowserFlameTimerCtrl:           .res  1
BowserFront_Offset:             .res  1
BridgeCollapseOffset:           .res  1
BowserGfxFlag:                  .res  30

FirebarSpinSpeed:               .res  16

VineFlagOffset:                 .res  1
VineHeight:                     .res  1
VineObjOffset:                  .res  3
VineStart_Y_Position:           .res  3

BalPlatformAlignment:           .res  1
Platform_X_Scroll:              .res  1

HammerThrowingTimer:
PlatformCollisionFlag:          .res  11

Player_Rel_XPos:
SprObject_Rel_XPos:             .res  1

Enemy_Rel_XPos:                 .res  1
Fireball_Rel_XPos:              .res  1
Bubble_Rel_XPos:                .res  1
Block_Rel_XPos:                 .res  2
Misc_Rel_XPos:                  .res  5
SprObject_Rel_YPos:
Player_Rel_YPos:                .res  1
Enemy_Rel_YPos:                 .res  1
Fireball_Rel_YPos:              .res  1
Bubble_Rel_YPos:                .res  1
Block_Rel_YPos:                 .res  2
Misc_Rel_YPos:                  .res  6

Player_SprAttrib:
SprObject_SprAttrib:            .res  1

Enemy_SprAttrib:                .res  11

SprObject_OffscrBits:
Player_OffscreenBits:           .res  1

Enemy_OffscreenBits:            .res  1
FBall_OffscreenBits:            .res  1
Bubble_OffscreenBits:           .res  1
Block_OffscreenBits:            .res  2
Misc_OffscreenBits:             .res  2
EnemyOffscrBitsMasked:          .res  12
Block_Orig_YPos:                .res  2
Block_BBuf_Low:                 .res  2
Block_Metatile:                 .res  2
Block_PageLoc2:                 .res  2
Block_RepFlag:                  .res  2
SprDataOffset_Ctrl:             .res  2
Block_ResidualCounter:          .res  1
Block_Orig_XPos:                .res  8
AttributeBuffer:                .res  7
SprObject_X_MoveForce:          .res  1

Enemy_X_MoveForce:
YPlatformTopYPos:
RedPTroopaOrigXPos:             .res  21

SprObject_YMF_Dummy:
Player_YMF_Dummy:               .res  1

Enemy_YMF_Dummy:
BowserFlamePRandomOfs:
PiranhaPlantUpYPos:             .res  21

Bubble_YMF_Dummy:               .res  7

Player_Y_MoveForce:
SprObject_Y_MoveForce:          .res  1

CheepCheepOrigYPos:
Enemy_Y_MoveForce:
PiranhaPlantDownYPos:           .res  8

Block_Y_MoveForce:              .res  20
MaximumLeftSpeed:               .res  6
MaximumRightSpeed:              .res  20

Whirlpool_Offset:
Cannon_Offset:                  .res  1

Whirlpool_PageLoc:
Cannon_PageLoc:                 .res  6

Cannon_X_Position:
Whirlpool_LeftExtent:           .res  6

Whirlpool_Length:
Cannon_Y_Position:              .res  6

Cannon_Timer:
Whirlpool_Flag:                 .res  6

BowserHitPoints:                .res  1
StompChainCounter:              .res  12
Player_CollisionBits:           .res  1
Enemy_CollisionBits:            .res  8

Player_BoundBoxCtrl:
SprObj_BoundBoxCtrl:            .res  1

Enemy_BoundBoxCtrl:             .res  6
Fireball_BoundBoxCtrl:          .res  2
Misc_BoundBoxCtrl:              .res  10

BoundingBox_UL_XPos:
BoundingBox_UL_Corner:          .res  1

BoundingBox_UL_YPos:            .res  1

BoundingBox_DR_XPos:
BoundingBox_LR_Corner:          .res  1

BoundingBox_DR_YPos:            .res  1
EnemyBoundingBoxCoord:          .res  80
Block_Buffer_1:                 .res  208
Block_Buffer_2:                 .res  208
BlockBufferColumnPos:           .res  1
MetatileBuffer:                 .res  13
HammerEnemyOffset:              .res  9
JumpCoinMiscOffset:             .res  5
BrickCoinTimerFlag:             .res  2
Misc_Collision_Flag:            .res  13
EnemyFrenzyBuffer:              .res  1
SecondaryHardMode:              .res  1
EnemyFrenzyQueue:               .res  1
FireballCounter:                .res  1
DuplicateObj_Offset:            .res  2
LakituReappearTimer:            .res  2
NumberofGroupEnemies:           .res  1
ColorRotateOffset:              .res  1
PlayerGfxOffset:                .res  1
WarpZoneControl:                .res  1
FireworksCounter:               .res  2
MultiLoopCorrectCntr:           .res  1
MultiLoopPassCntr:              .res  1
JumpspringForce:                .res  1
MaxRangeFromOrigin:             .res  1
BitMFilter:                     .res  1
ChangeAreaTimer:                .res  2
SprShuffleAmtOffset:            .res  1
SprShuffleAmt:                  .res  3

SprDataOffset:
Player_SprDataOffset:           .res  1

Enemy_SprDataOffset:            .res  7

Alt_SprDataOffset:
Block_SprDataOffset:            .res  2

Bubble_SprDataOffset:           .res  3
FBall_SprDataOffset:            .res  2
Misc_SprDataOffset:             .res  9

SavedJoypad1Bits:
SavedJoypadBits:                .res  1

SavedJoypad2Bits:               .res  2
Player_X_Scroll:                .res  1
Player_XSpeedAbsolute:          .res  1
FrictionAdderHigh:              .res  1
FrictionAdderLow:               .res  1
RunningSpeed:                   .res  1
SwimmingFlag:                   .res  1
Player_X_MoveForce:             .res  1
DiffToHaltJump:                 .res  1
JumpOrigin_Y_HighPos:           .res  1
JumpOrigin_Y_Position:          .res  1
VerticalForce:                  .res  1
VerticalForceDown:              .res  1
PlayerChangeSizeFlag:           .res  1
PlayerAnimTimerSet:             .res  1
PlayerAnimCtrl:                 .res  1
JumpspringAnimCtrl:             .res  1
FlagpoleCollisionYPos:          .res  1
PlayerEntranceCtrl:             .res  1
FireballThrowingTimer:          .res  1
DeathMusicLoaded:               .res  1
FlagpoleSoundQueue:             .res  1
CrouchingFlag:                  .res  1
GameTimerSetting:               .res  1
DisableCollisionDet:            .res  1
DemoAction:                     .res  1
DemoActionTimer:                .res  1
PrimaryMsgCounter:              .res  1

ScreenEdge_PageLoc:
ScreenLeft_PageLoc:             .res  1

ScreenRight_PageLoc:            .res  1

ScreenEdge_X_Pos:
ScreenLeft_X_Pos:               .res  1

ScreenRight_X_Pos:              .res  1
ColumnSets:                     .res  1
AreaParserTaskNum:              .res  1
CurrentNTAddr_High:             .res  1
CurrentNTAddr_Low:              .res  1
Sprite0HitDetectFlag:           .res  1
ScrollLock:                     .res  2
CurrentPageLoc:                 .res  1
CurrentColumnPos:               .res  1
TerrainControl:                 .res  1
BackloadingFlag:                .res  1
BehindAreaParserFlag:           .res  1
AreaObjectPageLoc:              .res  1
AreaObjectPageSel:              .res  1
AreaDataOffset:                 .res  1
AreaObjOffsetBuffer:            .res  3
AreaObjectLength:               .res  3
AreaStyle:                      .res  1
StaircaseControl:               .res  1
AreaObjectHeight:               .res  1
MushroomLedgeHalfLen:           .res  3
EnemyDataOffset:                .res  1
EnemyObjectPageLoc:             .res  1
EnemyObjectPageSel:             .res  1
ScreenRoutineTask:              .res  1
ScrollThirtyTwo:                .res  2
HorizontalScroll:               .res  1
VerticalScroll:                 .res  1
ForegroundScenery:              .res  1
BackgroundScenery:              .res  1
CloudTypeOverride:              .res  1
BackgroundColorCtrl:            .res  1
LoopCommand:                    .res  1
StarFlagTaskControl:            .res  1
TimerControl:                   .res  1
CoinTallyFor1Ups:               .res  1
SecondaryMsgCounter:            .res  1
JoypadBitMask:                  .res  4
AreaType:                       .res  1
AreaAddrsLOffset:               .res  1
AreaPointer:                    .res  1
EntrancePage:                   .res  1
AltEntranceControl:             .res  1
CurrentPlayer:                  .res  1
PlayerSize:                     .res  1
Player_Pos_ForScroll:           .res  1
PlayerStatus:                   .res  1
FetchNewGameTimerFlag:          .res  1
JoypadOverride:                 .res  1
GameTimerExpiredFlag:           .res  1

OnscreenPlayerInfo:
NumberofLives:                  .res  1

HalfwayPage:                    .res  1
LevelNumber:                    .res  1
Hidden1UpFlag:                  .res  1
CoinTally:                      .res  1
WorldNumber:                    .res  1
AreaNumber:                     .res  1

OffscreenPlayerInfo:
OffScr_NumberofLives:           .res  1

OffScr_HalfwayPage:             .res  1
OffScr_LevelNumber:             .res  1
OffScr_Hidden1UpFlag:           .res  1
OffScr_CoinTally:               .res  1
OffScr_WorldNumber:             .res  1
OffScr_AreaNumber:              .res  1
ScrollFractional:               .res  1
DisableIntermediate:            .res  1
PrimaryHardMode:                .res  1
WorldSelectNumber:              .res  5
OperMode:                       .res  2
OperMode_Task:                  .res  1
VRAM_Buffer_AddrCtrl:           .res  1
DisableScreenFlag:              .res  1
ScrollAmount:                   .res  1
GamePauseStatus:                .res  1
GamePauseTimer:                 .res  1
Mirror_PPU_CTRL:                .res  1
Mirror_PPU_MASK:                .res  1
NumberOfPlayers:                .res  5
IntervalTimerControl:           .res  1

Timers:
SelectTimer:                    .res  1
PlayerAnimTimer:                .res  1
JumpSwimTimer:                  .res  1
RunningTimer:                   .res  1
BlockBounceTimer:               .res  1
SideCollisionTimer:             .res  1
JumpspringTimer:                .res  1
GameTimerCtrlTimer:             .res  2
ClimbSideTimer:                 .res  1
EnemyFrameTimer:                .res  5
FrenzyEnemyTimer:               .res  1
BowserFireBreathTimer:          .res  1
StompTimer:                     .res  1
AirBubbleTimer:                 .res  3
ScrollIntervalTimer:            .res  1
EnemyIntervalTimer:             .res  7
BrickCoinTimer:                 .res  1
InjuryTimer:                    .res  1
StarInvincibleTimer:            .res  1
ScreenTimer:                    .res  1
WorldEndTimer:                  .res  1
DemoTimer:                      .res  5
PseudoRandomBitReg:             .res  9
MusicOffset_Noise:              .res  1
EventMusicBuffer:               .res  1
PauseSoundBuffer:               .res  1
Squ2_NoteLenBuffer:             .res  1
Squ2_NoteLenCounter:            .res  1
Squ2_EnvelopeDataCtrl:          .res  1
Squ1_NoteLenCounter:            .res  1
Squ1_EnvelopeDataCtrl:          .res  1
Tri_NoteLenBuffer:              .res  1
Tri_NoteLenCounter:             .res  1
Noise_BeatLenCounter:           .res  1
Squ1_SfxLenCounter:             .res  2
Squ2_SfxLenCounter:             .res  1
Sfx_SecondaryCounter:           .res  1
Noise_SfxLenCounter:            .res  1
DAC_Counter:                    .res  1
NoiseDataLoopbackOfs:           .res  3
NoteLengthTblAdder:             .res  1
AreaMusicBuffer_Alt:            .res  1
PauseModeFlag:                  .res  1
GroundMusicHeaderOfs:           .res  3
AltRegContentFlag:              .res  13

TopScoreDisplay:
DisplayDigits:                  .res  6

PlayerScoreDisplay:
ScoreAndCoinDisplay:            .res  27

GameTimerDisplay:               .res  4
WorldSelectEnableFlag:          .res  1
ContinueWorld:                  .res  2
WarmBootValidation:             .res  1

Some of the tabs are messed up, looks okay in my editor, but otherwise it should work. :)

Edit: Fixed tabs.
fwber
Posts: 4
Joined: Fri Jan 18, 2013 5:54 am

Re: comprehensive SMB1 disassembly

Post by fwber »

Read through the entire thing line by line and started to understand assembly (thanks to the comments, no way I would have otherwise), this is a huge effort and I greatly appreciate it, thanks doppelganger.

I wonder how much they changed the physics between SMB1 and SMB3, it's basically the same code with a lot more junk added, right?
strat
Posts: 396
Joined: Mon Apr 07, 2008 6:08 pm
Location: Missouri

Re: comprehensive SMB1 disassembly

Post by strat »

Mario 3 feels different enough that it must have been recoded from scratch. Features like the P-meter would not have been easily integrated into the old code.

While taking a look at the AreaParser routines to understand them better, I started following the game in a debugger just to understand a variable called 'BackloadingFlag' (Which stores the page where the player respawns after dying past the checkpoint and is used to set the AreaData offset at the correct byte). This makes me a little tempted to really analyze the code and recomment it (Giving credit to the original reverse engineer, of course), mainly by breaking the code into subsystems and explaining the program flow and giving a more detailed explanation of the variables.
fwber
Posts: 4
Joined: Fri Jan 18, 2013 5:54 am

Re: comprehensive SMB1 disassembly

Post by fwber »

That would be cool. I'd like to see a breakdown of the hard-coded speed values and some pseudocode for the movement/physics routines for both SMB1 and SMB3 (perhaps the most popular and well-known platformers).

There are just too many bad mario clones out there because nobody knows how to get the movement right.
From reading the source, it isn't even very complicated.
Last edited by fwber on Sun Jan 27, 2013 6:58 pm, edited 2 times in total.
Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: comprehensive SMB1 disassembly

Post by Sik »

Honestly, most clones that have horrible physics are like that because they don't bother implementing acceleration properly (or at all). Yes, gravity included (that's downwards acceleration). Seriously, it's so simple to implement it isn't fun how many games get it wrong. The other issue is control lag, which again I don't get (implementing lagless controls is easier and simpler, seriously o_O just react as soon as the input comes).
fwber
Posts: 4
Joined: Fri Jan 18, 2013 5:54 am

Re: comprehensive SMB1 disassembly

Post by fwber »

From what I can tell, SMB1 doesn't really have "correct" physics at all, just some hardcoded limits based on a modifier (if running faster than [magic number], jump [magic number] height) and arbitrary force values that clamp at a limit, probably whatever felt the best to the designers.

I actually went into thinking it was going to be some fairly complex physics equations but it looks like a bit of a hackjob to me.
Last edited by fwber on Sun Jan 27, 2013 6:59 pm, edited 1 time in total.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Re: comprehensive SMB1 disassembly

Post by 3gengames »

I'm going to guess that you don't know how to program NES, but the reason the game doesn't have hugely complex physics is because the NES is a 1.78Mhz machine. Programming is an art. And putting a full sized physics equation to code doesn't mean it's better programmed at all, most people here would say it's worse. I know I would. That's one thing about programming games back then, you had to find a happy medium between complexity and what result you envisioned. They found a simple, easy way to do it that worked just fine and wasn't hard for the NES to run. Why overcomplicate it? It gains you nothing, and you only lose CPU+RAM. :)
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: comprehensive SMB1 disassembly

Post by Movax12 »

A more readable smb PlayerPhysicsSub: http://mynesdev.blogspot.ca/2013/01/dai ... ost-7.html

I'm going to release the entire HL converted source soon, maybe tomorrow. I am finished converting it, I would just like to name some local variables.
fwber
Posts: 4
Joined: Fri Jan 18, 2013 5:54 am

Re: comprehensive SMB1 disassembly

Post by fwber »

Movax12 wrote:A more readable smb PlayerPhysicsSub
That's fantastic! The assembly commands still take me some time to decipher/look up/get my head around, but this is very readable for noobs like me.
When this is complete perhaps I'll take a shot at porting it to a C-like, so it can be referenced for other platforms.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: comprehensive SMB1 disassembly

Post by tepples »

Sik wrote:The other issue is control lag, which again I don't get (implementing lagless controls is easier and simpler, seriously o_O just react as soon as the input comes).
Perhaps it's that the operating system itself isn't designed around low latency. Some touch screens, for example, sample multiple times to ensure more accurate position readings. Keyboard input is often heavily processed based on an assumption, valid most of the time, that the keyboard is used for inputting text in any of several languages, some of them with fairly complex writing systems. And some adapters from classic SPI controllers to USB add latency as well. Furthermore, video and audio latency contribute to the perception of lag; an operating system's media subsystem may be geared toward the CPU-efficient and/or battery-efficient playback of noninteractive music and video more than toward gaming.
Post Reply