Hi! To all Vectrex hardware freaks. (Sorry you others... this has gotten a bit too long) If you have looked at DVE (Dos Vectrex Emulator) you might have noticed a few deficiencies. I would like DVE to be better. (I think it is very well done, congratulations Keith). I already did some minor changes, as you might have noticed there is now a version 1.20. Two major marks a still left to be ticked of. a. 3D games emulation (thanks to Rob Stickles for some documentation) b. Correcting incorrect Vector offsets (like Clean Sweep) Some minor: a. Spike random generator seems not to work correctly b. Sound is not so great c. Joystick... ... First I would like to tackle major b. (that's why it is second on the list). I actually tried some things, but nothing really helped yet. This letter is about the above problem. Maybe you can help. It is no secret, that I'm not into hardware, I have not even seen a Vectrex in real life yet. So if something I say is simply wrong, don't be annoyed, just be glad that you know it better... and please tell me! ............................................................... Q:So what is wrong? A:Something with vector coordinates. Q:Where can it be seen? A: 1. Clean Sweep! 2. Spinball! 3. Intro Screen, Text should be centered. ... some other places (is it one or more bugs?) A:What does Keiths documentation say about it? Q: " There is still an image offset problem on some games, notably Spinball & Clean Sweep. I haven't tried to fix it yet. " AND " 3.3 Emulation Problems ---------------------- There are two games I desparately wanted to get running perfectly as they are the only two with graphical faults : Clean Sweep & Spinball. It seems unlikely that the vector offset problem will be fixable without considerable effort on my part to improve the modelling of the integrators within the vectrex. The gist of the problem is that DVE models "perfect" integrators that always reach the point they were programmed to reach, in a linear fashion. On the real machine the integrators arent perfect, its this imperfection that is very hard to model correctly. The problem manifests itself slightly in most games, the most obvious is the non-centered text on the boot screen. This feature also prevents line clipping being implemented fully as the edge of the screen is in different places for many games, i.e Vectrex Vaders is much wider than others. Although each game can have its own VOL file and as such you can have different clipping for each game. " Q:Where is that Integrator in the source code? A: DVE 1.00 File: ANALOG.C Function: fAnalogTick() Where: A great deal of that function actually. The integration process (adding) is right after the comment "// Emulate zero/ramping circuits" ... // Emulate zero/ramping circuits if(tSIGDEF_ZEROB) { if((!tSIGDEF_RAMPB && !tLastRamp) || (tSIGDEF_RAMPB && !tLastRamp)) { lwTickMark=lwGblSystemTickTotal-lwTickMark; lSIGDEF_XOUTPUT+=lXSampleHold*lwTickMark; lSIGDEF_YOUTPUT+=lYSampleHold*lwTickMark; } } ... Zeroing ... is somewhere near... DVE 1.20 File: ANATICK.CC Function: fAnalogTick() Where: A great deal of that file... The integration process (adding) is right after the comment "Emulate zero/ramping circuits" ... /*********************************/ /* Emulate zero/ramping circuits */ /*********************************/ if (tSIGDEF_ZEROB) { if (!tLastRamp) { lwTickMark=lwGblSystemTickTotal-lwTickMark; lSIGDEF_XOUTPUT=lSIGDEF_XOUTPUT+lXSampleHold*lwTickMark; lSIGDEF_YOUTPUT=lSIGDEF_YOUTPUT+lYSampleHold*lwTickMark; } } ... Q:Where is it in the Vectrex? A: If you have a copy of the service manual (TIF-Scans available at a known ftp site): Page 29. Block Diagramm , right in the middle of the page, something called: "Y-AXIS Integrator" something called: "X-AXIS Integrator" Page 31. Logic Board Schematics. Right hand side... right of IC302. IC 303 (LF347) and capacitor C312, resistor R316, wires and some other stuff... Y-Axis Right hand side... right of IC302. IC 303 (LF347) and capacitor C313, resistor R319, wires and some other stuff... X-Axis (NON PROPORTIONAL FONT ON) I I_______ I\+ IC303 (LF347) I \___________I R319 I / I _____________analog switch__/\/\/\__I/- I I I I C 313... I I___I I_______I I I (NON PROPORTIONAL FONT OFF) If that is right it should be something called 'Miller Integrator'. Q: What about the the other half of the IC 303 (LF 347), don't it belong to the integrator as well? (Page 29. Block Diagram, something called "Y-Axis Sample & Hold" Page 29. Block Diagram, something called "X-Axis Sample & Hold" Page 31. ... corresponding) A: Dunno, I'm no electronic guy, anybody help out? Q: What is that LF 347. A: A standard ... (dunno english name) 'Operations Verstaerker' (operation amplifier? 4 times) Datasheet can be found on the net as a *.PDF file. Q: Formulars for that Integrator: A: Miller Integrator: (NON PROPORTIONAL FONT ON) I^ u I q 1 I i = ---- = i -> u = - --- * I i dt e R f a C I f N f I u I^ I 1 I =- --- * I u dt , T = C * R T I q i f N i I u (NON PROPORTIONAL FONT OFF) Ti is the integration time. Q: What is that in Vectrex terms? A: Keith's Internal.txt (from ftp site...) on Vector drawing hardware: ###################################################################### Vector Drawing hardware ~~~~~~~~~~~~~~~~~~~ I apologise in advance for the patronising nature of some of the text in this section, if you know it already ignore it it isnt aimed at you. The text is aimed at computer literate people who may not have dabbled in the fuzzy world of Digital/Analog interfacing. When I use the word ASSERTED or ACTIVE state with reference to a signal I an talking about the state in which it is active. ie RAMP is only active when its LOW (ZERO) and INACTIVE when HIGH. INACTIVE or NEGATED means the signal is not in the ACTIVE state. See the descriptions of the different signals for what there particular active state is. It will to understand this section if you have a copy of the Vector drawing block diagram (see vector.gif). The vector drawing circuit is a mixed analog/digital circuit, consisting of the following parts. When the text says SET or CLEAR a line or feature refer back to these descriptions of how to set-up the hardware for a particular function: 1) The DAC. (Digital to Analog Convertor) This is the most crucial part of the Vector block. It is connected directly to PORT A of the 6522. (See 6522A Section for details on how to setup and write to PORT A). The DAC takes this 8 bit digital value and converts it into an analog signal proportional to the value of the byte presented to the DAC. DAC Vout = (PORTA - OFFSET) * Constant The range if the DAC output if from +?.??V to -?.??V in steps of ?.??V. Be warned there is NO enable control on the DAC so whatever value you present will be converted. The DAC output connects to the input of the multiplexer and the input of the X Axis integrator. PORT A which feeds the DAC also connects to the AY-3-8192 so when you write to the sound chip make sure that either/both the BLANK and RAMP signals are not asserted, otherwise you may draw crap all over the CRT. 2) The MULTIPLEXER (Mixed Digital/Analog) The output of the DAC is connected to the input of the Multiplexer IC (one half, the other half is used for AtoD conversion of the joypad potentiometers). The Multiplexer takes the input signal and switches to any one of FOUR output lines, the input signal is only ever connected to one output line at any one time. The multiplexer has 3 control inputs. The first, the ENABLE signal comes from the 6522A SWITCH line from PORT B Bit0 (See the 6522A section on how to set/clear this bit). When this line is ACTIVE the input pin is connected to the selected output pin, just as if a mechanical switch were thrown, when NEGATED the input and output pins are completely isolated from each other. The other two inputs SEL0 and SEL1, again from PORT B of the 6522 Bits 1 & 2 respectively. These bits are used to form a 2 bit number in the range 0-3, and when the multiplexer is active (see above) these inputs are used to decide which ouput pin is connected to the input pin. The Pin/Channel numbers for the Vector multiplexer are given below: 0 - Y Axis integrator channel 1 - X,Y Axis integrator offset 2 - Z Axis (Vector Brightness) level 3 - Connected to sound output line via divider network 3) X-Axis integrator, Y-Axis integrators (Analog) Before the input to each integrator is an analog switch, this switch is connected to the RAMP line from the 6522PIA PORT B Bit7. When the switch is closed (RAMP=0) the integrators will integrate the Value presented on the input, when RAMP is negated and the switch opened no integration action can occur and the integrators will hold their current value (see ZERO function). The outputs will follow the following form: ^ | 1 | - --- | ( Vin - Voffset ) dT + Constant CxR | | v For the X,Y integrators R=10000 and C=0.01x10E-6 When we fill the numbers in we get: Vout = - ((10000 x (Vin-Voffset) x Integration time) + Voutstart) Assuming that the full deflection voltages are +5V and -5V we can calculate the beam movement. This is always a relative movement based on the last position of the beam. If you want to be sure of where the beam is make sure you ZERO the integrators first then you can be sure the beam is at 0,0. IntInput = (DAC value - 128) * (10/256) IntOffset = (DAC value - 128) * (10/256) The 10/256 comes from a 10 volt possible swing on the DAC in 256 steps, therefore one step is 10/256 Volts. The -128 turns the DAC value into a plus/minus value. delta X = - ((10000 x (IntInput-IntOffset) x RAMPtime) + X) (or Y) X = X + detla X Assuming the vextrex usable screen area is 8 Inches which converts to 20.3 cm. This is equal to 10 volts of swing. (Note 8 inches is a guess, I dont have a vectrex screen to measure so please correct me if I'm wrong, also these firgures dont take into accound any overdrive of the screen area, and will therefore be slightly incorrect, though by how much I wouldnt like to say) X pos = X (volts) * 2.03 (cm/volt) (or Y) This value is again referenced to the 0,0 point in the centre of the screen. The power supply to the integrator comes from the +5V and -5V analog power supply. No matter how long we integrate for we can never exceed the supply rails, if we integrate for too long then then integrator will saturate. Typicall the integration time, the length of the active RAMP pulse will be quite short, in the order of microseconds or milliseconds. To move over the full range of swing (10volts) it will take ?? Assuming Voffset=0 and Voutstart=0 and no saturation. 10 = - 10000 x -10 X Integration time Integration time = 100us = 0.1ms This is for drawing the largest possible vector, from one side of the screen to the other. Vout = -5V to +5V in both X and Y Axis 4) RAMP (Digital, Active Low) As mentioned above the RAMP signal controls the integrator integration time described in the previous section. This line is an active low signal and is connected to the 6522 PIA Port B Bit 7. 5) ZERO (Digital, Active Low) This line is connected to the 6522 CA2 line, see the 6522 section for info on how to set this line up. As with RAMP is is an active low signal. During any integration operation this line must be set to the inactive state (HIGH). When ACTIVE this line will cause the integrator output to be set to 0V which will be the centre of the screen. This line should be ACTIVATED before any line drawing sequence to set the integrators to a known value. The integrator output value is held by a small capacitor and this will leak charge, basically the result is that over a period of time the when the integrator in not in RAMP mode its output will slowly fall to zero. So after drawing a sequence of vectors it is best to zero the output to give a solid reference. 7) Z-Axis Signal (Analog) This signal controls the Z Axis of the CRT, the brightness. It is set be setting the multiplexer to the Z-Axis setting and writing a value to the DAC. This signal is connected to a Sample and Hold circuit so you can switch the multiplexer away from this signal and it will hold it value. As with the integrators (See 3,7) the sample and hold will slowly drift towards zero, so every now and then in will need to be re-written. A good idea would be to write this value once for each object being drawn, or once per group of screen refresh if you are using a constant brightness, of course if your vectors are of differing brightness then you will need to set this value for each vector anyway. 6) BLANK (Digital, Active High) So that you dont need to change the brigness when positioning the CRT beam on the Screen you can use this line to temporarily BLANK off the Z-Axis signal, when NEGATED the Z-Axis signal will return to its old value. Bringing it all together The main basis if the vector drawing as weve seen is the X and Y integrators, the Z Axis brightness is a passive system and easily understood. Just in case the technical bit has lost you here is an analogy to explain the integrator system. We'll convert all of our electrical system to some household plumbing. Voltages will convert to water pressure and current/charge to water flow. So our DAC is a TAP and the value we write to is the water pressure behind the tap. An integrator can be thought of as a water tank. The screen deflection is measured by the level of the water in the tank. So when we set the DAC values we set the water pressure at the tank inlet. The RAMP switch controls the ON/OFF of the tap. So the higher the pressure (X,Y integrator values from the DAC) the faster the water will flow into the tank and the faster the level will rise, ie the water level is the vector position, we have two tanks X and Y. So you can see we have two ways of regulating the water levels, the water pressure and the amount of time we leave the tap on for. Halfway down the side of each tank is a valve marked ZERO. We always start with our tanks half full. And after we've poured our water in we can open the ZERO valve to dump out excess water and bring ourselves back to the zero point (the screen centre). But our system has a twist, we can set the input taps to a negatve pressure and suck water from the tank, and when we open the ZERO valve water will flood in to fill us back up to the mid point. Our system also has a few minor problems, our tanks have holes in them and slowly let the water out back down to the middle level, and the pressure we set on the Tap slowly fades away, so we must always ZERO and set the Tank pressure before a flush/fill cycle. Its in this manor that we can push the CRT beam around the screen to create the vectors we require. How to draw a Vector ~~~~~~~~~~~~~~~~ Maybe after reading the above you now have a pretty good idea about how to draw vectors, or maybe you werent really interested and skipped it, so here is the info on how to draw a vector. Step 1 Set the BLANK bit to 0, it should already be set to this to stop it dribbling crap on the screen when idle 2 Set the ZERO bit to 0 to clear the integrators 3 Set the RAMP bit to 1 4 Set the ZERO bit back to 1 5 Enable the Multiplexer and select Z-Axis 6 Write your Vector Brightness to the DAC 7 Setect the X,Y Axis integrator offset and write your value to the DAC, this can be used to scale the X,Y axis up/down. ---> 8 Set the BLANK line according to wether this operation | is going to be a DRAW or POSITION operation | | 9 Select the Y-Axis to the multiplexer and write your | Y-Axis Vector Velocity value to the DAC. | | 10 Disable the Multiplexer | |loop 11 Write your X-Axis Vector Velocity to the DAC. | | 12 Set RAMP to 1 | | < Vector is now being drawn> | --- 13 Set RAMP to 0 < Vector has finished > 14 Set BLANK to 0 to stop any more info being drawn on the CRT no that weve finished. The above can be run in a loop for each object or the whole screen, I dont know how the EXEC ROM does it but I would run the 1-14 sequence once for each object, ie the 8-13 loop for the components of the object. This would ensure the repeatability of object positioning as each object is always placed with reference to zero rather than the last object drawn. If you dont do a zero its likely that errors will build up and your objects may appear wobbly or jittery. Parts 5&6 of the sequence can be omitted if you are only positioning the vector ready for drawing. Now comes the tricky bit, just how do we calculate the values for X and Y velocity, X,Y integrator offset and how long do we make the RAMP pulse. The LENGTH of the RAMP pulse is critical if the screen is to appear stable, you MUST disable the interrupts during the vector drawing cycle as an interrupt occuring when RAMP is active would alter the length of the RAMP pulse. As I see it there are 3 possible ways to drive the system. All assuming that X,Y integrator offset is constant, you can use is for zoom in/out effects. 1) The most likely way the EXEC ROM does it (IMHO). We have a FIXED length of RAMP pulse for ALL vectors. Then with the 8 bit DAC values we have a 255 unit resolution on vectors in both the X and Y axis. This doesnt mean the screen resolution os 256x256, depending on the values used for RAMP time and XY integrator offset a 255 unit vector could be extremely small OR very large, its because everything is done relative to the last integrator position. I reckon this method involves the least calculation. You fix RAMP and then set the unit length with the XY integrator offset. 2) We have a look-up table of X,Y values depending on the direction that we want to move (you could calculate the values) and these are all scaled for a single fixed unit length vector. We then have a choice of either varying the RAMP length or XY integrator offset to procuce the length of vector we required, we just multiply the values of X and Y integrator settings for the fixed unit length by the length we require. 3) The most complicated way. We can vary all of the variables, but god only knows how we would calulate them, we would have four varibles. Solutions 1 and 2 look the most promising as they restrict the number of variables we have to calculate. Using a fixed value of RAMP would seem the easiest thing so that we avoid any problems of CPU cycle counting to get the required RAMP settings, we would need good control of the RAMP time resolution, which is awkward, though not impossible in software expecially when there is no hardware timer. Without access to a Vectrex and some development tools to write some test code I cannot test any of these THEORYs and work out conversions from DAC values,times to Screen positions. As I dont know what the full screen deflection voltages are, I would assume that the Max/Min integrator values will corrspond to the Max/Min screen deflection values, or maybe the Max/Min value is off screen, but by how much ?? WARNING: Dont go poking around the insides of the vector delecftion circuitry. The logic board only contains low voltage circuitry but the voltage chopper for the vector deflection circuit produce voltages of around 5000Volts. YOU HAVE BEEN WARNED. When I get time to Disassemble the EXEC ROM I can clear up once and for all how the EXEC draws vectors. ###################################################################### ..... My problems: Is it really the Integrator? Or something else? Integrator related: Where is the saturation point of the integrator? Is there a formular to take that into account? What is the suply voltage of that integrator? This can not be excceded? How does such an Integrator react on a sign change? If Integrator: Well, since integrators like the above are based on capacitors there is some imperfectness about them. Like they leak a bit of charge. And they can be saturated. The problem with the emulator is, that vectors are not all drawn where they belong to. Keith suspects that the reason is to be found with emulating the integrators. The problem is VERY apparent at two games only, Clean Sweep and pinball, which seem not to use the EXEC rom to draw vectors, but draw them on their own. They don't reset to zero... so it (clean sweep) draws the whole labyrinth in one go. Adjusting integration errors on the fly by tweaking the coordinates. My problem now... I don't REALLY know how these integrators work and what formulars are required. The integral-formula Keith gives in his description is all well, I even found that in a textbook of mine. But that formular is without flaws. Somewhere there should be an e-function, that takes satuaration into account. I tried inserting willfully the capacitor charging formular (Uc=Ui*(1-e^(-t/TAU)) somewhere in that integration formular, but to no avail. Keith suggested the following: >You'd need to model it with either lookup tables or floating point, the >problem is the ramp rise profile is dependant on the start position >which >makes things a little more complex for lookup tables. > > >V =Vstart+( Vtarget-Vstart)* (1-pow(e,-z*Time)) > >Where e=2.71828 and z is the RC time constant of the circuit >(approximates to R/C or C/R (can't remember)). Nice equation eh !! I >think I've got it right, I'd need to get some of my old textbooks out to >prove it. (in the above case, z=1/rc) Since dependency on time, dac value AND starting point a lookuptable implementaion is probably impossible (8-16Mb of lookuptable from what I figure). I tried the above, but it seems it does not work. OK... you have any idea what I have been talking about? The way integrators are modelled now is very simple lwTickMark=lwGblSystemTickTotal-lwTickMark; lSIGDEF_XOUTPUT=lSIGDEF_XOUTPUT+lXSampleHold*lwTickMark; lSIGDEF_YOUTPUT=lSIGDEF_YOUTPUT+lYSampleHold*lwTickMark; (Tickmark is time since last integration)... Some other thoughts... Following is an extract of what I think the emulator does or might do... (or the integrator...) The integrators highest possible value (since they are capacitors) can not exceed the input value. That would mean (in terms of your emulator) That 20000 to -20000 would represent +5 to -5 volt! DAC values equally have a range rom +5 to -5 volts, but these are represented as 128 to -128. What is represented, perfect integrators, not including the characteristics of their capacitor nature. So the integrator-capacitor could be 'overcharged'. For example 10000 represents 2.5 volt (as does 64 for the DAC). If another integration cycle would come along a 10064 would be in the integrator. But that should have been impossible, as it would exceed 2.5 volt restriction provided by DAC input of 64. Would that be right? Well I guess that's not the issue. But a capacitor is loaded slower as it comes near input voltage (see that e function...), and that also is not represented in your model. Still some other thoughts. Vectrex programmers definitly use different Vector drawing techiques. The problem is not seen with every technique. For example the opening screen: The 'scrolling' lines are centered perfectly. Only Text and such is not centered. (Same goes for Minestorm moving objects, which are correct. The Score is slightly incorrect!) If it IS the integrator getting 'incorrect' near satuation, wouldn't that mean that objects further 'off-center' would allways be at some false position? This is not the case, since the 'scrolling' lines from the opening screen are further to the border than the text. Thanks a lot for your time... If you have anything to say, please do... Chris PS 3D... The article of Rob Stickles. I tried the 100Hz 2.player button four trick with the emulator... It just didn't work, only for one or two button 'pushs'... If you have a short answer... (I didn't look into it, was just a five minute hack out of interest)