Jump to content


New Members
  • Content Count

  • Joined

  • Last visited

Everything posted by stepho

  1. Using different words: If there is something in the code that is very easy to break, then it should be documented in the code itself - ie right next to the part that breaks easily. I've lost count of the number of times that the previous programmer just "knew" that certain things had to be done or not done. But the knowledge wasn't passed on to me and I broke things that needlessly took me ages to find out why. When I eventually fixed them I put a comment in the code about why something had to be done in a certain way. Thinking ahead for the next guy to modify the code is what separates the hackers from the professionals.
  2. Always document caveats. Otherwise someone will modify it later and it will crash for an unfathomable reason.
  3. For the few games that don't work on real hardware, you still have the option of using an emulator. Maybe a different experience than real hardware but at least you can play the games.
  4. My own experience (35 years embedded) is similar. Get the algorithm right (eg, an O(n) search routine is not as good as an O(log(n)) search routine). Beware of C++ habits where the values get transparently translated back and forth with each layer. Eg, object A stores a figure as a int. Object B wants that figure as a string - luckily object A has a interface that translates it to a string. Object C wants that figure from B (with operations done to it) but wants it as a float - luckily object B has a interface that translates it to a float. Object D wants that figure from C (with operations done to it) but wants it as a int - luckily object C has a interface that translates it to a int. More time spent on wasteful conversions instead of the actual operations. Write the code with an eye towards the platform. Saw a colleague write an 8-bit AVR program using 32-bit signed ints throughout. Changed it to 8-bit unsigned ints and it was dramatically smaller and faster. But do not optimise it to death so that it is unreadable and unmaintainable until after the critical parts are identified by a profiler. Replacing code like x*8 with x<<3 is just making life hard for the maintenance programmer. Modern compilers usually do this far better and lets you leave the code far cleaner. Leave these "tricks" in the 80's where they belong unless timing is super critical or your compiler is old.
  5. I would modify that slightly - do hand optimisations only when they are needed. The compiler should be free to do automatic optimisations whenever possible. Although some hints from the author can change which optimisations the compiler can choose from. Eg, in C, the volatile keyword on a variable disallows a pile of optimisations but allows the variable to read from a hardware location. Some other hints from the author also tell the compiler to optimise for speed or size - usually as a global option via command line flags. This reflects a basic tenant of mine - let the machine do the work.
  6. Thanks. I still don't understand but at least I'm in good company. Perhaps it's something to do with how fast the TIA can change the signal level or how fast a typical TV can follow the change. After all, TV's are designed for continuous tone images rather than sharp edges. Cleverly exploited though.
  7. ok, but I still don't know what's happening. Can you go into more details.
  8. This is new to me. I can see that the pics have wall steps of 4 dots and sometimes 1 of those dots is turned off to make the vertical black lines. Can you explain (or point to an explanation) how this works? Thanks.
  9. From work I have done on other embedded devices (not Atari), you can double the amplitude of the output waveform and it will not sound like double the volume to our ears. That's because the device is using linear values but our ears work on logarithm values. Most TV's with digital volume also suffer from this (ie volume 10% sounds okay but to double the perceived volume you need to go way up to 30% or more) For my device (which only needs simple buzzer-like sounds at various, fixed, frequencies), I set the amplitude according to the crude formula: amplitude = (vol^2)/100 where: volume is the desired volume 0..100 % amplitude is the amplitude of the output waveform 0..100 % Not truly logarithmic but parabolic is close enough. With this, the user can double the desired volume value and the perceived sound also appears to double.
  10. Both look good. I suspect the buggy version is due to round off errors due to the trig functions not being evenly spaced. Eg, sin(1)-sin(0) is a lot larger than sin(90)-sin(89) where 90 degrees is a right angle, not radians. I worked through the original algorithm and the maths is fine - assuming infinite precision. I tried to think of other variations but none were as fast (theoretically) as yours.
  11. For Total Commander, I found I had to enable passive mode in the FTP connection settings. Haven't used FTP for years, so not sure if it makes any difference today.
  12. Rodney Zaks "Programming the 6502", courtesy of the Internet Archive. https://archive.org/details/Programming_the_6502_OCR Zaks "programming the Z80" was my second book for learning assembler back in the day (PDP-11 assembly handbook was the first).
  13. Sorry, by motion blur I meant that for the fall back position (ie no repeated frame was found) of just grabbing the last X frames and then blending/averaging them, then anything that moved would show up in both old and new positions. Like the red box in your last image. The system would do it's best to look for repeated frame(s). If it can't find repetitions then it just takes the last 10 frames (or whatever number you deem best). Manual splicing is always an option - we just try to let the computer do as much of the work as possible. My day job is designing automated equipment that can go for months in the field without human intervention. So I naturally try to make it as self sufficient as possible. I hadn't thought of showing phosphor fading in the final static image. If you took multiple snapshots then there is no guaranteeing the same first frame in each snapshot - which means the fading could be different for each snapshot. But it might be a nice option in the GIF. Each final frame in the GIF would contain a weighted average from the other frames - with special care taken so the first few frames contain faded info from the last few frames. I have a few thoughts on how to do that but I'll wait a bit in case I've gone an option too far.
  14. It's nice that it is possible to get an image but requiring the user to slice and dice it by hand kind of goes against the whole idea of having computers in the first place. Whenever a human is doing work for the computer, then something is wrong. A key point that I mentioned above is for the tool to watch for recurring frames. If it sees frames like ABABABABABA (ie a 2 frame kernel) then it grabs A, grabs B, grabs another A, notices that the 3rd frame is identical to the first and then blends the first 2 frames. But this doesn't capture flickering stuff like ABACABACABAC and could miss the C frame. So we look for 2 consecutive frames. It grabs A, grabs B, grabs A (no AB match yet), grabs C (no AB match yet), grabs A (no AB match yet), grabs B, notices that last 2 frames match the first 2 frames and then blends the 4 frames (ie every frame minus the last 2 matching). If the player is moving around then it may take a few cycles before it finds a set that don't have movement. We are hoping that the game is not having things move at 50 or 60 times a second (or at least that it does so cyclically) otherwise no player could keep up with a screen that screams by in a flash. Fall back is that after say 10 frames it just blends all 10 and just accept some possible motion blur. The above could be coded with a single parameter n. n=1 means just look single frame identical to a previous frame. Handles AAAA, ABABABA, ABCABC, ABCDABCD type cases n=2 means looks for 2 identical frames in sequence., Handles ABACABACABAC type cases n=3 means look for 3 identical frames in sequence. Handles more complex cases but I can't think of examples. Might have trouble with motion blur.
  15. I'm curious about how you do the phosphor fade. Do you store n raw frames in a sliding window and then do a weighted average for the display? Or do you use a simple signal filter? eg: frame=getNewFrame(); frame = ( (oldFrame * k) + frame) / 2; // where 0<k<1 display( frame ); oldFrame = frame;
  16. Perhaps Gopher could capture frames until it finds a frame identical to one that it has captured before (with an upper limit of say 10 if the screens have objects that move around a lot). Then the user could choose to save that as either: a single frame formed by averaging all the frames an animated GIF showing each captured frame in turn, using the same timing as they were captured. Should work for ABABAB (captures AB), ABCABCABC (captures ABC), ABCDABCD (captures ABCD). Would still fail for ABCBABCB but do many games do that? If need, could make it stop when it sees 2 successive frames that are identical to 2 previous success frames. Ie, ABCBABCB would capture ABCB because AB was seen before.
  17. Any bits that are not explicitly defined should always be masked out. Otherwise you will find that some implementations will give %xx000001 but you may also find some other implications give other numbers. Or even the same hardware under different conditions (temperature, timing, previous operations). Never trust what isn't fully documented (and only partly trust what is documented ).
  18. True, I should have said "global variables".
  19. It's not my code either but I can answer some of your questions. Most C compilers initialise variables to 0 (unless some other value is specifically given for a specific variable). So all the borders are initialised to have no border walls and are later modified to have bit 0 and/or 1 turned on via |= RIGHT or |=BOTTOM. Macro function can usually be converted to ordinary function in a mechanical fashion. static int GoodDir( int Cell, int Dir ) { return (g.Maze[Cell].Border & Dir) == 0; } Called by bool flag; flag = GoodDir( Cell, Dir );
  20. You are probably thinking of https://en.wikipedia.org/wiki/Bresenham's_line_algorithm
  21. I thought I knew IBM PC history and Atari history quite well but that was a new one for me. Found some more info at http://forum.6502.org/viewtopic.php?f=3&t=5256
  22. The 8-bit machines died only because technology moved on. Bit size increased to 16/3/64-bits to allow bigger programs and the handling of bigger numbers. Speed increased hugely. Memory size increased hugely. Power usage decreased hugely. We love our old machines but it would be silly to expect them to still be mainstream. The other thing to consider is that the video stream was a relentless task master running at (relatively) high speed. Pauses in almost everything else are not noticeable by the user but if the video stream ever paused then the user would notice it. There is no way to pause or skip sections of it while the machine deals with other things (calculations, disk, keyboard, etc). Everything else is either done at slow speeds (eg sound can be updated between screen frames) or is not timing critical. Therefore, the video must get top priority. Even in the 16/32-bit era, the PC, Mac, Amiga, etc had special buses for the video (eg PC had VL or AGP buses and the Amiga had the Copper chip). PCIe and Thunderbolt buses are still designed to specifically handle video streams.
  23. Not in significant numbers and not backed by the government like they were in the UK. Mostly it was the Apple II or the Microbee (Z80 CPM machine).
  • Create New...