Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Ask all programming questions here!

Apr 22, 2014 at 4:56:21 PM
DoNotWant (1)

(Ham Sammich) < Eggplant Wizard >
Posts: 441 - Joined: 12/08/2011
Sweden
Profile
Originally posted by: KHAN Games

Originally posted by: Roth

A pointer is going to be a 16-bit number. So where you have.... lda texts, x  sta Text_Pointer... you are loading an 8-bit value. To be super generic about it, you could just do:

lda <#PauseText
sta Text_Pointer+0
lda >#PauseText
sta Text_Pointer+1

Then you would have to use the Y register and not the X. Since the address is in zero page, using (), y will get you want you want:

lda (Text_Pointer), y
sta $2007
iny
;etc etc

Be sure to change Text_Pointer to .res 2, because you want to reserve 2 bytes for it since it is going to be used as a 16-bit address.

Dunno if there's errors in what I said, but that's what it looks like needs to be done to me. Hope it helps! Oh, and the syntax I use is for ca65, you may need to adjust for whatever assembler you use.

Only difference for the NESASM compiler is he'll have to use [] instead of ().  (Assuming he keeps the beginning of his old routine the same.)
 
Sorry to be a picky little dweeb here, but NESASM is an assembler. Compilers are usually a lot more complex than assemblers.



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

Apr 22, 2014 at 5:02:53 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8126 - Joined: 06/21/2007
Florida
Profile
Originally posted by: Mega Mario Man

Originally posted by: KHAN Games

Originally posted by: Roth

A pointer is going to be a 16-bit number. So where you have.... lda texts, x  sta Text_Pointer... you are loading an 8-bit value. To be super generic about it, you could just do:

lda <#PauseText
sta Text_Pointer+0
lda >#PauseText
sta Text_Pointer+1

Then you would have to use the Y register and not the X. Since the address is in zero page, using (), y will get you want you want:

lda (Text_Pointer), y
sta $2007
iny
;etc etc

Be sure to change Text_Pointer to .res 2, because you want to reserve 2 bytes for it since it is going to be used as a 16-bit address.

Dunno if there's errors in what I said, but that's what it looks like needs to be done to me. Hope it helps! Oh, and the syntax I use is for ca65, you may need to adjust for whatever assembler you use.

Only difference for the NESASM compiler is he'll have to use [] instead of ().  (Assuming he keeps the beginning of his old routine the same.)
 
Sorry, using NESASM.

It dislikes < and >. I'm messing with the code trying different things.

 

  LDA #low(PauseText)
  STA TextPointer
  LDA #high(PauseText)
  STA TextPointer+1

Originally posted by: DoNotWant

Sorry to be a picky little dweeb here, but NESASM is an assembler. Compilers are usually a lot more complex than assemblers.

Terminology has never been my strong suit .

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Apr 22, 2014 at 5:13:02 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Working, thanks everyone!

Final code:

TEXTLENGTH .rs 1
TEXTLOWBYTE .rs 1
TEXTHIGBYTE .rs 1
TextPointer .rs 2

  LDA #$05
  STA TEXTLENGTH
 
  LDA #$0E
  STA TEXTLOWBYTE  
  LDA #$21
  STA TEXTHIGBYTE
 
  LDA #low(PauseText)
  STA TextPointer
  LDA #high(PauseText)
  STA TextPointer+1
 
  JSR LoadText


LoadText:
    LDA $2002             ; read PPU status to reset the high/low latch
    LDA TEXTHIGBYTE                                                                                              ; variable
    STA $2006             ; write the high byte of $2000 address
    LDA TEXTLOWBYTE                                                                                             ; variable
    STA $2006             ; write the low byte of $2000 address
    LDX #$00              ; start out at 0

LoadTextLoop:
    LDA [TextPointer], y     ; load data from address (background + the value in x)                          ;variable
    STA $2007             ; write to PPU
    INY                   ; X = X + 1
    CPY TEXTLENGTH           ; Compare X to hex $80, decimal 128 - copying 128 bytes                         ; variable - Character Length
    BNE LoadTextLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
    RTS
 
PauseText:
   .db  $19,$0A,$1E,$1C,$0E     ;PAUSE
UnDrawPauseText:
   .db  $24,$24,$24,$24,$24     ;Undraw Pause





Why doing I need:
  LDA #high(PauseText)
  STA TextPointer+1

I never call for TextPointer+1 in the code. Is it because I somehow made something 16-bit?

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter


Edited: 04/22/2014 at 05:15 PM by Mega Mario Man

Apr 22, 2014 at 5:18:19 PM
DoNotWant (1)

(Ham Sammich) < Eggplant Wizard >
Posts: 441 - Joined: 12/08/2011
Sweden
Profile
Originally posted by: Mega Mario Man

Originally posted by: KHAN Games

Originally posted by: Roth

A pointer is going to be a 16-bit number. So where you have.... lda texts, x  sta Text_Pointer... you are loading an 8-bit value. To be super generic about it, you could just do:

lda <#PauseText
sta Text_Pointer+0
lda >#PauseText
sta Text_Pointer+1

Then you would have to use the Y register and not the X. Since the address is in zero page, using (), y will get you want you want:

lda (Text_Pointer), y
sta $2007
iny
;etc etc

Be sure to change Text_Pointer to .res 2, because you want to reserve 2 bytes for it since it is going to be used as a 16-bit address.

Dunno if there's errors in what I said, but that's what it looks like needs to be done to me. Hope it helps! Oh, and the syntax I use is for ca65, you may need to adjust for whatever assembler you use.

Only difference for the NESASM compiler is he'll have to use [] instead of ().  (Assuming he keeps the beginning of his old routine the same.)
 
Sorry, using NESASM.

It dislikes < and >. I'm messing with the code trying different things.

 
Watch out dude. If you do this:
STA #$00, X
intending that to be a zero page, X instruction, it won't be. It will still assemble to an absolute, X instruction, wasting 1 byte and 1 cycle.
In NESASM you would have to do it like STA <#$00, X so sometimes < is useful.


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

Apr 22, 2014 at 5:27:16 PM
Roth (67)
avatar
(Rob Bryant) < Lolo Lord >
Posts: 1777 - Joined: 09/14/2006
Illinois
Profile
You were trying to reach a 16-bit address with the table you had setup with .word. NES uses something called little endian (just Google that), and the +1 is the high byte of the address, whereas the +0 is the low byte. The only 8-bit addresses you'll be messing with are zeropage : ). But yeah, maybe just look up little endian 6502 or something. It should make sense. Ask questions if not!

-------------------------
http://slydogstudios.org...

Apr 22, 2014 at 5:40:53 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Roth

You were trying to reach a 16-bit address with the table you had setup with .word. NES uses something called little endian (just Google that), and the +1 is the high byte of the address, whereas the +0 is the low byte. The only 8-bit addresses you'll be messing with are zeropage : ). But yeah, maybe just look up little endian 6502 or something. It should make sense. Ask questions if not!
Thanks. I know what little endian and big endian are. So, it is calling the address of PauseText in the register? If so, that was a huge light bulb!

I always thought it was doing this (but I am guessing I was wrong):

  LDA #low(PauseText)                            = $19 (First number of .db  $19,$0A,$1E,$1C,$0E)
  STA TextPointer
  LDA #high(PauseText)                           = $0E (First number of .db  $19,$0A,$1E,$1C,$0E)                         
  STA TextPointer+1

PauseText:
   .db  $19,$0A,$1E,$1C,$0E     ;PAUSE


If I am right, it is saying PauseText is stored at $WXYZ (just using placeholder numbers) and Low is YZ and High is WX?
So, when you point to it using [TextPointer], it grabs it as $WXYZ.

I hope I am right now, because I used to be so lost with this! Thanks ROTH!
Sorry for all of the questions, this was good for me today...


-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 22, 2014 at 6:14:54 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8126 - Joined: 06/21/2007
Florida
Profile
You are correct with the address assumption.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Apr 22, 2014 at 7:38:35 PM
Roth (67)
avatar
(Rob Bryant) < Lolo Lord >
Posts: 1777 - Joined: 09/14/2006
Illinois
Profile
Right on! Now, to show you why this is so helpful, I'll make a short bit o' code for you to check out. If you already understand what I'm about to post, then cool, maybe it will help someone else hehe Anywho, let's use palettes as an example. And let's say for every level in the game, you have a different full 32 byte palette that you want to use. The typical way for a small game is to just do something like this:
 
 
ldx #$00
: lda palette_address, x
sta $2007
inx
cpx #$20
bne :-
 
 
Well now (assuming this is while rendering is off), someone could do this:
 
 
ldx current_level
lda palette_table_lo, x
sta palette_addy+0
lda palette_table_hi, x
sta palette_addy+1
 
lda #$3f
sta $2006
lda #$00
sta $2006
ldy #$00
: lda (palette_addy), y
sta $2007
iny
cpy #$20
bne :-
 
 
And then in ROM, you have two tables set up, and the order in which your palettes go according to the game engine:
 
 
palette_table_lo:
.byte <palette_lvl1, <palette_lvl2, <palette_lvl3, <palette_lvl4
palette_table_hi:
.byte >palette_lvl1, >palette_lvl2, >palette_lvl3, >palette_lvl4
 
 
And those two tables are pointing, with the low and the high addresses, to each 32 byte palette that you have stored:
 
 
palette_lvl1:
.byte $0f,$07,$04,$0f, $0f,$07,$19,$0f, $0f,$0c,$04,$0f, $0f,$00,$27,$16
.byte $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f
palette_lvl2:
.byte $0f,$00,$10,$30, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f
.byte $0f,$00,$10,$30, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f, $0f,$0f,$0f,$0f
palette_lvl3:
; etc
palette_lvl4:
; etc
 
 
So then, when a level is finished and you are ready to start loading the next level, you just increment the variable current_level. So the first time X would grab the low and high bytes of palette_lvl1, because the offset of current_level was at zero.  Then when loading the next level, palette_lvl2, the low and high bytes of the address, will be loaded by X because current_level is used as the offset, and it is at 1 now. Etc etc.
 
Hopefully that wasn't too much to digest, but I think learning this kind of concept early is REALLY helpful and will help set up programs with more ease than what some might think is possible when learning.

EDIT: Put missing bytes from the palette_table_lo table. Seems like NA's rendering of the code tag isn't all that haha

-------------------------
http://slydogstudios.org...


Edited: 04/22/2014 at 10:37 PM by Roth

Apr 22, 2014 at 9:45:58 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
This is great stuff. Even with the syntax I'm not familiar with (since I code for NESASM), I was able to follow it. I was thinking last week that you should be able to load different palettes for different levels.

I have been getting more used to seeing code written for the ca65 assembler because last week I download the !Clik! source code from your site to see how you handled moving from Title Screen to Game Play. Needless to say, I was pretty confused when I first saw it.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 23, 2014 at 2:07:23 PM
chowder (2)
avatar
(Rob H) < Eggplant Wizard >
Posts: 253 - Joined: 02/13/2014
England
Profile
It's really personal preference, but I love asm6 - it's simple, and the syntax just makes sense to me:
http://home.comcast.net/~olimar/NES/

There are some templates over on NesDev that can get you started quickly:
http://forums.nesdev.com/viewtopi...

ca65 is the way to go for huge projects I imagine, but the learning curve/extra setup stuff just isn't worth it to me at the moment.

Edit: Fixed broken asm6 link


Edited: 04/23/2014 at 02:08 PM by chowder

Apr 23, 2014 at 4:38:04 PM
DoNotWant (1)

(Ham Sammich) < Eggplant Wizard >
Posts: 441 - Joined: 12/08/2011
Sweden
Profile
Here you have CA65 templates for NROM and SG/SNROM. http://forums.nesdev.com/viewtopi...
I think one of the biggest hurdles when changing from NESASM, ASM6 or something similar to CA65 is the separate linker.

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


Edited: 04/23/2014 at 04:39 PM by DoNotWant

Apr 24, 2014 at 2:27:50 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
So, I need a way to check if I have exceed a limit.

Is this how I do it?


Subroutine:
   LDA Variable
   CMP #$50
   BMI SubroutineDone   
      CODE TO RUN

SubroutineDone:
  RTS


Basically, when Variable hits 50 or any number above 50, I want to run CODE TO RUN.

The issue is, I am incrementing Variable with different number (1,2,3,4,5), so my program may not always hit 50.

Thanks



-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 24, 2014 at 2:35:58 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Nevermind, I figured it out finally. I was right.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 24, 2014 at 9:31:23 PM
Mario's Right Nut (352)
avatar
(Cunt Punch) < Bowser >
Posts: 6636 - Joined: 11/21/2008
Texas
Profile
BMI and BPL deal with bit 7, or %10000000.

BCS and BCC deal with greater/less than. In that case, you'd use bcc.

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

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Apr 25, 2014 at 12:35:35 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Mario's Right Nut

BMI and BPL deal with bit 7, or %10000000.

BCS and BCC deal with greater/less than. In that case, you'd use bcc.
Interesting, BMI working great for me in many locations.

From what I read, the CMP will set the Negative flag (bit 7) if the compare is negative. In my case, I am enabling features in later levels. So, I compare the LevelVariable (set to Level 1) to #$04. The compare sets the negative flag because 1-4= -3. Once the Negative Flag clears in the compare (4-4=0 or 5-4=1), then the new feature is unlocked for the rest of the game.

I will be posting my new ROM in a bit on the private thread. You can check it out there.

EDIT: New ROM was posted last night.



-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter


Edited: 04/25/2014 at 07:49 AM by Mega Mario Man

Apr 25, 2014 at 7:33:04 AM
Mario's Right Nut (352)
avatar
(Cunt Punch) < Bowser >
Posts: 6636 - Joined: 11/21/2008
Texas
Profile
I guess we are both correct. I was talking about LDA. I didn't know you could use those commands for compare! Interesting.


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

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Apr 25, 2014 at 9:55:30 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
So, I was doing some research of general 6502 programming and it looks like the accepted standard way for 'less than & greater than\equal to' is BCC and BCS. BMI and BPL can do the same thing in a compare situation, however, it may be slow. I think I am seeing this issue when writing text to the sceen using BMI. I am going to replace BMI with BCC and see if it improves it.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 25, 2014 at 10:13:58 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
So, it may have been a fluke, but bcc seems like a faster command than bmi how I was using it. From 6502.org, here is the bast ways to do all comparisons:

If the Z flag is 0, then A <> NUM and BNE will branch
If the Z flag is 1, then A = NUM and BEQ will branch
If the C flag is 0, then A (unsigned) < NUM (unsigned) and BCC will branch
If the C flag is 1, then A (unsigned) >= NUM (unsigned) and BCS will branch

Link: http://www.6502.org/tutorials/com...

So basically:
BNE to check for not equal <>
BEQ to check for equal =
BCC to check for less than <
BCS to check for greater than equalto >=

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter


Edited: 04/25/2014 at 10:15 AM by Mega Mario Man

Apr 25, 2014 at 3:20:56 PM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
They operate the same speed, your code is 99% chance bugged. And using 2 branches is only acceptible when you HAVE to do the math a vertain way, because you can subtract 1 value from one of the numbers and do the compare and always get a 1-branch determination for what you need.

Apr 26, 2014 at 8:35:14 AM
Mario's Right Nut (352)
avatar
(Cunt Punch) < Bowser >
Posts: 6636 - Joined: 11/21/2008
Texas
Profile
Is there a way to program a game to auto detect if you're using an emulator or hardware?

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

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Apr 26, 2014 at 8:38:22 AM
Roth (67)
avatar
(Rob Bryant) < Lolo Lord >
Posts: 1777 - Joined: 09/14/2006
Illinois
Profile
Originally posted by: Mario's Right Nut

Is there a way to program a game to auto detect if you're using an emulator or hardware?


Get ahold of tepples. I believe he came up with code that does that.

-------------------------
http://slydogstudios.org...

Apr 26, 2014 at 11:02:57 AM
Shiru (0)

(Shiru Shiru) < Meka Chicken >
Posts: 677 - Joined: 06/08/2011
Russian Federation
Profile
It is possible to detect older or current emulators, but just as you use such detection, emulators will eventually consider your trick and it'll stop to work. Not to mention that all your tricky detection code could be disabled by a romhacker in minutes.

One of ways is to check initial RAM/VRAM contents. Emulators clear it out on start up, but it is never clear on actual hardware, and has semi-random data pattern instead.


Edited: 04/26/2014 at 11:03 AM by Shiru

Apr 26, 2014 at 11:17:43 AM
Mario's Right Nut (352)
avatar
(Cunt Punch) < Bowser >
Posts: 6636 - Joined: 11/21/2008
Texas
Profile
I more just want to set it to change control styles on emulator vs hardware.

Not really for hackers. Last time I had a choice on the start screen. It would just be cool to be automatic.

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

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Apr 26, 2014 at 11:40:32 AM
Shiru (0)

(Shiru Shiru) < Meka Chicken >
Posts: 677 - Joined: 06/08/2011
Russian Federation
Profile
In this case, there is no reliable way to detect emulators in general. The whole idea of emulators is to recreate a system as closely as possible, so in an ideal emulator there are no chances of detection at all, it should be 100% identical to the original. As emulators aren't 100% exact just yet (but close enough), you can detect flaws in certain emulators, or tricky things that aren't emulated properly so far. There are chances of false detections as well.

One way to provide reliable detection is to introduce virtual register in every emulator, which is not exist on the original hardware, and reading it will always provide clear answer is it emulator or not.

Apr 26, 2014 at 1:15:55 PM
bunnyboy (81)
avatar
(Funktastic B) < Master Higgins >
Posts: 7704 - Joined: 02/28/2007
California
Profile
Unfortunately ways to tell most emulators need eyeballs, like many get the grayscale flag wrong. At least most people use old emulators so any tricks you do figure out won't be fixed! Theres a few emu specific bugs like flags after BRK but it would take a lot of those checks to cover all the popular ones.