kategoria: ANSI C
[#1] Wyłączanie OS raz jeszcze
Tym razem będzie jednak o tym trochę szerzej niż zwykle. ;)
Wykoncypowałem sobie w moim łebku, że fajnie byłoby móc wyłączyć OS żeby mieć CPU i resztę tylko dla siebie. Na samym początku przygody z Amigą próbowałem się w to bawić, ale zwiechy mnie zniechęciły - teraz mam na to trochę więcej parcia.

W oparciu o listę rzeczy do zrobienia w startupowym kodzie znalezioną na pouecie zrobiłem sobie funkcję systemCreate() zawłaszczającą Amigę i systemDestroy() oddającą ją OSowi. W main() nie ma nic innego niż kolejno wywołanie systemCreate i systemDestroy. Jak włączam intena w systemDestroy to dostaję guru, jak tego nie robię to Amiga spodziewanie wisi bo nie wie co z sobą zrobić.

Z ostatniej chwili okazało się, że jak zakomentuję obie pętle z SetIntVector to wszystko jest cacy. Ideę miałem taką żeby zapamiętać przerwania systemowe, poużywać sobie gołych przerwań (nie handlerów bo to już miałem) u siebie w kodzie, po czym przywrócić systemowi jego przerwania. SetIntVector jest złym pomysłem? Jeśli tak, to jak to zrobić na żywca z VBR? Czym takie przerwanie się różni od tego podawanego w SetIntVector?

static UWORD s_uwOsIntEna;
static UWORD s_uwOsDmaCon;
static tInterrupt *pOsInterrupts[15] = {0};
static tInterrupt *pAceInterrupts[15] = {0};

void systemCreate(void) {

	// save the system copperlists and flush the view

	// get VBR location if you detect a 68010+ machine

	// save the state of the hardware registers (INTENA, DMA, ADKCON etc.)
	s_uwOsIntEna = g_pCustom->intenar;
	s_uwOsDmaCon = g_pCustom->dmaconr;

	// Disable interrupts (this is the actual "kill system/OS" part)
	g_pCustom->intena = 0x7FFF;
	g_pCustom->intreq = 0x7FFF;

	// Wait for vbl before disabling sprite DMA
	while (!(g_pCustom->intreqr & INTF_VERTB)) {
		continue;
	}
	// TODO disable DMA here

	// Save OS interrupt vectors
	g_pCustom->intreq = 0x7FFF;
	for(UBYTE i = 0; i < 15; ++i) {
		pOsInterrupts[i] = SetIntVector(i, 0);
	}

	// Enable needed DMA (and interrupt) channels

	// Reset active system uses counter
	s_wSystemUses = 0;
}

void systemDestroy(void) {
	// disable app interrupts/dma
	g_pCustom->intreq = 0x7FFF;
	g_pCustom->intena = 0x7FFF;
	g_pCustom->dmacon = 0x7FFF;

	// restore system copperlists

	// restore old DMA/INTENA/ADKCON etc. settings
	for(UBYTE i = 0; i < 15; ++i) {
		SetIntVector(i, pOsInterrupts[i]);
	}
	g_pCustom->dmacon = DMAF_SETCLR | s_uwOsDmaCon;
	g_pCustom->intena = INTF_SETCLR | s_uwOsIntEna; //<---- guru tu

	// restore old view

}
[#2] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #1

Jeżeli masz bibliotekę lowlevel.library (z Amiga OS3.1) to tam jest funkcja SystemControlA() dzięki której wyłączysz system całkowicie i bez problemów. Będziesz miał CPU i inne rzeczy do wyłącznej dyspozycji. Ta funkcja jest 100% bezpieczna, nie doświadczysz żadnych komplikacji.

Co do wyłączania w ten sposób, to nie mam w tym doświadczenia. Zapytaj Asmana, on na pewno będzie wiedział.
[#3] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #2

A no tak, zapomniałem powiedzieć że mówimy o kicku 1.3. Ale dzięki, po raz kolejny mi uzmysłowiłeś jak wiele lowlevel.library potafi ułatwić w życiu. ;)
[#4] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #3

Może napisz jaki numer guru dostajesz? Na pewno to pomoże.
[#5] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #4

A proszę Cię bardzo 8000 00003.

The dreaded 80000003-Guru is one of the most common on the Amiga: on the 68010- it signifies a word or longword access to an uneven address; on the 68020+ (which is capable of recognising the situation and performing two memory accesses in order to get the information they need) it is put up when the stack is pointing at an odd address. That should never happen, so either your RAM is faulty, or your program is screwing up bigtime. The stack being messed up is truly worthy of a CPU exception, the other reason is not. It's just to circumvent a design desicion.


Dalej nie widzę przyczyny. UAE ustawione na 020.
I nie, nie brakuje OpenLibrary("exec.library"), sprawdziłem ;)

Ostatnia aktualizacja: 18.03.2018 18:17:24 przez teh_KaiN
[#6] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #5

Z tego tekstu wynika, że ten błąd w przypadku 68020+ pojawia się, kiedy stos wskazuje na nieparzysty adres.

Proponuję:
1. Wywołać Forbid(), żeby wyłączyć multitasking oraz Permit() żeby go włączyć. Pomiędzy nimi robić te "niebezpieczne" instrukcje. Być może jakiś inny task manipuluje przerwaniami itp. w międzyczasie.

2. Sprawdzić funkcje Disable() i Enable(), które wyłączają przerwania. Może one Ci stykną zamiast ustawiać INTENA.

3. Ewentualnie skompilować program pomijając etap asemblacji i przyjrzeć się kodowi.

Jestem pewien, że podobny problem napotkałem kiedyś.
[#7] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #5

Hej! Przyjrzyj się przerwaniu nr 14 w kontekście SetIntVector(). INTF_INTENA (Master Interrupt) można tylko ustawiać. Może o to chodzi.
[#8] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #7

yyy nie, też sprawdzałem ;)

GCC mi wyprodukował na -O3 takie coś (na -O0 też nie działało ale byłoby więcej do analizy):

_systemCreate:
	movem.l a3/a2/d2,-(sp)	|,
	move.l _g_pCustom,a0	| g_pCustom, g_pCustom.0_4
	move.w 28(a0),d0	| g_pCustom.0_4->intenar, _5
	move.w d0,_s_uwOsIntEna	| _5, s_uwOsIntEna
	move.w 2(a0),d0	| g_pCustom.0_4->dmaconr, _7
	move.w d0,_s_uwOsDmaCon	| _7, s_uwOsDmaCon
	move.w #32767,154(a0)	|, g_pCustom.0_4->intena
	move.w #32767,156(a0)	|, g_pCustom.0_4->intreq
.L2:
	move.w 30(a0),d0	| g_pCustom.0_4->intreqr, _11
	and.w #32,d0	|, tmp57
	jeq .L2	|
	move.w #32767,156(a0)	|, g_pCustom.0_4->intreq
	lea _pOsInterrupts,a2	|, ivtmp.26
	moveq #0,d2	| ivtmp.19
	lea _SetIntVector,a3	|, tmp59
.L3:
	clr.l -(sp)	|
	move.l d2,-(sp)	| ivtmp.19,
	jsr (a3)	| tmp59
	move.l d0,(a2)+	|, MEM[base: _27, offset: 0B]
	addq.l #1,d2	|, ivtmp.19
	addq.l #8,sp	|,
	moveq #15,d0	|,
	cmp.l d2,d0	| ivtmp.19,
	jne .L3	|
	clr.w _s_wSystemUses	| s_wSystemUses
	movem.l (sp)+,d2/a2/a3	|,
	rts
	.align	2
	.globl	_systemDestroy
_systemDestroy:
	movem.l a4/a3/a2/d2,-(sp)	|,
	move.l _g_pCustom,a4	| g_pCustom, g_pCustom.1_4
	move.w #32767,156(a4)	|, g_pCustom.1_4->intreq
	move.w #32767,154(a4)	|, g_pCustom.1_4->intena
	move.w #32767,150(a4)	|, g_pCustom.1_4->dmacon
	lea _pOsInterrupts,a2	|, ivtmp.38
	moveq #0,d2	| ivtmp.31
	lea _SetIntVector,a3	|, tmp43
.L10:
	move.l (a2)+,-(sp)	| MEM[base: _25, offset: 0B],
	move.l d2,-(sp)	| ivtmp.31,
	jsr (a3)	| tmp43
	addq.l #1,d2	|, ivtmp.31
	addq.l #8,sp	|,
	moveq #15,d0	|,
	cmp.l d2,d0	| ivtmp.31,
	jne .L10	|
	move.w _s_uwOsDmaCon,d0	| s_uwOsDmaCon, _13
	or.w #-32768,d0	|, _13
	move.w d0,150(a4)	| _13, g_pCustom.1_4->dmacon
	move.w _s_uwOsIntEna,d0	| s_uwOsIntEna, _16
	or.w #-32768,d0	|, _16
	move.w d0,154(a4)	| _16, g_pCustom.1_4->intena
	movem.l (sp)+,d2/a2/a3/a4	|,
	rts


Na moje jest niby git, ale nie mam wprawy w czytaniu asemblera więc mogłem coś przeoczyć.

A z tą liczbą przerwań też jaja są, bo dokumentacja do SetIntVector jasno mówi że legalne są argumenty 0..14. Faktycznie czternastka ma mało sensu, ale jak skrócę zakres to nie robi to różnicy.

Ostatnia aktualizacja: 18.03.2018 19:33:24 przez teh_KaiN
[#9] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #8

Na moje jest niby git, ale nie mam wprawy w czytaniu asemblera więc mogłem coś przeoczyć.


Ale ten kod asemblera wyprodukowany przez kompilator C jest brzydki. Nie dziwię się, że trudno to odczytać.

Na moje oko to dziwię się, że przy wywoływaniu funkcji systemowych nie umieszcza adresu bazy biblioteki w rejestrze A6. Myślałem, że to wymagana przez system konwencja.

Pytanie: czy w tym kodzie z pouet.net jest jakaś wzmianka o Forbid()/Permit() ?
[#10] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #9

Nie, nie ma, bo zresztą na zdrowy rozsądek: OS jest preemptive czyli powrót do niego jest realizowany na przerwaniach. Jak wyłączysz wszystkie przerwania, to OS nie jest już w żaden sposób wołany - wróci gdy spowrotem zapełnisz intena a wcześniej przywrócisz wektory do stanu systemowego. Próbowałem dodawać forbid na początku systemCreate i permit na końcu systemDestroy, bez różnicy.

Bazowałem na pierwszym komentarzu StingRaya stąd.

Ostatnia aktualizacja: 18.03.2018 19:38:00 przez teh_KaiN
[#11] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #10

A to przepraszam, tak jak pisałem, mam mało doświadczenia z wyłączaniem systemu w ten sposób.

Na mój gust to jest jakiś konflikt z SetIntVector() i ręcznym ustawianiem INTENA. Sam piszesz, że bez SetIntVector() kod działa.
[#12] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #11

Też tak myślę, ale moje "chciejstwo" chce by było inaczej - bo wygodna jest funkcja, do której się pcha strukturę ze wskaźnikiem na kod i danymi do podania w argumencie. Gdyby OS był otwarty, to by można było podejrzeć co on tam robi.

Nic to, pozostaje czekać aż wypowie się ktoś z Panteonu Hardkorowych Wyjadaczy™. Rozwiązanie porównywalnie wygodne oparte o ręczne majtanie VBR też zaakceptuję. ;)
[#13] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #12

A mam jeszcze pytanie, które mnie nurtuje: jak to jest że Twój kod czeka aż napłynie przerwanie VERTB, po wyłączeniu przerwań? Tak można?

Ja uważam, że nie ma się co dziwić, że system trochę głupieje kiedy wyłącza się przerwania i ustawia je poprzez SetIntVector().

P.S. Ja również chciałbym usłyszeć opinii kogoś bardziej obcykanego w tym temacie.

Ostatnia aktualizacja: 18.03.2018 20:00:10 przez Hexmage960
[#14] Re: Wyłączanie OS raz jeszcze

@Hexmage960, post #13

Nie wiem czy tak można na Amidze, ale moje doświadczenie z mikrokontrolerów jest takie, że zasadnym byłoby gdyby Amiga działała tak:

- jeśli nastąpi warunek przerwania (VERTB) to IntEna dostaje jedynkę w odpowiednim miejscu
- jeśli włączone jest dane przerwanie w IntEna to jest ono wołane, jedynka dalej sobie jest na swoim miejscu
- hardware'owe przerwanie powinno na koniec wyzerować daną jedynke w IntReq, by jej ponowne pojawienie się striggerowało skok do przerwania.

Zatem IntEna może być puste a IntReq powinien dalej robić swoje, bo przecież możesz chcieć pracować w trybie odpytywania (pollingu).

Wracając do tematu, w tym temacie znalazłem w załączniku kod startowy StingRaya. Z tego co widzę, pozyskuje on adres tablicy wektorów, potem sobie wybrane wektory zapisuje na bok i podstawia adresy swoich funkcji. Nie ma nic o argumencie przekazywanym do przerwania. Zatem pewnie OS robi coś takiego, że wektor jest (prawie) taki sam dla każdego przerwania, jak któreś chlaśnie to rozkminia które jest aktywne i wtedy odpala "hardware'owy" w rozumieniu systemu wektor. Trzeba chyba będzie tak zrobić, bo w tym przykładzie nie ma całej zabawy z intena, więc pewnie SetIntVector tym zarządza sam w sobie. Tak czy inaczej, korzystanie z tej funkcji implikuje systemowe wektory przerwań, a zatem okazję dla systemu żeby się wtrącić i porobić swoje.

Obrona za 3 dni a ja guglam o 30-letnim komputerze. Kiedyś się to obróci przeciwko mnie. ;)

Ostatnia aktualizacja: 18.03.2018 20:16:00 przez teh_KaiN
[#15] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #14

Obrona za 3 dni a ja guglam o 30-letnim komputerze. Kiedyś się to obróci przeciwko mnie. ;)

Pamiętaj, że jak w zabawie w głuchy telefon, kod znaleziony przypadkowo w sieci może nie zawsze działać jak trzeba. Polegaj na sprawdzonych źródłach, najlepiej jakichś rzetelnych opracowaniach. Ja przynajmniej na tym polegam i moje programy są zazwyczaj stabilne.

Nie po to przecież ludzie pisali różne ROM Kernel Reference Manuale, podręczniki i poradniki programowania na Amidze.

Zaś co do obrony - rzeczywiście można zrobić sobie tuż przed obroną mały odpoczynek. Wszak uczyłeś się przecież do niej pewnie długo. Serdecznie życzę Ci powodzenia w obronie swojej pracy inżynierskiej. OK

A Amigę zostaw sobie na później, kiedy będziesz mógł na spokojnie do tego przysiąść.
[#16] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #1

Mi osobiście nazwa SystemCreate koajrzy się z tworzeniem jakiegoś Systemu a SystemDestroy z niszczeniem. Ja bym użył par OsTakeOver i OsRestore albo OsDisable i OsEnable.

Jeśli już pobierasz aktualny stan DMA to wypadałoby DMA wyłączyć. Bo Copperlista zrobi Ci psikusa i zmieni ten stan. Pomyśl też o tym co się wydarzy gdy zatrzymałeś przerwania, dma działa, copperlista się wykonuje i sobie włącza jakieś przerwanie.

Zatrzymując przerwania (intena = 0x7fff) czyścisz także oczekujące przerwania (intreq = 0x7fff), póżniej czekasz na ramkę co jest dobrę ale nie w ten sposób który napisałeś. Kto Ci zagwarantuje że VERTB się odpali albo zostało już odpalone, może jesteś w połowie ramki i wtedy twoja pętla od razu się zakończy. Do czekania na ramkę możesz na przykład uzyć rejestr VPOSR (czekając na V8 czyli bit 00 czekasz na linię 256, lub jej wielokrotność w zależności od rozdzielczości pionowej).

Jeśli już ubiłeś OS zatrzymując przerwania i dma to przy używaniu funkcji bibliotecznych trzeba być bardzo ostrożnym i wiedzieć co one robią - bo w przeciwnym razie zwis gotowy.

Jak wiesz w mc68000 nie ma jeszcze VBR, pojawia się on dopiero od 68010+, można założyć że VBR na 68000 to jest 0. W każdym razie od VBR do VBR+$400 leżą wektory przerwań (jest ich 256). I prostą pętlą możesz to sobie skopiować i później odtworzyć. Tylko zadaj sobie pytanie czy musisz to wszystko kopiować może wystarczy Ci tylko VERTB (offset 0x6c) i PORTS ( offset 0x68 ) - wtedy zapamiętasz tylko 8 bajtów. Pamiętaj że przerwania też nie są za darmo - około 50 cykli wciągają na dzień dobry.

Co do tego podjerzenia jak to OS sobie działa to możesz sobie obejrzeć choćby zdeasemblowany exec z kicka1.2 (link) i podpatrzeć jak działa taki SetIntVector. A jak jesteś super ciekawy to poszukaj na necie wyciekłych źródeł OS 3.1 - na pewno gdzieś tam znajdziesz.

Najważniejsze - skąd te nieszczęsne guru - włączając przerwania zapomniałeś włączyć Master interrupt (0xc000) i stąd te problemy. Handlery systemowe bardzo prawilnie (jak dobrze pamiętam) podchodzą do przerwań i zawsze sprawdzają gdzieś na początku czy bit 14 jest włączony i przeważnie wychodzą z przerwania jeśli nie był on włączony.

W Twoim wyłączaniu os brakuje oczywiście paru elementów z których zdajesz sobie sprawę bo jest komentarz o tym ale pamiętaj też że jeśli na przykład załadujesz dane z dyskietki i będziesz ubijać OS to dioda dysku sama nie zgaśne bo OS już tego nie kontroluje. Możesz załatwić to czekaniem na przykład paru sekund. Ale po prawdzie to tego nie wiesz bo nie wiesz kiedy przyjdzie wiadomość (szczególnie przy zapisie). Może trafisz a może nie. Najlepsze rozwiązanie które znam to zrobienie flusha (ACTION_FLUSH za pomocą DoPkt z DOS, w kick1.3 robisz PutMsg ).

W razie pytań lub niejasności pytaj. Powodzenia na obronie! Ode mnie tip to nic nie mówić jak nie wiesz - przynajmniej nie będziesz gadał bzdur. Ja przynajmniej tak zrobiłem.
[#17] Re: Wyłączanie OS raz jeszcze

@asman, post #16

Dzięki za masę przydatnych informacji! Guru faktycznie ustąpiło. Co do czekania to przed chwilą sprawdziłem sobie coś takiego:

for(UBYTE i = 0; i != 200; ++i) {
	g_pCustom->intreq = 0x7FFF;
	while (!(g_pCustom->intreqr & INTF_VERTB)) {}
}


I czeka faktycznie 4 sekundy w środowisku gdzie IntEna ma zero na INTF_VERTB. Oczywiście jak przerwanie się włączy i obsłuży w sposób prawilny (zerowanie flagi vertb w IntReq po zrobieniu swojego) to już nie ma gwarancji a wręcz szans że ten warunek odpali, więc trzeba naprawdę wiedzieć co się robi i liczba zastosowań jest ograniczona.

Co do nazewnictwa funkcji to sprawa nie jest łatwa, bo mam plan funkcją systemCreate zawłaszczać OS, po czym funkcjami osEnable i osDisable przywracać mu na chwilę kontrolę tak, by móc korzystać z funkcji fopen i pokrewnych - oczywiście robiąc wszystko na FDD OS jest zbędny, ale przy HDD i generalnie systemowym systemie plików już tak (chyba że o czymś nie wiem). Będę to robił tylko w czasie debugowania i loadingów, więc straty wydajności z związane z takim przełączaniem mnie nie obchodzą.

Najważniejsze, że mój kod ruszył i mogę brnąć dalej. Rzucę tu jeszcze pytanie odnośnie tego, jakie przerwania są pod jakim adresem w tablicy 256 wektorów - jeszcze odpowiedzi nie szukałem, ale być może odpowiesz mi szybciej niż ją samodzielnie znajdę - jeśli jednak będę pierwszy to tu napiszę. ;)

PS. Obroniłem się, więc to już mam z bańki. Więcej czasu i nerwów na wrestling z amigowym hardware'em, hyhy.

EDYT: znalazłem trochę info. 64 pierwsze wektory są hardware'owe (zdefiniowane w datasheecie 68k?), pozostałe 192 definiowane przez użytkownika. Cytując ADA:

8 levels of interrupt. each level have interrupt vector
level 1 - vector $64 : soft/DskBlk/Tbe
level 2 - vector $68 : keyboard
level 3 - vector $6c : Vbl/Copper/Blitter
level 4 - vector $70 : audio
level 5 - vector $74 : DskSyn/Rbf
level 6 - vector $78 : Cia-b

Ale czy to wszystko? I jak rozróżnić VBL od Coppera i Blittera?

EDYT2: Ale jestem głupi, właśnie przecież można rozróżnić przez IntReqR ;)

Ostatnia aktualizacja: 23.03.2018 20:29:29 przez teh_KaiN
[#18] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #17

oczywiście robiąc wszystko na FDD OS jest zbędny, ale przy HDD i generalnie systemowym systemie plików już tak (chyba że o czymś nie wiem).


Zależy w jaki sposób będziesz chciał odczytać/zapisać dane z FDD. Czy to poprzez system plików czy z pominięciem go - wczytując/zapisując odpowiednie sektory. Możesz też podejść do sprawy inaczej i wszystko odczytać zanim przejmiejsz OS. A zapis na przykład wyników robić dopiero po wyjściu z gry, co w przypadku flopa na pewno oszczędzi dyskietki.
[#19] Re: Wyłączanie OS raz jeszcze

@asman, post #18

To niestety nie przejdzie w openfire - gdzie w menu przed każdą partyjką masz selekcję map listowanych z folderu. Ale tak czy inaczej jestem ciekaw jak robi się surowy dostęp do HDD - przez jakieś rejestry, czy jak?
[#20] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #19

No jeśli chcesz rozkminiać Rigid Disk Block, partycje, standardy, FileSystemy, bad blocki i inne rzeczy to w sumie droga wolna, ale wiesz.
Tylko czy dos.library jest za wolny?

Zawsze możesz skorzystać ze scsi.device, jeśli rzeczywiście potrzebujesz dostępu do napędu.

Moim skromnym zdaniem jeśli chcesz grę z instalacją na HDD, to po prostu musisz skorzystać z OS. Różnice w prędkości minimalne i pomijalne tak naprawdę.
[#21] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #19

To po prostu wczytaj to na samym poczatku
[#22] Re: Wyłączanie OS raz jeszcze

@kiero, post #21

To po prostu wczytaj to na samym poczatku

Dokładnie, pięć punktów dla Gryfindoru.

Według mnie to najłatwiejsza i najmniej problematyczne podejscie. Jeśli będziesz to miał ogarniętę to nic nie stoi na przeszkodzie by spróbować z przełączaniem OS.
[#23] Re: Wyłączanie OS raz jeszcze

@asman, post #22

No w tej chwili przed samą pętlą gry wczytuję mapę i inne rzeczy, więc w samej grze żaden dostęp do dysku nie lata prócz debugowych logów - OS będzie cały czas wyłączony.

W samym menu gdzie jest wybór planszy OS musi być włączony, żeby wylistować katalog i wczytać wybraną planszę - bo nie mam zamiaru trzymać wszystkich w RAMie. ;) No i potem pojawia się np. opcja kampanii czy czegoś, gdzie w loadingach między kolejnymi etapami warto byłoby doczytać kolejną mapę z dysku, więc znowu trza OS włączyć i po chwili wyłączyć.

Mam już prawie skończone zarządzanie przerwaniami z cieniutką abstrakcją rozróżniania źródła int3, handlery są prawie jak systemowe - w A1 custom, w A2 ptr na dane podany przy rejestracji handlera. I to bez ani jednej linii asmu. Robi się z tego małe państwo w państwie. ;) Póki co spaliłem mnóstwo czasu na crashach gdy wskaźnik na tablicę wektorów wyglądał tak:

static volatile tHwIntVector * s_pHwVectors = 0;


Ale gdy zrobiłem:

static volatile tHwIntVector * const s_pHwVectors = 0;


to już wszystko jest git. GCC musiał jakieś brzydkie rzeczy z tym robić.
[#24] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #23

No to jedziemy dalej, bo utknąłem trochę. Mam handler przerwania int2 (PORTS), ale jak sprawdzić czy zostało ono wywołane klawiaturą? I w sumie, rozszerzmy to pytanie - jak sprawdzić źródło przerwania wywoływanego przez wiele rzeczy?

Int2: Parallel, keyboard, mouse, "some of disk functions"
Int3: VBL / Copper / Blitter - tu stawiam, że w zależności od tego co jest w intreq na jedynce?

z tego co widzę int5 i int1 też mają wiele źródeł, ale dyskowych rzeczy jeszcze nie tykałem i tu nawet nie będę hipotetyzował i w sumie mnie to jakoś bardzo nie obchodzi, bo będę sobie OS włączał żeby się z dyskiem męczył. ;)
[#25] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #24

No i sobie poradziłem - CIA mają rejestr ICR (Interrupt Control Register). Ich zawartość wskazuje na źródlo przerwania. Tyle że trzeba sobie od razu jego wartość zapisać na boku, gdyż odczyt go czyści. Zapis podobnie jak w IntEna pozwala włączać i wyłączać źródła przerwań.

Było to w HRM ale trzeba było wiedzieć gdzie szukać - rozdział o klawiaturze na to nie wskazuje, a sam rejestr opisany jest w dodatku. Więcej informacji znalazłem w cia6502.doc dostępnym tutaj

Ostatnia aktualizacja: 02.04.2018 10:22:04 przez teh_KaiN
[#26] Re: Wyłączanie OS raz jeszcze

@teh_KaiN, post #25

No i nie wiem czy nie zapędziłem się w kozi róg, no ale może ktoś mi coś podpowie.

Mam sobie sytuację taką, że OS jest włączany tylko na czas loadingów, co by sobie czytać pliki kolejnych poziomów itd. i załóżmy, że mam własny sprzętowy wektor od CIA na którym obsługuję klawiaturę. Wychodzę sobie z poziomu trzymając klawiaturową strzałkę w prawo, włącza się loading następnego i wraca OS, w tym momencie puszczam klawiaturę, mój sprzętowy handler CIA nie jest już na miejscu więc zdarzenie puszczenia klawisza przepadło. Loading się kończy, wyświetla się nowy poziom i postać dalej biegnie w prawo, bo gra cały czas myśli że strzałka w prawo jest wciskana.

Mógłbym resetować odczytane stany klawiszy po powrocie z trybu OS, ale oznaczałoby to zatrzymanie postaci nawet jakbym fizycznie trzymał klawisz, a np. w takim Flashbacku byłoby to niewskazane.

Jakimś rozwiązaniem byłoby założenie systemowego handlera klawiatury z kodem tożsamym dla niesystemowego, ale zastanawiam się czy nie dałoby rady jakoś sprytniej tego zrobić. Próbowałem oddawać OSowi kontrolę bez włączania jego wektora CIA, ale kończyło się to zwiechą.

To co mnie zniechęca przed systemowym handlerem, to to że musiałbym to zrobić jakoś tak żeby klawiatura nie propagowała się dalej na okna będące otwarte w tle gry - nie chcę też wracać do zakładania screena i windowa na cały ekran przechwytujących eventy intuition, bo szkoda mi na to RAMu. Próbowałem przez chwilę z SetIntVector ale coś mi nie działało, bo mimo że handler resetował odpowiedni bit IntReq i kończył się asmową instrukcją cmp d0,d0 to miałem zwiechę. Jeśli uważacie, że ten SetIntVector i dualny handler CIA (os i nie-os) jest najbardziej poprawną drogą to spróbuję raz jeszcze ale bardziej wytrwale. ;)

Ostatnia aktualizacja: 12.04.2018 23:49:03 przez teh_KaiN
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem