| www.retrosoftware.co.uk http://www.retrosoftware.co.uk/forum/ |
|
| COTPORS: Help with an assembler routine http://www.retrosoftware.co.uk/forum/viewtopic.php?f=73&t=489 |
Page 1 of 2 |
| Author: | Samwise [ Sun Jul 25, 2010 6:07 pm ] |
| Post subject: | COTPORS: Help with an assembler routine |
Calling On The Power Of Retro Software, My 6502 skills are pretty rudimentary and I've run into another headache adding Electron support to my CE project. Can anyone help me code an assembler routine to relocate some problematic data that I've mocked up with pseudocode? Basically, there are eight pointers (&0CC0 - &0CCF) which hold addresses to where to find eight sets of data. The individual sets of data can be of varying sizes. The one certainty is that in total they don't exceed &440 and so they will always fit between &0CD0 and &10FF. Unfortunately, that means the data is overwriting location &0D68 of the Plus 1's workspace, which is causing me a problem. To fix this, I need to intelligently copy the set of data which is overwriting that location, up to &3100 - &3200. This would be fine, but as the sets can be of varying sizes I can't be sure which set of data acually needs to be moved - it's usually set 1 or 2 but I can't be sure which and there isn't enough room to copy more than one of the sets. So that means I need to be able to work out from the pointers which set is overwriting that location, copy that problematic set of data up out of the way (don't think it matters if I copy slightly more bytes than in the actual set, so copying the next &FF bytes from the start of the set would be fine) and update the pointer to that data to its new location at &3100. I'm stuck at the first step atm, so whilst I've got some idea of how to do the next couple of steps I'll be eternally grateful to anyone who can provide me any pointers. Sam. Code: Pseudocode
---------- 1 - Search through eight pointers (&0CC0 - &0CCF) to find which data overwrites memory location &0D68 2 - Move that single set of data to memory location &3100 3 - Update that particular data set's pointer to point to new location &3100 Pointers to eight sets of data 0CC0 D0 0C data set 0 is at &0CD0 0CC2 3E 0D data set 1 is at &0D3E 0CC4 B2 0D data set 2 is at &0DB2 0CC6 4B 0E data set 3 is at &0E4B 0CC8 DC 0E data set 4 is at &0EDC 0CCA 6C 0F data set 5 is at &0F6C 0CCC E8 0F data set 6 is at &0FE8 0CCE 72 10 data set 7 is at &1072 Actual data - data can start at varying places, but complete set always sits between 0CD0 - 10FF 0CD0 ..... data set 0 (example, could be different) 0D3E ..... data set 1 (example, could be different) 0DB2 ..... data set 2 (example, could be different) 0E4B ..... data set 3 (example, could be different) 0ECD ..... data set 4 (example, could be different) 0F6C ..... data set 5 (example, could be different) 0FE8 ..... data 6 set (example, could be different) 1072 - 10FF ..... data 7 (example, could be different) |
|
| Author: | MartinB [ Sun Jul 25, 2010 8:37 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Is it the actual code that's troubling you or just the logical process? It's very simple to logically identify the offending data because, stepping along the eight pointers, the first pointer we encounter that is greater than (specifically excluding equal to) $0D68 tells us that the preceding data block is the offender. We then need to perform a 16 bit subtraction of the 'offending pointer' from the identified 'greater than pointer' which tells us the 'length' and then move the data from 'offending pointer' to ('offending pointer' + 'length' - 1) to $3100 updating 'offending pointer' to 00 31. (Is it possible for all the blocks to be tiny such that none exceed $0D68? If so, and the initial test therefore identifies none, as a safety measure you would probably always move the last block in case it is large compared to the preceding blocks and does itself overwrite $0D68.) Maybe you knew that but want the actual code? |
|
| Author: | Samwise [ Sun Jul 25, 2010 11:46 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Hi, Martin. Yes, the method I'm fine with - and if I know the data values and which level is overwriting &0D68, I have coded a suitable routine to move the offending data set. Problem is, I /don't/ - the values can vary depending on which levelset is loaded, which is why it needs to be generic. :/ I have just had a new thought on how I might be able to do it in BASIC before the program runs (which I didn't think was possible when I first posted) but I'm struggling to get that to work atm. If it doesn't, then I need to write the routine in assembler - and that's where I'm a bit lost. I'm not sure how to code that search through the pointers to identify the correct data set. To answer your other question, I think it's very unlikely that the total data set will ever be small enough to not overwrite &0D68. So, in summation, yes, now that I've worked out what I need to do, I was hoping for some help with actually implementing the code, whether that be assembler itself or even some pointers at the sort of techniques I should be using - particularly with step one. Sam. |
|
| Author: | Samwise [ Mon Jul 26, 2010 1:21 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Hmmm ... I think I might actually be able to do this in BASIC. I need to work out how to convert the pointers into hex values, but might actually be do-able in theory. I'll pursue the BASIC route for now, and shout back here if I have to resort to assembler. Sam. |
|
| Author: | RichTW [ Mon Jul 26, 2010 10:29 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Here's an (untested) attempt to do this in 6502 - what it does is starts at the last pointer and works backwards, looking for the last pointer whose address is less than or equal to &D68. When it finds it, it assumes that this is the block which contains address &D68, and then blindly just copies 256 bytes from that pointer address to the new address, and patches up the pointer to point to the data's new location. Code: pointerstable = &CC0 numpointers = 8 hotspot = &D68 relocaddr = &3100 .relocateblock LDX #(numpointers-1)*2 ; start at the last pointer and go backwards .searchloop LDA pointerstable,X CMP #(hotspot+1) MOD 256 LDA pointerstable+1,X SBC #(hotspot+1) DIV 256 BCC foundit ; branch if pointer <= &D68 DEX DEX BPL searchloop RTS ; if we got here, all pointers are greater than &D68 .foundit LDA pointerstable,X STA copy+1 LDA pointerstable+1,X STA copy+2 LDY #0 .copy LDA &FFFF,Y ; self-modified above STA relocaddr,Y INY BNE copy LDA #relocaddr MOD 256 ; patch up pointer STA pointerstable,X LDA #relocaddr DIV 256 STA pointerstable+1,X RTS If anyone fancies peer-reviewing that to make sure I'm not way off the mark, please go ahead. Alternatively you could just try it Why is this location causing trouble by the way? |
|
| Author: | Samwise [ Mon Jul 26, 2010 11:09 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Awesome work, Rich, now I'm spoilt for choice. I'll try this out over the next couple of evenings - it will take at least that long for me to get my head around it! Now I can see a way of doing it that will also work in BASIC, I haven't quite decided which would be the most efficient route according to how I'm moving stuff around in memory, but I suspect assembler might be so I will definitely try it out. The location &0D68 is used by the Plus 1 as part of it's workspace and the way CE tramples over it, means that when the joystick support patch is applied the directions don't work. The joystick routine works, as running the joystick-patched Electron version on a beeb works great - but I have to reset that particular location to use the sticks on an Electron with a Plus 1. This data is actually the level data so, of course, if I reset that location without moving that level's data out of the way, the level changes (using the original levelset data results in a missing platform at the top right of level 2). My issue stems from the fact that I want to continue supporting the ability to load in custom level sets so whilst I have a version of CE that runs OK with the original levelset, I want it to be able to handle the fact that the original level data has been replaced with any one of the other alternate levelsets, or even homegrown sets built with the level editor. In an ideal world, I'd have just moved all eight levels from their original place up to &3100 because the Electron version's change in MODE from the beeb version should mean in theory that I have the whole of &3100 - &5800 to play with but for some reason I don't understand everything above &3200 gets wiped out before the game starts. This leaves me with a measly &100 bytes which is only room to store one level at best - which is where this mucking about selecting the right level comes in. If I'd been able to figure out how to move all eight levels up to &3100 I'd dump all this messing about like a shot. I know I could also go the route of trying to re-assemble the game with stuff in different places, but one of the goals of the project was to keep it as a large patch file that would modify the original executable, rather than a whole new version. I don't know why that's important, but I've been doing it so long now that I'm loathe to give that up. PJ's also told me on several occasions that I could lose the redefine keys option to free up more memory, but again I'd like to keep it as close to the original as possible. The way it works atm is to allow you to toggle the features on/off so you can choose just how much or little you want the game customised ... and it was all going so well, until this bloody Plus 1 issue came up! Sam. |
|
| Author: | RichTW [ Mon Jul 26, 2010 11:32 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Yet again, what we really need is the source code as an file which can be edited, generally poked around with, and conditionally assembled for each platform with optional extensions. Then we could trivially move around the memory layout at will. I presume the Electron version shares most of its code with the Beeb version, but with changes for the sprite plotting and erasing. I've never looked at the Electron code. I guess it must have to erase the sprites in a different way (it can't use the EOR trick because it uses a lower colour depth mode), so maybe the spare memory between &3200..&5800 is used to cache the chunks of screen behind moving sprites, so it can be restored easily, although that's far more than it possibly needs. Just sounds rather like sloppy coding to me. Anyway, for now you ought to be able to append that assembler code to the end of the Chuckie Egg executable, and call it as soon as the code's been relocated to its final place. That'll be more difficult to do in Basic though. Give us a shout if you have any doubts! |
|
| Author: | Samwise [ Mon Jul 26, 2010 12:11 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Hi, Rich, I've dropped you an email with an example of my current test code, FYI. RichTW wrote: Yet again, what we really need is the source code as an file which can be edited, generally poked around with, and conditionally assembled for each platform with optional extensions. Then we could trivially move around the memory layout at will. Ahh, yes, but that would violate my attempt to keep it working without modifying the original executable on the disc. Of course, even though I've got a commented disassembly of the Beeb version kindly provided by Dave Devenport, turning it into a modern assembled version is really beyond my skills anyway, so it's not an option. Plus, we're also talking about the Electron version here, which I haven't even got a proper disassembly for. :/ RichTW wrote: I presume the Electron version shares most of its code with the Beeb version, but with changes for the sprite plotting and erasing. I've never looked at the Electron code. I guess it must have to erase the sprites in a different way (it can't use the EOR trick because it uses a lower colour depth mode), so maybe the spare memory between &3200..&5800 is used to cache the chunks of screen behind moving sprites, so it can be restored easily, although that's far more than it possibly needs. Sounds plausible to my layman's ear. Although I don't know why it overwrites it (or even how much of the memory is being overwritten - I'm not sure if it's all the way up to &5800), I'm just making the assumption that there's not enough available for me to move all &440 bytes of the level data in one go. RichTW wrote: Just sounds rather like sloppy coding to me. Of course! That's what CE is famous for. RichTW wrote: Anyway, for now you ought to be able to append that assembler code to the end of the Chuckie Egg executable, and call it as soon as the code's been relocated to its final place. That'll be more difficult to do in Basic though. Give us a shout if you have any doubts! With some previous help from PJ, I now know how to patch in the basic relocation code - what I need to do is see if I can modify that with your new code, to make it work with any generic levelset. To do it with BASIC, my plan was to use BASIC to identify the correct level, move it to somewhere above &5700 (everything needs rejigging as the initial joystick patch lives at &5700 atm) and update the appropriate pointer already loaded in to point to &3100. Then in the assembler, there would only need to be a simpler routine to move it down from &5700 to &3100, not any of the more clever stuff. As there has to be an assembled routine, even if it's only moving code from &5700 to &3100, it will probably be neater to use your code to put the logic in the assembler rather than the BASIC. I think I will need to load the CE code even lower now, but if I load the XLOADER patch in at &1100, I'm hoping that will still let me squeeze it all in (the full XLOADER is jam-packed with features now). Sam. |
|
| Author: | Samwise [ Mon Jul 26, 2010 3:39 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Hmm ... one thing has just occurred. Tom has suggested it might be wise to try and protect &D68-&D6F, as well as just &D68. I don't have the room to store two sets of data, if that range were split over the boundary between two levels, but it might be a bit more safe if I could manually reset any of that range which also falls under the missing level. This is very hacky and there's probably a cleaner way to do it but in BASIC, I'd put something like this, probably at the end of the routine: IF ?(pointerstable-1) > &D69 THEN &D69=&20 IF ?(pointerstable-1) > &D6A THEN &D6A=&20 IF ?(pointerstable-1) > &D6B THEN &D6B=&20 IF ?(pointerstable-1) > &D6C THEN &D6C=&20 IF ?(pointerstable-1) > &D6D THEN &D6D=&20 IF ?(pointerstable-1) > &D6E THEN &D6E=&20 IF ?(pointerstable-1) > &D6F THEN &D6F=&20 Is there a simple assembler equivalent I can bodge in? (the &20 values are just placeholders for now - they'll probably end up being the values from the original data, as they're known to work). Sam. |
|
| Author: | MartinB [ Mon Jul 26, 2010 5:29 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Hi again Sam. I don't really follow what you're trying to do there but one thing, you cant use '?' as that only returns a byte (8 bit) value. You need to use '!' which will return four bytes and then mask for the lower two bytes you're after. e.g. If &0CC0 holds &CD and &0CC1 holds &AB then you would return the required address of &ABCD with !&0CC0 AND &FFFF |
|
| Author: | Samwise [ Mon Jul 26, 2010 5:56 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
You've got me - I didn't try out the routine. As for what I'm trying to do, I'll try and explain better - the game overwrites the whole of that &0D00 page on startup. Rich's last patch lets me work out exactly which block of data overwrote &0D68 and then copy it up to &3100 - but that still leaves the &0D68 location in its trampled-on state. So I will add a couple of lines to manually reset &0D68 back to &20, so that the joysticks will work. Now, I'd also like to reset as many of the values in the &0D68-&0D6F range as possible after Tom's tip-off, in order to minimise the chance that overwriting them with some alternative levelset data will cause similar problems with the joysticks. It's possible that the original levelset data that trampled over &0D69-&0D6F just happened to match the values required to use the joysticks, but if I support loading in new levelsets then they might cause similar problems with the Plus 1 by overwriting the &0D69-&0D6F range with different data to the original. Unfortunately, I can't just reset all of them to specific values because the level data is of varying sizes and so it's possible that the range may get split across, e.g. level 2 and 3 - so I can only reset those values that also happen to fall under the same level as the one that is known to be problematic, &0D68. This is what the pseudo-BASIC code above tries to do. Unfortunately, it needs to be tagged on the end of Rich's assembled routine, which will be patched into the main program to be run when required - i.e. after my BASIC loader has been left behind. Hopefully, this will then enable Electron joystick support which will work with /most/ potential levelsets. It's not 100% guaranteed to work with all possible levelsets, but without any more obvious memory available to play with, it's the best I can do. If I compromised on not using a loader patch, but modified the executable instead or if I overwrote the original game's redefine keys menu, I could probably increase the chances that there will never be clashes, but I'm loathe to do that as I think this will, in practice, be good enough for 95% of the time and I want there to be the option of only selecting the modifications you want, rather than applying everything in one go. I daresay better coders than I could do a better job of it if they turned their full attention to it, but I'm bothering enough people with it as it is. I thought I'd finished with it all as it plays like a dream on a beeb, but trying it out on the Electron for the first time has thrown up a number of these issues, unfortunately. :/ Sam. |
|
| Author: | Samwise [ Tue Jul 27, 2010 11:16 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Gah! Although Rich's code works perfectly, for some utterly inexplicable reason, memory location &17CB is getting modified - which results in a graphical glitch in the letter K on the title screen. *sob* If I don't set &0D68 to &20 (the point of all this moving around), then it's fine. Trying to manually overwrite &17CB with the correct value immediately after resetting &0D68 makes no difference. This only happens on Elkulator, though - run in a beeb emulator, everything works exactly as expected. There's doesn't seem to be anything in the Electron Advanced User Guide about &17CB being anything but paged rom workspace/user space. I don't understand - I'm not touching anything near that address! *bangs head* Sam. |
|
| Author: | MartinB [ Tue Jul 27, 2010 11:57 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
I've just had a 'simulated' play on an Elk and there's no obvious connection between $17CB and modifications to $0D68. Can I help by trying your code/disc on an Elk with a Plus 1 and a disc interface or whatever config you need? |
|
| Author: | Samwise [ Wed Jul 28, 2010 12:00 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Check your inbox. Actually, it would be good to see if it happens on a regular Electron - that eliminates any problems with Elkulator. Also note: the joystick patch doesn't work if the ADFS ROM is loaded, so make sure you don't have that installed. (Don't know why that doesn't work either, given it's using DFS. :/) Sam. |
|
| Author: | Samwise [ Wed Jul 28, 2010 12:09 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Oooh, wait. I may be premature. I managed to get as far as the title screen with ElectrEm and that /doesn't/ have the glitch so maybe it's an emulator issue? Martin, if you could test the image I sent on a real Electron with Plus 1, Plus 3 and DFS, I'd be awesomely grateful. Sam. |
|
| Author: | Samwise [ Wed Jul 28, 2010 12:14 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
nngh ... Tried it again in ElectrEm and this time the glitch is there. Although weirdly, the first time I ran it in ElectrEm it /also/ had glitches in the two E's as well, which aren't there in Elkulator. Though, after a few restarts ElectrEm seems to consistently have only one glitch in the K, like Elkulator. So maybe it isn't an emulator thing, as I've now seen it in both? Something is definitely messing with it ... :/ It'd be interesting to know how a real Electron Plus 1/Plus 3 DFS combo handles it. I suspect it will be glitched, though I don't know why. Sam. |
|
| Author: | MartinB [ Wed Jul 28, 2010 12:41 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
I just had a quick try with the 'glitch' version and I got the loading screen with some instructions in the centre window but then 'Bad Program'. However, the Elk in question has a couple of other 'bolt-on's so in the morning I'll clean it back to just the required config and go again. Re ADFS, if the rom gets a sniff of a 'Hi There' from the OS it will jack up PAGE to it's silly &1F00 value and switching back to DFS won't lower it. If that's happening it may screw your stuff up? Did you also remember that with ADFS you can only safely reduce PAGE to &1600 and not &1100 as with DFS? Just some thoughts... Tomorrow then |
|
| Author: | MartinB [ Wed Jul 28, 2010 8:21 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Reduced the Elk to a Plus1 with Pegasus DFS and yes, with the data moving patch (your 'glitch' version), I'm afraid I do indeed see the corrupted 'K'. The non-patched version doesn't show the corruption. Looking closely at the 'K', it actually has a thin stripe missing from it's upper diaganol (about 4 pixels wide?) and then there's a loose pixel set about 4 pixels to the right of this and away from the K. My Plus 3 is not handy at the mo so trying ADFS will have to be in slower time but perhaps my comments about PAGE (above) might preclude a real test at this time? Incidentally, running either on a real Beeb just results in a Mode 7 screen full of lower-case 'e's and endless disc-reading. ('e' is the newly formatted sector pad character). This Beeb is my fully loaded development unit but it does seem to play most games quite happily. Anyway, if this bothers you I can try a bog Beeb at some point. |
|
| Author: | Samwise [ Wed Jul 28, 2010 10:18 am ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
MartinB wrote: Re ADFS, if the rom gets a sniff of a 'Hi There' from the OS it will jack up PAGE to it's silly &1F00 value and switching back to DFS won't lower it. If that's happening it may screw your stuff up? Did you also remember that with ADFS you can only safely reduce PAGE to &1600 and not &1100 as with DFS? Just some thoughts... Hmm ... I am expecting the disc to be run from DFS, and the first thing that the !BOOT file does is set PAGE to &1100, so I naively expect ADFS to leave PAGE alone until it's next selected as the current filing system. I mean otherwise, surely they're fundamentally incompatible, if ADFS sticks it's oar in every time? If that isn't the case, is there anyway to disable ADFS in software? MartinB wrote: Reduced the Elk to a Plus1 with Pegasus DFS and yes, with the data moving patch (your 'glitch' version), I'm afraid I do indeed see the corrupted 'K'. The non-patched version doesn't show the corruption. *sigh* ... as expected then. MartinB wrote: Looking closely at the 'K', it actually has a thin stripe missing from it's upper diaganol (about 4 pixels wide?) and then there's a loose pixel set about 4 pixels to the right of this and away from the K. Yes, this is because &17CB is not being set to what it should be - &E0. You can see it in a memory dump on Elkulator. Even manually trying to overwrite it with the correct value doesn't work - there's a line at the end of the single-level-relocate routine that tries to do that in the KGlitch image I sent you. MartinB wrote: My Plus 3 is not handy at the mo so trying ADFS will have to be in slower time but perhaps my comments about PAGE (above) might preclude a real test at this time? Well, Tom kindly agreed to have a quick look at the ADFS issue at some point, tho at first glance he agrees the patch itself doesn't appear to be overwriting anywhere that would be particularly sensitive to ADFS. Maybe he can shed some light. I was trying to focus on the smaller matter of this relocation routine that I thought was in my grasp, but which has stumped me at the final hurdle. MartinB wrote: Incidentally, running either on a real Beeb just results in a Mode 7 screen full of lower-case 'e's and endless disc-reading. ('e' is the newly formatted sector pad character). This Beeb is my fully loaded development unit but it does seem to play most games quite happily. Anyway, if this bothers you I can try a bog Beeb at some point. Hmm ... it works fine on B-Em and BeebEm without even the glitch!, tho granted I've had them set to Master mode and haven't tried them with a regular Model B setting recently. Or in fact with ADFS enabled. I can try those configurations out tonight. It's exactly the same joystick patch that was in the beta version of CE Pro Edition that I released a while back, tho - just updated to work with the Electron version. I think you tested that one on a real beeb at the time ... tho maybe you didn't try it with the joystick support? What was supposed to be a small patch is turning into a compatibility nightmare ... :/ Sam. |
|
| Author: | MartinB [ Wed Jul 28, 2010 12:00 pm ] |
| Post subject: | Re: COTPORS: Help with an assembler routine |
Might be food for Tom's thinking but I noticed that $0D68 contains $20 and $0D69 contains $BB. I was wondering whether this might then be a vector address, possibly for an IRQ associated with joysticks? If so, perhaps an IRQ could occur whilst all this shuffling is going on and there's an incorrect jump occurring? If not that, could it be an address for a look-up table or similar which is then transiently snotting some random addresses? Would obviously be part of the Plus 1 rom code and not the main OS. |
|
| Page 1 of 2 | All times are UTC [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|