--- uae/docs/README.PROGRAMMERS 2018/04/24 16:38:39 1.1 +++ uae/docs/README.PROGRAMMERS 2018/04/24 16:38:52 1.1.1.2 @@ -8,68 +8,88 @@ A few guidelines for anyone who wants to Even if no one else is working on this feature, there might be alternative and better/easier/more elegant ways to do it. - Some coding guidelines. - * Avoid GNU C extensions by all means. They make your code non-portable. + * Avoid GNU C extensions by all means. They make your code non-portable + (unless you can work around them with a bit of preprocessor magic). * Avoid GNU indentation style by all means. It makes your code unreadable. * Try to indent your code nicely. There are editors like JED, which is available from space.mit.edu:/pub/davis and highly recommendable, that do this for you automatically. * Use eight space tabs, four space tabs make a mess of the code. - If you have access to more than one Unix system, try compiling/running your - code on all of these. Remember, UAE is supposed to run on the DEC Alpha: so - don't assume sizeof(char*) == sizeof(int) == sizeof(long) + code on all of these. Remember, UAE is supposed to run on 64 bit machines: + so don't assume sizeof(char*) == sizeof(int) == sizeof(long) - If you have more than one Kickstart, try your code with each one. - Patches are welcome in any form, but diff -u or diff -c output is preferred. If I get whole source files, the first thing I do is to run diff on it. You can save me some work here (and make my mailbox smaller). Some possible projects, in order of estimated difficulty: +- Someone running *BSD on a x86 might want to try using X86.S on such a + system. It's likely that only configure needs to be modified. +- Add gamma correction +- Repair support of the serial interface. Sending data seems to work, + receiving does not. Maybe this has to be implemented in a completely + different way (a serial.device? If you do that, don't do it native. At least + not all of it. Amiga libraries shouldn't be implemented completely native + in UAE, the parts which are not speed critical should be Amiga native so + they can call other 68k code safely). - Someone with a 68020 data sheet might check whether all opcodes are decoded correctly and whether all instructions really do what they are supposed to do (I'm pretty sure it's OK by now, but you never know...). -- Modify UAE to run in two threads for systems that have more than one CPU. - I've thought of a way how to do it, but I don't have a multiprocessor board - to try this. Here's how it works: Start with smart update method #1. This - method nicely bundles all the data necessary for drawing a scanline into two - structures: linedescr and line_data. Instead of actually drawing the line - in the main task, signal the second one to use that information. Synchronize - the two at the end of a frame to avoid lossage. - If I haven't overlooked a big problem, it should be trivial. - Sound output could also be moved into a separate task, but the gain will be - much smaller. +- Multi-thread support is there now, it just needs someone to test it on a SMP + machine and to fix it so it improves speed instead of slowing the thing + down. - Improve the Kickstart replacement to boot more demos. - Snapshots as in CPE. Will need to collect all the variables containing important information. Fairly easy, but boring. (Use core dumps instead :-) + _If_ someone attempts this, please be more clever than the various CPC + emulators and dump state only at one fixed point in the frame, preferrably + the vsync point. - Find out why uae.device has to be mounted manually with Kick 1.3. The problem seems to be that we don't have a handler for it. I _think_ what we need is the seglist of the standard filesystem handler. Problem is, DOS hasn't been started when the devices are initialized and so we can't get to the DosBase->RootNode->FileHandlerSeg pointer, and then there is the confusing matter of BCPL GlobVecs and other weird stuff... -- The playfield hardware is the only important part of the Amiga that is - not really well documented in the HRM. Write some test programs that - do all sorts of weird things with the copper (like turning off bitplane - DMA during a line, and turning it directly on again: VERY interesting - result) and try to emulate this perfectly. - Not _really_ necessary, I think: Surprisingly, and unlike 8 bit computer - software, Amiga programs usually seem to make use only of documented hardware - features. +- Some incompatibilities might be fixed with user-modifiable fudge variables + the same way it's done in various C64 emulators. +- With the new display code, it would probably be easier than before to + implement ECS resolutions - however, a lot of places rely on the OCS timing + parameters and display sizes. - Figure out a diskfile format that supports every possible non-standard format. - Implement 68551 MMU. I have docs now. Not among the most necessary things. + Difficult, at least without using C++ exception handling. - Implement AGA support. Some bits and pieces exist. - Reimplement Amiga OS. (Well-behaved) Amiga programs could then be made to use the X Window System as a "public screen". Of course, not all the - OS would have to be re-done, only Intuition/GFX. [Started, look at gfxlib.c] -- Find some extremely clever ways to optimize the smart update methods. Maybe - try to support scrolling. Maybe find a way to update only parts of a line - (similar to LOW_BANDWIDTH). All such methods would probably be terribly - complicated, and not easy to get right without sacrificing compatibility. - Maybe it's not such a good idea. + OS would have to be re-done, only Intuition/GFX/Layers (which is enough). + [Started, look at gfxlib.c. The problem is that you need all of Exec native + first before you can do any non-trivial graphics operation.] +- Find some extremely clever ways to optimize the smart update methods. Some + ideas: + a) Always use memcmpy() to check for bitplane differences. If no differences + are found, see if BPLxDELAY got modified, if so, scroll. + Problems: + * You'd still have to draw a few pixels around the DIW borders. Not very + hard. + * Scrolling with memcpy in video memory can be terribly slow (no, I + shouldn't have bought the cheaper video card with DRAMs) + * At least every 15 pixels a full update has to be done since the + bitplane pointers get updated after that. And that's with the slowest + scrolling - if the playfield scrolls faster, the benefit converges + against zero. + You could also do vertical scrolling tests, but similar problems arise - + where should one check? One line above/below? What about faster + scrolling? You could use the bitplane pointers as hints, but with + double/triple buffering this gets problematic, too. + On the whole, I don't think it would be worth the effort, even if it + works very well for a few games. + b) Well, there is no b). If I thought of something I forgot it while + writing a). - Port it to Java and Emacs Lisp - A formal proof of correctness would be nice. -Things I don't really want to do: -- Full ECS support, with braindamage like Productivity and SuperHires. How it works @@ -77,10 +97,10 @@ Let's start with the memory emulation. A banks of 64K each. Each bank can define custom routines accessing bytes, words, and longwords. All banks that really represent physical memory just define these routines to write/read the specified amount of data to a chunk -of memory. This memory area is organized as an array of WORDs, which means +of memory. This memory area is organized as an array of UBYTEs, which means that those parts of the emulator that want to access memory in a linear -fashion can get a (WORD *) pointer and use it to circumvent the overhead of -the put_word() and get_word() calls. That is done, for example, in the +fashion can get a (UBYTE *) pointer and use it to circumvent the overhead of +the put_*() and get_*() calls. That is done, for example, in the pfield_doline() function which handles screen refreshes. Memory banks that represent hardware registers (such as the custom chip bank at 0xDF0000) can trap reads/writes and take any necessary actions. @@ -93,18 +113,39 @@ devices. To provide a good emulation of graphical effects, only one thing is vital: Copper and playfield emulation have to be kept absolutely synchronous. If the copper writes to (say) a color register in a specific cycle, the playfield -hardware needs to use the new information in the next word of data it +hardware needs to use the new information in the next word of data it processes. UAE 0.1 used to call routines like do_pfield() and do_copper() each time the CPU emulator had finished an instruction. That was one of the reasons why it was so slow. Recent versions try to draw complete scanlines in one piece. This is possible if the copper does not write to any registers affecting the display during that scanline. Therefore, drawing the line is deferred until -the last cycle of the line. If the copper writes to a hardware register before -that, the function pfield_may_need_update() is called and this one determines -whether it should fall back to the cycle-for-cycle approach. This is very -rarely needed, mainly for copper-plasma effects and such, and the general case -is much faster. +the last cycle of the line. However, sometimes a register which affects how +the screen will look is modified before the end of the line (think of copper +plasmas). That's what "struct decision thisline_decision" is for. It is +initialized at the start of each line. During the line, whenever a vital +register is changed, one of the decide_*() functions is called and may modify +thisline_decision. There are several independent decisions: + - which DIW should be used + - where does data fetch start/stop (or is the line in the border altogether) + - where should sprites be drawn (note: the same sprite can appear more than + once on one scanline, see Turrican I world 3 levels 1 and 3 for the best + example) + - what are the playfield pointers at the start of DDF. Related, what data do + they point to. + - what are the playfield modulos at the end of DDF + - coppermagic with the colors is remembered for later use + - so is copper magic with the bitplane delay values. I used to think there + was no useful application for modifying BPLCON1 while data is being + displayed, but Sanity demos can make Amiga emulator programmers look real + old. + +All of this is remembered while the raster line is processed by the hardware. +After the line (at hsync), all the decisions are made if they weren't made +before. At that point the line can be drawn by playfield_draw_line. +Additionally, all the decisions from the previous displayed frame are saved +and compared with the new ones, since often lines are not modified between +frames. This saves a lot of redrawing work. The CPU emulator no longer has to call all sorts of functions after each instruction. Instead, it keeps a list of events that are scheduled (timer @@ -112,6 +153,22 @@ interrupts, hsync and vsync events) and for the next event is checked after each CPU instruction. If it's higher than the current cycle counter, the CPU can continue to execute. +Things that can't be supported with the current "decision" model: + - Changes in lores/hires mode during one line. Dunno whether that was ever + used in reality. + - Changes to the bitplane DMA bit during one line. Hardly useful and not + likely to be used. [but there is at least two programs which does ugly + things like that, and there are some hacks in UAE that make those programs + work (Magic 12 Ray of Hope 2 is one of these demos)] + - Changes in bitplane data during one line. If programs do this kind of + thing, it's most likely accidental and the program is broken. Can happen + with programs that use the blitter incorrectly, like all the Andromeda + demos. + - others? (fill in if you can think of anything) + +All in all, it's unlikely that this causes compatibility problems. If it does, +fudge values could be introduced (although that sort of thing gets messy +quickly). Portability @@ -132,3 +189,8 @@ filesys.c, but also in debug.c. Put in a if necessary/possible, or make up a dummy unixfs-null.c file that contains stubs. Apart from all that, it's fairly portable... + + +How the compiler works + +.. yet to be written. To be decided, in fact.