Page 4 of 7
Re: Amiga disassembly
Posted: Sun Jul 03, 2011 12:29 pm
by tin
Haha! this is pretty amazing. It's a real shame I really don't have time to get involved in the Amiga disassembly. I am REALLY interested in the technique you have for recompiling! ;0
Regarding the bizarre order of the bytes - aside from the NOT, it makes some sense to me. for example with the reverse order, if the routine reading the state of the pin manually reads bit at a time, they will enter the computer in the reverse order than they are required. e.g. 11110000 would be sent serially as 00001111, but the Amiga is big-endian so it would have to work on the byte reversed. For the bit being entered as a byte, that makes some sense as well, as otherwise it would have to do bitwise operations on the byte being currently read in for each read of the pin. This way it only has to do bitwise operations after every whole byte recieved.
Well - conjecture by me as usual
Re: Amiga disassembly
Posted: Sun Jul 03, 2011 1:50 pm
by AriX
tin wrote:Haha! this is pretty amazing. It's a real shame I really don't have time to get involved in the Amiga disassembly. I am REALLY interested in the technique you have for recompiling! ;0
It took me a while to figure out how to get that working - I struggled for ages trying to get an Amiga-based assembler (AsmPro, AsmOne, etc.) to do the job, but I just couldn't do it. IDA's disassembly also couldn't be reassembled by any tool I tried. So in the end, I used the IRA disassembly that was posted in this thread, and I used the vasm assembler (specifically vasmm68k_mot). The assembler couldn't understand IRA's enums (for INTENA, CIAB_PRA, etc.), so I had to hand replace them with their original values. If anyone is interested, here is my modified disassembly (this one has the patches that I showed in my last post):
http://cl.ly/1B0s100t0Z1s1n3i2b03
And here is my custom-assembled ESQ:
http://cl.ly/1L0Y230D3q283H2V2n0r
In order to show the diagnostics, send 55 AA GG over serial after you send a byte over CTRL. Unfortunately, I have not been able to get this modified ESQ running at all on my real Amiga, because I have no way of sending it files. The machine only has one floppy drive, no hard disk, and I don't have anything that is capable of reading or writing Amiga floppy disks. I tried to use the file download command to send it a program that can receive files over serial, but the file was apparently too big to be sent (which makes me wonder how they achieved over-the-air updates of ESQ)
tin wrote:Regarding the bizarre order of the bytes - aside from the NOT, it makes some sense to me. for example with the reverse order, if the routine reading the state of the pin manually reads bit at a time, they will enter the computer in the reverse order than they are required. e.g. 11110000 would be sent serially as 00001111, but the Amiga is big-endian so it would have to work on the byte reversed. For the bit being entered as a byte, that makes some sense as well, as otherwise it would have to do bitwise operations on the byte being currently read in for each read of the pin. This way it only has to do bitwise operations after every whole byte recieved.
Well - conjecture by me as usual
I think you're absolutely right about the endianness. For the reading in of the bits as bytes, you may be right as well, but there are plenty of ways to accomplish the task other than how they did it. (I didn't think that this was the most efficient one, but I could be wrong.)
Re: Amiga disassembly
Posted: Sun Jul 03, 2011 3:27 pm
by LocalH
Ari, I must admire your work in assembly hacking of a program coded in C, that can't be easy. Too bad noone with high ASM knowledge in the Sonic scene has much interest in Prevue, as there are quite a few people with high skills in general reverse engineering as well as specific 68000 knowledge (only thing that wouldn't apply would be knowledge of Megadrive hardware, lol).
May I suggest a technique that worked quite well in the Sonic scene's early ASM hacking days? Someone modified an emulator to log all code execution to a file then proceeded to exercise as much of the code as possie. This helped differentiate between code and data. This would be especially helpful for you, Ari, as you're quite advanced in the art of UVSG data feeding (heh) and you already have a hacked emulator for feeding data in. You could also use it to find the specific routine that handles a command by sending only that command to the Amiga on an otherwise clean Prevue boot then looking for code that wasn't executed on just a dry run of the software. Something to think about for when you get back
Re: Amiga disassembly
Posted: Sun Jul 03, 2011 3:40 pm
by AriX
LocalH wrote:Ari, I must admire your work in assembly hacking of a program coded in C, that can't be easy. Too bad noone with high ASM knowledge in the Sonic scene has much interest in Prevue, as there are quite a few people with high skills in general reverse engineering as well as specific 68000 knowledge (only thing that wouldn't apply would be knowledge of Megadrive hardware, lol).
May I suggest a technique that worked quite well in the Sonic scene's early ASM hacking days? Someone modified an emulator to log all code execution to a file then proceeded to exercise as much of the code as possie. This helped differentiate between code and data. This would be especially helpful for you, Ari, as you're quite advanced in the art of UVSG data feeding (heh) and you already have a hacked emulator for feeding data in. You could also use it to find the specific routine that handles a command by sending only that command to the Amiga on an otherwise clean Prevue boot then looking for code that wasn't executed on just a dry run of the software. Something to think about for when you get back
Thanks! It's definitely hard, but it's really fun. I appreciate your suggestion, but I don't think that would be helpful in this specific instance, since luckily, IDA can (most of the time) figure out what is code and what is data. Also, finding what code is run when data is received is pretty straight-forward once you find where the received data is stored (the buffer location). Then, you can just look in the code to see where that memory location is accessed, and trace the code execution from there. I will keep that in mind, though, in case something happens that I can't quite figure out from the code.
Re: Amiga disassembly
Posted: Sun Mar 04, 2012 2:33 pm
by AriX
I got it to draw the overlay image!
Basically I reversed more of the CTRL routines, and found out that the Control-E command (the CTRL command with mode byte $05) takes only two bytes of input. So I sent the command 05 01 01 0D 08 (05 for mode byte, 01 01 for some data, 0D for end of command, and 08 for checksum), and then I hit the "L" and "R" keys on the keyboard, and it happily draws the TV Guide background. It seems that the first byte represents what overlay will be drawn on the right side and the second for the left side... 00 is nothing, and everything else I tried is the TV Guide Background - although perhaps some number represents the TV Guide Around Town background.
So, definitely good progress! Now to try and get it to work on my real Amiga...
Re: Amiga disassembly
Posted: Sun Mar 04, 2012 6:30 pm
by AriX
Even better news! I got it to work on my real Amiga... and in the process figured out how to send CTRL data reliably over serial.
Here is the code I finally came up with. This is C code, designed to be compiled with GCC under Mingw32 (yes, I actually wrote this for Windows - let me know if you need help getting it up and running) will send the CTRL command over the COM1 serial port.
Code: Select all
#include <windows.h>
#include <stdint.h>
HANDLE hSerial;
void uSleep(int waitTime);
void CTRL(int val) {
if (val) EscapeCommFunction(hSerial, SETRTS);
else EscapeCommFunction(hSerial, CLRRTS);
uSleep(3177);
}
void CTRLGroup(int r, int s) {
int i;
for (i=0;i<5;i++) {
CTRL(r);
}
for (i=0;i<5;i++) {
CTRL(s);
}
}
void sendByte(int8_t byt) {
CTRL(1); CTRL(1); CTRL(1); CTRL(1); CTRL(1); CTRL(1); // start
CTRLGroup(1, !(byt&1)>0); // start
CTRLGroup(!(byt&1)>0, !(byt&2)>0); // data
CTRLGroup(!(byt&2)>0, !(byt&4)>0); // data
CTRLGroup(!(byt&4)>0, !(byt&8)>0); // data
CTRLGroup(!(byt&8)>0, !(byt&16)>0); // data
CTRLGroup(!(byt&16)>0, !(byt&32)>0); // data
CTRLGroup(!(byt&32)>0, !(byt&64)>0); // data
CTRLGroup(!(byt&64)>0, !(byt&128)>0); // data
CTRLGroup(!(byt&128)>0, 0); // data
CTRLGroup(0, 0); // stop
}
int main(int argc, char *argv[]) {
// Set up serial
LPCSTR portname = "COM1";
DWORD accessdirection = GENERIC_WRITE;
hSerial = CreateFile(portname, accessdirection, 0, 0, OPEN_EXISTING, 0, 0);
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(hSerial, &dcbSerialParams);
dcbSerialParams.BaudRate = 2400;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.fRtsControl = RTS_CONTROL_ENABLE;
SetCommState(hSerial, &dcbSerialParams);
COMMTIMEOUTS timeouts = {0};
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(hSerial, &timeouts);
sendByte(0x05);
sendByte(0x01);
sendByte(0x01);
sendByte(0x0D);
sendByte(0x08);
CloseHandle(hSerial);
return 1;
}
void uSleep(int waitTime) {
__int64 time1 = 0, time2 = 0, sysFreq = 0;
QueryPerformanceCounter((LARGE_INTEGER *) &time1);
QueryPerformanceFrequency((LARGE_INTEGER *)&sysFreq);
do {
QueryPerformanceCounter((LARGE_INTEGER *) &time2);
} while((time2-time1) < waitTime);
}
The important parts of this code are the sendByte function - which I figured out a while ago by reversing the CTRL I/O functions in ESQ - and the delay interval. The interval that I found to work was 3177 microseconds, which is probably pretty flexible, by +/- 10 microseconds maybe. I found this by writing code to send the 0501010D08 command repeatedly, incrementing the interval each time, and repeatedly pressing the L and R keys on the keyboard. Once it started drawing the overlay, I stopped the code and looked at the log, where it had been outputting each tested interval. This seems to be considerably less than what I would have expected for 110 baud - it's something like 25 BITS per second! The CTRL I/O routines therefore run about 325 times per second.
(The overlay on the left is drawn by my old Prevue simulator, while the overlay on the right is drawn by ESQ.)
Re: Amiga disassembly
Posted: Sun Mar 04, 2012 9:43 pm
by woddfellow2
I created my own tagging-area background images:
...but they, or at least the latter one, cause it to throw ER010:
Here are the copies of the images that cause Prevue to throw ER010:
http://ompldr.org/vY3hxZw
Also, how would I send serial commands with the GNU/Linux version of E-UAE?
[2012-03-04T23:29-0600]
Update: Fixed link to ER010 screen shot
[2012-03-05T00:23-0600]
Update: Fixed it again
[2012-03-05T05:14-0600]
Update: Minor grammar change
Re: Amiga disassembly
Posted: Sun Mar 04, 2012 11:12 pm
by AriX
woddfellow2 wrote:Also, how would I send serial commands with the GNU/Linux version of E-UAE?
I hate to say it... but you literally have to code it yourself. There is a file called serial.c in the source of UAE that has an empty implementation of a serial interface, and you can write your own if you know C. Maybe there is a better solution - but I don't know of one. Certainly, on the Mac, I had to do it myself, although I have heard here that there is a way to do it on Windows with one of the versions of UAE.
If you want to use CTRL... it's even crazier. For some reason, ESQ in emulation does not poll the CTS pin like on a real Amiga, and I basically cobbled together my own version that runs the CTRL routine when I send it a serial command to. This makes it really SLOW. I would like to figure out how to get the emulated version to behave better.
When I open up the Prevue Server to everyone, I will release versions of the emulators with serial support for my "sender" software. Until then, my implementation is basically useless. Really most of what I have to do before it's done is make it work with emulators - especially on Windows.
No idea why those images don't work though - they look cool, but I have never really tried modding those images myself.
Re: Amiga disassembly
Posted: Mon Mar 05, 2012 5:21 am
by 20CenturyFan
I attempted to do this with my setup (VSPE + Com Port Data Emulator) and could not get my overlays to show up. However, I notice that pressing "L" sends a 0x01 back to my serial, an "R" sends an 0x02 back to my serial, and "G" sends an 0x03 back to my serial (and G works my graphics). When I run this, "blinky" appears on the right side of ESQ (so information is being received by the emulated Amiga), but I am thinking that the program is not understanding what I am sending it. This is what I type in my data source as "Text Strings"
05 01 01 0D 08 (typed as "#05#01#01#0D#08" so CPDE recognizes it as hex). Is there more to sending CRTL commands than just feeding these hex values into WinUAE? ESQ seems to want to interpret
everything as data rather than crtl, even though it is a crtl command.
I tried compiling your program earlier, AriX... but I failed. lol. I am horrible at trying to understand programming language.
Re: Amiga disassembly
Posted: Mon Mar 05, 2012 10:36 am
by AriX
20CenturyFan wrote:I attempted to do this with my setup (VSPE + Com Port Data Emulator) and could not get my overlays to show up. However, I notice that pressing "L" sends a 0x01 back to my serial, an "R" sends an 0x02 back to my serial, and "G" sends an 0x03 back to my serial (and G works my graphics). When I run this, "blinky" appears on the right side of ESQ (so information is being received by the emulated Amiga), but I am thinking that the program is not understanding what I am sending it. This is what I type in my data source as "Text Strings"
05 01 01 0D 08 (typed as "#05#01#01#0D#08" so CPDE recognizes it as hex). Is there more to sending CRTL commands than just feeding these hex values into WinUAE? ESQ seems to want to interpret
everything as data rather than crtl, even though it is a crtl command.
I tried compiling your program earlier, AriX... but I failed. lol. I am horrible at trying to understand programming language.
Yeah, unfortunately, CTRL commands aren't sent over serial the way regular commands are. They are sent by manipulating the CTS pin - or in your case, a software flag, on and off very quickly. Really the only way to send the command is to use my program or write your own.
If it helps - in order to compile mine, you'll need to install Mingw32, copy this source code I posted above with a filename like "CTRL.c" to the Mingw32 home directory, open a Mingw32 shell prompt, and type "gcc CTRL.c -o CTRL.exe". Then, just type "CTRL" to run the program. You may also want to change COM1 in my program to a different serial port. Let me know if you have further problems or compilation errors.
You can tell when you're at least receiving CTRL data by going to Diagnostic Mode and looking at the CTRL H: counter. The DATA H: counter is different.