It is currently Mon Oct 23, 2017 10:57 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 46 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 9:58 am 
Offline
User avatar

Joined: Wed Oct 16, 2013 7:55 am
Posts: 130
As mentioned earlier, shifts are used to combine what the hardware gives you (a single bit per read) into one byte. This byte represents the entire controller state, using a single bit for each button on the controller (conveniently, the NES controller has 8 buttons).

Shown below are typically the values for each button (depending upon how controller reading is performed, they may be backwards if reading is done in reverse):

Code:
RIGHT_BUTTON = $01
LEFT_BUTTON = $02
DOWN_BUTTON = $04
UP_BUTTON = $08
START_BUTTON = $10
SELECT_BUTTON = $20
B_BUTTON = $40
A_BUTTON = $80


As an example, here's what happens if the player is holding LEFT, START, A and B:

Code:
%1101_0010 = $d2
 || |   |
 || |   +-------- LEFT_BUTTON = $02
 || +------------ START_BUTTON = $10
 |+-------------- B_BUTTON = $40
 +--------------- A_BUTTON = $80


Using AND is a way to strip out a single bit at a time, to see if the corresponding button is currently being pressed.

For the previous example, here's what happens when that value is AND'd with the value for RIGHT_BUTTON, which is not currently being pressed:

Code:
%1101_0010 = $d2
   AND
%0000_0001 = $01 (RIGHT_BUTTON)
----------
%0000_0000


The result is zero, because RIGHT is not being pressed. If instead, the value was AND'd with the value for B_BUTTON:

Code:
%1101_0010 = $d2
   AND
%0100_0000 = $40 (B_BUTTON)
----------
%0100_0000


The result is $40, which is non-zero, because B *is* being pressed.

Whether the result is zero or non-zero is useful, because then we can use BEQ or BNE to jump to another piece of code.


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 10:00 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10068
Location: Rio de Janeiro - Brazil
Maybe it'll help if I rewrite this part:
Code:
;A, B, Select, Start, Up, Down, Left, Right
right = $01
left = $02
down = $04
up = $08
start = $10
select = $20
a_button = $40
b_button = $80

Like this:
Code:
;A, B, Select, Start, Up, Down, Left, Right
right = %00000001
left = %00000010
down = %00000100
up = %00001000
start = %00010000
select = %00100000
a_button = %01000000
b_button = %10000000

Looking at these numbers in binary, you can clearly see that they are masks used to isolate individual bits in a byte. By ANDing them with the byte that contains the states of all buttons you can isolate any bit you're interested in checking. AND is a bitwise operation that only results in 1 if both bits are 1, so the result will be 0 when the button is not pressed, and not 0 when it's pressed.

DementedPurple wrote:
I've figured out that the reason I was having a corrupt file was not the ROM, but rather the emulator. I got a corrupt file in Nestopia, but when I loaded it into Fceux, It worked just fine.

Errr... Nestopia is not crazy, if it says your file is corrupted, your file is not a valid NES ROM. FCEUX might be doing something behind the scenes to make it work, but this is something you should definitely be looking into. What's the exact byte size of the file?


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 10:41 am 
Offline

Joined: Sun Mar 27, 2011 10:49 am
Posts: 192
DementedPurple wrote:
And how would I get the other bit? Do you load a memory address and the use "AND other memory location"

Yes, this. Operations on the 6502 generally use what's in the accumulator as an implicit argument and as the implicit destination. So, for example, AND #$10 will perform a bitwise AND with whatever is in the accumulator and the constant number $10 (that's 10 in hexadecimal, a.k.a. 16 in decimal) and finally put the result in the accumulator. By "bitwise", I mean the rightmost bit of the accumulator will get AND'd with the rightmost bit of the number $10 to form the rightmost bit of the result.


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 11:16 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1787
Location: DIGDUG
Oh crap, did I get the button order wrong?

It should be...
b_button = %01000000 = $40
a_button = %10000000 = $80

Not...
a_button = %01000000
b_button = %10000000

Right?

Dustmop corrected me, tokumaru copied incorrectly from me.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 11:45 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
Okay, I think I get it, it's a way to see if two buttons are pressed. But I have one final question. How come when I run FARIDS edited code, I get a screen filled with the first sprite. I knew I would see the first sprite, but I expected to only see it in the middle of the screen. Is it a bug?


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 11:56 am 
Offline
User avatar

Joined: Wed Oct 16, 2013 7:55 am
Posts: 130
There's no way to know what's wrong with your modified code unless you post code. i, personally, am not psychic.


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 12:00 pm 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
This is the glitched code
Code:
There were a lot of mistakes in your code, I fixed some of them in a way that it works as you want :

Code:
;----------------------------------------------------------------
; constants
;----------------------------------------------------------------

PRG_COUNT = 1 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen

;----------------------------------------------------------------
; variables
;----------------------------------------------------------------

   .enum $0000

   ;NOTE: declare variables using the DSB and DSW directives, like this:

   ;MyVariable0 .dsb 1
   ;MyVariable1 .dsb 3

   .ende

   ;NOTE: you can also split the variable declarations into individual pages, like this:

   ;.enum $0100
   ;.ende

   ;.enum $0200
   ;.ende

;----------------------------------------------------------------
; iNES header
;----------------------------------------------------------------

   .db "NES", $1a ;identification of the iNES header
   .db $01 ;number of 16KB PRG-ROM pages
   .db $01 ;number of 8KB CHR-ROM pages
   .db $00|$01 ;mapper 0 and mirroring
   .dsb 9, $00 ;clear the remaining bytes

;----------------------------------------------------------------
; program bank(s)
;----------------------------------------------------------------

   .base $10000-(PRG_COUNT*$4000)

Reset:
   LDA #$3F
   STA $2006
   LDA #$00
   STA $2006

LDA #$3F
STA $2007
LDA #$30
STA $2007
LDA #$3F
STA $2007
LDA #$3F
STA $2007

LDY #%10001001
STY $2000
LDX #%00011110
STX $2001

LDX #128
STX $0000
STX $0001

Wait:

LDA #1
STA $4016
LDA #0
STA $4016

;Check A
   LDA $4016

;Check B
   LDA $4016

;Check Select
   LDA $4016

;Check Start
   LDA $4016

;Check Up
   LDA $4016
   AND #%00000001
   CMP #%00000001
   BEQ UP

;Check Down
   LDA $4016
   AND #%00000001
   CMP #%00000001
   BEQ DOWN

;Check Left
   LDA $4016
   AND #%00000001
   CMP #%00000001
   BEQ LEFT

;Check Right
   LDA $4016
   AND #%00000001
   CMP #%00000001
   BEQ RIGHT
JMP Wait

UP:
LDX $0001
INX
STX $0001
JMP Wait
DOWN:
LDX $0001
DEX
STX $0001
JMP Wait
LEFT:
LDX $0000
DEX
STX $0000
JMP Wait
RIGHT:
LDY $0000
INY
STY $0000
JMP Wait

NMI:

   LDY #$00
   STY $2003

   LDY $0001
   STY $2004
   LDY #0
   STY $2004
   STY $2004
   LDY $0000
   STY $2004

RTI
   
IRQ:

   ;NOTE: IRQ code goes here
RTI
;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

   .org $fffa

   .dw NMI
   .dw Reset
   .dw IRQ

;----------------------------------------------------------------
; CHR-ROM bank
;----------------------------------------------------------------

   .incbin "Graphics.chr"


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 12:17 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10068
Location: Rio de Janeiro - Brazil
You never initialized the name tables, so if an emulator initializes them with zeroes you're gonna get the first tile repeated over and over. If you want a blank background you have to include a blank tile in your tileset and write the index of that tile to the entire name table being displayed. Never count on anything being initialized automatically, always clear everything yourself. And please, add the PPU warm up loop in your reset code before using the PPU.


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 12:45 pm 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
Another question. Can you use multiple AND commands like this:
Code:
LDA Controller
CMP #1
AND #2
AND #4
BEQ Example


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 12:52 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10068
Location: Rio de Janeiro - Brazil
You can, but each AND will act upon the result of the previous operation, which is probably not what you want. If you want to use multiple masks at once you can do this:
Code:
AND #(1|2|4)

The symbol "|" performs a bitwise OR during assembly, to combine the separate masks into one.

For example, if you want to both START and A to perform the same action, such as start a game, you can do something like this:
Code:
LDA PressedButtons
AND #(MASK_START|MASK_A)
BNE StartGame


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Tue Mar 21, 2017 11:59 pm 
Offline
User avatar

Joined: Wed Apr 07, 2010 1:14 am
Posts: 484
Location: Iran
DementedPurple wrote:
Another question. Can you use multiple AND commands like this:
Code:
LDA Controller
CMP #1
AND #2
AND #4
BEQ Example


No that will not work as you want.
You must read joypad port ($4016) eight times, in order to find out the status of all buttons.
With each read of $4016 the state of only one button is revealed in this order : A B Select Start Up Down Left Right
When you read $4016 a value is loaded into reg A, right?
That value is in this format : #%xxxxxxxj
But the only bit related to joypad buttons is bit0 (j)
bit0 can have two possible values : it can be either 0 or 1, right?
If it is 0 then it shows that the button was not pressed.
If it is 1 then it shows that the button was pressed.
So we have to separate bit0 from other bits (bit1 ~ bit7), because other bits are related to other things which we don't care, they can be any random value
That is why we have to use AND opcode
We AND reg A value with #%00000001, so all of the bits from bit1 ~ bit7 are set to 0, but bit0 keeps it's own value (it means if it was 0 it will be 0, if it was 1 it will be 1)
Then we can use CMP opcode to check the value of bit0 and do the desired action according to it's state

Analyze this to find out what is going on :

Code:
;Check A:
LDA Controller
AND #%00000001
CMP #%00000000
BEQ A_was_not_pressed
CMP #%00000001
BEQ A_was_pressed

;Check B:
LDA Controller
AND #%00000001
CMP #%00000000
BEQ B_was_not_pressed
CMP #%00000001
BEQ B_was_pressed

.
.
.

;Check Right:
LDA Controller
AND #%00000001
CMP #%00000000
BEQ Right_was_not_pressed
CMP #%00000001
BEQ Right_was_pressed


Once you understand what is going on you can use more optimized codes to read joypad


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Thu Mar 23, 2017 10:17 am 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 800
Location: cypress, texas
After creating this line in my input asm file my easiness with the button byte increased dramaticly! :) :mrgreen: Hope it can help you too. :)
Code:
;abetudlr

Since select and start both begin with 's' I chose the second letter of both of them... that way there are 8 different letters each representing its bit! :mrgreen:


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Thu Mar 23, 2017 10:21 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10068
Location: Rio de Janeiro - Brazil
But you don't need to remember the bit order at all if you simply define 8 symbols to use as masks.


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Thu Mar 23, 2017 10:38 am 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 800
Location: cypress, texas
tokumaru wrote:
But you don't need to remember the bit order at all if you simply define 8 symbols to use as masks.

But it really helps me because I can open the trace file (created by FCEUX 2.2.2) with notepad and find "A:41 X:08" and it instantly goes to the first time I pressed a. It's very easy to check controller usage that way! :) :mrgreen:

edit: I'll make that easier to understand later today. : )


Top
 Profile  
 
 Post subject: Re: Corrupt File?
PostPosted: Thu Mar 23, 2017 9:51 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 800
Location: cypress, texas
unregistered wrote:
tokumaru wrote:
But you don't need to remember the bit order at all if you simply define 8 symbols to use as masks.

But it really helps me because I can open the trace file (created by FCEUX 2.2.2) with notepad and find "A:41 X:08" and it instantly goes to the first time I pressed a. It's very easy to check controller usage that way! :) :mrgreen:

edit: I'll make that easier to understand later today. : )


So in our read controller routine is a loop somewhat like this:
Code:
ldx #08
-loop lda $4016
      and #03
      Cmp #01
      rol currentControllerButtons
      Dex
      BNE -loop     


That's its heart. I think I found something like that in Michael Martin's NES 101 Tutorial. Anyways, when making a trace log file in FCEUX 2.2.2. ...the Trace Logger screen appears and I have checked
* Log state of registers
* Log Frames count
* Log emulator messages
* Log Processor status flags
* Log breakpoint hits
* Use Stack Pointer for code tabbing (nesting visualization)
* To the left from disassembly
I click Log to File. Then reset your game because that causes it to start at frame 0. A frame is one cycle through vblank interrupt (NMI) and after the rti it loops once through my main loop. Then it waits for the next vblank to start. Frame 0 ends, frame 1 begins, the i flag is set and frame 1's vblank begins. Causing it to start at 0 decreases the file size.

Move to point in your game where you want to start logging... have to go to sleep will finish tomorrow night.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 46 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group