Jump to content
IGNORED

Quadromania Redux developer blog


Recommended Posts

Raiders of the Lost ROM part 4 is now available! I discuss how to identify and patch joypad accesses in a Lynx ROM, as well as a couple of Quadromania-specific bugs I fixed along the way.

 

Note that when I talk about patching a Lynx ROM, you will of course need to re-encrypt the ROM after the patch. Unless your ROM has an encrypted boot loader on it that does not checksum the ROM.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 5/15/2020 at 9:42 AM, 42bs said:

Ever since I first tried panning I wonder if a real "surround" effect is possible. Means a sound source the virtually moves around ones head.

I don't know that you could accomplish that with panning on the Lynx. You certainly could add a depth component to the sound, though. I believe Klax does this already, where the blocks further away from you not only pan left and right, but are also quieter. Then they slowly get louder as they approach. So you could in a sense make the sound move closer or farther in addition to left or right, but I don't see how you could simulate up and down. It would be kind of neat though in a 3D game if a fireball could shoot towards the player then get quieter if it missed and kept traveling behind the player -- that would be pretty close to a surround effect.

 

On 5/15/2020 at 12:53 PM, LordKraken said:

Still super interesting, I like the amount of tech details without losing me :D

Thanks, that's my goal. :) I'm more of a brute-force hacker who looks for ways to add simple new features or fix key bugs. There are of course a lot of details I am glossing over, but I'm trying to give a higher-level view of the methodology behind the changes rather than an in-depth treatise on assembly programming.

Link to comment
Share on other sites

6 hours ago, Songbird said:

It would be kind of neat though in a 3D game if a fireball could shoot towards the player then get quieter if it missed and kept traveling behind the player -- that would be pretty close to a surround effect.

Yes. Now let's add some game play around the effect ?

Link to comment
Share on other sites

  • 2 weeks later...

Once again, really cool article. I was just wondering, when you change the layout of a level, you might increase its size and then it does not fit into the original location. So you switch the level pointer to the new definition, I get that, but does that mean you know exactly at what address you have some memory free? How do you figure it out? is it like crystal clear in the asm source?

 

(This is by the way the only real annoying thing when I code in C on the lynx, I have no clue how the memory mapping is done, and the compiler - well at least newcc65 - does not give me any clue, so come a time where variables just starts to overlap and the game just randomly crashes.)

Link to comment
Share on other sites

1 hour ago, LordKraken said:

(This is by the way the only real annoying thing when I code in C on the lynx, I have no clue how the memory mapping is done, and the compiler - well at least newcc65 - does not give me any clue, so come a time where variables just starts to overlap and the game just randomly crashes.)

Memory mapping is defined (as for any compiled language) in the linker/linker-script!

Link to comment
Share on other sites

In the case of Quadromania, the levels occupy a blob of RAM but have other variables before and after them. So I had to ensure that I worked within the original start and end RAM locations. That means individual levels could grow or shrink but I couldn't go past the original end. And actually, I could have gone past the original end of level RAM by finding a new unused location in RAM and updating the level pointer. So then I'd have more of a scatter/gather list instead of a contiguous chunk of level RAM. But as it turned out, a lot of the higher levels had so many blocks I found it easy to shrink levels rather than grow them.

 

As Bastian said, you should be able to see the memory map for C code during the build process. That's a tool I've used for many years on C programming -- just haven't done any C recently! But you usually get some kind of linker output that shows your text, data, and bss. For example, I wrote Remnant for the Lynx in C with cc65 20 years ago, and here's a snipped of the "map" file output:

 

R - relative A - absolute
T - text     Z - zeropage
text-segment base address 0400
 d:\prog\lynx\newcc65d\lib/runtime.run            (0400 to 09f4 =  1525 bytes)
 ufo1.obj                                         (09f5 to 0a81 =   141 bytes)
 ufo2.obj                                         (0a82 to 0b18 =   151 bytes)
 ufo3.obj                                         (0b19 to 0bab =   147 bytes)
 ufo4.obj                                         (0bac to 0c33 =   136 bytes)
 boss1.obj                                        (0c34 to 0df8 =   453 bytes)
 sled1.obj                                        (0df9 to 0e9f =   167 bytes)
...
more stuff
...
_LoadCartBlock          962c RT _viddma                 fd92 A? 
_remlogo                2137 R? incsp7                  0464 RT 
_cos1                   a0de RB _pFirstEnemy            a450 RB 
incsp8                  0468 RT __iodir                 0090 RZ 
_cos2                   a0e0 RB _scbnext                fc10 A? 
sreggeax                0774 RT _cos3                   a0e2 RB 
_SetBuffers             8f58 RT _debris                 a108 RB 
...
etc.

So I can see all my variable locations, data structs, and function calls (such as SetBuffers()).

 

Link to comment
Share on other sites

I'm not an expert in low level or compilation tools too...

 

Carl, do you remember which tool you used to get the map ?

Just tried -v option on link65 and redirect output to a text file, but I need to understand the output, not sure it is really useful apart the part in red :

Quote

[...]

NEW -> _objet_SPR 1C7, 27
-> addysp 17 0

NEW -> _ennemi_SPR 02F, 27
[...]
TEXT : 0400 (27411 bytes)
DATA : 6f13 (  819 bytes)
BSS  : 7246 (  276 bytes)
ZERO : 0080 (   44 bytes)
STACK: 775a ( 1024 bytes)

module:runtime.run                        TEXT 0400 DATA 6f13 BSS 7246 BSSZP 80
module:c37.obj                            TEXT 09ff DATA 6f3f BSS 7246 BSSZP 93

 

ennemi_SPR is an array defined like this :

char ennemi_SPR[10] = {0,IDX_BH_ENNEMI,IDX_TURRELS,0,0,0,0,0,0,0}

 

and objet_SPR

char objet_SPR[10] = {0,IDX_LIFT,IDX_TURRELS,IDX_ITEMS,0,0,0,0,0,0};

 

and should be consecutive in memory.

I do not see the relation with link65 output...

 

printobj seems to give something more interesting :

Quote

sym:_objet_SPR                       flags 2700 value : $eb00
sym:addysp                           flags 00 value : $0000
sym:_ennemi_SPR                      flags 2700 value : $e100
[...]

sym:_RENDER                          flags d00 value : $18e0
 

With endianness : $00e1 (ennemi_SPR) + 10 octets is 00EB (objet_SPR)

and RENDER is really defined at $E018 (forced in code)

 

Need to make some more test, and stop hijacking this thread :D

Link to comment
Share on other sites

My build invocations on Remnant were pretty bland:

cc65 -DCARTRIDGE main.c
xopt main.m65
ra65 main.m65
link65 -o remnant.o lynx.olb u*.obj b*.obj sled?.obj met*.obj ex*.obj cockpit?.obj remlogo.obj pw3d.obj main.obj
lynxer remnant.mak
make_lnx remnant.lyx -b0 256K

I don't recall running a special tool or tool parameter to generate the *.map file. I think I just redirected the text output to a file. But that was many years ago...

 

Link to comment
Share on other sites

  • 3 weeks later...
  • 1 month later...

Nah, Raiden is already available. This is something different. And it's almost done. :D

 

HOWEVER I should write an epilogue to my series on Quadromania called "the need for independent testing." Quadromania has been code complete for over two months, just waiting for me to perform a final regression test on it. I started that testing today and found a glaringly obvious bug in about, oh, 10 minutes. Independent testing probably would have caught this two months ago. At least I found it before I started building carts!

 

Link to comment
Share on other sites

OK, so I went ahead and wrote a Raiders of the Lost ROM epilogue covering the bug I found and the corrective steps I took to avoid it in the future. It's not as technical as the other blog posts I wrote, but hopefully it will help devs either thinking about adding EEPROM support to their games or just realize the value in independent testing. Enjoy and keep those Lynx games flowing! :) 

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...