Microdisc IRQ/Loading question

This is the best place to discuss about the various Oric operating systems like Sedoric, Randos, FT-Dos, and others, as well as serious software, utilities, word processors, disassemblers, etc... that runs on oric computers.
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Microdisc IRQ/Loading question

Post by Dbug »

I'm currently in the process of trying to understand the code of the loader we used in our old demos, it was not written by me (I'm not much of a hardware guy) and I'm kind of having problems understand some of the parts.

In particular the loader is using an IRQ, and contains this code:

Code: Select all

	ldy #<irq_handler
	lda #>irq_handler
	sty $fffe
	sta $ffff

	...
	...

irq_handler
	pla					; get rid of IRQ context
	pla
	pla
	lda #%10000001
	sta $0314			; disables disk irq
	lda $0310			; gets status and resets irq
	and #$7c
	rts
Does anyone understand why the code is doing pla/pla/pla/rts instead of using RTI for example?

The second question would be: What is the advantage of using the IRQ for loading instead of just polling the registers from the read_sector loop?
User avatar
Chema
Game master
Posts: 3013
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Microdisc IRQ/Loading question

Post by Chema »

Hi Dbug.

I Have a similar code in my games, which was based on Fabrice's. I can't have a look at it right now, so I might be wrong, but I think the main code calls a routine which waits in an infinite loop for the irq to occur. Thus the ISR you have there. It gets rid of the context and returns to the main routine, breaking the loop.

I guess there was a reason to do it that way, but I cannot remember now.

I don't see why it should not work with polling, unless there is some serious timing issue.
User avatar
Chema
Game master
Posts: 3013
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Microdisc IRQ/Loading question

Post by Chema »

Hi again.

Okay. It, of course can be polled. The first version of the code works as I told you, but after a lot of work, Fabrice rewrote everything for 1337 so it is done now through polling and also it avoids the Telestrat bug (which he wrote about in CEO-mag, IIRC).

You can find the code here http://miniserve.defence-force.org/svn/ ... INE/disk.s

It is dirty and poorly documented, as you might see instantly. It also includes both the old and the new version, which are compiled conditionally (use #define OLDROUTINES for the old code based on IRQ). I also entered statements like this one .dsb (($0313&3)-((*+3)&3))&3,$ea which add the needed number of nop intructions just to align accesses to the problematic registers in page 3 and avoid the Telestrat bug.

Also added some labels to test if they were correctly alligned (_chk_313b).

Anyway, to the differences between old and new versions. The read_data routine is

Code: Select all

 read_data 
   lda $0318 
   bmi read_data 
.dsb (($0313&3)-((*+3)&3))&3,$ea
   lda $0313
_chk_313b
   sta (pbufl),y 
   iny 
   bne read_data 
   inc pbufh 
   jmp read_data 
which reads a whole 256 sector in memory. You can see it ends up by inconditionally jumping to read_data, so the ISR is the one which should perform the RTS when the operation is finished (the code you asked about).

The new version:

Code: Select all

read_data
     bit $0314
     bpl end_read
     bit $0318
     bmi read_data
.dsb (($0313&3)-((*+3)&3))&3,$ea
     lda $0313
_chk_313d
     sta (pbufl),y
     iny
     bne read_data
     inc pbufh
     jmp read_data
end_read
     rts
This one makes the check and jumps to end_read when finished. No ISR trick here. The ISR in the new version is:

Code: Select all

     pha
test_via1
     bit $030D
     bpl test_via2
     lda #$7F
     sta $030D    ; cancel any VIA interrupt
test_via2
     bit $032D        ; on the Oric1/Atmos, this will test via1 again
     bpl test_acia
     lda #$7F
     sta $032D    ; cancel any VIA2 interrupt (VIA1 on the Atmos)
test_acia
     bit $031D    ; on the Oric1/Atmos, this will test via1 again !
     bpl test_fdc
                         ; reading the ACIA status has already cleared the interrupt, so no need to do anything
                         ; if it is a VIA interrupt on the Atmos, it has happened between the first via test and now,
                         ; so we ignore it: it will raise another interrupt that will be cleared during the second interrupt handler test_fdc
     bit $0314           ; $0314 reflects INTRQ state in negative logic
     bmi all_tests_done
test_fdc
.dsb (($0310&3)-((*+3)&3))&3,$ea
     lda $0310    ; read FDC status and clears interrupt request
_chk_310g
all_tests_done
     pla
     rti
The disk code Fabrice developed for pinforic used indirection through page 4 and other tricks to work with all drives (not only Microdisc) and also using a FAT fylesistem. All seemed black magic to me. I think I found some issues when trying to use it in Space:1999, so I stripped out the multi-support and make it only work on Microdisc (can't remember the details).

Hope all this helps
Post Reply