RE: SimCoupe 1.0 released

2006-07-24 Thread Simon Owen
Simon Cooke wrote:
 Interesting... Defender uses HPEN/LPEN... any idea how it 
 uses it?

It uses HPEN monitoring to track whether it's running late with the current
frame.  I believe it still expects to be over the main screen area after
completing certain tasks, and if it's into the border it runs straight into
the next frame without waiting for the frame interrupt to be signalled in
the status port.  The game uses the stack for lots of the drawing
code/lists, so runs with interrupts disabled at all times [you can confirm
that in the SimCoupe debugger by pressing U for 'execute until', and
entering 'ei' for the expression - the breakpoint will trigger next time
interrupts are enabled, which never happens].

The HPEN/LPEN fixes both correct the screen position they're based from.
Previously they were taken from the start of the TV scanline, but they
should be from the start of the right border area, which is also where both
frame and line interrups are triggered.  The fix didn't make a huge
difference to Defender, but it stopped the main scroller in Geoff's BSD demo
from jumping up and down!

The older problem with Defender was due to poor instruction timings, which
interfered with the HPEN frame syncing.  It caused the game speed to be very
variable, ruining all Chris's hard work!  That's why the infamous
anti-emulator code was added, which timed the interrupt period and would
only work if it was perfect.  Dave Laundon enhanced the SimCoupe core to
apply memory contention in the right mid-instruction positions, which fixed
the remaining problems with instruction timings.  Defender then passed the
timing test and the game ran at the correct speed, so everyone was happy.


 Support for unresponsive ASIC? Sounds kinda weird :) What's 
 that either? :)

It's something I ran into when testing the initial port and register states
when SAM is first powered on.  I flashed a custom ROM image (based on the
Speccy ROM), but I couldn't get anything to display on the screen.  Even
after changing it to set the palette and border colour I only got a black
screen.  It was eventually tracked down to the ASIC being unresponsive after
the first power-on.  Writes to any of the ports it managed (palette, border,
paging, etc.) had no effect, and reads from them always returned zero.

Adding a delay to the start of my test ROM cured it, and a further test to
measure the unresponsive period showed it was always around 49ms.  It may
explain the reason for the loop in BC at the start of the real SAM ROM,
though Andy Wright didn't remember quite why it was needed.  The
pre-production SAM ROMs we got from Simon Goodwin lack the BC delay, so they
might not work on modern hardware.  I changed it to be optional in SimCoupe
after Colin reported at least one of his SAMs wasn't affected by it - I've
no idea why it would only affect some machines.

On the subject of SAM quirks, don't miss the lower border effect in Andrew
Collier's Fred 65 menu
(ftp://ftp.nvg.ntnu.no/pub/sam-coupe/disks/demos/MNEMOtech/MnemotechMenu65.z
ip).  Expand the view size in SimCoupe using View - Border Size - Large
(TV-visible), and look under the main scroller...

Si


RE: SimCoupe 1.0 released

2006-07-24 Thread Simon Owen
Chris Pile wrote:
 SimCoupé has to be one of the best and most complete 8-bit 
 home computer emulators currently available.

Cheers!  The 1.0 release aimed for solid emulation accuracy across a
selection of platforms, which is pretty much there now.  Next I'd like to
add more features, many of which have been on hold for fear of delaying the
release even further.  These include tape support, input recording, movie
recording, save states, variable-speed emulation, etc.  I'd also like to
separate the video generation from the cpu+sound emulation, to make it much
more stutter resistant.  Any other requests?

Welcome back Chris :-)

Si


Re: SimCoupe 1.0 released

2006-07-24 Thread Chris Pile
 Simon Owen wrote:
 Simon Cooke wrote:
  Interesting... Defender uses HPEN/LPEN... any idea how it 
  uses it?
 
 It uses HPEN monitoring to track whether it's running late with the current
 frame.  I believe it still expects to be over the main screen area after
 completing certain tasks, and if it's into the border it runs straight into
 the next frame without waiting for the frame interrupt to be signalled in
 the status port.  The game uses the stack for lots of the drawing
 code/lists, so runs with interrupts disabled at all times [you can confirm
 that in the SimCoupe debugger by pressing U for 'execute until', and
 entering 'ei' for the expression - the breakpoint will trigger next time
 interrupts are enabled, which never happens].

Simon's explanation is correct.  I will expand (from memory!) why I used this 
method:

As we all know, the SAM is *seriously* underpowered.  To ensure Defender ran at 
a
constant (99.9% of the time!) 50-fps, all available horsepower needed to be 
squeezed
from the old Z80!  Often the fastest way to shunt data around is via the stack, 
so I
used the stack to dump/erase sprites and also used a stack-based linked list 
for the
world entities.  The landscape also uses a stack-based dumper, this pops off a 
value
which is added to the current landscape pixel position, moving the position 
either up,
down or up/right, down/right.  The mini-landscape used in the scanner is 
processed
in a similar way.  Even the 16 background stars are processed using a 
stack-based
routine!  Couple this with plenty of code unrolling, in-lining of graphics data 
and also
screen-line interleaving of sprite dumping the game holds on to the magic 
50-fps.

With so much stack activity occurring, often in crucial data areas, any 
unexpected
interrupts would be a disaster.  So Defender runs a constant DI state.  This is 
fine,
but introduces the problem of frame-syncing via the v-blank interrupt.  Because 
of
the DI state it is not possible for Defender to trap the v-blank interrupt.  
Instead, a
simple polling loop on the status port has to be used.  Again, this is fine if 
you can
complete all in-game processing before the next v-blank.  Defender does (just!) 
for
99.9% of the time.  This is where the problem lies.  If you miss the v-blank, 
but you
still wait in the status polling loop after all in-game processing, you 
effectively see
the next v-blank and not the one you really wanted to see, because you missed 
it!
This has the effect of dropping the game to 25-fps visually, and halves the 
speed of
all sound effects.  This is so very obvious to both eye and ear!!!  
Unacceptable!

As Defender only just misses the frame v-blank when things are hectic on-screen
it was totally unforgivable to allow the game to stutter to half its speed, 
ruining both
the game and its playability.  The solution was not to wait if we had missed a 
v-blank,
but simply continue processing the next game-loop as if we had just seen a 
v-blank.
This is simple if you can set a flag on a v-blank interrupt.  In Defender's 
case this is
not possible, so an alternative method for detecting missed v-blanks was used.

Enter HPEN!  Put simply, I read the HPEN value after processing approximately 
50%
of the in-game functions (50% *never* misses v-blank) and then read it again 
after all
in-game processing is done.  Then a few calculations determine if we missed the 
last
v-blank.  If so, then don't wait for a v-blank and simply blast into the next 
game loop.
The effect is a slight visual stutter on missed frames, and no real change in 
the sound
effects.  100% preferable to the 25-fps visual drop and audible slowdown of all 
effects!

In fact, the visual stutter is almost exactly the same as the real Defender 
machine
when it, too, misses frames.  The exception being that SAM Defender doesn't 
bother
hyperspacing entities off-screen on missed frames, which the real Defender 
does
when it trys to claw back some precious CPU time!!  ;-)

Job done!  :-)

Chris.