Amélie emulator v0.01af 2007/08/04 ==================================== BE AWARE THAT THIS IS A PREVIEW VERSION OF AMEM. IT IS NOT COMPLETE AND MAY CONTAIN BUGS. IT MAY ALSO CONTAIN "FEATURES". :-) What is Amélie? --------------- "Amélie" is my plan for a home-grown 6502 system. It will be modular, comprising: * 6502A processor, at 2MHz * 2K static RAM * 4K EPROM * 6522 VIA (digital I/O) * 6551 ACIA (serial I/O) * Latch, for four status LEDs (with four future outputs) * RTC/NVRAM [maybe?], communicated with using IIC via the VIA What Amélie is actually FOR changes weekly! Originally, it was intended to be a device to open and close my curtains at a set time, however as I write this I am thinking a little trundling 'bot would be cute, and that is the current direction. One of the main principles behind Amélie's design is that it is pretty 'general purpose'. By unplugging the motor and sensors for the curtain opener, all I need to do is pop in a different EPROM and plug in different motors and sensors and Amélie can be that robot. What is this emulator? ---------------------- At time of starting, I didn't have an EPROM eraser, nor do I care to sit and burn an EPROM for each development of the system, so I have written this software to 'emulate' Amélie. If it runs on this, it ought to run on the actual hardware. That, at least, is the plan. I have an EPROM eraser now, but no Amélie hardware (yet). So I think we'll still keep this one in the digital domain for the time being. LIMITATIONS ----------- At time of writing, the emulator is only: * 6502A: no support for BCD maths, minimal NMI * RAM * EPROM * Very simplified address decoding (rather like Amélie herself then!) * Basic VIA emulation * Basic ACIA emulation What are we missing? * Application front-end [only displays/sends chars from/to ACIA] * Parts of the VIA * IIC [will this be supported? or via options board?] * Erm... The BIOS? The rest of the AppCode? :-) Symantics --------- This is, properly, a "simulator" and NOT an "emulator". According to Gavin Wraith, the word "emulate" means to "rival" or "outdo" which isn't really the objective (unless you plan to get pedantic and decide that a 2GHz processor can put in a rather zippy emulation of a 2MHz processor!). My dictionary (Penguin English Dictionary (2002)) also lists the word as meaning "to imitate closely". This, then, is an example of language evolving.[*] Perhaps the word "emulate" wasn't a terribly good choice several decades ago when the first emulators came into being. Well, I've grown up with the word and I shall continue to use the word. If this bothers you, feel free to perform global search and replace until your heart is content... [*] For a much more common example, look up the word "gay". If your dictionary is old enough or enlightened enough to include the original meaning, perhaps you'll understand why the original Flintstones had a "gay old time", a quaint phrasing that is nowadays seen as 'unfortunate'. Getting started --------------- As "AmélieEm" (AMEM.EXE) starts, it defines 2K of RAM and 4K of EPROM. The image "EPROM.IMG" is loaded into the EPROM space (&F000 to &FFFF) and then the processor 'reset' is called via the usual vector. You'll when be directed into Tracey (with the first instruction pending), and shown a welcome message. RISC OS: Running the !AmélieEm application calls a helper program to set the desired screen mode and colour set. Sadly the mode used is 'letterboxed' on an SVGA monitor. The helper program is a short, commented, BASIC program so feel free to twiddle until you get a pleasing display. A BBC font is then loaded (in order to display the DOS 'box drawing' characters). The executable, "AmelieEm", then starts. Like the DOS version, it allocates 2K RAM and 4K ROM. The EPROM image file ".EPROMimage" is then loaded into the EPROM space, and the processor reset is called as is usual. You are then directed into Tracey and shown a welcome message. Refer to the copious amounts of 6502 information around for more details. I would also recommend Ian Birnbaum's book "Assembly Language Programming for the BBC Microcomputer"; despite the listings being rather difficult to read, and some bizarre phrasings - this book is packed with information, such as in what order are things pushed to the stack upon an IRQ... Note again: You are immediately dumped into Trace mode... Trace mode ---------- Trace mode is also referred to as "Tracey" and she is actually pretty powerful, yet friendly. There are several ways to get into Tracey: * Load AMEM (!AmélieEm) * In the emulation, press ^Break or Alt-T [ABSOLUTELY *DO* *NOT* USE ^Break UNDER RISC OS (it's the RISC OS equivalent of Ctrl-Alt-Del!)] * "Experience" an error :-) In the current version of AMEM, you've probably noticed that pressing ESC takes you to Tracey. DO NOT RELY UPON THIS. When the serial emulation has been written, pressing ESC will probably send 0x1B via serial... Note that the BRK instruction does NOT enter Tracey. You must set up a specific breakpoint inside Tracey in order to break into executing code. If you intentionally want to be thrown into Tracey, use the additional opcode "eTR"; but note that this is, obviously enough, not supported on a real 6502 (results undefined, may crash/reset). IMPORTANT: 1. When you are directed to press keys, it'll say something like "press [S]" or "press [S], [R]". In the first case, you should press only the 'S' key. In the second case, you should press 'S' and then 'R'. Do NOT type '[' or ''' or ',' etc... In other words, keys to press are shown within square brackets. This style is also used within AmélieEm. 2. ALL hex values are prefixed with an ampersand, as is the RISC OS style. Here are some equivalents: &EF = $EF [Pascal / Commadore style] &EF = &HEF [Visual Basic style] &EF = 0xEF [C style] &EF = EFh [DOS / x86 assembler style] Within Tracey, you'll see the screen is split into three sections. The top section looks like: .----------------------------------------------------------------. |->&F808 78 SEI X = &00 (000) Stack dump: | | &F809 D8 CLD Y = &00 (000) SP=&00 | | &F80A A2 FF LDX #&FF A = &00 (000) | | &F80C A9 00 LDA #&00 PSR= &24 czIdbvn &00 &00 &00 &00 | | &F80E 95 00 STA &00, X PC = &F807 &00 &00 &00 &00 | | &F810 9D 00 01 STA &0100, X Implied &00 &00 &00 &00 | | &F813 9D 00 02 STA &0200, X (mem=&00 tmp=&00) &00 &00 &00 &00 | '----------------------------------------------------------------' This tells you a lot about the state of the processor. On the left the current and following six instructions are disassembled. Tracey is entered with the instruction ready to be executed. The "->" marker shows where PC is at. If the instruction is shown in RED, it is a breakpoint. Looking in memory will show &BB, the instruction used as a breakpoint marker) but the disassembly will show the correct instruction. You can use [Cursor Up] and [Cursor Down] to move up and down the instructions. Note that stepping forwards through the code will always step instruction-by-instruction; however stepping back only goes one byte at a time, so it is very likely that the display will be gibberish until the address is syncronised with the code (the instructions of the 6502 are 1, 2, or 3 bytes in length). Here is an example: &FDDA 95 10 STA &10, X &FDDC E8 INX &FDDD BD 41 FE LDA &FE41, X Pressing [Up] would then display: &FDD9 FE 95 10 INC &1095, X &FDDC E8 INX &FDDD BD 41 FE LDA &FE41, X Pressing [Up] again would display: &FDD8 41 FE EOR (&FE, X) &FDDA 95 10 STA &10, X &FDDC E8 INX Pressing [Up] one last time will show the correct instruction: &FDD7 BD 41 FE LDA &FE41, X &FDDA 95 10 STA &10, X &FDDC E8 INX How do you know what's a correct disassembly? That's simple - when pressing [Up] starts messing with the previous instruction and leaves the one(s) below alone. Why this happens - imagine the following memory dump: FE 95 10 E8 BD 41 FE /\ The highlighted BD is where the disassembly pointer rests. Code from this point will be recognised. But what's the E8? It is an INX instruction. But, problem, 10 E8 is also a valid instruction ("BPL &FDC5"). It could take quite a bit of analysis to work out which is the 'correct' instruction; it may not be too hard with Amélie's development ROM dump, however all bets are off when we're talking about highly optimised code written by a professional. Pressing [Return] will execute the current instruction, stepping to the next. You can [G]oto a different address and resume execution from that point. You can also set [B]reakpoints, and also [S]et the processor's flags and registers. In the middle, the processor registers. X, Y, and A are shown in both hex and decimal. The PSR is broken down into flags (capitals mean the flag is set, lowercase means it is not set). The next-to-last line shows the addressing mode. The addressing mode shown ALWAYS reflects the top-most instruction. If this instruction is the current instruction (i.e. where PC points) then the addressing mode is given with a capital letter. If the instruction shown is not the current one, the addressing mode is all in lower case and enclosed within brackets. You can [S]et the registers and processor flags. The 'mem' and 'tmp' registers are not present in a real 6502. These are two things used within the emulation... The 'register' tmp is where the calculated address is stored, mem is the byte contained at that location. Therefore: JMP &xxxx simply copies tmp (=&xxxx) to PC LDA #&xx simply copies mem (=&xx) to A The addressing mode decoder is responsible for setting these values as necessary. When you see them, you'll be looking at the values for the PREVIOUS instruction. This display is primarily for testing and debugging the processor core, it is not really of much use to you within the context of Amélie. Finally, the right side lists the tail end of the stack. It is worth memorising the following offsets so you can read the data easily: FC FD FE FF F8 F9 FA FB F4 F6 F6 F7 F0 F1 F2 F3 It may look 'backwards' but it is in keeping with the stack's top-down approach. Note that you only see the top 16 bytes of the stack - you'll need to use the memory viewer to see other parts of it. You can use the "[F]ill memory with pattern" command to quickly wipe the contents of the stack. Simply [F]ill from &0100 to &01FF with byte value &00. The central part of the screen holds information on the useful VIA and ACIA registers. You can use the hardware [P]oke for the [V]IA to alter the VIA's registers directly. You cannot [P]oke the [A]CIA's registers, however you can tell the emulator to behave as if a serial cable is/is not connected. [the serial cable to use should have !DTR=!DSR=!DCD so it can tell if serial comms are available] The lower part of the screen displays 64 bytes of memory, and also contains the command prompt. [Page Up] and [Page Down] scroll through the memory. You can also use the [M]emory Address command to go to a specific address, and you can [C]hange bytes in memory (and, within Tracey, this includes EPROM!). Unlike several other emulator debugging tools, Tracey will actually prompt you for the information necessary. You don't have to learn the syntax of a dozen cryptic commands. Here, then, is an example. We've just started AmélieEm and the EPROM image has been loaded. The reset vector points to &F807 so that is where we are on entry to Tracey. The disassembly is something like: &F807 EA NOP &F808 78 SEI &F809 D8 CLD &F80A A2 FF LDX #&FF &F80C A9 00 LDA #&00 &F80E 95 00 STA &00, X &F810 9D 00 01 STA &0100, X &F813 9D 00 02 STA &0200, X &F816 CA DEX &F817 D0 F5 BNE &F80E Pretty straighforward, we loop through each memory location in the first three pages, setting it to zero. The backwards counting is because the Zero flag will be set when X reaches zero, it saves us from needing to use a CMP. But we're in Tracey, do we REALLY want to sit and watch it do this? Of course not! Press [Return] until PC is &F80C ("LDA #&00"). Now comes the magic - press [S], [R], [X], [1], [Return]. Now the X register says '&01'. In long-hand now: Tracey: > You : S Tracey: Set [F]lag or [R]egister : You : R Tracey: Set register (X, Y, A, Sp, or psR) : You : X Tracey: Value : &FF You : 0 You : 1 You : [Return] An quicker alternative could have been to set the Z flag, but you would need to do this *after* the DEX instruction. I'll show you how, anyway: You : (step until DEX has been executed, the "BNE &F80E" instruction will be highlighted) Tracey: > You : S Tracey: Set [F]lag or [R]egister : You : F Tracey: Set flag (C, Z, I, D, B, V, or N) : You : Z Tracey: Set the Zero flag to [T]rue or [F]alse : You : T Alternatively, you could have set up a breakpoint... For all of the operations within Tracey, you'll be prompted. The only thing likely to cause you problems is the method of entering numbers. When Tracey prompts for a number to be input, it will look like: &FF for most (byte-wide) values, and: &FFFF for addresses. As you would expect, pressing Delete would remove the least significant digit, i.e.: &1234 becomes &0123 And, likewise, pressing a number (0-9 and A-F) would add the digit as the least significant digit, i.e. if you enter '5': &0123 becomes &1235 Where it becomes confusing is that if you were to press '5' another time, it would have the same effect as before: &1235 becomes &2355 The old most significant digit (the '1') has been discarded. If you were to press Delete now, the number would become &0235 and NOT &1235. This might seem a really quirky way to do things. It has been done like this to make it really simple to type in known addresses. No longer do you need to delete anything, just tap out the address (or the byte value) and it'll replace what was previously there, but if deleting old values first seems more logical to you - that'll work too. You will notice that Tracey provides default values. These relate to, for example, the current PC value, the current memory contents, or a suggested 'default' value. There is a special extension available for value inputs to allow you to easily enter ASCII values. When the display says, for example: Change byte at &0040 to &00 Press '$'. The display will then say: Change byte at &0040 to $?? Press 'a', and the display will change to: Change byte at &0040 to &61 &61 is 97 decimal, which is 'a'. It is complex to explain, but pretty simple to get the hang of. Try it a few times, you'll see. It sure beats learning the values of all the characters...in hex! Here's a full worked example: Tracey: > You : M Tracey: Change memory display to &F000 You : 0 You : 4 You : 0 You : 0 You : [Return] Tracey: > [and memory display updated to display from &0400] You : F Tracey: Fill memory from &FDCA You : 0 You : 4 You : 0 You : 0 You : [Return] Tracey: Fill memory from &0400 to &FDCA You : 0 You : 4 You : 3 You : F You : [Return] Tracey: Fill memory from &0400 to &043F with &FF You : $ Tracey: Fill memory from &0400 to &043F with $?? You : X Tracey: Fill memory from &0400 to &043F with &58 You : [Return] Tracey: > [and memory display updated to show lots of 'X's] Tracey's functions: [Enter] or [-] This allows you to single-step through the code. Tracey will exit and exactly ONE instruction will be executed. Tracey will then pop back with the status updated. [?] Pressing this will force a screen redraw. It should not be necessary, but in case it is - there's a way to do it... This may be necessary after forcing an emulator reset. (if you're looking for Help, press [H], you'll be reminded) [B]reakpoints This allows you to set breakpoints. You can let your code run at full speed (i.e. without Tracy), and when the breakpoint instruction is reached, Tracy will pop back. The way breakpoints work is Tracey inserts a special opcode into memory, and puts the 'real' instruction into a list. Then careful juggling ensures the 'processor' sees the breakpoint first, and the correct instruction when it is time for it. You can have up to 16 breakpoints, which you can freely view and remove. You can also set breakpoints on events: * When IRQ vector is called * When an RTI instruction is about to be executed * When an RTS instruction is about to be executed * When a NOP instruction is about to be executed * When a JMP instruction is about to be executed Note that you cannot "remove" a breakpoint on an event; this is only available in the "add" option; so do that: [B]reakpoint -> [A]dd -> on [E]vent and then simply deselect those you no longer require. If there are NO breakpoints, the [L]ist will read: BREAKPOINTS: No breakpoints are currently defined... If there are NO breakpoints, but a break-on-event, [L]ist is: BREAKPOINTS: No breakpoints are currently defined... Break on event: IRQ If there ARE breakpoints, the [L]ist will be something like: BREAKPOINTS: (4 defined) 1: &FDCA NOP 2: &FDCB SEI 3: &FDCC CLD 4: &FDCD LDX #&FF Break on event: IRQ which shows the ADDRESS of the breakpoint, the INSTRUCTION at the breakpoint address, and also if there are any break- on-events defined. If there are NO break-on-events, you can list up to NINE breakpoints. If there are break-on-events, you can list up to SEVEN breakpoints. SIXTEEN breakpoints are possible; but I would imagine that many in use could become complicated. Remember - quick load and save [`] preserves breakpoint details, so it may be useful to make use of this while in the act of debugging. [C]hange byte This asks you for the address of the byte to change, and its new value. Tracey can change bytes in RAM or ROM (!), although in the second case you'll receive an additional prompt just so you know that what you are trying to do is impossible in reality. Amélie's hardware memory decoding means that some things MAY appear at multiple locations in the memory map simply due to 'gaps'; for example the RAM is located in the FIRST 2048 bytes of memory. The SECOND 2048 bytes of memory, if it is accessed, may appear identically to the FIRST because A11 (selects +2048-+4095) is not connected to anything; A0-A10 with A12-A15 low will be interpreted as a request to +0-+2047. This behaviour is NOT supported by AmélieEm. If you access anything outside of the 'legal' memory map, an error will be raised. NOTE: AmélieEm permits access to the FINAL byte of every 1K boundary (i.e. at +1023, +2047, +4095, +6143, +8191, +12287, +16383 and all the ones in between). This has been done to provide access to a method of detecting the amount of memory installed. [D]ump memory The RAM is saved as RAMAREA.IMG and the ROM is saved as ROMAREA.IMG. [RISC OS: ".RAMareaImg" and ".ROMareaImg" respectively] [F]ill memory with pattern This allows you to 'fill' memory from one address to another with the same value. As before, you CAN write to the ROM when you are within Tracey. You can also write &0000 to &FFFF (inclusive) as Tracey herself uses a special algorythm to write memory that ignores illegal values and doesn't return errors. [G]o to address This will set PC to the address specified. Because PC is sixteen bits wide and a special register, you must use this command to alter it (and not [R]). [I]mage This will load a new EPROM image. Tracey assumes the image is 4096 bytes in length and lies between &F000 and &FFFF. The default is "EPROM.IMG" (DOS) and ".EPROMimage" (RISC OS), though obviously you can enter other files. This may, perhaps, be useful if you altered the ROM area memory and wish to reload the original image without restarting the emulator. Note that [R]eset does NOT load in the EPROM image. [L]oad code into RAM This asks you for an address (which MUST be within RAM) and will load the specified file until you run out of RAM or you run out of data in the file. Tracey will report on how much was loaded, and where from/to. The default load address is &0400 as in Amélie, the upper four pages (from 1K to 2K in the RAM) are 'unused' and might have application for softloading extensions. Beware loading anything below &0200 as page zero and the processor stack both reside here. [M]emory display address This changes the address used for the memory display. [N] Disassembly address This changes the address used for the disassembly. It does NOT change PC. [P]oke hardware This allows you to poke registers in the VIA, or disable and re-enable serial communications. [Q] Invoke an IRQ This causes the processor to behave as if an IRQ had been asserted; which may be useful to test your IRQ handler. Note that this works better if you [P]oke the hardware to set the desired flags for the handler you wish to test, and then invoke the IR[Q]. Because, well, IRQs happen for a reason... [R]eset processor This causes the processor to behave as if it had been reset. A side effect of reset which does NOT occur in reality is the stack (&0100-&01FF) is cleared. It makes it easier to read if you clear out old information. Note that the initial EPROM image is NOT reloaded. If you have altered the ROM area, you will need to reload the image and THEN perform the reset. Note that such ROM area modifications can only be performed within Tracey; the emulation won't allow code to write to read only memory. [S]et flag/register This allows you to set processor flags and registers to a desired value. Note that you cannot set PC this way; use [G]oto for that. [T]race off This turns off trace mode and returns to normal execution. Remember, you can use ^Break or Alt-T to return to Tracey at any time; or you can set up breakpoints. (NEVER EVER use ^Break under RISC OS, only use Alt-T!!!) [U]nrolled repeat Like single-stepping lots of times by holding down [Return], without actually needing to do that... [V] Test system clock speed This sets up the following code from address &0000: DCB 0 : NOP : NOP : CMP #&00 : JMP &0001 This is then executed many times and from the speed it takes on your computer, it can be compared with the time a 2MHz 6502 would take to give you a clock speed. My 25MHz laptop (the "Craptop") pretends to be a 6502 that is running at a poorly 72.80kHz! My 466MHz Celeron laptop (Win98SE) runs at an estimated 1.29MHz in DOS fullscreen; while running in DOS in a window it achieves 1.38MHz, which is 0.69x the speed of a real 6502. These values should be taken lightly though; as different instructions will execute at different speeds (irrespective of actual clock cycles required) and the timing method uses the system ticker which doesn't have a high degree of accuracy (at something like 18.7 ticks per second, a second to us could last slightly different durations due to rounding errors). [`] QuickSave / QuickLoad Save or load a complete snapshot of the current status of the emulator. DOS: The file is called "QUICK.SAV". RISC OS: The file is called ".QuickSave". The two files are NOT compatible. [.] Display memory map Perhaps a useful reminder? e[X]it This quits AmélieEm. [Alt] and [X] This quits AmélieEm. [Alt] and [F4] This quits AmélieEm, but only works on the DOS version. [Cursor Up] Move the disassembly up to the previous instruction. This actually moves back one BYTE at a time, so the disassembly may be gibberish until the disassembly is resyncronised with the code. Note that this only moves the disassembly display, it does NOT alter the next instruction to be executed. [Cursor Down] Moves the disassembly to the next instruction. Note that this only moves the disassembly display, it does NOT alter the next instruction to be executed. [Page Up] Move the memory dump window 'up'; start at a memory address 48 bytes lower - wraps around. [Page Down] Move the memory dump window 'down'; start at a memory address 48 bytes higher - wraps around. I think you'll find Tracey to be quite useful in testing your BIOS code for the Amelie project. Several of the more advanced facilities are not provided, such as: * register/memory watch * step next 'n' instructions * step to (could be faked with a breakpoint?) * breakpoint on instruction 'n' or to address 'n' - certain useful 'events' are provided This is because Tracey is designed to be simple and concise. Memory map ---------- This is the memory map as it should be used. Pressing '.' when in Tracey will show this as a text-graphic. &0000 - &07FF RAM (2K) &0000 - &00FF Page zero Much is used by the BIOS. &80 to &DF is available for the application. &E0 to &FF is reserved for an MTU, if implemented. &0100 - &01FF System stack As required. Provisionally may be four stacks for MTU requirements. Amélie does not support this, yet. &0200 - &02FF Reserved for serial buffer: 128 bytes input buffer (for Xmodem block) 80 bytes output buffer (for line buildup) 48 bytes for low flying budgies and pizza &0300 - &07FF Currently unallocated (1K software upload area) &A000 - &A300 Memory-mapped hardware &A000 - &A00F System VIA Timer1 is 50Hz ticker for OS Timer2 is unallocated. Port A bit 0 is IIC data (SDA) Port A bit 1 is IIC clock (SCL) &A100 - &A103 ACIA Runs at 2400bps, 8N1, flow control undefined [may be altered to 9600bps, depends on effect to rest of system] &A200 Unallocated, reserved for ADC or VIA #2 RICKBOT uses this as a latch device used in reverse to provide options settings; which is easier/cheaper to implement than an NVRAM. &A300 Latch for LED status Bit 0 Green Bit 1 Yellow Bit 2 Yellow Bit 3 Red Bits 4-7 are unused. &F000 - &FFFF ROM (4K) &F000 - &F7FF Application code (~1.5K) and Setup code (~.5K) This is 'nominally' EPROM 1 &F800 - &FBFF Utility code (1K) &FC00 - &FFF9 BIOS code (1K (minus 6 bytes)) This is 'nominally' EPROM 2 &FFFA - &FFFB NMI vector &FFFC - &FFFD Reset vector &FFFE - &FFFF IRQ vector (part of EPROM 2) Refer to the Amélie BIOS specification for more detailed notes. If you are interested to see how the memory decoding sees things (you have 16K of RAM and ROM, 8K of I/O, and 24K unaddressable) then refer to the Versions file under date "2004/07/09", in which you will see an outline of the address decoding system. It would not be difficult to improve the decoding, but it works as it is. Making it better would only add more logic ICs for no real gain in functionality... Detecting the emulator ---------------------- The emulator provides a number of instructions that are not found on 'real' 6502 processors. You can use this to determine if you are using real hardware or the emulator. The first thing you may wish to test is the presence of a 65C02. If you find a 65C02 instruction works, it is possibly very likely that you are running in hardware - as the emulator only supports the NMOS 6502. This is the ACTUAL part specified for use within Amélie, and the part that is likely to be used initially. The reason why we may use a 65C02 is for increased efficiency. This emulator does NOT support any of the undefined NMOS instructions. The following code uses a clever method to detect the emulator. SP and PSR are preserved while X, Y, and A are corrupted. Two bytes are temporarily stacked. No memory locations are used. TSX ; SP -> X TXA ; X (SP) -> acc TAY ; copy it to Y so we know Y is non-zero PHA ; store acc (SP) PHP ; store PSR DCB &4B ; do opcode &4B PLP ; restore PSR PLA ; restore acc (SP) TAX ; acc -> X (SP) TXS ; restore SP INY ; Y++ DEY ; Y-- BEQ amem ; emulator in use, branch... ... ; else emulator not in use The INY and DEY might appear bizarre. It is to set the Z flag if Y is zero. We copied the stack pointer into Y at the start, so we know Y is non-zero. This WILL fail if SP is zero on entry, then again BAD things will happen to your stack, so... On a genuine 6502, instruction &4B is an undocumented instruction that does something bizarre like AND into the accumulator and then EOR it. Registers will be corrupted but no lasting effects. On a genuine 65C02, all undefined instructions are NOPs. Only the emulator will (hopefully!) set Y to zero, because &4B is a secret instruction to reset all registers. You might also like to try ORing X, Y, and A all together - the result of which (under the emulator) will still be zero. IMPORTANT: All registers are reset - you CANNOT stack the registers as the stack pointer is reset to &FF. Idea: You could stack all registers and push the value of the stack pointer to a memory location so you can pick it up after the test and then unstack the registers saved. Another, less fancy, method of detecting the emulator is that, at startup, the emulator sets the final few bytes of RAM to specific values: &7FA The string "AMEM", unterminated: &41, 4D, 45, 4D &7FE Emulator version, major byte &7FF Emulator version, minor byte So if &07FD is &4D ('M'), then you're running in the emulator. So long as nothing else writes an 'M' to that location. :-) Emulator-specific instructions ------------------------------ eRE (implied) - emulator RST &0B; 1 byte Forces the emulator into behaving as if !RST has been activated. Makes-believe the reset button has been pressed. eIR (implied) - emulator IRQ &1B; 1 byte Forces the emulator into behaving as if !IRQ has been activated. Makes-believe an interrupt has occurred. It is worth poking memory or device services to set up a valid interrupt condition for the IRQ handler to find prior to doing this. You can also replicate this bahaviour manually within Tracey by [C]hanging memory locations, then using [Q] to force an IRQ. eNM (implied) - emulator NMI &2B; 1 byte Forces the emulator into behaving as if !NMI has been activated. Makes-believe a non-maskable interrupt has occurred. Amélie does not use NMIs. The processor handling is incomplete, this has only been implemented to allow for testing of NMI pickup code. The Amélie code BIOS points NMIVEC to RSTVEC. Maybe not the best solution, but acceptable as NMIs should be HARDWIRED to never happen on Amélie! eSR (implied) &3B; 1 byte This instruction is for internal emulator testing. DO NOT USE - what it actually does may alter between releases. eZR (implied) - emulator zero the registers &4B; 1 byte This sets the registers to their 'reset' state: X - 0 Y - 0 A - 0 SP - &FF PSR - 36 (%00100100 - always-on-bit and IRQs disabled) PC is not altered. eTR (implied) - emulator invoke Tracey &5B; 1 byte This instruction invokes Tracey, so you can drop into trace mode programmatically. --- (---) &BB; ? --- (---) &CB; ? Used by the breakpoint system. BAD THINGS WILL HAPPEN IF YOU USE. The instructions &BB and &CB are used by the breakpoint mechanism. &BB invokes trace mode at the current instruction, and &CB is a deliberately invalid instruction returned for incorrect breakpoints. Because the breakpoint system maintains a list of breakpoints to swap around the instructions invisibly, neither of these instructions will be described and you should use neither, attempts to do so could crash the emulator. eAB (implied) - emulator abort &FB; 1 byte Aborts the emulation cleanly. Hasta-la-vista, we're outta here! It is common on other emulators to use the instruction &FF to exit the emulation. This has, deliberately, NOT been done because the value &FF is the value of a blank location in EPROM. Thus, an EPROM with unprogrammed areas will contain lots of &FF bytes and we want this to appear as an unknown instruction and not an emulator instruction. Some people say it is better to set blank areas of an EPROM to &00. This is worse than useless. If it is an unused area, you won't be needing to access it at all. Therefore, the choice is "do we want to wait while &00 is programmed?" Blank EPROMs have all bytes at &FF so programming &FF will simply be skipped over. Much better, no? Important note about memory access ---------------------------------- THE ERROR DESCRIBED IN THIS CHAPTER NO LONGER OCCURS, HOWEVER IT HAS BEEN RETAINED HERE AS IT MAY BE USEFUL TO UNDERSTAND HOW MEMORY ACCESS WORKS. In this version of AmélieEm, upon, say STX &A000 you will notice two errors appear. They both complain about access to an unimplemented VIA. They both look alike. Here's the thing - the first error is "RB" and the second is "WB". This means we try to read a byte, then we try to write one. Why read a byte for STX? Is it how the addressing mode decoder works. It does not know what the instruction actually does, so it pre-reads the byte so the opcode code can be less complicated. This MAY change in the future - I'll have to see how much of a hit it is to "read-addressed-value-always" as opposed to within specific instructions. It is important you are aware of this behaviour if you plan to implement something to have a read-sensitive behaviour. Note also that AmélieEm will 'fault' invalid reads/writes to memory in order that you are warned if something is accessing memory that does not exist. A real system would probably write to nowhere and return &00 (or the last thing on the data bus?). Bugs ---- I'm sure there are MANY. :-) What I won't do is vouch for the accuracy of the emulation (!). I have not had time to test it fully. Email: heyrick -at- merseymail -dot- com Source code ----------- It is expected that the finished version of AmélieEm will be supplied with source code. It is not currently supplied as this is not an official release, it is more a 'preview' of something in progress. If you would like to help with the development, contact me at: heyrick -at- merseymail -dot- com The source currently compiles under Borland TurboC++ version 1.0; with ALL warnings enabled it compiles with no errors or warnings. Various ARM assembler veneers and code exist for a RISC OS version, and it compiles, but with quite a number of warnings due to system and compiler differences. These warnings are not saying anything particularly useful, so I'll turn them off when I find the compiler manual to see which flags do that... Et aussi en français? --------------------- I would be interested if anybody could donate the time to cobble together brief instructions in French. I don't know how many French readers are likely to be interested, but since this is my country of residence, I figured it'd be nice to at least have *something* in French! I'd do it myself but I don't feel up to the technical aspects (unless you don't mind it written very simply, entirely in the present tense, and missing most of those tricky little words!). Likewise, if you prefer to provide translations in Italian, German, Swedish, etc etc then I'd be happy to include them in the package. If you look through the executable and translate the messages to your chosen language, I'll look to the possibility of multilingual versions... ...it shouldn't be too difficult - but I rather remember saying those exact same words when finger went to keyboard for the first time on the Amélie project! Contacts: --------- Email: heyrick -at- merseymail -dot- com I only have access to email once a week (!) at my local library. I tend to download messages and write replies for the following week. Please accept my apologies if you were hoping for a faster response, it is better than nothing - right? Website: http://www.heyrick.co.uk/amelie/ Thanks to --------- Bray, Dickens and Holmes: "The Advanced User Guide for the BBC Micro" ISBN: 0-946827-00-1 Date: 1983 Ian Birnbaum: "Assembly Language Programming for the BBC Microcomputer" ISBN: 0-333-34585-1 Date: 1983 A.P.Stephenson: "Discovering BBC Micro Machine Code" ISBN: 0-246-12160-2 Date: 1984 The Motorola NMOS 6502, CMOS 65C02, 6522 datasheets, sent to me on request by Farnell Electronic's data sheet service. The MOS 6522 datasheet, downloaded from "The BBC Lives!" website. The 6551 ACIA datasheet, downloaded from a Google link so don't actually know the URL. You ought to find a copy at www.6502.org "Extra instructions of the 65xx series CPU", by Adam Vardy and hosted on various 65xx related sites - again try www.6502.org www.6502.org for showing the 6502 is still going, even in these days of Pentiums and PICs. Acorn Computers for using the 6502 in their first computers, and again for using the lovely home-grown ARM in their later computers. Amelie would have been an ARM-based project if it wasn't for the fact that solding several hundred pins to a piece of veroboard fills me with abject horror! Borland, for releasing their older compilers. Mom, for paying the electricity bill and reminding me constantly. Sandrine and Françoise at the library, for allowing me to upload stuff from CD-ROM and, also, to download stuff and burn it onto CD-ROM. I don't think she has a clue what I'm doing, but she trusts me. That means a lot. As to what I'm doing - mostly PDF datasheets where each page is a bit image, and those "small" PC programs that somhow seem to do much less than the 5Mb filesize might imply... Maybe I'm too used to RISC OS where 5Mb (compressed) could represent an entire collection of software! Ewen for the 44.1khz streaming itself into my head. Glenn, for hosting HeyRick, and more... Gavan, for originally hosting HeyRick and telling the VIDC to do interesting things; even if he did promise me a copy of it and then forgot. :-) John and Irene for the kittens and the cheddar and the apple pies. Special thanks to Bob Power (howzat for a name?) for looking interested while I was explaining the ins and outs of the emulation. There's, like, NOBODY to talk to around here that understands this stuff! If you're female and a geek and you live somewhere between Rennes and Angers... get in touch! Thank you to Jewel Kilcher for more quirky music (I quite like "Hands" and "Barcelona" on the "Spirit" album), even if she has gone and "found religion" and mucked up her songs with it! This sounds like a lame acceptance speech. Shall I burst into tears and mutter incomprehensible nonsense like "you love me, you really love me!", or is that sailing dangerously close to a cliche? So... Thank you, finally, to YOU for trying my software and for bothering to read this cra...ahem...document. :-) That's all guys, go fire up AmélieEm and play with it!