News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - darkmoon2321

Pages: [1] 2 3
Personal Projects / Re: slidelljohn (a.k.a.[J]) snes projects page
« on: March 16, 2019, 01:46:50 am »
Maybe it would be a good idea to post your asm code. If enough of us put our ideas together we could
probable optimize the code more.

Here is a commented disassembly of the optimized code I did for sprite handling:

Code: [Select]
$80/9020 LDX #$0200 ;Initial address of object data
$80/9023 LDA #$08C0 ;final address
$80/9026 BRA $58    [$9080] ;process all objects between initial and final
$80/9028 LDA $000ED0
$80/902C CMP #$008F
$80/902F BEQ $11    [$9042]
$80/9031 LDA $0011D0
$80/9035 CMP #$0095
$80/9038 BEQ $34    [$906E]
$80/903A LDX #$08C0 ;Initial address of object data
$80/903D LDA #$1200 ;final address
$80/9040 BRA $3E    [$9080] ;process all objects between initial and final
$80/9042 LDX #$08C0 ;Initial address of object data
$80/9045 LDA #$0E40 ;final address
$80/9048 JSL $809080[$80:9080] ;process all objects between initial and final
$80/904C BCS $62    [$90B0] ;exit if no more room for sprites
$80/904E LDX #$0EC0 ;Initial address
$80/9051 LDA #$0F00 ;final address of object data
$80/9054 JSL $809080[$80:9080] ;process all objects between initial and final
$80/9058 BCS $56    [$90B0] ;exit if no more room for sprites
$80/905A LDX #$0E40 ;Initial address of object data
$80/905D LDA #$0EC0 ;final address
$80/9060 JSL $809080[$80:9080] ;process all objects between initial and final
$80/9064 BCS $4A    [$90B0] ;exit if no more room for sprites
$80/9066 LDX #$0F00 ;Initial address of object data
$80/9069 LDA #$1200 ;final address
$80/906C BRA $12    [$9080] ;process all objects between initial and final
$80/906E LDX #$0900 ;Initial address of object data
$80/9071 LDA #$1200 ;final address
$80/9074 JSL $809080[$80:9080] ;process all objects between initial and final
$80/9078 BCS $36    [$90B0] ;exit if no more room for sprites
$80/907A LDX #$08C0 ;Initial address of object data
$80/907D LDA #$0900 ;final address
$80/9080 STA $18 ;Store final address for object data (terminator)
$80/9082 STX $FC ;store address of object data
$80/9084 LDA $00,x ;Object word 0, offset to 03:0000 array that determines the sprite data
$80/9086 BEQ $1C    [$90A4]
$80/9088 STA $04 ;store the offset to the sprite data in ROM
$80/908A LDA $0A,x ;Object X position
$80/908C STA $08
$80/908E LDA $0E,x;Object Y position
$80/9090 STA $0A
$80/9092 LDA $02,x ;Object alternate attributes
$80/9094 STA $14 ;"Alternate attributes/palette" flag stored in top bit
$80/9096 ASL A
$80/9097 XBA
$80/9098 STA $13 ;store alternate attributes/palette
$80/909A LDA $04,x ;Object attributes
$80/909C STA $06
$80/909E LDX $04 ;Load relative offset of ROM sprite data into X
$80/90A0 BRA $0F    [$90B1]
$80/90A2 BCS $0C    [$90B0]
$80/90A4 LDA $FC ;Load address of object data
$80/90A6 CLC
$80/90A7 ADC #$0040 ;increment to the next object address
$80/90AA TAX
$80/90AB CPX $18 ;check for final address
$80/90AD BCC $D3    [$9082] ;loop until we reach the final address
$80/90AF CLC ;return carry clear, we still have room for more sprites
$80/90B0 RTL ;end sprite tile processing for the current set of objects
$80/90B1 LDA $030000,x ;get # of tiles in the sprite
$80/90B5 AND #$00FF
$80/90B8 STA $16 ;store num_tiles
$80/90BA INX
$80/90BB LDA $030002,x
$80/90BF XBA
$80/90C0 CMP #$FF00 ;check for FF value in last byte of sprite tile's data
$80/90C3 BCC $07    [$90CC]
$80/90C5 LDA $030000,x ;if last byte was FF, get new ROM offset for sprite data
$80/90C9 TAX
$80/90CA BRA $EF    [$90BB]
$80/90CC AND #$0010 ;check sprite size
$80/90CF BNE $07    [$90D8]
$80/90D1 STZ $0E ;store the sprite size toggle bit
$80/90D3 LDA #$FFFC ;load amount to offset the tile based on its size
$80/90D6 BRA $08    [$90E0]
$80/90D8 LDA #$0011
$80/90DB STA $0E ;store the sprite size toggle bit
$80/90DD LDA #$FFF8
$80/90E0 STA $0C ;store tile offset modifier based on sprite size
$80/90E2 STZ $11 ;Initialize upper byte of tile X position (16 bit) to zero
$80/90E4 LDA $02FFFF,x ;get tile's relative X position
$80/90E8 BPL $02    [$90EC]
$80/90EA DEC $11 ;if relative X is negative, set upper byte to FF
$80/90EC STA $10 ;store lower byte of relative X position
$80/90EE BIT $06 ;check object's attributes
$80/90F0 BVC $07    [$90F9] ;check if tile is horizontally flipped
$80/90F2 SEC
$80/90F3 LDA $08
$80/90F5 SBC $11 ;subtract tile relative X from object X if hflip
$80/90F7 BRA $05    [$90FE]
$80/90F9 CLC
$80/90FA LDA $08
$80/90FC ADC $11 ;if not flipped, add tile relative X to Object X
$80/90FE CMP #$0110 ;right boundary check
$80/9101 BMI $03
$80/9103 JMP $917B ;If we get here, do not draw tile
$80/9106 CMP #$FFF0 ;left boundary check
$80/9109 BPL $03    [$910E]
$80/910B JMP $917B  [$80:917B] ;If we get here, do not draw tile
$80/910E CLC
$80/910F ADC $0C ;Add relative offset based on sprite size toggle bit
$80/9111 STA $0000,y ;store final tile X to be transmitted to OAM
$80/9114 XBA
$80/9115 LSR A
$80/9116 ROR $00 ;rotate X most significant bit into extended OAM table temp variable
$80/9118 STZ $11 ;Initialize upper byte of tile Y position (16 bit) to zero
$80/911A LDA $030000,x ;get tile's relative Y position
$80/911E BPL $02    [$9122]
$80/9120 DEC $11 ;if relative Y is negative, set upper byte to FF
$80/9122 STA $10 ;store lower byte of relative Y position
$80/9124 BIT $06 ;check object's attributes
$80/9126 BPL $07    [$912F] ;check if tile is vertically flipped
$80/9128 SEC
$80/9129 LDA $0A
$80/912B SBC $11 ;if vflip, subtract relative Y from object Y
$80/912D BRA $05    [$9134]
$80/912F CLC
$80/9130 LDA $0A
$80/9132 ADC $11 ;if not flipped, add relative Y to object Y
$80/9134 BIT #$FF00 ;Make sure the upper byte of tile Y position is 0 at this point
$80/9137 BEQ $04    [$913D]
$80/9139 ASL $00 ;if upper byte of Y was not 0, pop the X MSB for this tile off the temp variable
$80/913B BRA $3E    [$917B] ;if we get here, do not draw tile
$80/913D SEC
$80/913E SBC #$0010 ;subtract 10 from tile Y position
$80/9141 CLC
$80/9142 ADC $0C ;add relative offset based on sprite size toggle bit
$80/9144 STA $0001,y ;Store final tile Y to be transmitted to OAM
$80/9147 LDA $030002,x ;get tile's relative attributes and tile #
$80/914B AND #$EFFF ;clear vflip flag?
$80/914E EOR $06 ;toggle bits from the object's attributes
$80/9150 BIT $14 ;check "alternate attributes/palette" flag
$80/9152 BPL $05    [$9159]
$80/9154 AND #$F1FF ;clear palette bits
$80/9157 ORA $13 ;set alternate attributes/palette
$80/9159 STA $0002,y ;store tile's final attributes and tile # to be transmitted to OAM
$80/915C INY ;update write offset for next tile's data
$80/915D INY
$80/915E INY
$80/915F INY
$80/9160 LSR $0E ;rotate the size toggle bit into our temp extended OAM variable
$80/9162 ROR $00
$80/9164 BCC $15    [$917B] ;check if we have filled our temp variable
$80/9166 CPY #$3E00 ;check if we have used up all available OAM space
$80/9169 BCS $1C    [$9187] ;if so, end sprite tile processing
$80/916B LDA $00 ;load our temp extended OAM variable
$80/916D STA ($02) ;indirect store the extended OAM table
$80/916F LDA $02
$80/9171 ADC #$0002 ;update the write address for extended OAM data
$80/9174 STA $02
$80/9176 LDA #$8000
$80/9179 STA $00 ;reset our temp extended OAM variable
$80/917B INX ;update the read offset for the next tile's data from ROM
$80/917C INX
$80/917D INX
$80/917E INX
$80/917F DEC $16 ;countdown until all tiles in the object have been processed
$80/9181 BEQ $03    [$9186]
$80/9183 JMP $90BB  [$80:90BB] ;loop over all tiles in the object
$80/9186 CLC
$80/9187 JMP $90A2  [$80:90A2] ;start on the next object

For the most part, it's pretty similar to the original, with a few exceptions.  In the original, the ROM location where tile data was located was loaded and stored into the X register a few times for every tile because the X register was re-used to hold the location of the extended OAM table in RAM.  Similarly, the address of the write location for tile data needed to be loaded for every tile because they also temporarily used the Y register to hold the value for the size-toggle dependent position offset.  They also checked for vertical/horizontal flips by doing:
Code: [Select]
LDA $06
BIT #$8000  ;#$4000 for hflip
BEQ $07    [$9135]

I simplified this using BIT $06 and either BVC or BPL.  There were several other minor modifications as well.  As for speeding up the math with $FC by using TAX/TXA, it's doable, but the value in the X register will need to be restored to the address of the object's data as soon as the object's sprites are finished being drawn.  In other words, this will only save processing time for the case where there is no active object in a slot.

Some info on darkmoon's sprite routine hack: It introduces glitchy graphics on the fire stage boss (the two-headed dragon) that isn't in the original fastrom hack.

I didn't know this.  I'll have to take a look and see if I can find out what's happening.  I must have missed something.
Edit: I'm not convinced this is from me.  I just ran both versions up to this boss using an invincibility cheat to test, and both showed some pretty glitchy graphics.  I think there are just too many overlapping sprites trying to be displayed at once.  The way the boss curls around on itself makes it particularly prone to glitchy sprites.  However, I did find a potential bug.  At $80/9166, it should be changed to:

Code: [Select]
LDA $00
STA ($02)
CPY #$3E00
BCS $18

In other words, extended OAM data needs to be saved prior to checking whether there are too many sprites on-screen. Otherwise the extended OAM data (size toggle, X MSB) might not be saved for the last few sprite tiles in the event that there are too many sprites on-screen at once.

Personal Projects / Re: slidelljohn (a.k.a.[J]) snes projects page
« on: January 10, 2019, 02:23:35 pm »
Sorry about the link, never had that issue with dropbox before.  I did some work on optimizing the sprite routine:

Apply this patch on top of your fastROM patch.  It reduces the amount of time spent computing individual sprite tiles by about 10% or so.  Further optimization is possible, but it would likely be at the expense of rom space and provide benefit mainly for large sprites containing lots of tiles.  In other words, creating separate routines for sprites that are vertically flipped, horizontally flipped, both, or neither.  This would eliminate the branch checking for these conditions that occurs for individual tiles right now.

Personal Projects / Re: slidelljohn (a.k.a.[J]) snes projects page
« on: January 08, 2019, 11:48:05 am »
In the main function if this line ($80/82A2 22 F1 8E 80 JSL $808EF1[$80:8EF1]) is nop'ed reload the cart from the begging and
just let the game play until the ship crashes. It should crash around 2 minutes and 31 seconds. Now if you let the game play
without removing that line the game will crash around 2 minutes and 46 seconds. So just that one line of code eats up 15 seconds.
Not sure if the collision detection is loaded from that line but I recall 2 or 3 sections of code that shows the slowdown.

That function does indeed call the sprite handling code.  I wrote a simple program that parses through Geiger's trace logs and counts the number of times each line of code executes so that I can find good targets for optimizing code.  The collision detection code that I identified before spans 80/EA7A to 80/EC3C.  From the main function, it is reached the line before the sprites, so ($80/829E 22 8E 87 80 JSL $80878E).  I'm not entirely sure if collision detection is all this code does, but it appears to be a significant part of it.  If you're interested in the short program I made, source is here:

I can take a quick look at optimizing the sprite display code a bit, I have a better understanding of that than the collision code at the moment.

Personal Projects / Re: slidelljohn (a.k.a.[J]) snes projects page
« on: January 04, 2019, 10:30:19 pm »
I could release the disassembled asm for gradius 3 but I’m not really sure what the right way is to release it. Can I release a text file with all of the asm on without getting in trouble or do I need to write a program that rips it out of the game?

I'm pretty sure you can release it here.  There are a few complete disassembly documents on the site already.  I don't see any for SNES titles yet though, so that could be a first.  I did go ahead and get a trace log on some of the lag, and I can see where it happens, but you're probably miles ahead of me if you already have a full disassembly.

Edit: I did a little more research into this.  The sprite drawing code does consume a lot of processing time, and I think it is possible to make it run more efficiently.  However, that's not the only issue.  On the lag trace that I got, the game didn't even reach the sprite drawing routine before it was interrupted by the next NMI.  It appears that collision detection is occupying the largest chunk of time, in my test case approximately half of an entire frame.

Personal Projects / Re: slidelljohn (a.k.a.[J]) snes projects page
« on: January 04, 2019, 08:54:24 pm »
Interesting.  Gradius III is a fun game that I played through a few times back in the day.  The game would slow to a crawl every time one of those big serpent creatures was on-screen though.  Out of curiosity, have you done any kind of analysis on the code to figure out why it is lagging so badly in the first place?  I haven't looked into the game's code myself, though I might take a look now.  My guess is that it would be significantly easier to correct some inefficient code rather than try to convert over to SA-1.  If it's an issue of graphics decompression, there is also the route of placing decompressed graphics directly in the ROM and bypassing the decompression routine, particularly for commonly used images.

Which is why, after writing my previous post, I opened Ninja Gaiden 1 and 2 and added a level skip feature. :D It's a bit rough: you just press Select the amount of times you want for your level, then start the game, but there's no visual indicator so you have to count by yourself. This is tricky on Ninja Gaiden 2 because it won't register if it's not on the title screen, and it goes back to the intro after about five seconds (maybe I'll disable that...).

FYI, Ninja Gaiden 1 already has a hidden level select feature, as mentioned on TCRF.  To enable it, just paste the bytes 20 E9 C0 at x1E547.

ROM Hacking Discussion / Re: MMC3 IRQ Problem
« on: September 19, 2018, 12:09:13 pm »
Really, you should do all of your drawing in VBlank first, then set your screen scroll values to whatever they need to be, then set up your IRQ counter dead last, but before rendering actually starts.  This will ensure that no matter how you muck up the IRQ counter with $2006, you'll be resetting it immediately afterwards so it doesn't matter.

Thank you! For some reason, I had stupidly gotten it into my head that having different amounts of data being transmitted to the PPU would interfere with the timing of the IRQ, not realizing that the counter normally won't decrement during vblank (outside of writes to $2006, obviously).

ROM Hacking Discussion / MMC3 IRQ Problem
« on: September 19, 2018, 02:39:15 am »
As part of the Deadpool hack of Ninja Gaiden, I've converted the game from MMC1 to MMC3 and am now using IRQs to trigger the split screen effects rather than sprite 0 hit detection.  For the most part, things are working fine.  However, in one stage I implemented parallax scrolling, which looks perfect in FCEUX but has issues on more accurate emulators and on real hardware with an Everdrive/Powerpak.  The problem is that sometimes the screen will appear to shake, shifting up and down by a single pixel.  With some help from the beta testers I was able to determine that the shifting coincides with a palette change.  Regarding the MMC3 IRQ counter, from Nesdev:

The counter is clocked on each rising edge of PPU A12, no matter what caused it, so it is possible to (intentionally or not) clock the counter by writing to $2006, regardless of whether PPU is/is not rendering.

It is normal for the game to write to $2006 during NMI when setting the address to update for the status bar on that frame.  But sometimes I write to $2006 when manually updating specific tiles or palettes during NMI also.  Will doing this always result in the IRQ triggering a scanline early?  Also, is there a fix for this other than going back to a sprite 0 hit?  I could also create a "hacky" fix that changes the IRQ reload counter based on whether I'm transmitting other data to the PPU on that frame.  However this will probably cause the screen shaking to occur when playing on FCEUX instead.  Also, I don't notice any additional screen shaking due to scrolling, despite the fact that loading new level data results in several writes to $2006.

Programming / Re: Converting SNES and NES addresses to PC address
« on: September 17, 2018, 11:39:00 pm »
For HiROM, the simple code I used to convert SNES addresses to ROM position recently was:

Code: [Select]
uint32_t convertAddress(uint32_t & addr){
addr &= 0x3FFFFF;
addr = (addr&0x8000)? addr&0x3FFFFF : 0;
return addr;

In the case were bit 22 and bit 15 of the 24 bit pointer are both clear, you end up in a situation where the program counter could point to RAM, SRAM, or to various hardware registers.  For the code I was working on (disassembler), I could not use such addresses without fully emulating the game, so I simply set the address to 0 and checked for that condition elsewhere in my code. Here's a resource for SNES memory mapping for more information:

For the game I was working on, I checked for and manually stripped the header prior to loading the ROM into memory, but if you want to keep track of it like in the example you linked, you could just add 0x200 to the final address if a header boolean is set.  You also want to compare the address to the file size to ensure you don't attempt to read faulty data or get a segmentation fault.  In my case I didn't bother to check for 0x7E0000 to 0x7FFFFF range (WRAM) as this would have already returned a value outside the file size, but if you are working on a general purpose tool you should check for it.

Here's information on the NES memory map:

On the NES there is also the additional complication of bank switching.  Which banks can be swapped out and size of the swappable regions depends on the mapper.  On some mappers, there may be multiple banks of the memory map that can be swapped out individually.  It is possible for a game to load the same part of the ROM to different parts of a memory map, which means that the same region in ROM may have more than one possible PC address.

With so much discussion, has any of these hack ideas come to life or are they lost in too many concepts put forward?

I got the idea to decensor/translate Wizardry V for the SNES from somebody's post on here. The project really only took me a few days and it was a game I already enjoyed. I only remember one other idea from this thread that got picked up since. But that's only like two ideas in over a year and a half. I thought about trying a couple more but haven't since I just don't have the time.

As far as animating, I think I would be content to set a frame count and then manually advance the scene that many frames every time I click a button, if that is more easily accomplished than real-time animation.

I don't quite understand what you mean with the transparent overlay and sprite editing. Do you mean you adjust the transparency slider to restrict what tiles are edited, then edit/replace just those tiles? Also, are you referring to editing in terms of swapping tiles, or at the pixel level within a tile?

Your Deadpool example raises another question: Is it possible to export an image from a scene? This would make small tweaks easier (such as changing Ryu's head to Deadpool's in your example), and otherwise help the user stay within some desired frame size. Perhaps it would be enough simply to take a screenshot of the application with the desired image shown, then edit outside the program and reimport the whole image.

I have gone through the cutscenes to see what additional questions might come up. With the parallax scrolling and panning that happens, is this handled differently for backgrounds vs sprites? Can the speed and duration be changed?

Is there any adjustment possible for the "earthquake" effect, such as the amplitude, frequency or duration? (Unrelated to this application, how feasible do you think it would be to create the earthquake effect during gameplay? Something I have thought about for a long time.)

Thinking about this tool, I went ahead and sketched some dialog and scenes for a hack I'm working on. :)

The transparent overlay is only for the BG portion of the images, not OBJ.  So you are only really editing the OBJ/sprite layer, and the transparent BG image is just there as a reference.  It's useful for situations where instead of having a sprite moving around on the screen, you just want to add some color to the background to get around the 4 colors per tile limitation.  This sort of thing is commonly something that you see for title screens in NES games, but it can be used to great effect in a lot of the NG cut scenes as well.  Editing is going to be done at the pixel level from within that image, as I didn't make a separate editor for individual tiles on the sprite editor.  The reasoning for this is that sprite tiles can overlap, which can make them difficult or annoying to select manually.

I want image editing to be simple enough to do from within the utility itself rather than relying on importing/exporting to external images, but you will be able to use the clipboard or the "load image" button to get sprite data from an external image.  Are you talking about exporting the whole image including both the BG and OBJ layer and importing that back in?  That's a lot more complicated, as it requires generating a new background image and sprite image at the same time, and all the difficulties involved in color-matching both parts within NES palette limitations.  When most people draw a picture in an external editor they aren't thinking about those palette limitations.  Also, depending on the size of the image and the locations of any color-fill OBJ tiles, multiple sprites may need to be generated, since there are only a fixed set of locations within a single sprite where tiles can be placed.

Scrolling for sprites and backgrounds is handled differently yes.  Sprites can have different movement patterns: fixed, linear, "shake", or accelerating.  These are set from within the SPRITESET command, but there is another MOVESPRITE command that can change it afterwards.  But each movement pattern except for fixed has its data defined separately, so you have a limited number of movement patterns available.  The editor can resize the number of movement patterns at will, with a maximum of 64 unique ones for each type.  Each type of movement pattern has different defined properties, such as X/Y velocity both coarse and fine, and acceleration.  The "Shake" effect cycles through a list of pre-defined sprite offsets and loops when it reaches the end.  So it doesn't necessarily need to look like the sprite is shaking, but that is the way that it is used in the original.

For backgrounds, there is a SCROLL_SETUP command that defines the number of scrolling splits and the properties of each.  The location, size, and speed of the parallax scroll splits can be changed, and is handled similarly to sprites in that there is a limit of 64 different unique sets of scrolling parameters that you can define.  The earthquake effect is handled differently and there is a command defined specifically for it.  Similarly to she "shake" movement pattern for sprites, earthquake cycles through a list of predefined scroll positions at a specified rate.  For both parallax scrolling and earthquakes, the effects continue until you manually stop them by calling another command such as SCROLL_SETUP, EARTHQUAKE, SCROLL_STOP, etc.

I sort of made an earthquake during gameplay for the bomb effect in Deadpool, but I cheated a bit by disabling collision for the player and freezing enemies during the effect.  The scroll position is directly tied to environment collision calculations, so environment collision sometimes fails during earthquakes.  It might be fixable though.

This is very cool. Beyond the cut scenes, might you expand the tool for other functions? I know it would likely be tricky, but an option to make walls (some or all of them) climbable like ladders would be awesome.

I'm still itching for a version of NG1 with NG2's wall climbing.

I already did that for the Deadpool hack.  If you want a separate patch for NG with just the wall climbing feature added I can put that here, no need to try to build stage editing functionality into the cut-scene editor:

It's a little different from NG2's climbing mechanics though in that you can climb to the top of the wall without jumping.  However there are some places where you still can't get up the top of the wall due to weird collision properties.  Also, that ips allows you to change Ryu's palette in different rooms by changing values in the array at x31C0.  I previously made this patch for another hacker, hence the inclusion of the palette hack.

Another thought about designating CHR tiles that can be overwritten... What if the user identifies one or more scenes they are willing to cannibalize entirely? For example, the scene where Malth first appears. Then, any tiles that are unique to that scene can be overwritten.

There are a few times when the cutscene flashes, such as Ryu before the final Jaquio fight. Is this scripted as a "flash" command and duration, or as a discrete series of palette changes? It would be nice to work with in shorthand form, although I suppose it's essentially a macro if you can copy and paste the text of those palette changes. Ditto for the sudden change to grayscale that sometimes occurs.

Being able to edit and view the changes from inside the program would really be impressive. If it saves you time, it would be a good first pass to simply patch a ROM so it starts the player just before the selected scene is triggered, then launch a designated emulator with that ROM.

Well, right now an image is automatically cannibalized if it is no longer used in any scenes.  But I do think it is a good idea to add a feature into the bg/sprite editors to allow selection of tiles or whole images that can be replaced.  As for the flashing, yes there is a command specifically made for this, rather than a series of palette changes.  So fortunately that effect is very straightforward to add or remove.  As for instances where the image is converted to grayscale without flashing, the original programmers always did that by setting the palette directly.  However, there is another command that they could have used to do it, and honestly I don't know why they didn't because it seems a lot more convenient.

I'm confident that I can make a convenient interface to edit the scene data directly from the editor, it's just the viewer part I'm worried about, since animated scenes in Qt is new for me.  I did make some more progress on the sprite editor, but not done yet.  Here's a screenshot showing the ability to overlay a transparent background image to make it easier to draw certain sprites:

This one shows an image from the Deadpool hack.  The original used those scattered sprites as a color-fill for the background, and the artists on the team had a hell of a time trying to arrange and draw the tiles properly.  There is a transparency slider so that the background can be partially hidden or shown in full color depending on what you want to see at the moment.

The background editor has some great features already. For the usage overlay, perhaps you could have a mode to show a count of how many times the tile is used, and maybe highlight it a different color if it's used in another scene, so the user doesn't inadvertently overwrite a tile used in multiple scenes. The auto color matching is a great idea. How about if the UI pops up a grid of the colors found in the imported bitmap; when the user clicks a color in the grid, the UI emphasizes those pixels somehow (perhaps shading all the others darker temporarily); and the user can click one of the palette colors to create the color mapping between the source bitmap and the ROM palettes. So you can build your color mapping manually, if for some reason you want to tweak the program's algorithmic guess.

The "tile usage" checkbox is intended to show whether a tile is used in another image already, although it only overlays the CHR patten view in the top right, not the current image arrangement.  As for showing a count of how many times the tile is used, the only good way I can think to do that would be to add a status bar, with a little message showing you the number of times the currently selected tile is used in the current image and in other images.  I think trying to list that information for all tiles at once would either end up in clutter or confusion.  I might be able to improve the color matching algorithm and implement it properly, but regardless, the user will be able to change colors at will.  My first attempt at automatically setting the palettes calculated the most frequently used colors in each 16x16 area and attempted to create a list of optimized palettes from that, and then choose based on the number of metatiles for which that palette was optimum.  But it didn't do well in accounting for cases where some of the optimum colors overlapped in between different palettes.  Thus it would create several palettes with mostly the same colors and overall matching would be poor.  I'm sure I can improve it with some more work.

It would be cool if it could analyze the imported bitmap for unique 8x8 tiles, performing any mirroring/aliasing as necessary. Then it could tell the user how many unique CHR tiles must be imported. If it were possible to see some different backgrounds (in the current scene, or ideally, any scene) in the UI and designate tiles to overwrite in that view, I think that would be great. Let's say I'm replacing Foster with Spider-Man. So I know I can overwrite all the tiles for Foster, and it would be nice to see an image of him and go click-click-click (or click-drag to select a rectangle) to designate tiles I'm willing to overwrite. It would also be cool to designate tiles in the imported bitmap that are irrelevant and should not be imported.

It actually already checks the image on the clipboard for matches with current CHR tiles.  Mirroring won't work for background images, that would require sprites.  Being able to see some of the other backgrounds is something I would like to do though.  There are several images that are near copies of each other with only minor changes, and as such all those tiles would be marked as shared, interfering with attempts to paste over the tiles.  I just haven't thought of a good way yet to present all the images with shared tiles and allow the user to mark which ones are ok to overwrite.  There are gridlines between the tiles, so maybe I could add a new select mode and then color in the lines around tiles that are marked as ok to overwrite.  As for designating parts of the imported bitmap that don't need to be copied, that can be done through transparency.  If you are using an external image editor, just make part of the image transparent and it won't try to import that bit.

Other ideas:
Can the program resequence cutscenes in the game? If I recall, this is a simple vector in memory, but it would be nice to have in the program. What about the Act-X screens? Can the user dictate when these show up? There is at least one series where it's a cutscene, an Act screen, and another cutscene. Is it possible to make an arbitrary-length series of cutscenes after a single level? This would simplify some of my goals.

Is it possible to resequence shots in the scene? For example, let's say I want to have the intro scene start with Ryu reading the letter, then cut to the ninjas running in the field, then back to Ryu reading, then to ninjas jumping, then back to Ryu reading, then to ninjas landing. In the ++version, I would like to compose a scene using existing shots from several scenes. For example, during Foster's lecture, replace the shots of Ryu with the up-close shot of his eyes.

Can the user change the number of shots in the scene? I suspect decreasing is easy, but increasing the number might not be.

Is it possible to shorten a scene to an arbitrary number of shots? If so, and if any number of scenes can be strung together between levels, then I have the ability to compose what looks like a single scene using any shots in the game.  :o

Yes to all of this.  The way to change the order of the scenes right now is to export all of them to text files, then re-import them in the locations you want.  There is a dialog box when selecting a scene to import that lets you choose the scene that you want to replace, so it's easy to just use the data from one scene and import it in a new place.  I might add an even simpler option to do this later once I've built scene editing directly into the GUI.  For the length of the cut-scenes and how many shots are displayed, all that is controlled through scripting that the editor can currently change.  The scene will continue until you put an "END_SCENE" command, regardless of how many shots you put in.  The only real limits are ROM space and CHR space.  You do need to keep in mind though that only certain combinations of sprites and backgrounds can appear on screen at the same time, due to their presence in particular CHR pages.  But if you use valid combinations, you can continue to include shots to your hearts content.  You could even take all the data from all scenes and just copy it into a single scene and show everything at once.

Is it possible to change the music and sound effects in the scene? In the opening scene, there are two songs and some sound effects, but I don't see that in the script output. There are also cutscenes with a specific sound at a specific time (e.g., Irene shooting Ryu). It would be cool to change that sound and the timing of that sound. For example, you could make it sound like Irene shoots Ryu twice.

Music and sound effects are started with the "MUSIC" command.  So the original scene with Irene shooting Ryu has this:
TIMER = 0077
PALETTE_SET  0: 0F 30 30  1: 0F 10 30  2: 0F 10 00  3: 0F 10 30  4: 0F 30 30  5: 0F 30 30  6: 0F 30 30  7: 0F 30 30

You can change it to this to add the second shot:
TIMER = 0010
PALETTE_SET  0: 0F 30 30  1: 0F 10 30  2: 0F 10 00  3: 0F 10 30  4: 0F 30 30  5: 0F 30 30  6: 0F 30 30  7: 0F 30 30
TIMER = 0067

Just tested, and it works to add the 2nd shot.  Writing script this way takes some getting used to, but it will get easier once editing can be done in the GUI itself.

Can the text speed be changed per line, per shot or per scene? There are times when this might heighten the dramatic or comedic effect.

The text speed can be set for each dialog/message.  Usually there is one dialog per shot, although there could be more.  There is no convenient way to change text speed on a line-by-line basis.  However, there is also the "delay" command within text, which adds a full second until the next character is printed.  It looks like this:
  "Ow... <DELAY>Where... <DELAY><BREAK>
   Where am I?"<BREAK>
  <DELAY>"I see the anesthetic is<BREAK&INDENT>
  wearing off."<END>

In the above dialog, the TEXT(2), indicates that there are 3 frames (2+1) in between characters displayed.  If you really needed to change text speed line-by-line, you could do it by creating multiple messages and carefully aligning the timing, probably adding some line breaks to the later messages so that they don't write over the top of the previous one.  Aligning the timing would be tedious though.  I hope to eventually get a preview pane into the editor so that you can immediately see the results of your changes and make timing adjustments and such.

Lastly, it looks like you're running on Linux. Will the program be compatible with Windows?

Thank you for making such a cool program!

Yes, it is coded using Qt, which can be compiled for different platforms.  The rest of the Deadpool team runs Windows, and I've already cross-compiled a couple alpha versions for them to try out.

This is a project I've been working on for a few months, and I have made some good progress on it:

The main window isn't a whole lot to look at right now, but it already allows you to edit the scene scripting through importing and exporting of the data to text files.  Here's an example of what the scene scripting looks like after it has been exported:

Scripting edited via the text files can then be imported back into the ROM and saved.  I have plans to incorporate editing into the GUI itself rather than using txt files, but for now it works well enough to change all aspects of the scene scripting.  It took me a long time to be able to handle all the quirks in the scripting language for the scenes in this game, but it seems to be working pretty well now.  Editing of backgrounds, objects/sprites, and dynamically loaded background images is going to be handled in separate dialog windows.  The background editor is currently functional:

The sprites/OBJ editor window is only partially done currently, and I haven't started the editor dialog for the dynamic background images yet, although they can be viewed in the folder with the ROM after using the "Export All Data" button.  After the image editing dialogs are complete, the plan is to allow editing the scene scripting from within the main window itself and then create a preview pane where you can view parts of the scene to verify the changes you made.  I initially started this project to improve on the quality of the cut-scenes in the Deadpool NG hack, so I have a few extra script commands built into the editor that I created for that hack.  However this editor is fully compatible with the original NG as well.  To prevent any confusion, I will most likely do a separate build without the extra commands, although there is no harm in attempting to use them in the original game (doing so has the same effect as using the "blackout" command).

I have plenty of experience hacking ROMs and making command line utilities, but making a GUI editor is pretty new to me, so I could use some opinions/advice.  In particular, the background editor may be functional, but I'm not happy with the appearance/layout.  I can put some labels on the clipboard viewer and tile viewer, but I still don't really like the way it's organized.  The "Recommend Colors" button makes a popup appear and suggest colors to use to best match the image currently on the clipboard.  I originally wanted it to automatically set the palettes to best match the clipboard image, but the results weren't turning out well, so for the moment I left it up to user discretion on how to set the colors after presenting the recommended ones.  Copying and pasting an external image into the editor DOES work, and matches as well as it can to the current palette, so long as there are enough free tiles in the CHR page to use.  Ctrl+C and Ctrl+V are used for copy and paste operations, and Ctrl+Z / Ctrl+Shift+Z undo/redo actions.  It feels natural to use for me, although relying on keyboard shortcuts without presenting a button or menu interface for the user to see the controls may not be best practice.  There is a "stamp" mode radio button that you can use to paste images directly into the background arrangement with only a click though.  The "show used" checkbox overlays a partially transparent image onto the CHR page showing the usage of tiles: green is unused, orange is used only by the current image, and red is shared or used by other images.

Any feedback is appreciated.

ROM Hacking Discussion / Re: How to form a team
« on: March 29, 2018, 03:53:22 pm »
I was more asking about how to sort out help offers after I've received them. I'm not entirely new to ROM hacking, but I've only worked alone before. I've received offers to help for things in the past, but was never sure what to do with them, how to tell how genuine they were, whether they would actually be helpful, etc. So for the purposes of what I'm asking, I'm assuming I already have something to show, and there are people interested in helping, which I wasn't clear on in the OP.

I'm currently on the team working on the Deadpool hack of Ninja Gaiden.  Danger X asked if I wanted to join after I solved some problems that he had asked about in a thread on this forum.  I know another of our current lead team members started out by showing the team some graphical assets that he had created specifically for the project.  If somebody is both willing and capable of helping, they should be able to show you samples of their work/abilities.  If you have a specific problem or area in which you need help, I'd ask about it and see whether they could actually give you something.  One option would be to make a thread about what you need in the help wanted section, and if somebody offers to help you via PM or on another forum, you could just point them to the help wanted ad.  That way if they don't work out, other people could see the ad too and you won't have wasted time waiting on somebody unknown.

Gaming Discussion / Re: NESMaker
« on: January 17, 2018, 08:34:38 am »
I saw this project a couple days ago.  From what I understand, they basically constructed the engine for a homebrew game, and they are providing a set of tools needed to create content for it (aka hack it).  From a romhacker's perspective, it is similar in ease/difficulty to making content for any NES game that already has had a set of good tools created for it.  The main advantage is that they freely allow you to use, edit, and possibly distribute that content.  I actually didn't see any mention of distribution, so I'm not sure about that last bit.  They only mentioned playing the game that you created yourself, not allowing others to play it too.  The quality of the tools and legal right to distribute your created content will determine how big of an impact this will end up having on the homebrew scene.  There is also a bit of a risk that the homebrew scene will get flooded with low effort productions.  I'm sure there will also be some good ones too though.

I have some ideas for ROM hacks mainly some improvements for games. For Ninja gaiden and Ninja gaiden 2 make it so that the enemies don't respawn so quickly or make them stay dead once you kill them. Also make it so that if you die to the final bosses of all the Ninja Gaidens you would start back in the third area of the last stages rather then starting back at the beginning of the final stages.

I've actually already done both of those things for NG1 as part of the Deadpool hack I'm helping with.  That hack is enormous though, and is still at least a few months away from completion.  I suppose if there is interest I could extract those changes and make a separate improvement patch for NG1.

Newcomer's Board / Re: Need help submitting nes rom hack
« on: October 11, 2017, 06:13:42 pm »
The file needs to be compressed to one of the accepted file types. I use 7zip (.7z).

ROM Hacking Discussion / Re: Zelda 2 FDS Translation
« on: October 09, 2017, 07:45:02 pm »
The checksum checking of BPS is a problem for the reason KingMike mentioned - though incidentally my patch deletes the save data, and I hope others making patches will do the same as it's probably appreciated by people who want a nice clean file. How about Xdelta? I've not used it, would it yield a better result in my case? Do you have to manually say where the extra bytes are or can it just figure it out by itself?

I use the utility here as a frontend for xdelta:

You can select whether or not to add a checksum when you create the patch.  As long as you disable the checksum you should be good.  It can figure out where the bytes are by itself.

Pages: [1] 2 3