Jump to content
IGNORED

how players are set internally


kisrael

Recommended Posts

I was toying around trying to make a clock in bB (see below for the old font I was going to use) and realized I was running out of time (ironically). I guess I could try doinking around with vblank but as I was thinking about optimizations, I started trying to visualize what bB was doing for player graphics... (basically I started thinking, wait, why wouldn't a tall player take up all the ram) - I guess when you set player0: that's setting a pointer into the definition of ROM that the kernel then reads...

 

anway, I'm still not sure if the Playfield clock I was thinking of is going to be feasible (I was thinking about making it a sidebar inside another animation) setting "that many" pixels adds up! 

 

smallpixelfont.png

Link to comment
Share on other sites


I don't think you're describing what you want very well


Here's a 2 digit count down timer that uses player0 in RAM

Pressing joy0fire resets the counter to 100 and it proceeds to count down by seconds to 00

You could put the numbers in ROM and it would be faster and save the four variables it uses

It would be 400 bytes of ROM for 100 numbers

 

  dim time = t.s
  dim d0 = temp2
  dim d1 = temp3

  COLUPF = $2C

  player0x = 80 : player0y = 44

  player0height = 4
  player0pointerlo = $EA : player0pointerhi = $00  ; set player0pointer to point to variable w
  COLUP0 = $1C
  
  gosub update_player


loop
  COLUP0 = $1C
  drawscreen

  if joy0fire && !f then t = 100 : s = 0   ;  set time to 99
  if joy0fire then f = 255 else f = 0

  if !(t | s) then loop                   ;  if time = 0 skip decremting the timer

  temp1 = time
  time = time - 0.017                     ;  decrement time by ~1/60

  if time > 99 then t = 0 : s = 0         ;  if underflow, set time to 0

  if temp1 = time  then loop              ;  if the decrement didn't change the integer part of time skip updating the display

  temp1 = time / 16
  dec temp1 = (time & $0F) + 0 + dnib[temp1]  ;  convert to bcd

  gosub update_player
  goto loop


update_player
  d0 = temp1 & 15
  d1 = temp1 / 16

  z = l0[d1] & $F0 : z = (l0[d0] & $0F) | z
  y = l1[d1] & $F0 : y = (l1[d0] & $0F) | y
  x = l2[d1] & $F0 : x = (l2[d0] & $0F) | x
  w = l3[d1] & $F0 : w = (l3[d0] & $0F) | w

  return


  data l0
  $77, $22, $77, $77, $55, $77, $33, $77, $77, $77
end

  data l1
  $55, $66, $33, $33, $77, $66, $66, $11, $77, $55
end

  data l2
  $55, $22, $66, $11, $11, $11, $55, $22, $55, $33
end

  data l3
  $77, $22, $77, $77, $11, $66, $77, $22, $77, $66
end

  data dnib
  $00, $16, $32, $48, $64, $80, $96
end

 

count_down_timer.bas count_down_timer.bas.bin

Edited by bogax
goofed up the BCD conversion
Link to comment
Share on other sites

11 hours ago, kisrael said:

I started trying to visualize what bB was doing for player graphics... (basically I started thinking, wait, why wouldn't a tall player take up all the ram) - I guess when you set player0: that's setting a pointer into the definition of ROM that the kernel then reads...

Yeah, that is exactly how setting the players works under the hood. The player graphics is read from a pointer. The pointer points to the portion of ROM with the player definition. When the player graphics are updated, the pointer is updated to point to the area of ROM with the new player graphics. 

  • Like 1
Link to comment
Share on other sites

Thanks for the feedback. Sorry if i was unclear- @Karl G got to the small question I was actually asking :-D

The rest of the ramble was noticing that it sems like there's not time to set to dozens and dozens of playfield pixels in the overscan + vblank... even with a minimal 3x4 font, that mans each charcter is like 8-12 pixels to set, so that's going to eat up a lot of time. (and I suspected that even a "once every minute timing glitch" would result in drift in the atari as a 60 FPS clock....)

Link to comment
Share on other sites

7 hours ago, kisrael said:

Thanks for the feedback. Sorry if i was unclear- @Karl G got to the small question I was actually asking :-D

The rest of the ramble was noticing that it sems like there's not time to set to dozens and dozens of playfield pixels in the overscan + vblank... even with a minimal 3x4 font, that mans each charcter is like 8-12 pixels to set, so that's going to eat up a lot of time. (and I suspected that even a "once every minute timing glitch" would result in drift in the atari as a 60 FPS clock....)

You're probably right that there's not enough time to create a playfield-based display one playfield pixel at a time. Probably you would need to set the playfield variables directly to save cycles, setting multiple pixels at once from stored data.

Link to comment
Share on other sites

I guess the answer then is that every thing is precalculated and kept in ROM

In the case of a player you just set a pointer to a table in ROM

In the case of the playfield the table in ROM gets copied to RAM


But you don't have to do it that way


According to RT's page you get 1675 cycles in vblank
 
If your clock needed to update every frame and you used 4 digits of 8 bytes each ie 128 pixels,
probably not enough time to do a pixel at a time.

If your clock only needs to update once a second it probably is enough time.


The code I posted takes around 150 cycles to compose the two 3 x 4 digits
but it doesn't do a pixel at a time


as for accuracy

I don't think glitching would be a problem
but crystals aren't all that accurate to begin with
a really good crystal would be like +-1 second a day

I calculate the code I posted at 106 seconds for the 100 second count down
I measured it to be 105 in Stella
 

Link to comment
Share on other sites


Here is another clock
It counts up seconds to one hour

It uses a brute force approach with every thing in 300 bytes of tables/ROM

It's more accurate and uses 16 fractional bits (of a second) for the increment

it takes about 110 cycles (not counting drawscreen) for the loop in the worst case, ie rollover to 00 00

  set optimization noinlinedata

  dim frames         = t.s
  dim seconds_lo     = player0pointerlo
  dim seconds_hi     = player0pointerhi
  dim minutes_lo     = player1pointerlo
  dim minutes_hi     = player1pointerhi
  dim seconds        = seconds_hi.seconds_lo
  dim minutes        = minutes_hi.minutes_lo

  def frame_time     = 4.274
  def reset_seconds  = seconds_lo = Pxtlo : seconds_hi = Pxthi
  def reset_minutes  = minutes_lo = Pxtlo : minutes_hi = Pxthi

  const max          = 60 * 5
  const rollover     = Pxtbl + max
  const Pxthi        = >Pxtbl
  const Pxtlo        = <Pxtbl
  const rollover_hi  = >rollover
  const rollover_lo  = <rollover

  player0x = 79 : player1x = 70
  player0y = 40 : player1y = 40
  player0height = 4 : player1height = 4
  reset_seconds
  reset_minutes


loop

  COLUP0 = $1C : COLUP1 = $1C
  drawscreen

  temp1 = t
  frames = frames + frame_time
  if t > temp1 then loop

  seconds = seconds + 0.02
  if seconds_lo <> rollover_lo then loop            ;  the player height and the bytes per page are coprime
                                                    ;  so rollover_lo only occurs once per cycle
  reset_seconds

  minutes = minutes + 0.02
  if minutes_lo <> rollover_lo then loop

  reset_minutes
  goto loop


  data Pxtbl

  $77, $55, $55, $55, $77, $71, $51, $51, $51, $71
  $77, $54, $57, $51, $77, $77, $51, $57, $51, $77
  $71, $51, $57, $55, $75, $77, $51, $57, $54, $77
  $77, $55, $57, $54, $77, $71, $51, $51, $51, $77
  $77, $55, $57, $55, $77, $77, $51, $57, $55, $77
  $17, $15, $15, $15, $17, $11, $11, $11, $11, $11
  $17, $14, $17, $11, $17, $17, $11, $17, $11, $17
  $11, $11, $17, $15, $15, $17, $11, $17, $14, $17
  $17, $15, $17, $14, $17, $11, $11, $11, $11, $17
  $17, $15, $17, $15, $17, $17, $11, $17, $15, $17
  $77, $45, $75, $15, $77, $71, $41, $71, $11, $71
  $77, $44, $77, $11, $77, $77, $41, $77, $11, $77
  $71, $41, $77, $15, $75, $77, $41, $77, $14, $77
  $77, $45, $77, $14, $77, $71, $41, $71, $11, $77
  $77, $45, $77, $15, $77, $77, $41, $77, $15, $77
  $77, $15, $75, $15, $77, $71, $11, $71, $11, $71
  $77, $14, $77, $11, $77, $77, $11, $77, $11, $77
  $71, $11, $77, $15, $75, $77, $11, $77, $14, $77
  $77, $15, $77, $14, $77, $71, $11, $71, $11, $77
  $77, $15, $77, $15, $77, $77, $11, $77, $15, $77
  $17, $15, $75, $55, $57, $11, $11, $71, $51, $51
  $17, $14, $77, $51, $57, $17, $11, $77, $51, $57
  $11, $11, $77, $55, $55, $17, $11, $77, $54, $57
  $17, $15, $77, $54, $57, $11, $11, $71, $51, $57
  $17, $15, $77, $55, $57, $17, $11, $77, $55, $57
  $77, $15, $75, $45, $77, $71, $11, $71, $41, $71
  $77, $14, $77, $41, $77, $77, $11, $77, $41, $77
  $71, $11, $77, $45, $75, $77, $11, $77, $44, $77
  $77, $15, $77, $44, $77, $71, $11, $71, $41, $77
  $77, $15, $77, $45, $77, $77, $11, $77, $45, $77
end

 

 

 

hour_clock.bas hour_clock.bas.bin

Edited by bogax
tweaked the frame_time
Link to comment
Share on other sites


I realized I should be doing an increment or a reset of seconds/minutes, not both
since I'm going for speed

And now the table needs padding to page align

Shaves 36 cycles so worst case is ~80 cycles


  set optimization noinlinedata

  dim frames         = t.s
  dim seconds_lo     = player0pointerlo
  dim seconds_hi     = player0pointerhi
  dim minutes_lo     = player1pointerlo
  dim minutes_hi     = player1pointerhi
  dim seconds        = seconds_hi.seconds_lo
  dim minutes        = minutes_hi.minutes_lo

  def frame_time     = 4.274
  def reset_seconds  = seconds_lo = Pxtlo : seconds_hi = Pxthi
  def reset_minutes  = minutes_lo = Pxtlo : minutes_hi = Pxthi
  def inc_seconds    = seconds = seconds + 0.02
  def inc_minutes    = minutes = minutes + 0.02


  const max          = 59 * 5
  const rollover     = Pxtbl + max
  const Pxthi        = >Pxtbl
  const Pxtlo        = <Pxtbl
  const rollover_hi  = >rollover
  const rollover_lo  = <rollover

  player0x = 79 : player1x = 70
  player0y = 40 : player1y = 40
  player0height = 4 : player1height = 4
  reset_seconds
  reset_minutes


loop

  COLUP0 = $1C : COLUP1 = $1C
  drawscreen

  temp1 = t
  frames = frames + frame_time
  if t > temp1 then loop

  if seconds_lo <> rollover_lo then inc_seconds : goto loop   ;  the player height and the bytes per page are coprime
                                                              ;  so rollover_lo only occurs once per cycle
  reset_seconds

  if minutes_lo <> rollover_lo then inc_minutes : goto loop

  reset_minutes

  goto loop

  data table_padding                                          ;  padding to align player definitions with a page boundary
  $00
end

  data Pxtbl
  $77, $55, $55, $55, $77, $71, $51, $51, $51, $71
  $77, $54, $57, $51, $77, $77, $51, $57, $51, $77
  $71, $51, $57, $55, $75, $77, $51, $57, $54, $77
  $77, $55, $57, $54, $77, $71, $51, $51, $51, $77
  $77, $55, $57, $55, $77, $77, $51, $57, $55, $77
  $17, $15, $15, $15, $17, $11, $11, $11, $11, $11
  $17, $14, $17, $11, $17, $17, $11, $17, $11, $17
  $11, $11, $17, $15, $15, $17, $11, $17, $14, $17
  $17, $15, $17, $14, $17, $11, $11, $11, $11, $17
  $17, $15, $17, $15, $17, $17, $11, $17, $15, $17
  $77, $45, $75, $15, $77, $71, $41, $71, $11, $71
  $77, $44, $77, $11, $77, $77, $41, $77, $11, $77
  $71, $41, $77, $15, $75, $77, $41, $77, $14, $77
  $77, $45, $77, $14, $77, $71, $41, $71, $11, $77
  $77, $45, $77, $15, $77, $77, $41, $77, $15, $77
  $77, $15, $75, $15, $77, $71, $11, $71, $11, $71
  $77, $14, $77, $11, $77, $77, $11, $77, $11, $77
  $71, $11, $77, $15, $75, $77, $11, $77, $14, $77
  $77, $15, $77, $14, $77, $71, $11, $71, $11, $77
  $77, $15, $77, $15, $77, $77, $11, $77, $15, $77
  $17, $15, $75, $55, $57, $11, $11, $71, $51, $51
  $17, $14, $77, $51, $57, $17, $11, $77, $51, $57
  $11, $11, $77, $55, $55, $17, $11, $77, $54, $57
  $17, $15, $77, $54, $57, $11, $11, $71, $51, $57
  $17, $15, $77, $55, $57, $17, $11, $77, $55, $57
  $77, $15, $75, $45, $77, $71, $11, $71, $41, $71
  $77, $14, $77, $41, $77, $77, $11, $77, $41, $77
  $71, $11, $77, $45, $75, $77, $11, $77, $44, $77
  $77, $15, $77, $44, $77, $71, $11, $71, $41, $77
  $77, $15, $77, $45, $77, $77, $11, $77, $45, $77
end

hour_clock_02.bas hour_clock_02.bas.bin

Edited by bogax
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...