You have to put a routine into two different locations in the code.
This way I can just copy and paste the same line DEBUGNLAO(cycleresetq,CYCLE_RESET_Q) and it will make the appropriate NETDEV_ANALOG_CALLBACK_MEMBER or NETLIST_ANALOG_OUTPUT.
One thing that's interesting in the debugger, if you "gt 1" you can see the strip of screen that gets painted during the millisecond. It shouldn't be too hard to make it possible to step by less than a millisecond.
Is the chip (AY-3-8760?) inside the "Stunt Cycle" home console based on similar logic gate circuit or is it some kind of microcontroller?
It's at least pretty certain it's not a microcontroller - microcontrollers that could actually do TV-based graphics didn't exist back then. There's no telling if it's based on "similar logic gate circuits" or not. It's an ASIC, all of the one-off TV game systems of that era were. It would require someone decapping such a chip and actually tracing out the silicon to work out an equivalent schematic to know anything more than that.
// TTL_74193(name, A, B, C, D, CLEAR, LOADQ, CU, CD)
// TTL_74193(L8, FIXED_RAMP_ZONE_Q, FIXED_RAMP_ZONE, P, P, JUMP_Q, LOAD_Q, P, GRAVITY) // Schematics say C and D should be to VCC - maybe ground instead?
// changed to GROUND and bike jumps!!!
TTL_74193(L8, FIXED_RAMP_ZONE_Q, FIXED_RAMP_ZONE, GROUND, GROUND, JUMP_Q, LOAD_Q, P, GRAVITY) // Schematics say C and D should be to VCC - maybe ground instead?
I also tried to model a bunch of stuff that leads up to the SPEED_PULSES and up to R38 and R39 but it ran super slow...like over a minute to generate a single frame.
It's interesting to study the different Atari TTL games of this period as they have quite a bit of similarities.
I thought I'd try to figure out how the rom in tank works too:
Code
f = io.open("/mnt/z/mame/roms/tank/90-2006.k10","r") a = f:read("*a")
function prtbyte(adr,a) if adr then io.write(string.format("%x",adr)..":") end for i=7,0,-1 do if (a & (2^i)) ~= 0 then io.write(i) else io.write(" ") end end end
function bit(x,y) return (x >> y) & 1 end
for score=0,63 do for v=0,7 do adr=((score<<3) | v | (1<<10)) io.write(score.." "..v..":") prtbyte(adr, a:byte(adr+1)) print() end end
for dir=0,31 do for v=0,7 do for h = 0,1 do adr=(v | bit(dir,4)<<3 | h<<4 | (dir & 0xf) << 5 | 1 << 10 | 1 << 9) prtbyte(nil,a:byte(adr+1)) end print() end print(string.rep("=",16)) end
for v=0,31 do for h=0,15 do adr=((v<<4) | h | (0<<9)) if h~=7 then prtbyte(nil,a:byte(adr+1)) end end print() end -- playfield 0
for v=0,31 do for h=0,15 do adr=((v<<4) | h | (1<<9)) if h~=7 then prtbyte(nil,a:byte(adr+1)) end end print() end -- playfield 1
So one of the things that had me baffled about tank was figuring out how it handles the mines. Specifically, how does it keep track of whether a mine has been hit or not?
It doesn't have a cpu, and it only has a ROM chip, no ram chips, so how does it know if a mine has been hit?
There's a dual 8 bit shift register, the Signetics N8277, that is used as a 16 bit shift register and that's enough to hold 1 bit of state for each mine.
In the playfield, there's a rectangular region defined for the mines, any bit that's set in this region will be a mine, but we're only allowed 1 mine per row.
When the game starts, the shift register is cleared, a 1 bit means that the mine has been hit.
As the playfield gets scanned vertically, this shift register gets cycled through and updated, collision with either tank1 or tank2 will remove the mine (set the bit to 1 that will get shifted in on the next clock). The D0A and D1A are set so that it inverts the input DSA on pin 4.
I managed to get one of the tanks displaying. It's super hacky but at least it shows something.
There's something very very wrong with one of the 74107's. Hooked up normally, IC_N1.6 GOES TO IC_M1.4 but for some reason, it never gets updated. If I put a debug net list analog output on IC_N1.6, it never gets updated, however if I put a debug net list analog output on IC_N1.5, it magically starts updating??? If it never updates properly THR1Q and THW1Q don't activate and the display window doesn't get activated.
Here you see a tank in the lower right, it jumps all around:
Got both tanks appearing, but jumping all over the place:
So modifying my PCBASIC program you can see the mine image, what's kind of interesting is that it doesn't occupy the entire 16x16 area, just the lower right 8x8.
Code
10 DIM A(5000),B(5000)
50 DEF FN cnot(xarg)=(xarg=0)*-1
60 DEF FN cbool(xarg)=(xarg<>0)*-1
70 DEF FN bit(xarg,yarg)=fn cbool( xarg and (2^yarg))
80 def fn cxor(xarg,yarg)=fn cbool(fn cbool(xarg) xor fn cbool(yarg))
90 DEF FN cnand(xarg,yarg)=fn cbool(fn cnot(fn cbool(xarg) and fn cbool(yarg)))
91 DEF FN cnor(xarg,yarg)=fn cbool(fn cnot(fn cbool(xarg) or fn cbool(yarg)))
100 SCREEN 7 : rem screen 2 too much resolution
101 SIZE=16
105 FOR FLASH = 0 TO 1
110 FOR X = 0 TO SIZE-1
120 FOR Y = 0 TO SIZE-1
130 P = FN cnand ( FN cxor( FN cxor( FN cxor(FN bit(y,2),FN bit(y,3)), FN cxor(FN bit(x,2),FN bit(x,3))), flash), FN cnor( FN cxor( FN bit(y,1),FN bit(x,1)), FN cnor( FN cxor(FN bit(x,2),FN bit(x,3)), FN cxor(FN bit(y,2),FN bit(y,3)) ) ) )
140 PSET(X,Y),FN CNOT(P)*4
150 NEXT : NEXT
155 IF FLASH = 0 THEN GET (0,0)-(SIZE-1,SIZE-1),A ELSE GET(0,0)-(SIZE-1,SIZE-1),B
160 NEXT
200 FOR I = 1 TO 500
210 FLASH = I MOD 2
220 IF FLASH = 1 THEN PUT(160-(size/2),100-(size/2)),A,PSET ELSE PUT (160-(size/2),100-(size/2)),B,PSET
225 FOR DELAY = 1 TO 10000:NEXT
230 NEXT
130 F13.11 = FN CXOR( FN BIT(X,1), FN BIT(X,2) ) : F13.8= FN CXOR( FN BIT(Y,1), FN BIT(Y,2) ) : F13.6 = FN CXOR( F13.8, F13.11) : A10.11= FN CNAND( FN BIT(Y,3), FN BIT(X,3) ) : D7.02 = FN CNOR( A10.11, F13.6) : P = D7.02
140 PSET(X,Y),FN CBOOL(P)*4
If I change the colors a little, you can see it only occupies the lower right quadrant.