--- /dev/null
+\r
+ _____ __ \r
+ / ___/__ __ ____ / /___ ___ ___ ___________________ \r
+ / /__ / // // __// // _ \ / _ \/ -_) ___________________ \r
+ \___/ \_, / \__//_/ \___//_//_/\__/ ___________________ \r
+ /___/ \r
+ ___________________ ____ ___ ___ ___ ___ \r
+ ___________________ / __// _ \ / _ \ / _ \ / _ \ \r
+ ___________________ / _ \/ _ // // // // // // / \r
+ \___/\___/ \___/ \___/ \___/ \r
+ \r
+___________________________________________________________________________\r
+\r
+\r
+This code is licensed under the GNU General Public License version 2.0 and the MAME License.\r
+You can choose the license that has the most advantages for you.\r
+\r
+___________________________________________________________________________\r
+\r
+\r
+What is it?\r
+-----------\r
+\r
+Cyclone 68000 is an emulator for the 68000 microprocessor, written in ARM 32-bit assembly.\r
+It is aimed at chips such as ARM7 and ARM9 cores, StrongARM and XScale, to interpret 68000\r
+code as fast as possible.\r
+\r
+Flags are mapped onto ARM flags whenever possible, which speeds up the processing of opcode.\r
+\r
+Developers:\r
+-----------\r
+\r
+Dave / FinalDave: emudave(atsymbol)gmail.com\r
+\r
+\r
+What's New\r
+----------\r
+v0.069\r
+ + Added SBCD and the flags for ABCD/SBCD. Score and time now works in games such as\r
+ Rolling Thunder 2, Ghouls 'N Ghosts\r
+ + Fixed a problem with addx and subx with 8-bit and 16-bit values.\r
+ Ghouls 'N' Ghosts now works!\r
+\r
+v0.068\r
+ + Added ABCD opcode (Streets of Rage works now!)\r
+\r
+v0.067\r
+ + Added dbCC (After Burner)\r
+ + Added asr EA (Sonic 1 Boss/Labyrinth Zone)\r
+ + Added andi/ori/eori ccr (Altered Beast)\r
+ + Added trap (After Burner)\r
+ + Added special case for move.b (a7)+ and -(a7), stepping by 2\r
+ After Burner is playable! Eternal Champions shows more\r
+ + Fixed lsr.b/w zero flag (Ghostbusters)\r
+ Rolling Thunder 2 now works!\r
+ + Fixed N flag for .b and .w arithmetic. Golden Axe works!\r
+\r
+v0.066\r
+ + Fixed a stupid typo for exg (orr r10,r10, not orr r10,r8), which caused alignment\r
+ crashes on Strider\r
+\r
+v0.065\r
+ + Fixed a problem with immediate values - they weren't being shifted up correctly for some\r
+ opcodes. Spiderman works, After Burner shows a bit of graphics.\r
+ + Fixed a problem with EA:"110nnn" extension word. 32-bit offsets were being decoded as 8-bit\r
+ offsets by mistake. Castlevania Bloodlines seems fine now.\r
+ + Added exg opcode\r
+ + Fixed asr opcode (Sonic jumping left is fixed)\r
+ + Fixed a problem with the carry bit in rol.b (Marble Madness)\r
+\r
+v0.064\r
+ + Added rtr\r
+ + Fixed addq/subq.l (all An opcodes are 32-bit) (Road Rash)\r
+ + Fixed various little timings\r
+\r
+v0.063\r
+ + Added link/unlk opcodes\r
+ + Fixed various little timings\r
+ + Fixed a problem with dbCC opcode being emitted at set opcodes\r
+ + Improved long register access, the EA fetch now does ldr r0,[r7,r0,lsl #2] whenever\r
+ possible, saving 1 or 2 cycles on many opcodes, which should give a nice speed up.\r
+ + May have fixed N flag on ext opcode?\r
+ + Added dasm for link opcode.\r
+\r
+v0.062\r
+ * I was a bit too keen with the Arithmetic opcodes! Some of them should have been abcd,\r
+ exg and addx. Removed the incorrect opcodes, pending re-adding them as abcd, exg and addx.\r
+ + Changed unknown opcodes to act as nops.\r
+ Not very technical, but fun - a few more games show more graphics ;)\r
+\r
+v0.060\r
+ + Fixed divu (EA intro)\r
+ + Added sf (set false) opcode - SOR2\r
+ * Todo: pea/link/unlk opcodes\r
+\r
+v0.059: Added remainder to divide opcodes.\r
+\r
+\r
+ARM Register Usage\r
+------------------\r
+\r
+See source code for up to date of register usage, however a summary is here:\r
+\r
+ r0-3: Temporary registers\r
+ r4 : Current PC + Memory Base (i.e. pointer to next opcode)\r
+ r5 : Cycles remaining\r
+ r6 : Pointer to Opcode Jump table\r
+ r7 : Pointer to Cpu Context\r
+ r8 : Current Opcode\r
+ r9 : Flags (NZCV) in highest four bits\r
+ (r10 : Temporary source value or Memory Base)\r
+ (r11 : Temporary register)\r
+\r
+\r
+How to Compile\r
+--------------\r
+\r
+Like Starscream and A68K, Cyclone uses a 'Core Creator' program which calculates and outputs\r
+all possible 68000 Opcodes and a jump table into files called Cyclone.s and .asm\r
+It then assembles these files into Cyclone.o and .obj\r
+\r
+Cyclone.o is the GCC assembled version and Cyclone.obj is the Microsoft assembled version.\r
+\r
+First unzip "Cyclone.zip" into a "Cyclone" directory.\r
+If you are compiling for Windows CE, find ARMASM.EXE (the Microsoft ARM assembler) and\r
+put it in the directory as well or put it on your path.\r
+\r
+Open up Cyclone.dsw in Visual Studio 6.0, compile and run the project.\r
+Cyclone.obj and Cyclone.o will be created.\r
+\r
+Compiling without Visual C++\r
+----------------------------\r
+If you aren't using Visual C++, it still shouldn't be too hard to compile, just get a C compiler,\r
+compile all the CPPs and C file, link them into an EXE, and run the exe.\r
+\r
+ e.g. gcc Main.cpp OpAny.cpp OpArith.cpp OpBranch.cpp OpLogic.cpp OpMove.cpp Disa.c\r
+ Main.exe\r
+\r
+\r
+Adding to your project\r
+----------------------\r
+\r
+To add Cyclone to you project, add Cyclone.o or obj, and include Cyclone.h\r
+There is one structure: 'struct Cyclone', and one function: CycloneRun\r
+\r
+Don't worry if this seem very minimal - its all you need to run as many 68000s as you want.\r
+It works with both C and C++.\r
+\r
+Byteswapped Memory\r
+------------------\r
+\r
+If you have used Starscream, A68K or Turbo68K or similar emulators you'll be familiar with this!\r
+\r
+Any memory which the 68000 can access directly must be have every two bytes swapped around.\r
+This is to speed up 16-bit memory accesses, because the 68000 has Big-Endian memory\r
+and ARM has Little-Endian memory.\r
+\r
+Now you may think you only technically have to byteswap ROM, not RAM, because\r
+16-bit RAM reads go through a memory handler and you could just return (mem[a]<<8) | mem[a+1].\r
+\r
+This would work, but remember some systems can execute code from RAM as well as ROM, and\r
+that would fail.\r
+So it's best to use byteswapped ROM and RAM if the 68000 can access it directly.\r
+It's also faster for the memory handlers, because you can do this:\r
+ \r
+ return *(unsigned short *)(mem+a)\r
+\r
+\r
+Declaring a Memory handlers\r
+---------------------------\r
+\r
+Before you can reset or execute 68000 opcodes you must first set up a set of memory handlers.\r
+There are 7 functions you have to set up per CPU, like this:\r
+\r
+ static unsigned int MyCheckPc(unsigned int pc)\r
+ static unsigned char MyRead8 (unsigned int a)\r
+ static unsigned short MyRead16 (unsigned int a)\r
+ static unsigned int MyRead32 (unsigned int a)\r
+ static void MyWrite8 (unsigned int a,unsigned char d)\r
+ static void MyWrite16(unsigned int a,unsigned short d)\r
+ static void MyWrite32(unsigned int a,unsigned int d)\r
+\r
+You can think of these functions representing the 68000's memory bus.\r
+The Read and Write functions are called whenever the 68000 reads or writes memory.\r
+For example you might set MyRead8 like this:\r
+\r
+ unsigned char MyRead8(unsigned int a)\r
+ {\r
+ a&=0xffffff; // Clip address to 24-bits\r
+\r
+ if (a<RomLength) return RomData[a^1]; // ^1 because the memory is byteswapped\r
+ if (a>=0xe00000) return RamData[(a^1)&0xffff];\r
+ return 0xff; // Out of range memory access\r
+ }\r
+\r
+The other 5 read/write functions are similar. I'll describe the CheckPc function later on.\r
+\r
+Declaring a CPU Context\r
+-----------------------\r
+\r
+To declare a CPU simple declare a struct Cyclone in your code. For example to declare\r
+two 68000s:\r
+\r
+ struct Cyclone MyCpu;\r
+ struct Cyclone MyCpu2;\r
+\r
+It's probably a good idea to initialise the memory to zero:\r
+\r
+ memset(&MyCpu, 0,sizeof(MyCpu));\r
+ memset(&MyCpu2,0,sizeof(MyCpu2));\r
+\r
+Next point to your memory handlers:\r
+\r
+ MyCpu.checkpc=MyCheckPc;\r
+ MyCpu.read8 =MyRead8;\r
+ MyCpu.read16 =MyRead16;\r
+ MyCpu.read32 =MyRead32;\r
+ MyCpu.write8 =MyWrite8;\r
+ MyCpu.write16=MyWrite16;\r
+ MyCpu.write32=MyWrite32;\r
+\r
+You also need to point the fetch handlers - for most systems out there you can just\r
+point them at the read handlers:\r
+ MyCpu.fetch8 =MyRead8;\r
+ MyCpu.fetch16 =MyRead16;\r
+ MyCpu.fetch32 =MyRead32;\r
+\r
+( Why a different set of function pointers for fetch?\r
+ Well there are some systems, the main one being CPS2, which return different data\r
+ depending on whether the 'fetch' line on the 68000 bus is high or low.\r
+ If this is the case, you can set up different functions for fetch reads.\r
+ Generally though you don't need to. )\r
+\r
+Now you are nearly ready to reset the 68000, except you need one more function: checkpc().\r
+\r
+The checkpc() function\r
+----------------------\r
+\r
+When Cyclone reads opcodes, it doesn't use a memory handler every time, this would be\r
+far too slow, instead it uses a direct pointer to ARM memory.\r
+For example if your Rom image was at 0x3000000 and the program counter was $206,\r
+Cyclone's program counter would be 0x3000206.\r
+\r
+The difference between an ARM address and a 68000 address is also stored in a variable called\r
+'membase'. In the above example it's 0x3000000. To retrieve the real PC, Cyclone just\r
+subtracts 'membase'.\r
+\r
+When a long jump happens, Cyclone calls checkpc(). If the PC is in a different bank,\r
+for example Ram instead of Rom, change 'membase', recalculate the new PC and return it:\r
+\r
+static int MyCheckPc(unsigned int pc)\r
+{\r
+ pc-=MyCpu.membase; // Get the real program counter\r
+\r
+ if (pc<RomLength) MyCpu.membase=(int)RomMem; // Jump to Rom\r
+ if (pc>=0xff0000) MyCpu.membase=(int)RamMem-0xff0000; // Jump to Ram\r
+\r
+ return MyCpu.membase+pc; // New program counter\r
+}\r
+\r
+Notice that the membase is always ARM address minus 68000 address.\r
+\r
+The above example doesn't consider mirrored ram, but for an example of what to do see\r
+PicoDrive (in Memory.cpp).\r
+\r
+\r
+Almost there - Reset the 68000!\r
+-------------------------------\r
+\r
+Next we need to Reset the 68000 to get the initial Program Counter and Stack Pointer. This\r
+is obtained from addresses 000000 and 000004.\r
+\r
+Here is code which resets the 68000 (using your memory handlers):\r
+\r
+ MyCpu.srh=0x27; // Set supervisor mode\r
+ MyCpu.a[7]=MyCpu.read32(0); // Get Stack Pointer\r
+ MyCpu.membase=0;\r
+ MyCpu.pc=MyCpu.checkpc(MyCpu.read32(4)); // Get Program Counter\r
+\r
+And that's ready to go.\r
+\r
+\r
+Executing the 68000\r
+-------------------\r
+\r
+To execute the 68000, set the 'cycles' variable to the number of cycles you wish to execute,\r
+and then call CycloneRun with a pointer to the Cyclone structure.\r
+\r
+e.g.:\r
+ // Execute 1000 cycles on the 68000:\r
+ MyCpu.cycles=1000; CycloneRun(&MyCpu);\r
+\r
+For each opcode, the number of cycles it took is subtracted and the function returns when\r
+it reaches 0.\r
+\r
+e.g.\r
+ // Execute one instruction on the 68000:\r
+ MyCpu.cycles=0; CycloneRun(&MyCpu);\r
+ printf(" The opcode took %d cycles\n", -MyCpu.cycles);\r
+\r
+You should try to execute as many cycles as you can for maximum speed.\r
+The number actually executed may be slightly more than requested, i.e. cycles may come\r
+out with a small negative value:\r
+\r
+e.g.\r
+ int todo=12000000/60; // 12Mhz, for one 60hz frame\r
+ MyCpu.cycles=todo; CycloneRun(&MyCpu);\r
+ printf(" Actually executed %d cycles\n", todo-MyCpu.cycles);\r
+\r
+To calculate the number of cycles executed, use this formula:\r
+ Number of cycles requested - Cycle counter at the end\r
+\r
+\r
+Interrupts\r
+----------\r
+\r
+Causing an interrupt is very simple, simply set the irq variable in the Cyclone structure\r
+to the IRQ number.\r
+To lower the IRQ line, set it to zero.\r
+\r
+e.g:\r
+ MyCpu.irq=6; // Interrupt level 6\r
+ MyCpu.cycles=20000; CycloneRun(&MyCpu);\r
+\r
+Note that the interrupt is not actually processed until the next call to CycloneRun,\r
+and the interrupt may not be taken until the 68000 interrupt mask is changed to allow it.\r
+\r
+( The IRQ isn't checked on exiting from a memory handler: I don't think this will cause\r
+ me any trouble because I've never needed to trigger an interrupt from a memory handler,\r
+ but if someone needs to, let me know...)\r
+\r
+Accessing Cycle Counter\r
+-----------------------\r
+\r
+The cycle counter in the Cyclone structure is not, by default, updated before\r
+calling a memory handler, only at the end of an execution.\r
+\r
+If you do need to read the cycle counter inside memory handlers, there is a\r
+bitfield called 'Debug' in Cyclone/Main.cpp.\r
+You can try setting Debug to 1 and then making the Cyclone library.\r
+This will add extra instructions so Cyclone writes register r5 back into the structure.\r
+\r
+If you need to *modify* cycles in a memory handler, set Debug to 3, this will read back\r
+the cycle counter as well.\r
+\r
+Accessing Program Counter and registers\r
+---------------------------------------\r
+\r
+You can read Cyclone's registers directly from the structure at any time (as far as I know).\r
+\r
+The Program Counter, should you need to read or write it, is stored with membase\r
+added on. So use this formula to calculate the real 68000 program counter:\r
+\r
+ pc = MyCpu.pc - MyCpu.membase;\r
+\r
+The program counter is stored in r4 during execution, and isn't written back to the\r
+structure until the end of execution, which means you can't read normally real it from\r
+a memory handler.\r
+However you can try setting Debug to 4 and then making the Cyclone library, this will\r
+write back r4 to the structure.\r
+\r
+You can't access the flags from a handler either. I can't imagine why anyone would particularly\r
+need to do this, but if you do e-mail me and I'll add another bit to 'Debug' ;)\r
+\r
+\r
+Emulating more than one CPU\r
+---------------------------\r
+\r
+Since everything is based on the structures, emulating more than one cpu at the same time\r
+is just a matter of declaring more than one structures and timeslicing. You can emulate\r
+as many 68000s as you want.\r
+Just set up the memory handlers for each cpu and run each cpu for a certain number of cycles.\r
+\r
+e.g.\r
+ // Execute 1000 cycles on 68000 #1:\r
+ MyCpu.cycles=1000; CycloneRun(&MyCpu);\r
+\r
+ // Execute 1000 cycles on 68000 #2:\r
+ MyCpu2.cycles=1000; CycloneRun(&MyCpu2);\r
+\r
+\r
+Thanks to...\r
+------------\r
+\r
+* All the previous code-generating assembler cpu core guys!\r
+ Who are iirc... Neill Corlett, Neil Bradley, Mike Coates, Darren Olafson\r
+ and Bart Trzynadlowski\r
+\r
+* Charles Macdonald, for researching just about every console ever\r
+* MameDev+FBA, for keeping on going and going and going\r