It is currently Tue Nov 20, 2018 8:31 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 4:35 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
So I'm creating some new demo code and I've been playing around with the ca65 .cfg file to try and understand it better (as you may know if you've answered some of my previous questions on this forum).

In my Nesteroids game when I set up the vectors I was doing it the way I learned from rainwarrior's demo code.

It looked like this:
Code:
.segment "VECTORS" ; THIS IS THE LAST 6 BYTES OF THE FILE, USED AS ADDRESSES FOR INTERRUPTS
.word nmi
.word reset
.word irq


For some reason in my new code, the irq was getting executed instead of the nmi, so I had to reverse the order in that segment like this:
Code:
.segment "VECTORS" ; THIS IS THE LAST 6 BYTES OF THE FILE, USED AS ADDRESSES FOR INTERRUPTS
.word irq
.word reset
.word nmi


I had been playing around with the .cfg files to try and understand them better. Here is the original:
Code:
MEMORY {
    ZP:     start = $00,    size = $0100, type = rw, file = "";
    OAM:    start = $0200,  size = $0100, type = rw, file = "";
    RAM:    start = $0300,  size = $0500, type = rw, file = "";
    HDR:    start = $0000,  size = $0010, type = ro, file = %O, fill = yes, fillval = $00;
    PRG:    start = $8000,  size = $8000, type = ro, file = %O, fill = yes, fillval = $00;
    CHR:    start = $0000,  size = $2000, type = ro, file = %O, fill = yes, fillval = $00;
}

SEGMENTS {
    ZEROPAGE: load = ZP,  type = zp;
    OAM:      load = OAM, type = bss, align = $100;
    BSS:      load = RAM, type = bss;
    HEADER:   load = HDR, type = ro;
    CODE:     load = PRG, type = ro,  start = $8000;
    TABLES:  load = PRG, type = ro,  start = $E000;
    RODATA:   load = PRG, type = ro;
    VECTORS:  load = PRG, type = ro,  start = $FFFA;
    TILES:    load = CHR, type = ro;
}


And this is the new version that was calling the irq instead of the nmi:
Code:
MEMORY {
    ZP:     start = $00,    size = $0100, type = rw, file = "";
    OAM:    start = $0200,  size = $0100, type = rw, file = "";
    RAM:    start = $0300,  size = $0500, type = rw, file = "";
    HDR:    start = $0000,  size = $0010, type = ro, file = %O, fill = yes, fillval = $00;
    PRG:    start = $8000,  size = $8000, type = ro, file = %O, fill = yes, fillval = $00;
    CHR:    start = $0000,  size = $2000, type = ro, file = %O, fill = yes, fillval = $00;
}

SEGMENTS {
    FASTVARS: load = ZP,  type = zp;
    OAM:      load = OAM, type = bss, align = $100;
    VARS:     load = RAM, type = bss;
    HEADER:   load = HDR, type = ro;
    CODE:     load = PRG, type = ro,  start = $8000;
    ROMDATA:  load = PRG, type = ro,  start = $E000;
    VECTORS:  load = PRG, type = ro,  start = $FFFA;
    IMG:      load = CHR, type = ro;
}


Any idea why the vectors segment might work out differently?

Thanks

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 4:49 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
No, you can't rearrange the vectors like that, this order is built into the hardware.

If you're getting the IRQ or NMI happening unexpectedly, the problem is going to be either with your IRQ/NMI handler routines, or with your code that sets up (or disables) the IRQ devices or NMI.

Your CFG looks fine, though I'd recommend keeping the ZEROPAGE segment with that original name. That name is special and indicates to the assembler that the segment is in fact on the zero page.

You can tell it that other segments are on the zero page too, but it requires an annotation on your .segment directive:
Code:
.segment "FASTVARS" : zeropage


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:03 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3694
Location: Mountain View, CA
Re: vectors: this is a 6502 architecture thing. The vectors must be at $FFFA-FFFF for any of them (NMI, RESET, IRQ/BRK) to work.

$FFFA-FFFB: NMI
$FFFC-FFFD: RESET
$FFFE-FFFF: IRQ/BRK

http://wiki.nesdev.com/w/index.php/CPU_memory_map

They cannot be rearranged or changed or moved. They must always reside at those addresses.

This probably helps explain why most (but not all!) mappers have a "fixed bank" that tends to be at $C000-FFFF. I'm intentionally avoiding talking about mappers that let you swap in/out $C000-FFFF. Not worth going into in this thread. But just wanted to point out the "why", re: fixed bank.

You can check to see what the values are at each respective vector in the ROM itself by using either a hex editor, or emulator with a debugger that will show you them.

If you had a situation where on NMI your IRQ/BRK handler was being called, or where in IRQ your NMI handler was being called, you have a bug of some sort in your program, or the addresses at those vectors are wrong (e.g. point to the wrong routines). There's no other possibility -- those are it.

Most emulators will let you debug this situation with NMI quite easily, but the failsafe way is to look at where the NMI vector points, examine the code there, and ensure it's correct (what's in your asm files vs. what's in the debugger). If it looks correct, add a breakpoint at the start of NMI routine and then in the emulator choose "Run one frame", or just do Continue/Run and wait until the breakpoint gets hit.


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:08 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
rainwarrior wrote:
If you're getting the IRQ or NMI happening unexpectedly, the problem is going to be either with your IRQ/NMI handler routines, or with your code that sets up (or disables) the IRQ devices or NMI.


I think you're right... stepping through the reset, it looks like it's hitting a BRK somewhere... not sure why.

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:20 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
Ok, so I changed some macros in the reset vector to procedures. For some reason when the procedure calls the rts it jumps to address $0001. I'm trying to figure out what's going on there, but if someone has an idea of what I'm doing wrong, please let me know.

Thanks for all your help

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:22 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 423
I mean interrupts use RTI instead RTS. Is that the problem?

no wait I think I misunderstood what you were saying


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:28 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
pubby wrote:
I mean interrupts use RTI instead RTS. Is that the problem?

no wait I think I misunderstood what you were saying



So I changed my clear_ram procedure to the following and it worked:

Code:
.proc clear_ram
   lda #0
   ldx #0
   clear_ram_loop:
      sta $0000, X
;      sta $0100, X
      sta $0200, X
      sta $0300, X
      sta $0400, X
      sta $0500, X
      sta $0600, X
      sta $0700, X
      inx
      bne clear_ram_loop
    rts
.endproc


I commented out the place where it's clearing the stack. I guess when it was a macro it didn't need the stack. I'm not sure if this would have been a problem before, or could be a problem now.

Any thoughts?

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:31 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 423
Yeah the return address is stored on the stack, so if you clear the stack then you're wiping away the return address.

RTS adds 1 to the value before jumping, so that's why it's going to $01.


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 5:32 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3584
Location: Indianapolis
This is when a trace log comes in handy. FCEUX has one, other emus might.

You might need to create a break point so it will stop where you want, but the trace log will then let you look at the all the previous instructions that ran, up to that point.

Solved before I posted it, but yeah, trace logs.


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 6:17 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3694
Location: Mountain View, CA
Re: any thoughts?: yup. If you were using the stack prior to zeroing it out, you'd lose what was previously pushed on. That affects ANYTHING that uses the stack, which includes stuff like JSR/RTS, RTI, and so on.

I'm not going to get into a debate about this, but in general this is why I don't subroutine-ise system init/setup routines, as all it takes is me moving a "clear RAM" routine to sometime *after* I've done something that uses the stack to potentially cause problems. I tend to just have a single macro or single bunch of code (tend to prefer the latter) that does it all. I get really ticked off when I see people over-analysing system init/setup routines and trying to "make them all super nice and modular and blah blah blah" -- it isn't worth worrying about/hem-hawing over. It's done once at reset.

In general, I recommend you **do** clear/zero RAM (including the stack), but do so ASAP -- i.e. before you start JSR'ing to routines or whatever else. It should be one of the first things you do. Same goes for pre-initialising PPU RAM and the like (be sure to set all the palette values to $0F ASAP too, so that any previous graphics not yet cleared out become black).

There's one case where zeroing ZP/RAM on RESET isn't desired: some games *intentionally* do not clear/zero parts of memory on RESET, allowing for fun easter eggs. A good one is Zanac's stage select: you RESET (soft reset, not hard power-cycle!) the system 13 times, then press Start at the main menu, then use Left/Right to pick what stage you want to start on. The way this works is pretty easy: they only clear memory location $019A (RAM) on power-on, otherwise on a soft RESET, they increment it by 1. There are some other variables involved too, so the code logic is not as obvious/simple as something like lda $019a / cmp #13 / beq AllowStageSelect -- it's more convoluted. How they differentiate power-on vs. RESET is cute but is a subject for another thread. There's only one risk involved here: they assume that the value, on a fresh power on (say, after a NES had been powered off for a few minutes), will contain 0. It's not necessarily guaranteed, but it's how the game was programmed, and a fun/cool easter egg. (I've never seen this fail/mess up on a real NES, but it's possible. There's no sense in discussing power-on values of ZP/RAM either, there is a massive thread on the subject already, and quality emulators let you pick how you want the memory to be initialised on power-on.)

Just something to keep in mind if you ever consider something cute like this.


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 7:33 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
Since you've noticed that a BRK triggers an IRQ, I might point out that this is the reason I set fillval=$00 in my example. The $00 is the BRK opcode, and until your ROM starts to get full the majority of accidents with the stack will end up making an RTS to somewhere filled with $00 and immediately causing a BRK. Clearing RAM to 0 similarly helps with this, as you've just discovered.

If you're not otherwise using IRQ for anything, I find this is a convenient way to catch some kinds of errors during development (usually problems with PHA/PLA). You can put a breakpoint on your IRQ handler, or maybe some infinite loop in there will make it easy to spot when that happens. In my last project I actually put a crash diagnostic screen in my IRQ handler.


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 8:27 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2334
Location: DIGDUG
BRK was designed with debugging in mind.

On 6502 computers, they would have the BRK vector jump to some code that prints an error message on the screen and print the contents of the registers, and maybe pop the last address off the stack (where the BRK was) and print that. Or print the contents of a RAM address that you're watching.

This would aid in debugging a program, as they would intentionally insert / patch 0s (BRK) at specific points in the program to halt the program at that point.

These BRKs were called "breakpoints".

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


Top
 Profile  
 
 Post subject: Re: Weird Vectors issue
PostPosted: Mon Nov 05, 2018 8:52 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
Thanks everyone. It turned out not to be the issue I thought it was, but once again I feel like my understanding has been advanced.

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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