It is currently Tue Feb 19, 2019 4:18 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Feb 06, 2019 1:07 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
EDIT: My problem has been solved! Among other things, I was stupid and tried to TYX. Interestingly enough, ASM6 seems to have read that as a label and didn't fail on compile.

Hey all,

I've been working on this for a while, and I've hit a point where I just don't know what to fix.

I'm working on a metatile routine. Metatile is 2x2 tiles, and it seemed to work alright. However, now I'm working on adding attribute mapping based on the metatile, and it's all messed up.

Here's my metatile attribute routine. The idea is that it's supposed to read the metatile number from the game map in "metascr", and then use that index to lookup the palette number (0 - 3) for the corresponding metatile in "METAattr". Right now, all of the metatiles should be with palette 0 except for the blank sky, #$15, which is palette 01. Then I'm shifting bits to the left, and adding the resulting number to the attribute number I have stored. At the end, I'm writing the number to $2007. I think I'm starting at the right address in $2006, just doing what NerdyNights had.

Var attrtemp is used to store my attribute byte, and var attrx is used to store my X counter before I TAX.

Code:
LoadMETAattr:
  LDA $2002      ;read PPU to reset high/low latch
  LDA #$23
  STA $2006      ;write hight byte of $23C0 address
  LDA #$C0
  STA $2006      ;write low byte of $23C0 address
  LDX #$00
  LDY #$00
LoadMETAattrLoop:
  TYX
  LDA metascr, x   ;load data from metatable
  STX attrx
  TAX
  LDA METAattr, x
  STA attrtemp      ;load first attr
  LDX attrx
  INX
  LDA metascr, x
  STX attrx
  TAX
  LDA METAattr, x
  ASL A
  ASL A            ;multiply second attr by 4
  CLC
  ADC attrtemp
  STA attrtemp
  LDX attrx
  DEX
  TXA
  CLC
  ADC #$10
  TAX
  LDA metascr, x
  STX attrx
  TAX
  LDA METAattr, x
  ASL A
  ASL A
  ASL A
  ASL A            ;multiply third attr by 16
  CLC
  ADC attrtemp
  STA attrtemp
  LDX attrx
  INX
  LDA metascr, x
  STX attrx
  TAX
  LDA METAattr, x
  ASL A
  ASL A
  ASL A
  ASL A
  ASL A
  ASL A            ;multiply fourth attr by 64
  CLC
  ADC attrtemp
  STA attrtemp
  STA $2007
  INY
  INY
  CPY #$10
  BNE LoadMETAattrLoop
  JMP METAattrdone


When I compile and run, I get something really weird. My loop increments Y twice at the end, and should end when Y==16, so I'm only expecting to apply attributes to the first 8 32x32 attribute squares (if this was working correctly, the first row of 16px metatiles would be palette 0, the second would be palette 1, all subsequent would be palette 0). But it seems that instead, random 32px attribute squares are of only palette 1, all over the screen. To compound this, more and more attribute squares are changed to palette 1 when I reset. Making things weirder still, when I change to PAL mode, I can see that there is a single background tile on the top which is completely incorrect, and this tile changes position when I reset.

I know there are multiple things I must be doing wrong. I know this means I'm not handling my reset correctly, but I don't know enough to fix it. Could someone out there walk me through the changes I need to make to apply this correctly? I realize this is a lot to ask.

Attached is the entire ASM file. It's not too huge, based on the NerdyNights week 6, and in ASM6 symtax.

EDIT: Also attached are the CHR and NES files if you want to test it out.


Attachments:
abduction.chr [8 KiB]
Downloaded 3 times
metatile_attr.nes [24.02 KiB]
Downloaded 3 times
metatile_attr.asm [12.42 KiB]
Downloaded 3 times


Last edited by samwise970 on Wed Feb 06, 2019 4:20 pm, edited 2 times in total.
Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 1:40 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 958
Location: cypress, texas
Note: There isn't a tyx available in 6502. You could tya, tax... or, like tokumaru taught me, you could set up a page of ROM (i.e. $E0xx) to hold its low byte value... i.e. $E000 holds #$00, $E001 holds #$01, etc... and then use ldx $E000, y. :)


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 1:46 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2437
Location: DIGDUG
Also, don't calculate this during v-blank (inside the NMI). Preferably, you would pre-calculate this and store it in a buffer, and then, during NMI just copy the changes quickly.

Maybe it works now, but maybe you try to add something, like palette swapping, and this runs into the frame, and fails.

One more thing.
6 asl's is the same as

lsr
ror a
ror a

and "ora" is a bit faster than "clc adc" for this.

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


Last edited by dougeff on Wed Feb 06, 2019 1:51 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 1:49 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
Some of the problem seems to lay in lines 170,171 & 224,225 of my code.

170,171
Code:
  LDA #%00000000   ; disable sprites, disable background, no clipping on left side
  STA $2001


224,225
Code:
  LDA #%00011110   ; enable sprites, enable background, no clipping on left side
  STA $2001 


I was disabling rendering and enabling it again before and after my main Metatile routine. When I ran the attribute routine, I had rendering already on.
However, it doesn't seem to have totally fixed the problem. It looks a lot better, but only the first 32px attribute tile is what I'd expect (top two 16px tiles are palette 0, bottom two are palette 1). The rest of the attribute tiles are all palette 1, top and bottom...

Attached is a revised .NES

after I uploaded the file I saw unregistered's reply. I'll take that into account and see if it fixes anything!

Doug, thanks as always... I didn't think I was calculating inside the NMI.. clearly I need more knowledge on NMI and vblank


Attachments:
metatile_attr.nes [24.02 KiB]
Downloaded 3 times
Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 2:02 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
unregistered was right. I should've known about TYX. Changing to TYA and then TAX fixed the issue. It seems to work now!

https://wiki.nesdev.com/w/index.php/The_frame_and_NMIs
I see what you're talking about now Doug. I'm drawing to $2007, so that code has to be in vblank. And there's not much vblank time, so I'm wasting it on logic.

You're saying I need to write to a buffer var instead of directly to $2007, then write to $2007 all at once, right? What size does my buffer need to be? Hopefully it doesn't need to be the entire size of the screen (960 bytes). Can I have a 32 byte buffer and write each row at a time?


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 2:10 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3866
Location: A world gone mad
I'm curious: what assembler are you using that permitted you to use the 65816 tyx ($bb) opcode? If it's a 65816 assembler that doesn't offer a way to enable a strict 6502 (not 65c02!) mode, then OK, mistakes happen. Else if it does offer such (and is used), or it's a 6502 assembler, then that's incredibly broken and should be reported.


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 2:13 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
koitsu wrote:
I'm curious: what assembler are you using that permitted you to use the 65816 tyx ($bb) opcode? If it's a 65816 assembler that doesn't offer a way to enable a strict 6502 (not 65c02!) mode, then OK, mistakes happen. Else if it does offer such (and is used), or it's a 6502 assembler, then that's incredibly broken and should be reported.


I'm using ASM6 v1.6

EDIT: On further investigation, I think ASM6 doesn't process commands that it doesn't recognize. I tried imputting some garbage, just randomly typed LDO, and it still compiled with no affect on the program. It's not that ASM6 was using the TYX, it just was skipping over that line since it didn't recognize TYX as a command.


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 2:32 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3866
Location: A world gone mad
samwise970 wrote:
I'm using ASM6 v1.6

Congratulations, you've found a quirk/bug in the assembler. The parser is treating lines that don't match opcodes as labels. In other words, it thinks tyx is a label:

Code:
D:\downloads\x>\console\bin\asm6

asm6 1.6

Usage:  asm6 [-options] sourcefile [outputfile] [listfile]

    -?          show this help
    -l          create listing
    -L          create verbose listing (expand REPT, MACRO)
    -d<name>    define symbol
    -q          quiet mode (no output unless error)

See README.TXT for more info.

D:\downloads\x>\console\bin\asm6 test.asm test.o test.lst
pass 1..
test.o written (12 bytes).
test.lst written.

D:\downloads\x>type test.lst

                                  .org $8000
08000
08000                           main:
08000 78                          sei
08001 18                          clc
08002                             tyx       ; this should ideally fail to assemble
08002 A9 01                       lda #$01
08004 A9 02                       lda #<tyx
08006 85 00                       sta $00
08008 A9 80                       lda #>tyx
0800A 85 01                       sta $01
0800C

asm6f (version as of this writing) suffers from the same problem.

In short: opcode typos or existence assumptions in asm6 v1.6 can (will) result in the assembler treating such mistake as a label, resulting in successful assembly (because it's perfectly OK to have a label on a line by itself) rather than an error. Improving the parser (making it substantially more strict) is the only way to accomplish this. There are some ways to kludge-fix this but that subject's off-topic for this thread.


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 2:58 pm 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 578
Location: Central Illinois, USA
koitsu wrote:
samwise970 wrote:
I'm using ASM6 v1.6

Congratulations, you've found a quirk/bug in the assembler. The parser is treating lines that don't match opcodes as labels. In other words, it thinks tyx is a


Wow, that's disastrous. That means typos compile happily and break silently. How is this not already widely known?

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:02 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
Sick! Thanks for the explanation.

If ASM6 is treating "TYX" as a label, does that mean I could later write something like
Code:
  LDX #$00
TYX
  INX
  CPX #$10
  BNE TYX

Talk about confusing.

In my mind, this could be fixed by simply checking labels for a colon ":" at the end. If it did that, then
Code:
  LDX #$00
TYX:
  INX
  CPX #$10
  BNE TYX

would compile, and my first example would fail. But IDK.


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:03 pm 
Offline
User avatar

Joined: Fri Nov 24, 2017 2:40 pm
Posts: 126
dougeff wrote:
Also, don't calculate this during v-blank (inside the NMI).


Yeah... and don't try and save memory by reading attribute table back back from the PPU either. In the end I had > 1k of memory sitting unused, and I wrote this monstrosity to save 64 bytes. O_o (Though it did work, and was kinda fun to write anyway) https://github.com/slembcke/critical-ma ... etatiles.s


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:12 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3866
Location: A world gone mad
gauauu wrote:
Wow, that's disastrous. That means typos compile happily and break silently. How is this not already widely known?

Loopy kept asm6 as simple as possible, adhering to KISS quite strictly. Take a look at the code sometime if you haven't -- it's nothing like you probably imagine (it wasn't for me anyway, as an author of a disassembler). Parsers are notoriously painful to implement (and C doesn't make this any easier/more pleasant). The subject of spacing (read: whitespace and tabs) becomes important quickly, and just as quick brings up the importance of a BNF for syntax compliance, thus bringing things like yacc/bison into the mix, and suddenly you have a whole non-KISS-compliant assembler with dependencies. One of the things that makes asm6 beautiful is that it's a single .c file with no dependencies (practically a diamond-tipped needle in a haystack compared to most of today's software).

Generally speaking, a kludge fix would be to require that labels by themselves (on a single line) must end with : (and trailing spacing stripped/ignored), else the line should be parsed/treated as opcodes/macros/whatever (i.e. whatever it currently does). But here I am giving a terse simple solution that hasn't been tested or even ensured it can work; I don't write assemblers, so I shouldn't be considered authoritative on how to solve such parsing complexities. Anyway, it's subject for another thread...


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:18 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11166
Location: Rio de Janeiro - Brazil
Is it really a bug, though? If that's not a supported instruction, it is a valid label after all. Are assemblers supposed to blacklist certain words because they're instructions in other CPUs?

Not requiring a colon after labels was definitely a design choice, not an oversight, probably for compatibility reasons. I don't know how one word to shoot fixing this "bug" without breaking that compatibility or blacklisting words based on instructions from other CPUs...

I'm coding my own assembler right now and I'm pretty sure it'll have this "bug" too, for the same reasons.


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:34 pm 
Offline

Joined: Tue Oct 17, 2017 12:13 am
Posts: 15
tokumaru wrote:
Is it really a bug, though? If that's not a supported instruction, it is a valid label after all. Are assemblers supposed to blacklist certain words because they're instructions in other CPUs?

Not requiring a colon after labels was definitely a design choice, not an oversight, probably for compatibility reasons. I don't know how one word to shoot fixing this "bug" without breaking that compatibility or blacklisting words based on instructions from other CPUs...

I'm coding my own assembler right now and I'm pretty sure it'll have this "bug" too, for the same reasons.


I guess my question would be, do CA65 and NESASM also interpret all non-commands as labels? I understand your argument for compatibility, but idk if I agree. I'm trying to imagine if Python interpreted everything it didn't recognize as an IF statement missing the colon haha


Top
 Profile  
 
PostPosted: Wed Feb 06, 2019 3:59 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11166
Location: Rio de Janeiro - Brazil
ca65 requires colons after labels by default. There is a "labels_without_colons" option, but then it forces labels to be placed at the very beginning of the line. These rules slone are enough to prevent this bug (as long as instructions are indented, which is the norm in assembly), but since it's also aware of other 65xx variants, it may in fact handle this case more specifically.


Last edited by tokumaru on Wed Feb 06, 2019 4:02 pm, edited 1 time in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  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