It is currently Sun Nov 19, 2017 5:32 pm

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 292 posts ]  Go to page Previous  1 ... 15, 16, 17, 18, 19, 20  Next
Author Message
PostPosted: Mon Aug 07, 2017 1:37 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 581
Another example I discovered today. This KS for a simple SNES game was estimated to take 6 months; now it's taken two years and three months, and it's still not complete.

https://www.kickstarter.com/projects/43 ... ns-of-dea/


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 5:32 am 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 145
So, like most Kickstarter projects then? You also neglected to mention that they said they were building the engine from scratch. Which, yeah, is going to take longer. This really just highlights the importance of having engines available for people to use.

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 6:21 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7266
Location: Chexbres, VD, Switzerland
calima wrote:
Another example I discovered today. This KS for a simple SNES game was estimated to take 6 months; now it's taken two years and three months, and it's still not complete.

https://www.kickstarter.com/projects/43 ... ns-of-dea/

The NES game I'm working on started development in early 2005, and it's still not complete.


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 6:55 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19230
Location: NE Indiana, USA (NTSC)
The thing about "engines" is that the Super NES probably isn't powerful enough for something as generic as, say, Unity or Unreal. Feel free to prove me wrong, but though an RPG, a platformer, and a vertical shmup could share a large set of hardware libraries, their engines would probably be structured very differently.


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 11:06 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 581
Writing a platformer engine that doesn't even scroll would be a matter of weeks, not years.


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 12:37 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2359
calima wrote:
Another example I discovered today. This KS for a simple SNES game was estimated to take 6 months; now it's taken two years and three months, and it's still not complete.

https://www.kickstarter.com/projects/43 ... ns-of-dea/


I laughed when I saw that guy in the video. How many unfinished SNES games has that guy advertised?


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 1:46 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1823
Location: DIGDUG
Quote:
now it's taken two years and three months


But, that's how long I would expect a game like this to take to develop. '6 months' was just foolishly optimistic.

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


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 2:26 pm 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 145
tepples wrote:
The thing about "engines" is that the Super NES probably isn't powerful enough for something as generic as, say, Unity or Unreal. Feel free to prove me wrong, but though an RPG, a platformer, and a vertical shmup could share a large set of hardware libraries, their engines would probably be structured very differently.

Engines can be different sizes. Unreal and Unity are designed around modern systems with a lot more complexity to manage under the hood because they're designed to scale to environments that take 8,000x as much RAM as the SNES actually has. They're also designed around a lot of micro optimizations that are only found in newer hardware and simply doesn't apply to the SNES. Word alignment? Haha, no need for that here.

The entire reason I'm making an argument for engines is that I only ever see people talking about how to implement DMA queues instead of actually making games. A lot of this is infrastructure that applies to a wide variety of genres and can easily be made reusable, just like the existence of code libraries, only an engine is more tightly integrated.

When it comes to genres, much of my initial inspiration for my SNES engine comes from Alien Soldier, which fits both "platformer" and "shmup". Action games share a surprising amount of infrastructure and are easily generalizable. If it's overhead from unused stuff that concerns you, then one of my design goals has been to allow objects to only do as much processing as they need to. If an object needs to move, it calls MoveObject. Same idea for drawing sprites and animation. An object that doesn't need to draw a moving sprite simply doesn't call the movement or animation functions. I have recently introduced an optimization so that an empty scene capable of having 128 objects only uses 7% CPU (excluding time spent in Vblank). That's pretty good if you ask me.

(I realize that there are some smaller details that users might want to tweak, and I'd like to help them do so via proper documentation and allowing user adjustment of object list sizes, etc. Still, I want to keep options open which is why I always do performance testing with high object counts, but also try to design my systems around flexibility.)

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Mon Aug 07, 2017 3:28 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2359
I'm also trying to do an Alien Soldier type game, but I'm also doing a hell of a lot of sprite animation, which is why that animation code is so long. It has to figure out how a constantly changing combination of sprites onscreen are going to fit into VRAM.

I'm still trying to crunch the code down. I hope this is a noticeable improvement.


Code:
animation:
ldy {metasprite_request}
bne +            //no animation, if "metasprite_request" is blank
jsr clear_vram_slot
stz {frame_id}
rts
+;
lda {animation_update}      //sprite is animated if "metapsprite" is different from
bne +            //"metasprite_request" or "animation_update" is set
cpy {metasprite}
bne +
rts
+;
lda $000c,y
tax
clc
adc {total_dma_legnth}      //check if there is enough DMA time for sprite
cmp #$0081
bcc ++
lda {first_object_to_dma}
bne +
tdc
sta {first_object_to_dma}
+;
rts
+;
stx {vram_size}
jsr clear_vram_slot      //clear previous animation frame
stz {180_degrees_flip}
lda {animation_update}
cmp #$0002         //if "animation_update" is 2, then frame is rotated 180 degrees
bne +
lda #$c000
sta {180_degrees_flip}
+;
stz {animation_update}
ldy {metasprite_request}
sty {metasprite}

lda $000e,y
clc
adc {animation_index}
inc #2
sta {frame_id}
tax
lda {animation_copies},x
inc
sta {animation_copies},x
dec
beq +            //if animation_copies is not 0, then no further processing is needed
rts
+;

lda $000a,y         //find the ROM address of sprite graphics
asl #5            //ROM address = metasprite ROM address + (animation frame)*(metasprite ROM size)
sta {vram_width}
sep #$20
lda {animation_index}
lsr
sta $4202
lda $000c,y
sta $4203
nop
rep #$20
lda $4216
asl #5
clc
adc $0006,y
sta {temp3}         //"temp3" is ROM address
lda $0008,y
sta {temp2}         //"temp2" is ROM bank
lda $0010,y
bpl +            //if $0010,y is $7fff or less, it is the metasprite data itself
tya            //if $0010,y is $8000 or more, it is the address pointing to metasprite data
clc
adc {animation_index}
tax
ldy $0010,x
+;
phd
lda #$0000
tcd
ldx #$ffff
-;
   lda $0010,y
   bne +
   txa
invalid_chr:
   pld
   ldx {frame_id}
   sta {animation_chr},x
   lda {vram_size}
   clc
   adc {total_dma_legnth}
   sta {total_dma_legnth}
   rts            //this is where the game exits the routine
   +;
   sty.b {temp5}
   lda $0012,y
   sta.b {temp_x}
   lda $0011,y
   and #$0070
   lsr #4
   sta.b {temp8}         //"temp8" counts down the horizontal sprite run
   lda $0018,y
   adc.b {temp3}
-;
      sta.b {temp}            //"temp" is the ROM address of the sprite being added
      sta.b {temp9}            //"temp9" is the ROM address of the top sprite in a vertical run
      lda $0014,y
      sta.b {temp_y}
      lda $0011,y
      and #$000f
      sta.b {temp7}         //"temp7" counts down the vertical sprite run
      jmp find_vram_slot
find_vram_slot_done:
      ldy.b {temp5}         //this puts all the "OAM" information
      lda.b {temp6}         //onto the linked list
      ora $0016,y
      sta {sprite_attributes},x
      lda.b {temp4}
      sta {sprite_size},x
      lda.b {temp_y}
      sta {sprite_y},x
      clc
      adc.b {temp10}
      sta.b {temp_y}
      lda.b {temp_x}
      sta {sprite_x},x
      dec.b {temp7}         //decreases "temp 7" until all sprites
      bpl find_vram_slot      //in the vertical run are put on linked list
      dec.b {temp8}         //decreases "temp 8" until all sprites
      bmi +            //in the horizontal run are put on linked list
      clc
      adc.b {temp10}
      sta.b {temp_x}
      lda.b {temp10}
      asl #2
      adc.b {temp9}
      jmp -
+;
   tya
   clc
   adc #$000a
   tay
   jmp --


find_vram_slot:
lda $0010,y
txy
and #$0003
dec
beq small_slot
cmp #$0001
beq large_slot

repeat_slot:         //this finds repeat slots
tsb.b {temp4}
ldx {repeat_slot_stack_index}
dex
dex
bpl +
tya
jmp invalid_chr
+;
lda {repeat_slot_stack},x
stx {repeat_slot_stack_index}
tax
tya
sta {sprite_name},x      //puts it on linked list
jmp find_vram_slot_done

macro add_and_store(a,b) {
adc {a}
sta {b},y
}

macro find_slot(stack_index,stack) {
sta.b {temp4}
ldx {stack_index}
dex
dex
bpl +
tya
jmp invalid_chr
+;
lda {stack},x
stx {stack_index}
tax
tya
sta {sprite_name},x      //adds slot to linked list
lda x16_lut,x
ldy.b {dma_updates}
sta {dma_destination},y      //sets up dma queue
clc
add_and_store(#$0100,{dma_destination}+8)
}


small_slot:         //this finds 16x16 VRAM slot
find_slot({small_slot_stack_index},{small_slot_stack})
lda.b {temp}
sta {dma_address},y
add_and_store({vram_width},{dma_address}+8)
adc {vram_width}
sta.b {temp}
lda.b {temp2}
ora #$4000
sta {dma_bank},y
sta {dma_bank}+8,y
lda #$0010
jmp ++

large_slot:         //finds open 32x32 VRAM slot
find_slot({large_slot_stack_index},{large_slot_stack})
add_and_store(#$0100,{dma_destination}+16)
add_and_store(#$0100,{dma_destination}+24)
lda.b {temp}
sta {dma_address},y
add_and_store({vram_width},{dma_address}+8)
add_and_store({vram_width},{dma_address}+16)
add_and_store({vram_width},{dma_address}+24)
adc {vram_width}
sta.b {temp}
lda.b {temp2}
ora #$8000
sta {dma_bank},y
sta {dma_bank}+8,y
sta {dma_bank}+16,y
sta {dma_bank}+24,y
lda #$0020
+;
sta.b {temp10}
clc
adc.b {dma_updates}
sta.b {dma_updates}
stx.b {temp6}
jmp find_vram_slot_done


x16_lut:
dw $0000,$0020,$0040,$0060,$0080,$00a0,$00c0,$00e0,$0110,$0120,$0140,$0160,$0180,$01a0,$01c0,$01e0
dw $0200,$0220,$0240,$0260,$0280,$02a0,$02c0,$02e0,$0310,$0320,$0340,$0360,$0380,$03a0,$03c0,$03e0
dw $0400,$0420,$0440,$0460,$0480,$04a0,$04c0,$04e0,$0510,$0520,$0540,$0560,$0580,$05a0,$05c0,$05e0
dw $0600,$0620,$0640,$0660,$0680,$06a0,$06c0,$06e0,$0710,$0720,$0740,$0760,$0780,$07a0,$07c0,$07e0
dw $0800,$0820,$0840,$0860,$0880,$08a0,$08c0,$08e0,$0910,$0920,$0940,$0960,$0980,$09a0,$09c0,$09e0
dw $0a00,$0a20,$0a40,$0a60,$0a80,$0aa0,$0ac0,$0ae0,$0b10,$0b20,$0b40,$0b60,$0b80,$0ba0,$0bc0,$0be0
dw $0c00,$0c20,$0c40,$0c60,$0c80,$0ca0,$0cc0,$0ce0,$0d10,$0d20,$0d40,$0d60,$0d80,$0da0,$0dc0,$0de0
dw $0e00,$0e20,$0e40,$0e60,$0e80,$0ea0,$0ec0,$0ee0,$0f10,$0f20,$0f40,$0f60,$0f80,$0fa0,$0fc0,$0fe0
dw $1000,$1020,$1040,$1060,$1080,$10a0,$10c0,$10e0,$1110,$1120,$1140,$1160,$1180,$11a0,$11c0,$11e0
dw $1200,$1220,$1240,$1260,$1280,$12a0,$12c0,$12e0,$1310,$1320,$1340,$1360,$1380,$13a0,$13c0,$13e0
dw $1400,$1420,$1440,$1460,$1480,$14a0,$14c0,$14e0,$1510,$1520,$1540,$1560,$1580,$15a0,$15c0,$15e0
dw $1600,$1620,$1640,$1660,$1680,$16a0,$16c0,$16e0,$1710,$1720,$1740,$1760,$1780,$17a0,$17c0,$17e0
dw $1800,$1820,$1840,$1860,$1880,$18a0,$18c0,$18e0,$1910,$1920,$1940,$1960,$1980,$19a0,$19c0,$19e0
dw $1a00,$1a20,$1a40,$1a60,$1a80,$1aa0,$1ac0,$1ae0,$1b10,$1b20,$1b40,$1b60,$1b80,$1ba0,$1bc0,$1be0
dw $1c00,$1c20,$1c40,$1c60,$1c80,$1ca0,$1cc0,$1ce0,$1d10,$1d20,$1d40,$1d60,$1d80,$1da0,$1dc0,$1de0
dw $1e00,$1e20,$1e40,$1e60,$1e80,$1ea0,$1ec0,$1ee0,$1f10,$1f20,$1f40,$1f60,$1f80,$1fa0,$1fc0,$1fe0

no_slot_to_clear:
plb
rts

macro clear_slot(stack_index,stack) {
ldx {stack_index}
sta {stack},x
inx
inx
stx {stack_index}
}

clear_vram_slot:   //this routine clears the VRAM slots of the previous animation frame
pea $807e
plb
ldy {frame_id}
beq no_slot_to_clear
lda {animation_copies}-$7e0000,y
beq +
dec
sta {animation_copies}-$7e0000,y
bne no_slot_to_clear
+;
lda {animation_chr}-$7e0000,y
-;
cmp #$ffff
beq no_slot_to_clear
tay
ldx {sprite_size}-$7e0000,y
beq clear_small_slot
cpx #$0001
beq clear_large_slot
clear_slot({repeat_slot_stack_index},{repeat_slot_stack})
bra +

clear_small_slot:
clear_slot({small_slot_stack_index},{small_slot_stack})
bra +

clear_large_slot:
clear_slot({large_slot_stack_index},{large_slot_stack})
+;
lda {sprite_name}-$7e0000,y
jmp -


Last edited by psycopathicteen on Tue Aug 08, 2017 7:57 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Aug 08, 2017 12:07 pm 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 987
Location: Pennsylvania, USA
I've considered moving to SNES at some point in the future, but I'm reluctant just due to the implicit, rather large jump in scope. We're a 2 person operation and each NES game we've made clocks in right around 3.5 to 4 years at the pace we work (this is with me doing everything but the art, so music for instance is of manageable scope). I think that's about the limit of my patience for a large project which has extra difficulty (working with old hardware) imposed on it. If I made a SNES game I'd probably take 6, maybe 7 years on the type of game we might make. I think it's more realistic I may jump to gameboy, potentially. The graphics format was so similar I was able to make small modifications to my NES tools to output data for gameboy just tinkering one weekend. That plus the growing number of people in the gameboy scene makes it an attractive second option (more resources, tools, game jams, etc.). I think the reality boils down to SNES projects need larger teams (or just a lot more time), and as hobbyists keeping together large teams is obscenely difficult. It's difficult for all indie devs, probably, but with modern dev it's much easier to change out members of a team who can easily ramp up on some modern language codebase versus obscure old hardware.


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 12:56 am 
Offline

Joined: Fri Jul 04, 2014 9:31 pm
Posts: 801
Just about all of the projects I want to do on the SNES are either primitive practice games, one-shot tech demos, or ports. The only exception is a full-scale SA-1/MSU1 F-Zero game, which is so far down the list that I don't expect to ever start. Maybe I'm subconsciously trying to push back against the scope overload that seems to plague everything I do... or maybe I'm simply protected by my lack of artistic initiative. Either way, I've been laying the groundwork for my first SNES project for over three years now. Hopefully once I'm out of grad school things will loosen up a bit...


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 10:40 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 581
I was also looking at getting on the Gameboy, when Krikzz announced the GB-X everdrive some time ago. It has lower power consumption, and a RTC, so you can finally play 2nd gen pokemon as intended :P
Of course there are plenty of z80 C compilers.


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 11:14 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19230
Location: NE Indiana, USA (NTSC)
That'd work for the ColecoVision, Master System, or Game Gear. But I'll open another topic in GBDev about C on the LR35902.


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 1:36 pm 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7266
Location: Chexbres, VD, Switzerland
GradualGames wrote:
I've considered moving to SNES at some point in the future

Same here, I planned to move to SNES once I released some 3-4 games on NES. Exept I'm still at 0 games for the NES.


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 5:31 pm 
Offline

Joined: Tue Mar 01, 2016 8:22 pm
Posts: 21
I've been wanting to get into SNES development for a while now, but really don't know where to start. I know x86 assembly fairly well (enough to write some functions in ASM for use in C code and to have an understanding of how to structure and write ASM code) and have learned most of the commonly used 65816 opcodes. I've been following bazz's tutorial on superfamicom.org and got to the point where I put a 1x1 tile image on the screen while understanding about half of what I was doing. Haven't really gotten much further than that.

I love coding in assembly, and making a SNES game has been a lifelong dream of mine. Some pointers would be much appreciated.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 292 posts ]  Go to page Previous  1 ... 15, 16, 17, 18, 19, 20  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 10 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:  
cron
Powered by phpBB® Forum Software © phpBB Group