Jump to content
IGNORED

INTIM issue in Berzerk?


DavidEth

Recommended Posts

Looking at pitfall.asm, what is the <[sym1 - sym2] syntax? I know < means the lower byte of the value, but why does it use square brackets instead of parentheses?

 

DASM uses square brackets for arithmetic grouping. Ordinary parentheses will also work for arithmetic grouping in some contexts, but will be interpreted as special addressing modes in other contests. I tend to just use square brackets in DASM instructions whether or not it's necessary in any particular context.

 

For example: if FOO is $4321 and BAR is $1234, "JMP [FOO-BAR]" will be regarded as "JMP $30ED", while "JMP (FOO-BAR)" will be assembled as "JMP ($303D)", a different instruction.

 

That makes a lot of sense, thanks for explaining that. I've done a lot of x86 programming in the years between when I did 6502 and now, so it was never an issue because that platform already used square brackets for indirect addressing.

 

Okay, some questions on DCP, LAX, SAX, SBX (the four instructions recommended as being critical on the 2601 blog)

 

(They also mention a two-cycle NOP -- but I thought that was 0xEA already? Is there a different one?)

 

Based on the explanations on http://www.oxyron.de/html/opcodes02.html, DCP is unclear. Should it really be:

 

{adr}:={adr}-1 and then A:=A-{adr}

 

and does A have the old or newly-decremented version of [adr] in it? EDIT - According to a NES page, it computes A-{adr} (the newly decremented value) like a compare and doesn't store the result, just tests the flags.

 

LAX and SAX both seem pretty simple. I assume they take the "usual" number of cycles for a load operation and a store operation?

 

Finally, SBX is nowhere to be found on that page.

-Dave

Edited by DavidEth
Link to comment
Share on other sites

Another minor update. Implemented a bunch of NOP variants, along with LAX and SAX.

 

Also added a four-stage delay to writes to the playfield registers to fix the Halo 2600 title and the ladders in Mountain King. No idea why the delays are really needed, but hey, it works now. The delays run even during HBLANK, otherwise the leftmost edge was getting screwed up.

 

Earlier today I noticed that Berzerk was hanging on startup again (the original reason for this thread) and had to initialize INTIM to a minimum of 3 to get it to not hang. But the good news is that the game appears to work pretty much perfectly now!

 

-Dave

my2600src.zip

Link to comment
Share on other sites

EDIT - According to a NES page, it computes A-{adr} (the newly decremented value) like a compare and doesn't store the result, just tests the flags.

 

LAX and SAX both seem pretty simple. I assume they take the "usual" number of cycles for a load operation and a store operation?

 

Finally, SBX is nowhere to be found on that page.

-Dave

 

I think that's the right meaning for DCP (Decrement and ComPare)

 

SBX:

X=A&X-#imm

 

I think it ignores the carry in the subtraction but sets it the same as SBC

Edited by eshu
Link to comment
Share on other sites

On a side note, I think I'm far enough along to justify picking up some actual 2600 hardware. Obviously I want the Harmony cart, but I'm wondering what I should plug that into?

 

Just buy an old 2600 off of ebay and hope for the best? I've got some old CRT televisions around here so the AV mod isn't too important. Would I be better off trying to track down a 7800?

 

I think I have an old Sega Genesis with some controllers too, those will work in a 2600, right?

 

-Dave

Link to comment
Share on other sites

Another minor update, added support for TigerVision (-T flag on command line) and Parker Brothers (-P flag on command line) ROM bank switching methods.

 

I'm curious how the FE method used by Robot Tank and Decathalon can "detect" a JSR / RTS and bankswitch properly. Only other method still to implement is the M-Network method, but it has some crazy RAM decode.

 

I think for my own stuff, I'll stick to the standard F8/F6 variants and maybe use a superchip.

 

EDIT - Included some compile fixes for non-PC systems, assembler works again.

 

-Dave

my2600src.zip

Edited by DavidEth
Link to comment
Share on other sites

Okay, question about "late HMOVE" processing. When I fixed Halo 2600, I ended up breaking River Raid. If I tweak the offset within the HMOVE adjustment table, I can fix River Raid but then Halo 2600 breaks.

 

So I guess I'm asking, when do people generally hit HMOVE?

 

River Raid hits it on color cycle -68 and cycle 157, meaning both the first and last cycle on a scanline. Ed mentioned that Halo hits it on cycle 74. I think that was a CPU cycle though?

 

So if I understand things correctly, hitting HMOVE at the beginning of the scanline can cause the ugly black borders. So people try to hit it later on (dealing with the fact that it's interpreted strangely) to hide the bars?

 

I started with the table at http://www.bjars.com/resources/hmove.txt, but had to move all the lines marked HBLANK to the top of my table, because I index the 76 entries at (color_cycle + 68) / 3, where color_cycle ranges from -68 to 159. I can't seem to find a consistent bias there that works for both River Raid and Halo 2600.

 

The really tricky bit is that there's a huge discontinuity between the last and first cycles.

 

EDIT - Are there circumstances where hitting HMOVE always works the "documented" way? I think River Raid glitches out when it's trying to position something that is just scrolling onto the screen from the top. So maybe HMOVE always works properly if it's hit when we're in vertical blank? If I put back my old code which always did an HMOVE as a straight "value minus (factor >> 4)" River Raid works again.

 

EDIT 2 - It seems that if HMOVE is hit on the first scanline, I should ignore any compensation factors. Both River Raid and Halo 2600 work.

 

New version attached with both Halo 2600 and River Raid working. Also finally tracked down the gaps in the copyright strings, and it was really mundane -- my repeat counts for duplicated sprites was off by a cycle because they didn't get decremented on the cycle they were refreshed.

 

-Dave

my2600src.zip

Edited by DavidEth
Link to comment
Share on other sites

That HMOVE listing is from some testing that Brad Mott did, and it can be found in the "Atari 2600 Advanced Programming Giode." I didn't like its presentation, so I rearranged it to make it more compact and easier to understand (for me, at least). You can find my version here, and I'm reposting it below for convenience:

 

... 75 04 05 07 08 09 11 12 13 15 16 17 19 20 21 55 56 57 59 60 61 63 64 65 67 68 69 71 72 73
$70 <7 <6 <5 <4 <3 <2 <1  0 >1 >2 >3 >4 >5 >6  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A <B <C <D <E <F
$60 <6 <6 <5 <4 <3 <2 <1  0 >1 >2 >3 >4 >5 >6  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A <B <C <D <E
$50 <5 <5 <5 <4 <3 <2 <1  0 >1 >2 >3 >4 >5 >6  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A <B <C <D
$40 <4 <4 <4 <4 <3 <2 <1  0 >1 >2 >3 >4 >5 >6  0  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A <B <C
$30 <3 <3 <3 <3 <3 <2 <1  0 >1 >2 >3 >4 >5 >6  0  0  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A <B
$20 <2 <2 <2 <2 <2 <2 <1  0 >1 >2 >3 >4 >5 >6  0  0  0  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <A
$10 <1 <1 <1 <1 <1 <1 <1  0 >1 >2 >3 >4 >5 >6  0  0  0  0  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8 <9
$00  0  0  0  0  0  0  0  0 >1 >2 >3 >4 >5 >6  0  0  0  0  0  0  0  0 <1 <2 <3 <4 <5 <6 <7 <8
$F0 >1 >1 >1 >1 >1 >1 >1 >1 >1 >2 >3 >4 >5 >6  0  0  0  0  0  0  0  0  0 <1 <2 <3 <4 <5 <6 <7
$E0 >2 >2 >2 >2 >2 >2 >2 >2 >2 >2 >3 >4 >5 >6  0  0  0  0  0  0  0  0  0  0 <1 <2 <3 <4 <5 <6
$D0 >3 >3 >3 >3 >3 >3 >3 >3 >3 >3 >3 >4 >5 >6  0  0  0  0  0  0  0  0  0  0  0 <1 <2 <3 <4 <5
$C0 >4 >4 >4 >4 >4 >4 >4 >4 >4 >4 >4 >4 >5 >6  0  0  0  0  0  0  0  0  0  0  0  0 <1 <2 <3 <4
$B0 >5 >5 >5 >5 >5 >5 >5 >5 >5 >5 >5 >5 >5 >6  0  0  0  0  0  0  0  0  0  0  0  0  0 <1 <2 <3
$A0 >6 >6 >6 >6 >6 >6 >6 >6 >6 >6 >6 >6 >6 >6  0  0  0  0  0  0  0  0  0  0  0  0  0  0 <1 <2
$90 >7 >7 >7 >7 >7 >7 >7 >7 >7 >7 >7 >7 >7 >7  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 <1
$80 >8 >8 >8 >8 >8 >8 >8 >8 >8 >8 >8 >8 >8 >8  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

The column headings represent machine cycles. Rather than list all 76 machine cycles (numbered 0 to 75), I've listed only the first one where a particular pattern begins in the results. For example, the first column heading is 75 and the second column heading is 04, so that means strobing HMOVE on cycles 75 through 03 (75, 00, 01, 02, or 03) produces the results shown in the first column.

 

The row headings represent the value stored in the HM* registers (HMP0, HMM0, HMP1, etc.). The numbers shown in the "cells" or row/column intersections indicate how much movement will occur, and in which direction. For example, <7 means move left 7 color clocks, and >8 means move right 8 color clocks. Values over 9 are shown as hex digits (<A, <B, etc.).

 

I made this rearranged table to help myself better understand the patterns, because the table from Brad Mott was kind of confusing to me.

 

If you want to convert the machine cycles to your terminology for "color clock," multiply by 3 and subtract 68. That gives what I call "screen position":

 

Machine cycles -- 00 to 75

Color clocks -- 000 to 227

Screen positions -- -68 to 159

 

Michael

Edited by SeaGtGruff
Link to comment
Share on other sites

I read the discussion here: http://www.atariage.com/forums/topic/162520-fine-positioning-not-working/page__view__findpost__p__2006722

 

and it clears up a lot of things for me, thanks. It sounds like people generally hit HMOVE on either:

 

- Cycle 0 (right after a WSYNC) or cycle 75, giving you an eight-pixel black bar.

- Or cycle 73 or 74, which eliminates the black bar but only lets you move the sprite left.

 

-Dave

Link to comment
Share on other sites

Okay, Conquest of Mars had the same lockup on startup problem Berzerk had. It was setting the interval to 64 and doing a series of STA WSYNC / LDA INTIM / BNE TOP checks, and it would skip hitting exactly zero.

 

I hacked around it by nerfing the RIOT behavior of resetting the decrement interval to 1 once INTIM reaches zero, but I suspsect something else must be going wrong here?

 

Conquest of Mars also didn't produce a display because my emulator only resets the raster back to the top when it sees VBLANK D2 go from one to zero, which has worked well on other cartridges.

 

When VSYNC D2 goes from 1->0, I flip the screen buffer and process events. When VBLANK D2 goes from 1->0, I was resetting the emulated raster to the top, but it seems like Conquest only ever writes 0 to VBLANK, is there some special reason for that?

 

(I also have to track down what opcode 0xC7 is, I'm guessing it's DCP)

 

-Dave

Link to comment
Share on other sites

I'm curious how the FE method used by Robot Tank and Decathalon can "detect" a JSR / RTS and bankswitch properly. Only other method still to implement is the M-Network method, but it has some crazy RAM decode.

 

I don't want to hijack the DPC+ thread - so I just wanted to confirm I think I gave the correct answer there - from http://www.qotile.net/minidig/docs/sizes.txt

 

-FE: Used only on two carts (Robot Tank and Decathlon). You select banks

via accesses to the stack. You set the stack pointer to FF, and then a

JSR switches banks one way, while RTS switches you back to the original

bank (both banks are 4K). This allows the programmers to perform

'automatic' bankswitching. All the subroutines are in one bank, while

all the game code is in another. When you perform a JSR; you switch banks

to the bank containg the subroutines. Upon encoutering an RTS, the bank

is switched back to the original calling bank. Pretty spiffy!

 

You might be interested in this as well:

 

-E7: Only M-Network used this scheme. This has to be the most complex

method used in any cart! :-) It allows for the capability of 2K of RAM;

although it doesn't have to be used (in fact, only one cart used it-

Burgertime). This is similar to the 3F type with a few changes. There are

now 8 2K banks, instead of 4. The last 2K in the cart always points to

the last 2K of the ROM image, while the first 2K is selectable. You

access 1FE0 to 1FE6 to select which 2K bank. Note that you cannot select

the last 2K of the ROM image into the lower 2K of the cart! Accessing

1FE7 selects 1K of RAM at 1000-17FF instead of ROM! The 2K of RAM is

broken up into two 1K sections. One 1K section is mapped in at 1000-17FF

if 1FE7 has been accessed. 1000-13FF is the write port, while 1400-17FF

is the read port. The second 1K of RAM appears at 1800-19FF. 1800-18FF

is the write port while 1900-19FF is the read port. You select which

256 byte block appears here by accessing 1FF8 to 1FFB.

Link to comment
Share on other sites

- Or cycle 73 or 74, which eliminates the black bar but only lets you move the sprite left.

 

I think it pushes the sprite to 8 pixels left on the original position, the HMXX values still working, left or right.

The sprite and the background color actually. This why the black line is removed. (The black line is a background color bug).

 

Also there is a hardware bug, if you hit HMOVE less than 24 machine cycles after setting HMxx value, the result will be incorrect.

 

Good luck with your project.

Edited by LS_Dracon
Link to comment
Share on other sites

- Or cycle 73 or 74, which eliminates the black bar but only lets you move the sprite left.

 

I think it pushes the sprite to 8 pixels left on the original position, the HMXX values still working, left or right.

The sprite and the background color actually. This why the black line is removed. (The black line is a background color bug).

 

Also there is a hardware bug, if you hit HMOVE less than 24 machine cycles after setting HMxx value, the result will be incorrect.

This is the 'illegal' HMOVE functionality that I mentioned earlier in the thread. It is independent of the table given above. That is, the values in such a case are a combination of those from the table and another amount, the value of which is somewhat complex to calculate (it depends on several factors). I'd be very interested in seeing an algorithm/solution that incorporates both the table of values, and the additional values from 'illegal' HMOVEs.

Link to comment
Share on other sites

(The black line is a background color bug).

Actually, the black HMOVE bar isn't a bug, it's a deliberate part of the design. Normally the position registers are incremented only during the active portion of the scan line. But if you strobe HMOVE, the TIA will increment the position registers during the horizontal blank by feeding extra pulses to them. The values you've stored in the motion registers will determine how many extra pulses get fed to each position register, although extra pulses will get fed to the position registers *only* during the horizontal blank, so it also makes a difference how close you are to the end of the line when you strobe HMOVE.

 

There is no way to *subtract* pulses from the position registers, so feeding them extra pulses can move the sprites left, but can't move them right. To enable the sprites to move right, strobing HMOVE sets a latch that makes the TIA delay the resetting of HBLANK by 8 color clocks. This effectively subtracts 8 pulses from the position registers, so instead of moving between 15 left and 0 left, the sprite moves between 7 left and 8 right. But again, it also makes a difference how far you are into the HBLANK when you strobe HMOVE, so you might not be able to get the full range of movement.

 

So how does the early HMOVE get rid of the black bars? Strobing HMOVE sets the special HBLANK latch, but the leading edge of HBLANK causes the latch to get reset (to keep the end of HBLANK from being delayed on every subsequent scan line). So if you strobe HMOVE more than 1 cycle before the start of HBLANK, the latch gets set, but then gets cleared again as soon as HBLANK begins, hence there's no extra blanking, and no right motion. If you strobe HMOVE on cycle 75 (1 cycle before HBLANK begins), the latch gets set, but not soon enough for it to get cleared right away.

 

Michael

Link to comment
Share on other sites

Started keeping a proper changelog. Got massively sidetracked improving the assembler so I could hack on more of the example code out there quickly and easily. Not convinced REPEAT/REPEND handling is quite correct yet.

 

		- VDELBL was broken, Pitfall vine works again
		- Assembler improvements: 
			- * and . equate to program counter
			- File inclusion works
			- IFCONST, IFNCONST work
			- Preserves case on everything except opcodes
			- Opcode parsing improved
			- Don't need -a flag any longer, just pass in .asm file
			- No longer has built-in version of VCS.H, but can re-enable with -V flag.
			- .z opcode suffix forces zero page (like .w)
			- MAC / ENDM / SET / EQU now understood.  SET and = can reassign values, EQU cannot.
			- REPEAT / REPEND now understood.
			- local labels work (inherits context from macro invokation line and/or SUBROUTINE)
		- Runtime trace displays effective address and contents of memory when appropriate
		- SDL usage can be completed compiled out
		- Added DCP opcode
		- Messed around with VBLANK/VSYNC handling a bit

my2600src.zip

Link to comment
Share on other sites

I'd be very interested in seeing an algorithm/solution that incorporates both the table of values, and the additional values from 'illegal' HMOVEs.

 

Me too!

It's a bit disapointing when the game run ok in the emulator but in real hardware display this graphic error.

Nothing that cannot be avoided, anyway.

Stella is my favorite 2600 emulator for long time. ;)

Link to comment
Share on other sites

/*
ChangeLog
	28 Sep 2010
		- More refactoring of assembler and debugger
		- Implemented BRK and RTI (BRK was necessary for cave1k)
		- Cleaned up insn decoder, added expected insn counts for clarity, assert they match at runtime
		- REPEAT / REPEND work better now (well, they don't quite nest yet, see dkong.asm)
		- Can write assembler output to a file now.
		- SEG.U turns off initialization, SEG turns it back on
		- ORG and RORG can now be used to generate at least 8k roms (bzone.asm, montezuma.asm). */

 

-Dave

my2600src.zip

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