16-bit pointers on the SPC-700
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
16-bit pointers on the SPC-700
Hi,
does anyone have experience of working with 16-bit pointers on the SPC-700? From what I can tell by reading the manual, there is no such addressing mode. (I'm not referring to absolute addressing.)
I can't get my head around writing even something as simple as a memory clear routine. How would I pass the destination address argument? The only way I can think of, is using self-modifying code together with absolute addressing. It doesn't feel like a clean solution.
Cheers
does anyone have experience of working with 16-bit pointers on the SPC-700? From what I can tell by reading the manual, there is no such addressing mode. (I'm not referring to absolute addressing.)
I can't get my head around writing even something as simple as a memory clear routine. How would I pass the destination address argument? The only way I can think of, is using self-modifying code together with absolute addressing. It doesn't feel like a clean solution.
Cheers
Re: 16-bit pointers on the SPC-700
I have written some custom bootloader for the SMP. Maybe the code will help. The SMP can do indirect 16 Bit addressing, you would need to write something like this:
Where $xx is in the page0 memory space (I am not sure it needs to be page0 or page1, but I guess it is like the 6502, where 16 Bit indirect addressing only works in zero-page).
Here is my bootloader (assembled with bass, use it as you want
):
Though my SNES Uploader does not use it, the bootloader supports random writes and I could easily support reading as well.
Code: Select all
ldy ($xx),y
Here is my bootloader (assembled with bass, use it as you want

Code: Select all
//spc_player_init SPC side
//By el_seyf
//Code is used to copy all RAM and restore Registers of SPC
//Code is located in Stack, just above the last pointer
arch snes.smp//assemble to be a SNES executeable
output "custom_spc_downloader.spc", create//specifies output name,
//will overwrite existing file
//------------------------------------------------------------------//
//Code will check $F4:
// if "not 0" => Byte in $F7 will be written to addr in $F5-F6
// if "is 0" => Routine will copy values from specific
// Address into Registers A,X,Y,SP,PSW and jump to addr in $F5-F6
//------------------------------------------------------------------//
origin $0000
//turn off DSP:
str $F2=#$6C
str $F3=#$E0
//tell SNES that custom routine is ready to receive data:
lda #$59
sta $F4//store 'Y' in $F4 => SMP is ready to receive Data
ldy #$00
//Wait for $F4 to be "not last value":
check_for_not_last_val:
eor #$FF//not value in A
check_for_not_last_val_loop:
cpy $F4//command=end?
beq end_transfer
cmp $F4//command="not last value"? -> new byte available
bne check_for_not_last_val_loop
tax//temp save "not last val"
//Load Byte from $F7 and store at address in $F5-F6
lda $F7
sta ($F5),y
txa
sta $F4//write received value to command port
bra check_for_not_last_val//saves a byte compared to jmp
//--------------------------------------------------//
end_transfer:
//needs to be redone:
ldx #$00//SP
txs
lda #$00//PSW
pha
lda #$00
ldx #$00
ldy #$00
str $F2=#$6C//DSP_CTRL
str $F3=#$00
str $F2=#$00
str $F3=#$00
str $F1=#$00
plp
jmp $0000
//--------------------------------------------------//
origin $0040
Re: 16-bit pointers on the SPC-700
That's the problem I'm referring to. Only 8-bit indirect addressing is available (for pages 0 and 1). How would I go about to use indirection for any location in RAM?elseyf wrote:I am not sure it needs to be page0 or page1, but I guess it is like the 6502, where 16 Bit indirect addressing only works in zero-page
Suppose I have a number of patterns containing notes to be played. How could I write a routine that plays any of those patterns, without using 16-bit pointers? I've coded Z80 a lot, but I have a hard time getting my head around the SPC700.
Re: 16-bit pointers on the SPC-700
Sorry, I replied too quickly, before completely understanding your answer. So I guess indirection is possible! As long as I store the address in zero page 

Re: 16-bit pointers on the SPC-700
Indirect addressing on the SPC700 is the same as on the 6502 or 65816: the pointer has to be in direct page, but the pointed-to address can be anywhere.
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: 16-bit pointers on the SPC-700
You might want to brush up on your 65x. The SMP is a variant of the 65x. Address registers on something like the z80 (ie. HL, BC), are just address vectors. 65x just happens to put those address vectors in ram (with single byte addressing to speed it up) instead of internal to the processor itself.dalton wrote:Sorry, I replied too quickly, before completely understanding your answer. So I guess indirection is possible! As long as I store the address in zero page
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
-
- Posts: 2979
- Joined: Wed May 19, 2010 6:12 pm
Re: 16-bit pointers on the SPC-700
With the 65816, the index registers themselves can be used as pointers.AWJ wrote:Indirect addressing on the SPC700 is the same as on the 6502 or 65816: the pointer has to be in direct page, but the pointed-to address can be anywhere.
Re: 16-bit pointers on the SPC-700
Oh, it's on! I heard from Breakin' that you two decided to make some stuff...
As many already mentioned, working with memory is almost identical to how you would do things on 65xx – although I'm in the camp that thinks the SPC700 differs enough from 65xx to not simply think of it as such and use an aliased instruction set and what-not. (Let's not go there this time, but I should do a proper comparison some day!)
Anyway. Any and all indirection use the zeropage, with optional X/Y-indexing either pre- or post-indirection. Passing addresses to a subroutine using only registers is thus not as straight forward as on 65816 or Z80. If you'd really want to, I guess it's most effective to put the address in YA, and then in the subroutine use "movw $dp,ya" to move the argument into a zeropage address. Which is all pretty moot since you're using a fixed zeropage address in the end, anyway...
The common pattern in to reserve different zeropage addresses for specific tasks and just write to those addresses before calling the subroutine. That's how the C64 basic kernal work, and most other 65xx code I've looked at.
Another approach, which I've seen in some SNES games, is to use a fixed zeropage range more like a register file, which is pushed/pulled together with the actual registers when necessary. Not as crazy as it sounds for some designs, I suppose – but for the specific and isolated tasks you usually do on the SPC700 I don't really see an argument for not using the zeropage as a fast (and huge) scratchpad.
As many already mentioned, working with memory is almost identical to how you would do things on 65xx – although I'm in the camp that thinks the SPC700 differs enough from 65xx to not simply think of it as such and use an aliased instruction set and what-not. (Let's not go there this time, but I should do a proper comparison some day!)
Anyway. Any and all indirection use the zeropage, with optional X/Y-indexing either pre- or post-indirection. Passing addresses to a subroutine using only registers is thus not as straight forward as on 65816 or Z80. If you'd really want to, I guess it's most effective to put the address in YA, and then in the subroutine use "movw $dp,ya" to move the argument into a zeropage address. Which is all pretty moot since you're using a fixed zeropage address in the end, anyway...
The common pattern in to reserve different zeropage addresses for specific tasks and just write to those addresses before calling the subroutine. That's how the C64 basic kernal work, and most other 65xx code I've looked at.
Another approach, which I've seen in some SNES games, is to use a fixed zeropage range more like a register file, which is pushed/pulled together with the actual registers when necessary. Not as crazy as it sounds for some designs, I suppose – but for the specific and isolated tasks you usually do on the SPC700 I don't really see an argument for not using the zeropage as a fast (and huge) scratchpad.
- Jarhmander
- Formerly ~J-@D!~
- Posts: 518
- Joined: Sun Mar 12, 2006 12:36 am
- Location: Rive nord de Montréal
Re: 16-bit pointers on the SPC-700
Just to be clear, you can put the zeropage (or rather, direct page) either in page 0 or 1. There's a bit in the status register for that.
((λ (x) (x x)) (λ (x) (x x)))
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: 16-bit pointers on the SPC-700
I'm of the opinion, that if you're gonna write code - you should probably have a perspective/mentality of a software engineer, not a hardware engineer. From your perspective, if those 256 bytes of zeropage were located on the processor vs ram, it'd be accessed the same way with the same opcodes (you'd still need one extra byte to complete the effective address because that's too many registers to be emdedded into an 8bit opcode). When I'm writing code on the original 68k cpu, I don't give a crap that the ALU is 16bit and the microcoded opcodes use a dual pass on it; I'm writing code for a 32bit processor. And I treat it as such.Optiroc wrote: Passing addresses to a subroutine using only registers is thus not as straight forward as on 65816 or Z80. If you'd really want to, I guess it's most effective to put the address in YA, and then in the subroutine use "movw $dp,ya" to move the argument into a zeropage address. Which is all pretty moot since you're using a fixed zeropage address in the end, anyway...
The common pattern in to reserve different zeropage addresses for specific tasks and just write to those addresses before calling the subroutine. That's how the C64 basic kernal work, and most other 65xx code I've looked at.
Another approach, which I've seen in some SNES games, is to use a fixed zeropage range more like a register file, which is pushed/pulled together with the actual registers when necessary. Not as crazy as it sounds for some designs, I suppose – but for the specific and isolated tasks you usually do on the SPC700 I don't really see an argument for not using the zeropage as a fast (and huge) scratchpad.
ZP are just registers in external memory instead of internal. Voila - up to 128 address registers, or 256 data registers. However you use them. Thus, is becomes straight forward in how to use them. If you're pointing to a string of arguments with HL or BC on the z80, then you're doing the same thing with any ZP pair. It's no different. I even push ZP bytes into the hardware stack, as if I were pushing cpu regs on the stack - because I needed nested routine support using the same "regs".
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
Re: 16-bit pointers on the SPC-700
I agree with all of the above. The not so "straight forward" part of what I said is that for data to end up in the direct page, it almost always has to take the detour through an actual CPU register. Pushing/popping stuff between direct page and the stack quickly eats up cycles.
That said, direct page access is one of the key areas where SPC700 has several great improvements over 6502:
That said, direct page access is one of the key areas where SPC700 has several great improvements over 6502:
Code: Select all
mov dp,#imm ;store immediate value in direct page
mov dp<d>,dp<s> ;transfer byte from <s> to <d>
cmp dp,#imm ;compare byte in direct page with immediate value *
cmp dp,dp ;compare bytes in direct page (absolute) *
cmp (x),(y) ;compare bytes in direct page (indirect) *
* also available for the other ALU operations
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: 16-bit pointers on the SPC-700
^ I wish emulators hand an option for opcode statistics when a running game; record the occurrence rate of each opcode. Some opcodes look great, but if they're not particular useful or used in most iterations that make up the larger chunks of resource, then they won't have much of an impact regardless of how nice they are to use. In such cases, macros serve the same purpose on lesser processors.
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
-
- Posts: 2979
- Joined: Wed May 19, 2010 6:12 pm
Re: 16-bit pointers on the SPC-700
Something that drives me insane is that you have to clear either x or y in order to use indirect addressing mode on the SPC700.
Re: 16-bit pointers on the SPC-700
That's pretty much a result of it being so heavily modeled after the 6502, which has the same property.
Re: 16-bit pointers on the SPC-700
Yeah, no additions were made to indirect access outside of the zero page. In fact, ldy abs,x and ldx abs,y was curiously removed.
Also removed was the only instruction using absolute indirect addressing, jmp (abs). Or rather, it was replaced by jmp [!abs+x]...
Anyway, I quite enjoy the quirky additions and omissions SPC700 has compared to 65xx and using the "controversial" assembler syntax better gets my mind into SPC700-mode than using a 65xx:esque alias set.
Also removed was the only instruction using absolute indirect addressing, jmp (abs). Or rather, it was replaced by jmp [!abs+x]...
Anyway, I quite enjoy the quirky additions and omissions SPC700 has compared to 65xx and using the "controversial" assembler syntax better gets my mind into SPC700-mode than using a 65xx:esque alias set.