Jump to content
IGNORED

My Atari XEGS Project


boisy

Recommended Posts

Cool.

 

You can use a store to WSync ($D40A) for a delay, it's the norm when doing most midscreen colour changes.

Although you end up with a mess unless you also do some VBlank processing (NMI).

 

A quick/dirty way to get a static screen with lots of colours is to load from VCOUNT ($D40B) then store to the background ($D01A).

VCount gives the upper 8 bits of the current scanline value.

Link to comment
Share on other sites

OStest3.bin

 

Here's another, this time with screen. There's no character set available so I just pointed to the program itself.

 

 

Source code -

OStest3.txt

 

 

Also, if you want to test out in emulation rather than burning Eproms each time, just generate a 16K file instead, use *=$C000 instead of *=$8000

 

OStest1.bin did work, but I loaded it up after the computer was running. I'm using a ROM emulator plugged into the ROM socket of the Atari, so I can change the ROM contents on the fly with a program running on my Mac. It's a lot faster than burning ROMs :)

 

I'm away from the computer for the night, but will try this tomorrow and report results. Again, thanks for the help.

 

Rybags, I wanted you to know I've successfully converted this code to 6809 assembler and it works great. My post on http://liber809.blogspot.com/ talks about it.

Link to comment
Share on other sites

Good stuff.

How about try for some NMI action?

 

Store $40 to $D40E to enable VBlank NMI.

Just have it do something like increment a counter in RAM.

 

You could then have the main code do something like (in 6502) :

 

loop:  lda vcount  ; $D40B
clc
adc counter
sta colbak ; $D01A
jmp loop
; NMI handler below
nmi:  inc counter ; some location in RAM
rti

 

That should produce a curtain effect that moves up the screen.

Link to comment
Share on other sites

Good stuff.

How about try for some NMI action?

 

Store $40 to $D40E to enable VBlank NMI.

Just have it do something like increment a counter in RAM.

 

You could then have the main code do something like (in 6502) :

 

loop:  lda vcount  ; $D40B
clc
adc counter
sta colbak ; $D01A
jmp loop
; NMI handler below
nmi:  inc counter ; some location in RAM
rti

 

That should produce a curtain effect that moves up the screen.

 

Well, it is doing something. I see bars of color, but they're stationary. There's a slight flutter to them.

 

Could you put together the working 6502 code? I'll assemble with atasm and run it with the 6502C to see how it is supposed to run.

 

NMI Test

Edited by boisy
Link to comment
Share on other sites

6502 code for the OS ROM would be something like:

 

counter = $2000
*=$F000
startup   ldx #$FF
 txs
 cld
 sei
 inx
 txa
cleario   sta $D000,x
 sta $D200,x
 sta $D300,x
 sta $D400,x
 dex
 bne cleario
 lda #3
 sta $D20F
 lda #$40
 sta $D40E
loop   lda $D40B
 clc
 adc counter
 sta $D01A
 jmp loop
nmi  inc counter
irq   rti
 *=$FFFA
.word nmi
.word startup
.word irq

 

That should work. The important thing is to store #$40 into $D40A to enable VBlank NMI. Of course do this after the "cleario". And the system vectors @ $FFFA need to be correct, and of course arranged as your 6809 needs them.

 

If you already have the proper setup, then maybe the NMI line isn't connected?

 

Another point - Atari made a mistake with the NMI line - we've discussed elsewhere. Antic only pulls /NMI low for a couple of cycles and if the 6502 is in early processing of an IRQ you can have a "missed NMI" situation.

 

Probably worthwhile looking up the docs of the 6809 and check what's required there. If there's a problem with the shortness of the NMI, then you'd need to add in a latch mechanism that increases the duration of /NMI from the CPU point of view.

 

On 6502, /NMI is edge-triggered, /IRQ is level triggered. Another potential pitfall is if /NMI stays low, it then inhibits further NMIs. Atari never does this, but on some machines like C64, you can retain NMI low by triggering a timer NMI but not clearing it.

Link to comment
Share on other sites

6502 code for the OS ROM would be something like:

 

counter = $2000
*=$F000
startup   ldx #$FF
 txs
 cld
 sei
 inx
 txa
cleario   sta $D000,x
 sta $D200,x
 sta $D300,x
 sta $D400,x
 dex
 bne cleario
 lda #3
 sta $D20F
 lda #$40
 sta $D40E
loop   lda $D40B
 clc
 adc counter
 sta $D01A
 jmp loop
nmi  inc counter
irq   rti
 *=$FFFA
.word nmi
.word startup
.word irq

 

That should work. The important thing is to store #$40 into $D40A to enable VBlank NMI. Of course do this after the "cleario". And the system vectors @ $FFFA need to be correct, and of course arranged as your 6809 needs them.

 

If you already have the proper setup, then maybe the NMI line isn't connected?

 

Another point - Atari made a mistake with the NMI line - we've discussed elsewhere. Antic only pulls /NMI low for a couple of cycles and if the 6502 is in early processing of an IRQ you can have a "missed NMI" situation.

 

Probably worthwhile looking up the docs of the 6809 and check what's required there. If there's a problem with the shortness of the NMI, then you'd need to add in a latch mechanism that increases the duration of /NMI from the CPU point of view.

 

On 6502, /NMI is edge-triggered, /IRQ is level triggered. Another potential pitfall is if /NMI stays low, it then inhibits further NMIs. Atari never does this, but on some machines like C64, you can retain NMI low by triggering a timer NMI but not clearing it.

 

Ok ran the 6502 code.

 

Well, it's definitely doing more than the 6809. The logic analyzer shows the NMI is being asserted for about 2 cycles on the 6809, but for some reason the routine isn't being hit. I see the registers spilling into the stack. Hmm... will have to study this more.

Link to comment
Share on other sites

You could use a Timer IRQ instead.

 

Take the STA $D40E out, replace with:

 

lda #131  ; 262/2 = 131, half the screen height NTSC
sta $D200 ; Set Timer1 value
lda #1
sta $D208 ; Set main audio divider to 16 KHz (TV line frequency)
lda #1
sta $D20E ; Enable Timer 1 IRQ
cli  ; Enable IRQs on the 6502

 

In the routine "irq", change to:

 

lda #0
sta $D20E
lda #1
sta $D20E ; clear then re-enable Timer1 IRQ
inc counter
rti

 

Set the system IRQ vector @ $FFFE to point to that IRQ routine and it should give a moving display.

Link to comment
Share on other sites

You could use a Timer IRQ instead. Take the STA $D40E out, replace with:
 lda #131 ; 262/2 = 131, half the screen height NTSC sta $D200 ; Set Timer1 value lda #1 sta $D208 ; Set main audio divider to 16 KHz (TV line frequency) lda #1 sta $D20E ; Enable Timer 1 IRQ cli ; Enable IRQs on the 6502 

In the routine "irq", change to:

 lda #0 sta $D20E lda #1 sta $D20E ; clear then re-enable Timer1 IRQ inc counter rti 

Set the system IRQ vector @ $FFFE to point to that IRQ routine and it should give a moving display.

 

This code seems to behave the same way. Instead of a rolling curtain that I see on the 6502, on the 6809 I'm seeing the same color bars stay in place with a very slight up and down jitter.

 

The logic analyzer definitely shows /IRQ being asserted, and I can see the ISR being executed in the instruction stream.

 

BTW, I re-ran the NMI version and the NMI ISR routine *IS* being executed. I missed it somehow in my earlier analysis.

 

So, the difference in behavior between the 6502 and the 6809 versions on the screen brings to mind several possibilities:

 

1. I did not translate the code correctly between the 6502 and the 6809. I double checked this and I'm almost 100% sure the code is correct.

2. The pattern is dependent upon instruction timings of the 6502? One thing that Gary pointed out is that the /NMI on the 6502 only throws the PC and condition code register on the stack. On the 6809, the entire register set is spilled onto the stack, leading to a much longer period before the NMI ISR is executed.

Link to comment
Share on other sites

Are you translating "INC" properly ? That's a simple increment of a memory location.

 

VCount is added to this number to give the colour, since the value of the number increments the colour bars roll up the screen.

 

I just realised something - I forgot to push the registers onto the stack with the IRQ modification I provided earlier. On 6502 that would be PHA as first instruction, PLA as the last (before RTI). Since "A" is the only register used, no need to save X/Y.

In this case it didn't matter a lot since the mainline code only does that small loop.

 

Maybe add some audio feedback to the thing.

 

After your cleario stuff, add:

 

 LDA #$A6
 STA $D203

 

To the interrupt routine, add after the INC COUNTER:

 

 LDA COUNTER
 STA $D202

 

(also put PHA / PLA to preserve "A" in the NMI routine)

Edited by Rybags
Link to comment
Share on other sites

Are you translating "INC" properly ? That's a simple increment of a memory location. VCount is added to this number to give the colour, since the value of the number increments the colour bars roll up the screen. I just realised something - I forgot to push the registers onto the stack with the IRQ modification I provided earlier. On 6502 that would be PHA as first instruction, PLA as the last (before RTI). Since "A" is the only register used, no need to save X/Y. In this case it didn't matter a lot since the mainline code only does that small loop. Maybe add some audio feedback to the thing. After your cleario stuff, add:
 LDA #$A6 STA $D203 

To the interrupt routine, add after the INC COUNTER:

 LDA COUNTER STA $D202 

(also put PHA / PLA to preserve "A" in the NMI routine)

 

I'm an idiot.

 

My "counter" variable was at a location around $C000... in ROM, not in RAM. So incrementing it didn't change it.

 

I relocated the counter variable to $1000 in RAM, and now it's working... with sound! :)

 

Thanks Rybags. It looks like the NMI is doing its thing. The bars are scrolling like the 6502 version and a nice descending sound is happening too!

Link to comment
Share on other sites

Cool.

 

So by the looks of things, you have NMI and IRQ working. Antic and Pokey are doing their stuff.

 

So what next?

 

With this stuff verified, I think the next step is to get the design to a board house to make some good test boards. Gary's wrapping up the design and adding a second 40 pin socket so we can put the 6502C on the same daughterboard. We'll setup a jumper to enable/disable the 6809E/6502C so that folks don't have to yank out CPUs.

 

I think Gary's going through PCBExpress for this run. We'll make four boards based on the current design. I'll keep one and sell the other three to folks who can hopefully do some cool stuff. Then if there's more interest, we'll go with a different board house and make a larger run, and probably redo the design to reduce part count.

Link to comment
Share on other sites

A quick update before we leave for some Mardi Gras festivities this evening...

 

I've made slight modifications to the NitrOS-9 kernel to accommodate the memory map of the XEGS. Right now I'm limiting the NitrOS-9 boot file to 16K even though there's 32K of ROM. That's because we could use as much RAM as possible, and also because of the XEGS having its I/O space at $DXXX.

 

Using the code to clear the DXXX region and set the screen color, I'm able to verify that Krn is executing fully and passing control to KrnP2. Although I cannot inspect memory, I'm assuming things look good. Certainly for the OS to get this far, things have to be working right. At the point where I've verified control, system calls have been installed and called several times by that point.

 

My next step is to get a primitive screen driver written so I can at least see some text. I'm blind at the moment, and having the ability to show text would be helpful.

 

So the good news is that it appears that the NitrOS-9 kernel is coming up and at the point where it's ready to open the /Term device.

  • Like 1
Link to comment
Share on other sites

Setting up a screen is pretty easy.

 

I take it you have register maps for the I/O (Antic, Pokey, GTIA, PIA) ?

 

Simply set DMACTL to $22 for standard (40 column) or $21 for narrow (32 column).

 

Point DLISTL/H to a Display List. A text screen display list is easy to build. Just make sure it doesn't cross a 1K boundary.

 

Sample Display List:

 

display_list
 .byte $70,$70,$70   ; 3 * 8 blank scanlines
 .byte $42  ; Mode 2 with LMS (Load Memory Scan).  Mode 2 = 40 column hires text, next 2 bytes L/H determine screen origin
 .word screen  ; screen origin.  Usually put at top of available RAM.  Screen data will wrap around 4K boundary unless another LMS is used
; default with Atari OS in >= 48K system is $9C40 for a 40*24 screen
 .byte 2,2,2,2,2,2,2,2,2,2
 .byte 2,2,2,2,2,2,2,2,2,2
 .byte 2,2,2
; 23 extra mode 2 lines for total of 24.  240 scanlines can be used for display area, but a hires line can't be on scanline 240 due to an Antic bug
 .byte $41  ; This is the end of Display List command JVB (Jump and wait for Vertical Blank)
 .word display_list  ; point to top of display list

 

I'd suggest modify your OS to add some housekeeping stuff.

The Atari OS by default has the VBlank NMI enabled. This does stuff like increment clock counter (just a 3 byte VBlank count), and maintaining shadow registers.

Shadow registers are RAM copies of certain hardware registers that either get copied from or to the I/O chips.

 

Some screen-related stuff like Display List pointers should only normally be changed during VBlank. Also, having colour shadows means colour changes can be made glitch free.

 

I guess we should dig up some OS source materials, you could adapt some of what's already used for the 6809.

Link to comment
Share on other sites

Setting up a screen is pretty easy.

 

I take it you have register maps for the I/O (Antic, Pokey, GTIA, PIA) ?

 

Simply set DMACTL to $22 for standard (40 column) or $21 for narrow (32 column).

 

Point DLISTL/H to a Display List. A text screen display list is easy to build. Just make sure it doesn't cross a 1K boundary.

 

Sample Display List:

 

display_list
 .byte $70,$70,$70   ; 3 * 8 blank scanlines
 .byte $42  ; Mode 2 with LMS (Load Memory Scan).  Mode 2 = 40 column hires text, next 2 bytes L/H determine screen origin
 .word screen  ; screen origin.  Usually put at top of available RAM.  Screen data will wrap around 4K boundary unless another LMS is used
; default with Atari OS in >= 48K system is $9C40 for a 40*24 screen
 .byte 2,2,2,2,2,2,2,2,2,2
 .byte 2,2,2,2,2,2,2,2,2,2
 .byte 2,2,2
; 23 extra mode 2 lines for total of 24.  240 scanlines can be used for display area, but a hires line can't be on scanline 240 due to an Antic bug
 .byte $41  ; This is the end of Display List command JVB (Jump and wait for Vertical Blank)
 .word display_list  ; point to top of display list

 

I'd suggest modify your OS to add some housekeeping stuff.

The Atari OS by default has the VBlank NMI enabled. This does stuff like increment clock counter (just a 3 byte VBlank count), and maintaining shadow registers.

Shadow registers are RAM copies of certain hardware registers that either get copied from or to the I/O chips.

 

Some screen-related stuff like Display List pointers should only normally be changed during VBlank. Also, having colour shadows means colour changes can be made glitch free.

 

I guess we should dig up some OS source materials, you could adapt some of what's already used for the 6809.

 

Rybags, I've been reading up on this a bit, and also chatted with some helpful guys on the IRC group yesterday. They mentioned that the display list could not cross a 1K boundary. They also said the text screen had to start on 4K boundary? Your comment in the dlist above seems to contradict that... the screen starts at $9C40.

 

Also, I need to get the clock running in the OS and need a clock source. It sounds like the VBI is just the thing. I presume that fires off at 60 times per second?

Link to comment
Share on other sites

First off - do you have a rough guestimate of what the board will cost and how many internal modifications to the machine would be needed?

I'm tempted to jump into this thing.

 

Screen - no, you can start it anywhere, the Antic hardware only has 12 bits as counter though, so crossing a 4K boundary wraps around to the start of the 4K. You need a second LMS ($4x) type instruction in the DList to cross the 4K.

It's generally only an issue in the hires modes that use more than 4K.

 

OS size - it's actually 14K not 16. The 2K that would otherwise appear in the IO space gets mapped to $5000. Atari uses this 2K for the Self Test routines which essentially run as a standalone and coldstart the machine when you exit.

But, the Basic/Missile Command ROM mapping is contiguous with the OS, ie $A000 - $BFFF = Basic ROM, $C000 - $CFFF = low portion of OS ROM.

 

I'd suggest use the Missile Command slot if you need more than 14K. That way if you have a dual CPU machine, the Atari side only loses the game, Basic is ultimately more useful.

The problem though in using that extra ROM is that it's only present on the one chip on XEGS machines. The remainder of the XL/XE machines have Basic on it's own 8K chip. All other XL/XE have the OS on single 16K chip, except 1200XL which has it on 2 8K chips.

 

The VBlank is near enough to 60 FPS NTSC, 50 for PAL. In reality it's slightly less, but sufficient to maintain a clock that runs 0.5% or so slower than it should.

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