Corrupt File?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Corrupt File?

Post by DementedPurple » Sun Mar 19, 2017 2:07 pm

I'm trying to test my code. It assembles correctly, but when I load my ROM into an emulator, I get a corrupt file. Here is my code:

Code: Select all

;----------------------------------------------------------------
; 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 #$30
STA $3F01
LDA #$3F
STA $3F00
STA $3F02
STA $3F03
LDY #%10001001
STY $2000
LDX #%00011110
STX $2001
LDX #128
STX $0000
STX $0001
LDA #3
STA $4014
JMP ReadController
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
ReadController:
LDA #1
STA $4016
LDA #0
STA $4016
NOP
NOP
LDA 4016
TAY
CPY #5
BEQ UP
CPY #6
BEQ DOWN
CPY #7
BEQ LEFT
CPY #8
BEQ RIGHT
JMP Wait
Wait:
JMP Wait
NMI:
   LDA #$3F
   STA $2006
   LDA #$00
   STA $2006
   LDA 0001
   STA $2004
   LDY #0
   STY $2003
   STY $2003
   LDA 0000
   STA $2004
   
IRQ:

   ;NOTE: IRQ code goes here

;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

   .org $fffa

   .dw NMI
   .dw Reset
   .dw IRQ

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

   .incbin "Graphics.chr"

Pokun
Posts: 1272
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Corrupt File?

Post by Pokun » Sun Mar 19, 2017 4:59 pm

It runs for me (I padded the CHR ROM using a .dsb directive). How big is your "Graphics.chr" file? It should be 8 kB (8192 byte) to fill out all of the CHR ROM space.

This is unrelated, but I also noticed that your NMI- and IRQ-handlers are not ending in RTI instructions. Without an RTI they won't be able to return back to the main code after they have finished, and your game will not work as you want.

User avatar
dougeff
Posts: 2616
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Corrupt File?

Post by dougeff » Sun Mar 19, 2017 5:11 pm

It doesn't matter. None of this code is good.

Look on the bright side. If your file weren't corrupt, it would correctly find it's way to the start of your code (reset), at which point, lots of bad things happen that don't make sense, and wouldn't do what you want. At some point, an NMI would fire, and it would go to NMI, and never come back (without an RTI).

Removed comment. Sounded too harsh.

Would it be ok if I rewrote your code, with code that actually works? Or would you rather work it out for yourself?
nesdoug.com -- blog/tutorial on programming for the NES

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: Corrupt File?

Post by DementedPurple » Sun Mar 19, 2017 5:34 pm

It works when I use a .dsb directive, but when I .incbin "Graphics.chr", I get a corrupt file. One thing I've noticed is that when I do use the .dsb directive and run it in an emulator, I don't see the value in the address storing the X-position increasing when I press the right arrow.

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: Corrupt File?

Post by DementedPurple » Sun Mar 19, 2017 5:39 pm

DementedPurple wrote:It works when I use a .dsb directive, but when I .incbin "Graphics.chr", I get a corrupt file. One thing I've noticed is that when I do use the .dsb directive and run it in an emulator, I don't see the value in the address storing the X-position increasing when I press the right arrow.
And yes, I used RTI

User avatar
FARID
Posts: 484
Joined: Wed Apr 07, 2010 1:14 am
Location: Iran
Contact:

Re: Corrupt File?

Post by FARID » Sun Mar 19, 2017 11:33 pm

There were a lot of mistakes in your code, I fixed some of them in a way that it works as you want :

Code: Select all

;----------------------------------------------------------------
; 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"

User avatar
Hamtaro126
Posts: 765
Joined: Thu Jan 19, 2006 5:08 pm

Re: Corrupt File?

Post by Hamtaro126 » Mon Mar 20, 2017 12:28 am

Next time, do this when necessary:

Code: Select all

OPC $nn ;ZP mode, Optimal
instead of:

Code: Select all

OPC $00nn ;THIS IS RUBBISH!!!
This way it is optimized by using the Zero Page model for opcodes instead of Absolute, It makes a BIG difference in your code when doing this

OPC is an example opcode, Not really a valid 65-series opcode!
AKA SmilyMZX/AtariHacker.

User avatar
tokumaru
Posts: 11466
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Corrupt File?

Post by tokumaru » Mon Mar 20, 2017 12:49 am

Actually, I think ASM6 will optimize for ZP addressing even if you write addresses in the form of $00xx. Whenever I needed to access ZP using absolute addressing (usually in timed code part of Atari 2600 programs) I had to either use mirrors or output the instructions in hex using .db (e.g. .db $ad, $01, $00 for lda $0001).

Anyway, you shouldn't be using hardcoded addresses to begin with... A person can easily forget what each address is used for, which addresses are free, and so on. To avoid bugs that can result from misusing memory positions, you should be naming your variables instead. This is what ENUM, DSB and DSW are for.

Pokun
Posts: 1272
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Corrupt File?

Post by Pokun » Mon Mar 20, 2017 1:41 am

Yeah declare the variables after the ".enum $0000" part like the template explains. Hard-coding RAM registers isn't very useful.
DementedPurple wrote:It works when I use a .dsb directive, but when I .incbin "Graphics.chr", I get a corrupt file. One thing I've noticed is that when I do use the .dsb directive and run it in an emulator, I don't see the value in the address storing the X-position increasing when I press the right arrow.
As I thought, your CHR file is the wrong size. Make sure it's exactly 8192 byte.
The X-position doesn't change because your code has too many problems to work, like people already pointed out. But fix one problem at a time, first make sure the file is the correct size, then you can worry about the code.
DementedPurple wrote: And yes, I used RTI
I don't see an RTI in your code. The missing RTI isn't the only problem though. You read the controller only once. You need to keep reading it every frame (polling) to see if the player pushes any buttons or it will not work. So it must be inside the endless loop like in Farid's fix.

User avatar
dougeff
Posts: 2616
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Corrupt File?

Post by dougeff » Mon Mar 20, 2017 5:55 am

Both @DementedPurple and @FARID...those controller routines are rubbish.

Don't put sprites in the #1 page ($100-1ff). That's the hardware stack.

PPU state and/V-blank are not guaranteed on Reset. You can't write to the PPU outside of v-blank, unless rendering is off. Therefore, you must explicitly disable rendering before writing to PPU, at the start of init code...

LDA #0
STA $2001

and, you SHOULD wait 2 v-blanks before writing to PPU, to ensure it has gone through a 'warm up'.

Controller reads should be done once per frame and rolled/shifted into a RAM address, probably inside the NMI routine. You can then do logic based on a consistent value, throughout the frame (by reading this RAM address).

See the wiki.

EDIT, to clarify. You need to read 4016 8 times to get 8 bits, but only do those 8 reads, once per frame.
nesdoug.com -- blog/tutorial on programming for the NES

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: Corrupt File?

Post by DementedPurple » Mon Mar 20, 2017 7:06 am

Well, I changed the code after putting it on here. And my CHR bank was the exact right size.

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: Corrupt File?

Post by DementedPurple » Mon Mar 20, 2017 10:06 am

And also, could you maybe give an example of a good controller routine?

DementedPurple
Posts: 318
Joined: Mon Jan 30, 2017 5:20 pm
Location: Colorado USA

Re: Corrupt File?

Post by DementedPurple » Mon Mar 20, 2017 10:10 am

And maybe teach me how to make a variable?

User avatar
dougeff
Posts: 2616
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Corrupt File?

Post by dougeff » Mon Mar 20, 2017 10:49 am

3 approaches...

-----------------------------------

SMB2,US (edited)
Reads both controllers, and Japanese expansion controllers

Code: Select all

ReadController:
	LDX #$01
	STX $4016
	DEX
	STX $4016
	LDX #$08
ControllerLoop:
	LDA $4016
	LSR
	ROL $00F5 ;controller 1
	LSR
	ROL $06F4 ;japanese expansion controller 1
	LDA $4017
	LSR
	ROL $00F6 ;controller 2
	LSR
	ROL $06F5 ;japanese expansion controller 2
	DEX
	BNE ControllerLoop
	RTS

Simplified =

Code: Select all

ReadController:
	LDX #$01
	STX $4016
	DEX
	STX $4016
	LDX #$08
ControllerLoop:
	LDA $4016
	LSR
	ROL $00F5 ;controller 1
	DEX
	BNE ControllerLoop
	RTS
-----------------------------------

SMB3
(ran twice, or more, because of possible DMC sound bug, if DMC channel is active)

Code: Select all

	LDY #$01
CheckBothControllers:
	JSR ReadControllers
ControllerCheckAgain:
	LDA $00
	PHA
	JSR ReadControllers
	PLA
	CMP $00
	BNE ControllerCheckAgain

	LDA $00 ;edited
	ORA $01 ;edited combine regular controller and expansion controller bits
	STA $00F7,Y ;controller 1 at f7, controller 2 at f8
	DEY
	BPL CheckBothControllers: ;loops twice, once for each controller
	...
(somewhere else)

Code: Select all

ReadControllers:
	LDA #$01
	STA $4016
	LSR
	STA $4016
	LDX #$08
ControllerLoop:
	LDA $4016,Y ; $4017 first time, 4016 second time
	LSR
	ROL $00	; Controller 2 on first loop, Controller 1 on second loop
	LSR
	ROL $01 ; Japanese Expansion Controller
	DEX
	BNE ControllerLoop:
	RTS
--------------------------

Silver Surfer
;each button shifted to a different RAM address
;A, B, Select, Start, Up, Down, Left, Right

Code: Select all

	LDX #$01
	STX $4016
	DEX
	STX $4016

	LDA $4016
	LSR
	ROR $0321 ;A
	LDA $4016
	LSR
	ROR $0320 ;B
	LDA $4016
 	LSR
	ROR $031F ;Select
	LDA $4016
	LSR
	ROR $031E ;Start
	LDA $4016
	LSR
	ROR $031D ;Up
	LDA $4016
	LSR
	ROR $031C ;Down
	LDA $4016
	LSR
	ROR $031B ;Left
	LDA $4016
	LSR
	ROR $031A ;Right

(similarly for controller 2)
The advantage here, is you can tell how long a player has been pushing a certain button, up to 8 frames worth.


EDIT - I didn't test these. There has been slight editing in some. I'll check them a little later.

Edit2 - typo
Last edited by dougeff on Mon Mar 20, 2017 2:17 pm, edited 2 times in total.
nesdoug.com -- blog/tutorial on programming for the NES

tepples
Posts: 21752
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Corrupt File?

Post by tepples » Mon Mar 20, 2017 11:10 am

And here's the one I use, which treats the 2nd player's bits as a ring counter to avoid having to load X:

pads.s

Post Reply