Jump to content
IGNORED

PAL/NTSC detection proposal.


Wilheim

Recommended Posts

Hi, everyone!

 

Due that by this time we have a lot of NTSC and PAL users, and increasingly the coders are supporting both formats, I would like to discuss something about it.

 

Currently, the majority of the programs that adjust PAL/NTSC timers are based on detecting the PAL address ($D014) on the GTIA, then if its NTSC or PAL, adjust the timers and colors if necessary. That would work for about 99% of the Atari 8-bit machines, but unfortunately it doesn't work, for example, to NTSC computers that the ANTIC is swapped from NTSC to PAL. The timers are adjusted for NTSC but running at a 50 Hz screen rate.

 

Because of that, I would like to propose a standard to adjust timers and/or colors.

 

1.- Detecting ANTIC instead of GTIA for NTSC/PAL timing.

2.- Using PAL address of the GTIA to adjust colors.

 

According to the XL/XE memory map from Mapping the Atari, the address $62 is used for PAL/NTSC timing. Maybe we could use that address for that purpose and modifying it when detecting the ANTIC type.

 

Based on these principles, I would like to share a small routine to detect if the ANTIC is PAL or NTSC. It's just an example that writes on screen if the ANTIC is NTSC or not. The routine just takes the maximum scanline detected by VCOUNT. If it's less than 135, then the ANTIC is NTSC. Otherwise, is PAL.

 

I will appreciate any feedback about it, as well as any suggestion to improve this proposal.

 

Regards!

paltest-v2.asm

Edited by Wilheim
Relocating attached file
  • Like 3
  • Thanks 1
Link to comment
Share on other sites

We discussed this some years back and came to the same conclusion - the scanline method.

It works well for an initial decision but we have the problem of emulation where it can be changed on the fly and it's not really practical to check the max scanline count every frame.

 

The PAL register method is good in that you can easily take the value and manipulate it with a couple of extra instructions to create an index.

 

SECAM - There isn't an easy way to detect it.  The one difference with SECAM is that since multiple pins were reassigned for the video output, there's only a single TRIG input which is fed each scanline by a shift register.

As such, I'd propose an detection method:

- get the user to press the joystick fire button a few times (this could be part of a skip intro sequence before entering the game)

- on SECAM the TRIG value should only change at an early part of the scanline which should be the same every time. 

- have your program wait for TRIG=0 while in a loop, hitting WSYNC and counting up an index register so we have an approximate scanline hpos.

- if the TRIG transitions are all occurring at the same index value then we're likely running on SECAM.

 

 

Edited by Rybags
Link to comment
Share on other sites

@R0ger: Two issues:

1. I'm not sure colors are the same in PAL and SECAM. My observation is that vertical scroll by one scanline changes colour on SECAM, although doesn't it on PAL (maybe it's connected with LCD monitor I've used - LG FLATRON M1917A; I haven't tested it on CRT yet).

2. Let's say that you need to know exact frequency of CPU, because you need to generate exact 1 kHz wave (there is no possibility of manual tuning). How to do this without detection of CPU speed (TV system in this case, because all I/O devices are clocked by the same frequency as CPU)?

They're just theoretical examples, but knowledge about TV system can be used to correction of game colors (once you develop your game) or when you use Atari as audio device playing unisono with other devices of different kind and clocked by completelly different frequency.

Link to comment
Share on other sites

I've never seen a Secam system for real but would guess the colours are different.

The CPU speed - that's one thing we probably can't deduce for sure since you could mix/match Antic and GTIA with foreign master clocks - I should think the difference would be tolerated by most TVs.

I'm not aware of any music though that caters for clock speed differences WRT it's note playback, only stuff that always plays at ~ 50 Hz by skipping every 6th frame if the system is at the NTSC framerate.

Edited by Rybags
Link to comment
Share on other sites

Hi,

What should be changed in the end to do something like loading PAL.xex or NTSC.xex accordingly?:

mensaje_pal
//	.by "PAL!!"
	.by $9b

	opt h-
	ins 'PAL.xex'
	opt h+	

mensaje_ntsc
// 	.by "NTSC!!"
	.by $9b

	opt h-
	ins 'NTSC.xex'
	opt h+

max	.byte 0

.endp

	run init

 

Edited by tane
Link to comment
Share on other sites

@tane, that would be overkill as 99% of the code and data is going to be the same 

 

To the most part I've found the simple PAL register check to be fine but would agree that the scanline check is better due to machines that can handle switchable customer chips and clocks.

 

Where needed you can set variables appropriately, e.g. for the Doom-Fire demo I used this: (DETECT = $D014)

 

    .proc SetColours
    LDA DETECT ; reads PAL/NTSC
    AND #2
    BEQ @+
    LDA #$10
@:  STA c0
    CLC
    LDA #0
    STA PCOLR0
    LDA #$30
    ADC c0
    STA PCOLR1
    LDA #$32
    ADC c0
    STA PCOLR2
    LDA #$22
    ADC c0
    STA PCOLR3
    LDA #$24
    ADC c0
    STA COLOR0
    LDA #$26
    ADC c0
    STA COLOR1
    LDA #$28
    ADC c0
    STA COLOR2
    LDA #$EA
    ADC c0
    STA COLOR3
    LDA #$EC
    ADC c0
    STA COLOR4
    ;
    LDA #$80
    STA GPRIOR
    RTS
    .endp

 

For music though this is more tricky, so for a more professional production both a NTSC and a PAL version could be built to same address.

For example, in a MADS built xex you could then use a 'ini' section to load the second to another address, decide if it is needed, copy over the first if it is, then continue the load.

  • Like 1
Link to comment
Share on other sites

2 hours ago, Wrathchild said:

that would be overkill as 99% of the code and data is going to be the same 

Agree and disagree, it depends on the situation. If you're writing from scratch I totally agree not to have duplicates.

 

But for hacks, if the original is for example NTSC and you want to make a PAL version with the "right" colors, it's easy just to make a duplicate, it can be done in a few minutes without disassembling the code, and without a full knowledge of the language. If you're not a good coder in assembler, the first, and also the most professional option, is no way. So, having a NTSC.xex and a PAL.xex, and if the size is small, it's very useful a code to join them in one single file. That's what I'm looking for at this stage.

 

So, regarding the code of the first post, that by the way its publication is very useful, what should be changed to do something like loading PAL.xex or NTSC.xex accordingly?

(first post code: paltest-v2.asm)

 

I did some changes with the following, but no luck.

opt h-
ins 'PAL.xex'
opt h+	

opt h-
ins 'NTSC.xex'
opt h+
Edited by tane
Link to comment
Share on other sites

Not sure what you are trying here, 'ins' includes the binary in the resulting object and so you are copying both into the result binary but without wrapping them with any labels to later relocate them?

 

Going back to a hack of an existing binary, the result is having the two files. But that can be seen as 'being lazy' and can be taken a stage further and a diff of the files produces a delta which can be translated into a form (e.g. table of addresses and values) that can be turned into a small binary that runs through the table and applies the values. That is then injected back into the original binary instead of the 'run' block. Voila, you have a single binary that caters for both platforms.

 

Link to comment
Share on other sites

4 minutes ago, Wrathchild said:

Not sure what you are trying here, 'ins' includes the binary in the resulting object and so you are copying both into the result binary but without wrapping them with any labels to later relocate them?

I'm trying to include both binaries. One should be loaded in a NTSC system, and the other in a PAL system, automatically.

An of course the code is not complete, that's why I'm asking what must be changed /added in the post #8.

 

8 minutes ago, Wrathchild said:

Going back to a hack of an existing binary, the result is having the two files. But that can be seen as 'being lazy' and can be taken a stage further

Is not the best solution, but is a good solution with what is available to do.

If you go to a highway and start asking the driver why you are not driving a car of 300 km/hr of maximum speed, you'll have the same answer: "This is better instead of walking".

 

So what should be added to the code of the post #8 for this "second class, still working" solution?

Link to comment
Share on other sites

5 minutes ago, tane said:

One should be loaded in a NTSC system, and the other in a PAL system, automatically.

You can't do that as (presumably) they occupy the same address

 

15 hours ago, Wrathchild said:

in a MADS built xex you could then use a 'ini' section to load the second to another address, decide if it is needed, copy over the first if it is, then continue the load.

this approach would satisfy that but then this is limiting the size to half of the available memory.

Link to comment
Share on other sites

20 minutes ago, Wrathchild said:

You can't do that as (presumably) they occupy the same address

Ok, thank you. So is not a straightforward approach as I was thinking, just as inserting the binaries in the code.

 

This is the original file I was working on: River Raid (1983)(Activision)(US)[a4].xex , so in order to have a PAL and a NTSC version, with customs colors each, I'll have to do 2 different files (PAL.xex & NTSC.xex), instead of having at the end, 1 file with all together.

Link to comment
Share on other sites

7 hours ago, tane said:

Ok, thank you. So is not a straightforward approach as I was thinking, just as inserting the binaries in the code.

 

This is the original file I was working on: River Raid (1983)(Activision)(US)[a4].xex , so in order to have a PAL and a NTSC version, with customs colors each, I'll have to do 2 different files (PAL.xex & NTSC.xex), instead of having at the end, 1 file with all together.

I think I understand your intention: to have two binaries of the game for PAL or NTSC and run the right one for each case. IIRC, in this case in particular, River Raid detects PAL or NTSC machines at the beginning. The same goes for Pitfall II.

 

By the way, the ATR image of Yoomp! does the PAL/NTSC detection by GTIA. I think it would be interesting to change the detection routine, so the correct version will load.

 

Link to comment
Share on other sites

1 hour ago, Wilheim said:

IIRC, in this case in particular, River Raid detects PAL or NTSC machines at the beginning.

Mmmm..., but then when running in both systems there are different speeds and colors, i.e. there is only one speed and color in the code.

Link to comment
Share on other sites

I tried to use the VCOUNT method in Altirra. Running from a default graphics 0 "blue screen" and loading VCOUNT as the first instruction of an immediate VBLANK routine VCOUNT is $7C regardless of PAL or NTSC being selected for emulation.

 

Any ideas?

Link to comment
Share on other sites

The VBlank interrupt occurs after the normal 240 scanline display which is why you get the same result.

A reliable method is to do compare/load until the new value goes back to positive.

 

e.g.

START  BIT VCOUNT

  BPL START

WAIT1 LDA VCOUNT

  BPL VBOVER

  TAX

  BMI WAIT1

VBOVER CPX #$90

 LDA #0

 ADC #0

 STA PALFLAG

 

It's the best way as there's no possibility of having DLIs in the region where the extra PAL scanlines occur.

Disadvantage is that it's not practical to run every VBlank (in case of emulator on the fly changes).  In such a case a Pokey Timer could be used to minimize the CPU burden but then you're dedicating an audio channel to that task which isn't practical either.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

5 hours ago, Rybags said:

 

Disadvantage is that it's not practical to run every VBlank (in case of emulator on the fly changes).  In such a case a Pokey Timer could be used to minimize the CPU burden but then you're dedicating an audio channel to that task which isn't practical either.

Thanks, it's perfect for me as I only need it during intitialization so it needs to run only once. 

Link to comment
Share on other sites

  • 1 year later...

Some progress with the language. ?

 

// Color and Speed Test for Atari 8-bits

; Results:
;
;         Test           | COLOR.ADDRESS | SPEED.ADDRESS |
; -----------------------|---------------|---------------|
; NTSC-60 (default NTSC) |      00       |      60       |
; NTSC-50                |      00       |      50       |
; PAL-60                 |      01       |      60       |
; PAL-50  (default PAL)  |      01       |      50       |
;
; GTIA ($d014): NTSC colors: 0f
;                PAL colors: 01


ORG.ADDRESS = $4000      ;Location of this code
SPEED.ADDRESS = $42ff    ;EDIT: Address of the mark of the speed (50 if PAL, 60 if NTSC)      -> EDIT address
COLOR.ADDRESS = $42fe    ;EDIT: Address of the mark of the color (01 if PAL, 00 if NTSC)      -> EDIT address
vcount =$d40b		         ;vertical line counter

  org ORG.ADDRESS
.proc paltest
start

loop1
  lda vcount
  cmp #100
  bcc loop1             //Wait till scanline 200
  sta max
loop2
  lda vcount
  cmp #10
  bmi loop2.fin
  cmp max
  bmi loop2
  sta max
  bpl loop2
loop2.fin	
  ldx #$60              ; 60 = NTSC default
  lda max
  cmp #135
  bmi ntsc.test
  ldx #$50              ; 50 = PAL default
ntsc.test
  stx SPEED.ADDRESS

  lda $d014             ; GTIA (color)
  cmp #$01              ; 01=PAL, 0f=NTSC
  beq it.is.color.pal
  lda #$00              ; 00=NTSC
  sta COLOR.ADDRESS
  rts
it.is.color.pal
  lda #$01              ; 01=PAL
  sta COLOR.ADDRESS
  rts
max .byte 0
.endp
  ini ORG.ADDRESS

 

  • Like 1
Link to comment
Share on other sites

On 2/27/2020 at 11:27 PM, Rybags said:

It works well for an initial decision but we have the problem of emulation where it can be changed on the fly and it's not really practical to check the max scanline count every frame.

 

I think the games should be made to work as well as possible on real machines.  No one expects emulation to be perfect, and reloading a game after an emulator change takes 2 secs.

 

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