Jump to content

danwinslow

Members
  • Content Count

    2,871
  • Joined

  • Last visited

Posts posted by danwinslow


  1. Yeah, I was looking at a more general case than just switching out entire applications in a 16k bank.

    If I am successful, we will have an easily installed ethernet device in a few months, for around 100$ of hardware, with an optional 32MB flash 'hard drive' for $50 or so more.


  2. Hmm, upon further thought I guess the way to do this would be with a (soft) segmented architecture like x86 /shudder. You could have a couple page 0 locations that were 'segment selectors', and would control which 16k block of extended memory was swapped into the RAM window. They would also form the base for 0-16k offsets into the currently selected segment. So swapping segments would be a matter of loading the segment selector with the correct value and swapping in the correct block. An actual address would be an 16k offset from the segment base..uh you'd need like 14 bits for that offset. So if the segment 'registers' were 8 bits, that would give you 256 16k segments. Added to the 14 bits for offset, that gives you 22 bits...which is cool as you have 2 bits left over to do something else with...dirty bits or status bits or something, maybe if you paged to disk as well. You'd need to add direct support for this in your compilation tool..all data accesses would have to be relative to the beginning of your RAM window. You take a 24 bit address, split off the segment selector 8 bits, check if that block is current and swap it in if not, and then use the bottom 14 bits as an offset. Does this make sense or am I babbling?


  3. Yeah, thats true. I have been thinking about that too...without a page fault type of mechanism you would either need to (a) manually trap all instructions to go through page checking/swapping routines for control transfers and memory fetches, or (b) restrict yourself to memory accesses through an allocator that maintained usage and location tables, or © design things so that they are naturally packaged in 16k chunks, ie., no user program could be over 16k in length.

    (a) would be really really slow I would think. (b) would be good...but it would some overhead itself to maintain page tables and would really only work for data. © seems possible but restrictive.

    Mostly I have been thinking about (b). There would need to be unswapped data in low memory that would be a page table that indexed some virtual space of chunks of data.

    You would have to set up all memory allocations and subsequent access through user code. You would also need some kind of RAM window to map your data in and out. You couldn't just hit any piece of data with a direct load...probably best would be to set up a lower memory access window, say 1 page. When the memory access routine went to fetch a particular address, it would figure out which 16k mem bank has the data, swap it in, move the appropriate page to the RAM window, and swap back in the 16k block ( which might after all have contained code that is currently expecting to run ). So, really you'd have to use a completely new addressing scheme...something like a 24 bit scheme in which bits 0..7 specify an offset from the RAM window start, and bits 8..15 specify any one of 256 1 page chunks, and the other bits select a 16k block....or something like that, you get the idea. Another issue is that the biggest memory object you could work with at once would be 256 bytes...maybe if you took like the last 2 bytes and made it a 'chain field' to the next block you could stitch things together.

     

    At any rate, you'd have to go to a completely new way of addressing memory. You would need to build direct support for it into the compiling tool. It definitely wouldn't be compatible with any existing source code. It might be interesting tho for something like Contiki.


  4. Fiath, you are indeed wrong about the subject of bit degradation over copies, at least copies made using the normal means of transferring through RAM. The reason is that while the bit as stored on disk is analogue, the bit while stored in RAM is not. If the bit on disk is strong enough to be read as a 1, a 'perfect' 1 gets placed digitally in RAM, with absolutely no memory of how strong or weak the mag flux was on the source disk bit position, other than that it was sufficiently strong to be interpreted as a 1 in the first place. This perfect bit is then transferred to the destination disk, where it becomes re-expressed as an analog mag flux. While the bit as stored on the destination may or may not be perfectly laid down, its condition in *no* way is dependent on the original source bit.

     

    Now, if you are using some kind of direct magnetic transferral, ie source mag flux to a signal strength on a wire to a desitnation mag flux, then yes, thats a perfect analog of copying a magnetic tape and it will degrade across multiple copies. But, as far as I am aware, this copy method is pretty unusual and would take special hardware. Standard copies of disk to disk that do transfers through a digital media such as RAM do *not* degrade. If you can offer any proof that they do, I know of an entire industry and scientific establishment that will be quite interested.


  5. Oh, and on the USB subject, I have a cart too, and have done some preliminary experimenting with a ethernet/USB. Using the USB CART project stuff from the ABBUC guys I was able to see the ethernet USB...the atari driver didn't know what it was of course, but it did manage to dump out some of the ident strings and stuff from the descriptors. It didn't look right, some of the strings I think are longer than what they had planned for, but as far as it went it seemed to be able to find it.


  6. I have looked at uIP. Its seems to be workable, but its not ported yet, and its not complete. The real problem is that it is just impractical to get a functional TCP stack and an ethernet driver layer together on an 8 bit machine, *and* have room left over for applications. I don't want to say its impossible, but if it is, its beyond what I can do. I am taking a different tack that will involve an external smart ethernet board. The stack and support hardware will be on the board. Then on the Atari side will be a light weight SIO-style driver underneath a sockets.h type library. The sockets.h layer will just be a passthrough, but it will allow native compilation of standard TCP apps on the atari, with almost no TCP overhead. You will be limited, of course, to the 19.2k SIO transfer rate, but that really can't be helped...*unless* maybe I can interface the smart board and software on a cart..say a flash cart maybe. Or maybe just putting Contiki or whatever on the flash cart would be good. Bank swapping could allow some stretch room..I think.

    But anyway, specifically Contiki, along with maybe one of the tiny linuxes (lng maybe ) is my target. I would really like to strip the TCP layers out of Contiki, it would make it a lot more practical in terms of size.


  7. Uh...no screen ram? I take it its all done on the fly as the raster is drawn? Ouch, I didn't realize that. No wonder the timing issues are scary. But as far as emulators go, part of their job is to realize a 2600 screen, right? Somewhere in there, a screen gets drawn, and mapped ( I expect ) to video RAM or something on the host machine. If the internal state of the emulator gets copied to another one sufficiently fast...or maybe just the host machine screen RAM...I dunno.

     

    I still think that if you wrapped hooks around every internal function of a server 2600 emulator such that any time a machine state item got changed ( ie., a register got written, ram changed, etc. ) it would replicate the change to a slave machine...Yknow, you should be able to make like a recording of all the operations, like a macro...and play it back to reproduce exactly a given session. So you wouldn't really need a client 2600 so much as a slaved emulator session. If the emulator could optionally be in slave or master mode, then the same software would serve as either side. You would have to have a syncronization key...probably an internal virtual jiffy count that got sent along with each update or at intervals or something. The clients would block waiting for updates packets to arrive, and the server would block waiting for acks for each jiffy update cycle...so the server could not advance the jiffy until the previous jiffies' update had been ack'ed by the clients..that would lock them in sync. Controller reads would be by request., ie, the server machine would access the appropriate port, which would be hooked to send a read port request to the client, The client would then do a controller read and send the packet.

     

    The whole shebang would all slow down or speed up together, servers and clients, based on the highest latency for the jiffy acks. But I bet a smart routine for packing the updates and acks together in larger time chunks, and maybe also controlling internal server run speed based on current latency info, I bet you could get a decent session going.


  8. No, I generally agree that if the target is real hardware on the client side, it becomes very difficult to do. But, given emulators on both ends there are lots of things that could be done. I think its pretty possible to do a decent job given careful programming, there are lots of tricks. You may well end up with some choppiness and slowdown, but you cant escape that on net games.


  9. OK, I think this is very, very doable with both servers and clients as emulators. If you wanted to be able to drive real hardware on the client side, thats going to be much harder...but I think it would still be possible.

     

    With the clients as stella emulators as well, all you would have to do is put update hooks around all of your writes into the simulated machine on the server side, so that each write to your internal simulated 2600 would result in a corresponding update packet to the listening client 'emulators'. Really the clients would be an 'emulator emulator' at that point. Or something like that.


  10. Ooooh...on the chip state issue....you could put hooks around your internal 'chips' that would automatically generate a corresponding update to the client machine.....yar. So we would get a stream of chip state changes as they should occur anyway to the client. That and the video RAM updates ought to make for a playable situation...hmmm.


  11. The issues of mapping controller inputs to specific ports on the server side are easily handeled. Thats a standard issue. As you mentioned, there is usually a negotiation at some point ( unbeknownst to the user perhaps ).

     

    As far as knowing when to seek input from the clients, its handled in a couple of ways. Often you set up a stream of UDP packets from the client constantly sending data concerning the inputs...this is then cached and staged if necessary and played into the server. Its usually UDP because its largely redundant data so if we drop one or two its usually no big deal. The wrapper around the server just keeps the virtual controllers updated with the most recent data, and the server just reads them whenever it normally would. You can also send just delta packets ( ie., only when the value changes ) and thats usually more efficient but if packets get dropped it can have more impact on the play.

     

    Syncronizing machine state back to the client is a different matter...first of all, how much data are we talking about? How big is a stella state file, for instance. If thats larger than we feel comfortable pumping out 60 or 30 times a second, we can generate deltas ( list of addresses and changed values ) instead of the whole thing every time. That (usually) decreases the data size but can add handling overhead.

    Also, whats the apply overhead like? How long would it take to flash a new state in?

     

    There are also other chip states to worry about...music comes to mind. It seems like it would be hard to get an unbroken stream of music to play on the client if its coming in discrete chunks and you have to slam a new state onto the chips every frame. For specific chip states like that we would probably send an initial state, but then rather than updating with the entire stream of state changes, we would let it 'play' on its own for a while on the client box...then resync it to a known point every so often, or when something changes. It would still probably sound choppy but I bet a smart routine could combine periodic updates with a 'free play' time window and get a good matchup. The screen ram we ought to be able to pack up and send very often in its entirety I would think, and if its fast enough ( around 10 frames per second if I recall my limits of normal human perception ).

     

    So that idea all has to do with the game being plaued on the server, and the clients just being 'dumb' displays. That solves a LOT of sync problems, but its high overhead. If you have to get to the point where the game needs to run on the clients too ( with periodic state updates ) then things start to get dicey. Most on line games have very thick clients, that do almost all of the display work in between periodic updates, animating characters and walking things along in the last known direction, etc, with the server side just giving object x,y,z and various state updates periodically. This leads to wierd effects from lag though, and probably wouldn't be good on something like a 2600 game, which has no knowledge at all that it might be being lagged.


  12. Here's maybe how to do it :

     

    1. Drop the concept that your 2600 emulation has to properly draw the screen. I suspect that a lot of the delicate timing issues come from having to syncronize things like NOP loops waiting for raster beam positioning with the ACTUAL raster as drawn by the host computer. If you aren't worried about realizing the screen on a host display, all of a sudden your timing becomes relative, and you can go as fast or as slow as you want as long as it's internally consistent. You would be tracking your own 'virtual' raster beam, so to speak.

     

    2. So set up a 2600 emulator 'server' that runs on a host computer, and is only concerned about maintaining the internal state of the machine, namely the ram/rom contents.

     

    3. Wrap this emulator in a TCP-enabled shell that interrupts it every X jiffies, snaps the machine state and broadcasts it via TCP. The game running on the emulator never knows anything happened.

     

    4. Create emulator 'clients' that can run on a variety of host machines, and are set to connect to the server and only do 2 things : read and send the joystick info, and receive and display the machine state. The game itself would not be running at all on the clients.

     

    5. Since the server no longer needs to be slaved to a particular display, you can run ther server as fast or slow as you need to..you could use a positive ack/nak protocol to let the server adjust for latency times. This would lock the clients in sync. The display may get choppy still due to latency, but you would always know that you are in sync.

     

    6. If you wanted to play via real hardware, you could take a SBC ( Single Board Computer ), like this one, and fit it into a freakin cartridge if you wanted to, plus some extra chippage to do the interfacing into the 2600. Plug the cartridge in the 2600, stick an ethernet line into it, and off you go. The cartridge would read and send the joystick info, and receive the machine state pulses and write them into the actual 2600.

     

    You could even have a BIG server running lots of these 2600 server instances, and host it all under a custom framework, kind of like battle.net or team fortress or what have you.

     

    You wouldnt have to reprogram the games themselves at all.


  13. *edit*

    The amount of RAM data required to represent a 2600 screen has got to be pretty small....maybe 1k or so? Not really sure. So maybe rather than grabbing the screen off the TV with a digitizer, you could have a hardware device that can snap the screen memory off of a running game every vblank. If its around 1k that would fit into one packet and would be very easy to send to the client and have him update his screen. As long as you kept the screen refresh stream going in one direction and the client joystick data in the other you'd be set. You'd still be laggy sometimes but you can't get away from that in net games.


  14. Well, you don't so much need to connect the two 2600's across the 'net, you just need to connect a joystick and screen deltas. So set up a client 2600 to just read the joystick and send it to the 'server' 2600 ( the one actually running the game ). That would be easy in comparison to the screen deltas. You'd have to have some kind of external hardware piece that could snap the screen at every vblank or something and compress and send the screen data. Video capture or maybe some kind of conferencing tool. The client 2600 would receive and display the screen updates, and send the joystick data, and thats it. The server machine would be the only one actually running the game, and so that eliminates the sync problems to some extent. Still, the client machine would probably look and feel laggy if there were significant latency.

×
×
  • Create New...