Jump to content
IGNORED

Minidig Updates


Paul Slocum

Recommended Posts

Anybody have any suggestions for updates to my Minidig website? New disassemblies that I don't have? New programming tricks? Tools, documentation, or other links I'm missing?

 

I think I'll add that wavy text trick. Definitely need a link to 2600 Basic.

 

http://www.qotile.net/minidig/

 

Also, if anyone has anything to add to my advanced 2600 programming guide, feel free to write it up.

 

http://www.qotile.net/minidig/docs/2600_ad..._prog_guide.txt

 

-paul

Edited by Paul Slocum
Link to comment
Share on other sites

Anybody have any suggestions for updates to my Minidig website?  New disassemblies that I don't have?  New programming tricks?  Tools, documentation, or other links I'm missing?

That's cool that you're going to update this. I find it invaluable.

 

I think you have these but here are a couple of disassemblies I had done. Hopefully you can grab SWTAG from [stella] because I don't have it on this PC.

disassemblies.zip

Link to comment
Share on other sites

Also, if anyone has anything to add to my advanced 2600 programming guide, feel free to write it up.

 

http://www.qotile.net/minidig/docs/2600_ad..._prog_guide.txt

I'll say, as well, that the minidig is fantastic - I use it often.

 

Some things you might add to the advanced programming guide are T Jentzsch's SwitchDraw routine, Manuel's FlipDraw, and this method of drawing variable-height balls/missiles:

   lda BallHeight
  dcp BallY
  sbc BallAdjuster  ;BallAdjuster = BallHeight - 2
  sta ENABL

14 cycles for that. If BallHeight is a constant then you can modify it and get down to 12 cycles.

 

Also, the 'jsr' trick of positioning two objects right next to each other on a single scanline (see Manuel's Worm Whomper demo for a fun example of how this can be used).

 

Also, for the paddle-reading section, I think the routine should be:

   lda INPT0              ;3
  bpl paddles1           ;2 or 3
  .byte $2c              ;1    bit abs opcode
paddles1:
  sty padVal1            ;3

Instead of "bmi" as it is written currently.

 

Also, in the time-wasting section, a way to waste 11 cycles lists this:

   sta $8000,X
  lda ($80,X)

The $8000 should be changed to $7000 or some other odd-numbered 4K block, since $8000-$80FF are mirrors of TIA registers and the RIOT RAM, so writing there will have potentially odd results.

 

Another also: maybe add the documents found in this post by Kroko to the minidig.

 

Finally, the information in this post by Eckhard S would be nice to add:

A RESP will set the objects position to the pixel at which the write happens. But the TIA needs a couple of cycles from the pixel clock to set up the actual output. Therefore all objects will be delayed by a couple of pixels.

 

The offset is 4 pixels for missiles and the ball, 5 pixels for single-width players, and 6 pixels for double- and quadrouple-width players. You need to take these offsets into account when calculating the position of an object.

Link to comment
Share on other sites

Also, the 'jsr' trick of positioning two objects right next to each other on a single scanline (see Manuel's Worm Whomper demo for a fun example of how this can be used).

923266[/snapback]

We could slightly modify the advanced programming guide for this trick. How does this look?

 

Using BRK or JSR with RESXX

--------------------------------------------------------------

Eckhard Stolberg, with contribution by Zach Matley

==============================================================

 

 

Pole Position puts the stack pointer over the RESxx registers and then does a

BRK. There are three write cycles in a BRK instruction, so the three position

registers for the objects that make up the road in PP, get accessed in three

consecutive cycles. This is how PP managed to get the road to meet so closely in

the horizon. The JSR instruction can put two objects close together in a similar fashion.

Edited by Zach
Link to comment
Share on other sites

How about adding the alternate bankswitching scheme that was posted here...http://www.atariage.com/forums/viewtopic.php?t=57849&start=0?

 

This is what I have in my modified version of your advanced 2600 programming guide

==============================================================

Alternate F8 Bankswitch scheme added 03/09/2005

from batari in the AtariAge thread

http://www.atariage.com/forums/viewtopic.php?t=57849&start=0

==============================================================

Weirdest thing... I had a dream about this last night. IF you want to use RAM to

set up custom entry points, you can manipulate the stack. Then you use just two

bytes of temp RAM that you would probably be using for the stack anyway. All

you need to do is put an RTS in the right place.

 

example:

 

Bank 0:

FFF8: RTS

 

Bank 1:

FFF7: RTS

 

Now recall from earlier posts, Kroko pointed out that an RTS accesses the next

byte and throws the value away, but the side effect is that it will switch

banks since we're accessing FFF8 and FFF9. But since it's an RTS, we can also

use it set up an entry point using stack pushes and "return" there. To call the

routine, do something like this:

 

LDA #>ROUTINE

PHA

LDA #<ROUTINE-1 ; a JSR stores low byte -1 (as I understand)

PHA

JMP $FFFx ;x=8 if currently in bank 0, 7 in bank 1.

 

I haven't tested this - just at the idea phase, but it should work in theory

unless I've made a mistake somewhere. The only limitation I see is that ROUTINE

can't be on an address ending in 00.

 

==========================

change tested with A-Team

==========================

bank 0:

      LDA    #$F6    ;2

      PHA    ;2

      LDA    #$68; return address -1 from above

      PHA    ;2

      JMP $FFF8

;then  18 NOPs to fill in replaced code

 

bank 1:

      LDA    #$B0    ;2

      PHA    ;2

      LDA    #$27; return address -1

      PHA    ;2

      JMP $FFF7

 

;then 18 NOPs

 

Oh, and Andrew's post about moving 1/n pixels...

==============================================================

==============================================================

Moving objects 1/n pixels

--------------------------------------------------------------

Andrew Davie

==============================================================

==============================================================

 

I asked a question about fractional delay on [stella] and this

was Andrew's response

(Re: Moving objects 1/n pixels (was Re: RE: [stella] Climber5

source and binary)

Date: Sat, 19 Apr 2003 01:35:57 +1000

 

Conceptually, yes.  Visually on the screen it is at pixel 15.  But as far as

your program is concerned, it's at pixel 15.5.

Let's say it was moving 1/2 a pixel per frame.  so the very next frame it

would visually shift to pixel 16.  The frame after that it would still

visually be at pixel 16, but as far as your program is concerned it is at

pixel 16.5.

 

The point of this is that you could, for example, have two object moving at

very slightly different speeds (say, 1/20th of a pixel per frame, and 1/21st

of a pixel per frame).  After 21 frames they would be visually separated by

exactly 1 pixel.  You have excellent "resolution" on movement - and

adjustment for various TV frame-rates, or game features such as

acceleration/decelleration, etc., are as simple as adjusting the increment

you add to the position per frame.  You don't need to play around with delay

counters or anything.

 

It's just a shift in thinking.  Rather than thinking "actually moves one

pixel every n frames" you are conceptually (and this is closer to how

objects actually move anyway) moving the object 1/n pixels every frame.

 

To represent the fractional movement, it's just a matter, as I said, of

having 2 bytes per coordinate.

 

xCoord ds 2

 

    lda #0

    sta xCoord            ; fractional

    lda #15

    sta xCoord+1        ; integer

 

the object is now at pixel position 15.0

 

    clc

    lda xCoord

    adc #128

    sta xCoord

    lda xCoord+1

    adc #0

    sta xCoord+1

 

the object is now at pixel position 15.5

Note: the draw only cares about the integer position - that is, "xCoord+1" -

which is still 15

 

    clc

    lda xCoord

    adc #128

    sta xCoord

    lda xCoord+1

    adc #0

    sta xCoord+1

 

We've just added another half a pixel movement.

This time the carry will be set after the first add to xCoord, so we end up

adding one more to xCoord+1

ie: the visual part of our coordinate has adjusted from 15 to 16

 

Adjusting things from NTSC to PAL is as simple as changing the "movement"

you add to the coordinates every frame.  And you get much finer control than

"delay n frames".  For example, you can set the object to move one pixel

every 3.2 frames - just set the increment to 256/3.2 (=80 exactly) - doing

that with a "delay n frames" system would be rather tricky.

 

Let's say you wanted an object to move 20 pixels per second.  On NTSC we

have 60 frames/second, so the fractional increment is 20/60 = 1/3 of a pixel

per frame (so the increment is 256/3 = 85 (close enough)).  On PAL we have

50 frames/second, so the fractional increment is 20/50 = 2/5 of a pixel per

frame (so the increment is 256*2/5 = 102 (close enough)).  So we use exactly

the same code in each case - we just use different movement increments for

PAL or NTSC.

 

Hope that's clearer.

 

Cheers

A

Link to comment
Share on other sites

Thanks guys.  I'll put those updates in soon.

 

-paul

923859[/snapback]

What I'd like to see is more detailed descriptions of how to use skip/switch/flipdraw. I know how to use them now, but it wasn't very obvious at first based on the descriptions and I had to look at others' code to see everything in the proper context. And still it took me a while to figure out how it worked.

 

And not just the kernel code should be explained, but also how to set the pointers properly for skip/switchdraw. This wasn't obvious (at least to me.)

Link to comment
Share on other sites

I am no longer 100% sure that the above alternate F8 bankswitching will work

on all F8 boards that are available.

 

When we discussed this, I was only taking into account the way the F8 switching is done on the Krokodile Cartridge.

 

Now that I have thought about how to do a bankswitching board without clocked logic, I have doubts, that the above method really always works. I also had a look at the schematics from existing discrete F8 boards.

 

Here is the problem:

 

The Krokodile detects a change of adress lines, but a F8 board does not (necessarily) do that.

 

A F8 board could detect a hit of the hotspot area. If the hotspot area is hit, it loads the external capacitor and waits until the voltage has reached the "high" level. If the hotspot area is still hit after this delay, it clocks A0 into the bank register.

 

So if we hit the hotspot area twice in a row, we will most likely get only one rising edge of the "hotspot" detector which means we are only switching once.

 

I have no idea, how all the F8 boards out there work, but at least I fear there is a great risk, that the above code will not work on some of them.

 

The above method would only work on F8 boards, that can also clock A0 into the bankswitching register after a change of A0 within the hotspot area. Unfortunately I have not seen a schematic yet, that does it like that.

 

Has anybody tested the alternate F8 method on different F8 boards, yet ?

 

Armin

Link to comment
Share on other sites

The Krokodile detects a change of adress lines, but a F8 board does not (necessarily) do that.

 

I would almost wager that, given two consecutive addresses to hotspots, some boards would always react to the former and ignore the latter, some would always react to the latter, and some would behave inconsistently. I would also expect that some would always return the data from the old bank, some would always return data from the new bank, and some would be inconsistent, sometimes returning something else entirely.

 

Certainly I could design discrete-hardware boards to yield any of those results, and given the variety of approaches I've seen to even something as simple as inverting /CS, I would not be surprised if different devices use different approaches.

Link to comment
Share on other sites

I am no longer 100% sure that the above alternate F8 bankswitching will work

on all F8 boards that are available.

 

When we discussed this, I was only taking into account the way the F8 switching is done on the Krokodile Cartridge.

 

Now that I have thought about how to do a bankswitching board without clocked logic, I have doubts, that the above method really always works. I also had a look at the schematics from existing discrete F8 boards.

 

Here is the problem:

 

The Krokodile detects a change of adress lines, but a F8 board does not (necessarily) do that.

 

A F8 board could detect a hit of the hotspot area. If the hotspot area is hit, it loads the external capacitor and waits until the voltage has reached the "high" level. If the hotspot area is still hit after this delay, it clocks A0 into the bank register.

 

So if we hit the hotspot area twice in a row, we will most likely get only one rising edge of the "hotspot" detector which means we are only switching once.

 

I have no idea, how all the F8 boards out there work, but at least I fear there is a great risk, that the above code will not work on some of them.

 

The above method would only work on F8 boards, that can also clock A0 into the bankswitching register after a change of A0 within the hotspot area. Unfortunately I have not seen a schematic yet, that does it like that.

 

Has anybody tested the alternate F8 method on different F8 boards, yet ?

 

Armin

924000[/snapback]

I've had some problems with the trick when a RTS is put at a BS location, like one at FFF8 which is intended to switch to bank 1 via FFF9. I'm not sure yet is this is due to the problem you described above or to the attempt to read from a BS hotspot which could give the wrong byte back.

 

But I still think that an RTS at FFF7 should work in all cases. I say this because an FFF7 should not trigger the hardware since they would need to be wired to A3, and at FFF7, A3 is 0 and FFF8-9 it is 1.

Link to comment
Share on other sites

I am no longer 100% sure that the above alternate F8 bankswitching will work on all F8 boards that are available.

I doubt it, because I once did a 16K hack of Battlezone ("TC") using about the same trick which turned out not to work on real hardware.

Link to comment
Share on other sites

I am no longer 100% sure that the above alternate F8 bankswitching will work on all F8 boards that are available.

I doubt it, because I once did a 16K hack of Battlezone ("TC") using about the same trick which turned out not to work on real hardware.

924279[/snapback]

I think I remember your post and IIRC was regarding indexing, like LDA FFF6,x where x is the bank. I can see how that wouldn't work if it's due to what Kroko described.

 

However, I think indexing is very likely to work if you did something like FF00,x where x=F6-F9.

Link to comment
Share on other sites

I think I remember your post and IIRC was regarding indexing, like LDA FFF6,x where x is the bank.

No, it was exceuting code ON the hotspots.

924302[/snapback]

Oh... But didn't you say once that you had problems with indexing the hotspots?

 

Either way, I've also been unsuccessful trying to execute code in hotspots, even when the same byte is copied to every bank.

Link to comment
Share on other sites

First I gotta say that I really appreciate the Mini-Dig. It's an invaluable resource. I've been a [stella] lurker for a while now and I've even coded some demo stuff just to get my feet wet. I just have a few Mini-Dig suggestions...

 

What I'd like to see is more detailed descriptions of how to use skip/switch/flipdraw.  I know how to use them now, but it wasn't very obvious at first based on the descriptions and I had to look at others' code to see everything in the proper context.  And still it took me a while to figure out how it worked.

 

And not just the kernel code should be explained, but also how to set the pointers properly for skip/switchdraw.  This wasn't obvious (at least to me.)

923965[/snapback]

 

I second this. Maybe submissions to the mini-dig can be sent to the original authors (or volunteers) for some heavy commenting. Even a brief comment before each code block like "Do this during variable inits" or "This goes in the kernel" or "Do this during overscan" etc. would help a great deal for beginners.

 

Brief comments describing variables to the point where there's no second-guessing would also be great.

 

Lastly, a brief summary of how and why something works would be fantastic. For example, the line in SkipDraw:

 

bcx .skipDraw

 

:?: When/why does the math clear the carry flag?

 

I'm the type of person that likes to figure stuff out for himself but some things just elude me entirely.

 

Also, I'm a little embarrassed to admit it now but I searched all over the [stella] archives and 6502.org looking for the 'bcx' opcode, not figuring out until a little trial and error that it can mean either 'bcc' or 'bcs'. D'oh! :ponder:

 

One more thing: is there room in the Mini-Dig for an explanation of how to use pointers? I did a write-up in HTML on my site but I can convert it to plain text if it's submissible. Here's the link for review...

 

http://home.earthlink.net/~jjrein/stella/a...s/pointers.html

 

I also did a quick write-up of how to use pointer tables...

 

http://home.earthlink.net/~jjrein/stella/a...ntertables.html

 

Just my 2 bytes...

 

- Jason

Link to comment
Share on other sites

I also did a quick write-up of how to use pointer tables...

 

http://home.earthlink.net/~jjrein/stella/a...ntertables.html

Those are pretty good documents, but I think you cut 'n' pasted the wrong code into that one.

 

This:

Definition…

   ldx #0	; <-index into chosen data set (0<=x<6 in this case)
   lda #<GreatBytes; A = LSB of Set_x' address
   sta pointer
   lda #>GreatBytes; A = MSB of Set_x' address
   sta pointer+1

Should be this, I think:

Definition…

   ldx #0	; <-index into chosen data set (0<=x<6 in this case)
   lda LoPtrTable,X; A = LSB of Set_x' address
   sta pointer
   lda HiPtrTable,X; A = MSB of Set_x' address
   sta pointer+1

Link to comment
Share on other sites

Those are pretty good documents, but I think you cut 'n' pasted the wrong code into that one.

 

Whoops! I'll fix it when I get off work later. Thanks for catching that. :)

 

- Jason

 

EDIT: Fixed!

Edited by Emehr
Link to comment
Share on other sites

  • 3 weeks later...

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...