11 January 2024, 03:46 | #1 |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
PTPlayer in a C program - VBR?
I'm working on a roguelike written in C. I recently incorporated ptplayer. I'm getting a MuForce hit on read/write from $78. That is happening in mt_install_cia:
Code:
_mt_install_cia: ; Install a CIA-B interrupt for calling mt_music. ; a6 = CUSTOM ; a0 = VectorBase ; d0 = PALflag.b (0 is NTSC) ifnd SDATA move.l a4,-(sp) lea mt_data(pc),a4 endc clr.b mt_Enable(a4) ; remember level 6 vector and interrupt enable lea $78(a0),a0 Code:
; _mt_install_cia(a6=CUSTOM, a0=VectorBase, d0=PALflag.b) ; Install a CIA-B interrupt for calling mt_music or mt_sfxonly. ; The music module is replayed via mt_music when _mt_Enable is non-zero. ; Otherwise the interrupt handler calls mt_sfxonly to play sound ; effects only. VectorBase is 0 for 68000, otherwise set it to the CPU's ; VBR register. A non-zero PALflag selects PAL-clock for the CIA timers ; (NTSC otherwise). What's my best plan for getting the right VBR value to pass to mt_install_cia? One more point of info: I am trying to make this an OS-friendly game, not a take-over-the-hardware game. I noticed today that the docs for ptplayer frown on, but don't totally poo-poo that: Code:
This player is intended for games/demos which take over the hardware and disable the OS. Running with the OS alive may work, as the OS doesn't use the CIA-B timers, but it is not recommended. Here's a thread I found with some ASM code, but I can't evaluate this and am not sure how I could use this: https://eab.abime.net/showthread.php...&highlight=VBR (and reading follow-up from Toni Willen, seems like it wouldn't be best for my situation, even if I could transplant that). FWIW, the player seems to work so far on 68030 and 68000, passing 0 for VBR: [ Show youtube player ] (game starts at about 11:25). |
11 January 2024, 03:55 | #2 |
Registered User
Join Date: Jan 2019
Location: /home
Posts: 122
|
VBR is 0 on 68000 and can not be changed. If you use 0 in your code you should be fine.
VBR points to the start of the CPU exception vector table, which your code seems to use to get interrupt level 6 to jump to a specific location. From 68010 the CPUs have a specialized register to move those vectors to an arbitrary address in memory. |
11 January 2024, 04:11 | #3 |
Registered User
Join Date: Dec 2017
Location: Austin, TX
Age: 41
Posts: 406
|
Here's my implementation: https://github.com/amigageek/modsurf.../system.c#L391
|
11 January 2024, 05:07 | #4 | ||
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Quote:
I think maybe Supervisor() is a 2.0+ function. Could that be? It's in clib/exec_protos.h in the newer SDKs I have, and I see it in RKRM, but not in clib/exec_protos.h in my 1.3 NDK. Maybe I could use SuperState to accomplish same thing? Quote:
Googling for some SuperState() examples... |
||
11 January 2024, 05:20 | #5 | |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Oh, no...
Quote:
|
|
11 January 2024, 10:08 | #6 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
If you're not taking over the hardware, you should probably use OS functions to install your ISR. It's been many years since I last did this, but I think you can use cia.resource to make sure the timer is available, and install the ISR.
|
11 January 2024, 10:28 | #7 | |
Amigan
Join Date: Feb 2012
Location: London
Posts: 1,311
|
Quote:
http://amigadev.elowar.com/read/ADCD.../node0326.html |
|
11 January 2024, 16:19 | #8 | |
Registered User
Join Date: Dec 2017
Location: Austin, TX
Age: 41
Posts: 406
|
Quote:
I guess try it and see. |
|
11 January 2024, 16:46 | #9 | |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
|
Quote:
Yes, except that he isn't trying to add a VERTB ISR To add a cia ISR, use cia.resource AddICRVector() |
|
11 January 2024, 18:13 | #10 |
Amigan
Join Date: Feb 2012
Location: London
Posts: 1,311
|
|
12 January 2024, 02:20 | #11 | |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Quote:
Code:
/* ERROR: The struct Resource doesn't exist in the includes, in the autodocs is only an APTR */ /* APTR */ #ifndef EXEC_TYPES_H #include <exec/types.h> #endif /* struct Library */ #ifndef EXEC_LIBRARIES_H #include <exec/libraries.h> #endif /* struct Resident */ #ifndef EXEC_RESIDENT_H #include <exec/resident.h> #endif /* struct MsgPort, struct Message */ #ifndef EXEC_PORTS_H #include <exec/ports.h> #endif /* struct Interrupt */ #ifndef EXEC_INTERRUPTS_H #include <exec/interrupts.h> #endif /* struct List */ #ifndef EXEC_LISTS_H #include <exec/lists.h> #endif /* struct Node */ #ifndef EXEC_NODES_H #include <exec/nodes.h> #endif /* struct Task */ #ifndef EXEC_TASKS_H #include <exec/tasks.h> #endif /* struct Device */ #ifndef EXEC_DEVICES_H #include <exec/devices.h> #endif /* struct IORequest, struct IOStdReq */ #ifndef EXEC_IO_H #include <exec/io.h> #endif /* struct Semaphore, struct SignalSemaphore */ #ifndef EXEC_SEMAPHORES_H #include <exec/semaphores.h> #endif /* struct MemHeader, struct MemList */ #ifndef EXEC_MEMORY_H #include <exec/memory.h> #endif typedef void (*__fptr)(); /*------ special functions ---------------------------------------------*/ void InitCode(long, long); void InitStruct(char *, char *, long); struct Library *MakeLibrary(long**, char *, __fptr, long, char *); void MakeFunctions(char *, long**, long); struct Resident *FindResident(char *); void InitResident(struct Resident *, char *); void Alert(long, APTR); void Debug(long); /*------ interrupts ----------------------------------------------------*/ void Disable(void); void Enable(void); void Forbid(void); void Permit(void); long SetSR(long, long); long SuperState(void); void UserState(char *); struct Interrupt *SetIntVector(long, struct Interrupt *); void AddIntServer(long, struct Interrupt *); void RemIntServer(long, struct Interrupt *); void Cause(struct Interrupt *); /*------ memory allocation: ---------------------------------------------*/ void * Allocate(struct MemHeader *, long); void Deallocate(struct MemHeader *, void *, long); void* AllocMem(long, long); void AllocAbs(long, void*); void FreeMem(void *, long); long AvailMem(long); struct MemList * AllocEntry(struct MemList *); void FreeEntry(struct MemList *); /*------ lists: ---------------------------------------------------------*/ void Insert(struct List *, struct Node *, struct Node *); void AddHead(struct List *, struct Node *); void AddTail(struct List *, struct Node *); void Remove(struct Node *); struct Node *RemHead(struct List *); struct Node *RemTail(struct List *); void Enqueue(struct List *, struct Node *); struct Node *FindName(struct List *, char *); /*------ tasks: ---------------------------------------------------------*/ void AddTask(struct Task *, char *, char *); void RemTask(struct Task *); struct Task *FindTask(char *); long SetTaskPri(struct Task *, long); long SetSignal(long, long); long SetExcept(long, long); long Wait(long); void Signal(struct Task *, long); long AllocSignal(long); void FreeSignal(long); long AllocTrap(long); void FreeTrap(long); /*------ messages: ------------------------------------------------------*/ void AddPort(struct MsgPort *); void RemPort(struct MsgPort *); void PutMsg(struct MsgPort *, struct Message *); struct Message *GetMsg(struct MsgPort *); void ReplyMsg(struct Message *); struct Message *WaitPort(struct MsgPort *); struct MsgPort *FindPort(char *); /*------ libraries: -----------------------------------------------------*/ void AddLibrary(struct Library *); long RemLibrary(struct Library *); struct Library *OldOpenLibrary(char *); void CloseLibrary(struct Library *); __fptr SetFunction(struct Library *, long, __fptr); void SumLibrary(struct Library *); /*------ devices: -------------------------------------------------------*/ void AddDevice(struct Device *); long RemDevice(struct Device *); long OpenDevice(char *, long, struct IORequest *, long); void CloseDevice(struct IORequest *); long DoIO(struct IORequest *); void SendIO(struct IORequest *); long CheckIO(struct IORequest *); long WaitIO(struct IORequest *); void AbortIO(struct IORequest *); /*------ resources: ----------------------------------------------------*/ /* ERROR: void AddResource(struct Resource *); void RemResource(struct Resource *); struct Resource *OpenResource(char *, long); */ /* Prototypes that appears in the Autodocs */ void AddResource(APTR); APTR OpenResource(char *); /* Only one argument in autodocs */ void RemResource(APTR); /*------ new functions:*/ long GetCC(void); void TypeOfMem(char *); long Procure(struct Semaphore *, struct Message *); void Vacate(struct Semaphore *); struct Library *OpenLibrary(char *, long); /*------ 1.2 new semaphore support*/ void InitSemaphore(struct SignalSemaphore *); void ObtainSemaphore(struct SignalSemaphore *); void ReleaseSemaphore(struct SignalSemaphore *); long AttemptSemaphore(struct SignalSemaphore *); void ObtainSemaphoreList(struct List *); void ReleaseSemaphoreList(struct List *); struct SignalSemaphore *FindSemaphore(char *); void AddSemaphore(struct SignalSemaphore *); void RemSemaphore(struct SignalSemaphore *); /*------ 1.2 rom "kickstart" support + memory support*/ void SumKickData(void); long AddMemList(long, long, long, char *, char *); void CopyMem(char *, char *, long); void CopyMemQuick(char *, char *, long); /*------ Common support library functions ---------*/ void BeginIO(struct IORequest *); struct IORequest *CreateExtIO(struct MsgPort *, long); struct MsgPort *CreatePort(char *, long); struct IOStdReq *CreateStdIO(struct MsgPort *); struct Task *CreateTask(char *, long, char *, unsigned long); void DeleteExtIO(struct IORequest *); void DeletePort(struct MsgPort *); void DeleteStdIO(struct IOStdReq *); void DeleteTask(struct Task *); void NewList(struct List *); And the one from m68k-amigaos: Code:
#ifndef _VBCCINLINE_EXEC_H #define _VBCCINLINE_EXEC_H #ifndef EXEC_TYPES_H #include <exec/types.h> #endif ULONG __Supervisor(__reg("a6") void *, __reg("a5") ULONG (*userFunction)())="\tjsr\t-30(a6)"; #define Supervisor(userFunction) __Supervisor(SysBase, (userFunction)) VOID __InitCode(__reg("a6") void *, __reg("d0") ULONG startClass, __reg("d1") ULONG version)="\tjsr\t-72(a6)"; #define InitCode(startClass, version) __InitCode(SysBase, (startClass), (version)) VOID __InitStruct(__reg("a6") void *, __reg("a1") CONST_APTR initTable, __reg("a2") APTR memory, __reg("d0") ULONG size)="\tjsr\t-78(a6)"; #define InitStruct(initTable, memory, size) __InitStruct(SysBase, (initTable), (memory), (size)) <SNIP> #endif /* _VBCCINLINE_EXEC_H */ |
|
12 January 2024, 03:24 | #12 | |
Registered User
Join Date: Dec 2017
Location: Austin, TX
Age: 41
Posts: 406
|
Quote:
Code:
$ grep -r Supervisor vbcc_target_m68k-kick13 vbcc_target_m68k-kick13/targets/m68k-kick13/include/clib/exec_protos.h:ULONG Supervisor(ULONG (*userFunction)()); vbcc_target_m68k-kick13/targets/m68k-kick13/include/inline/exec_protos.h:ULONG __Supervisor(__reg("a6") void *, __reg("a5") ULONG (*userFunction)())="\tjsr\t-30(a6)"; vbcc_target_m68k-kick13/targets/m68k-kick13/include/inline/exec_protos.h:#define Supervisor(userFunction) __Supervisor(SysBase, (userFunction)) |
|
12 January 2024, 06:05 | #13 |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Well shiver me timbers. I never thought VBCC's 1.3 target would be getting updates.
Before I saw that, this is what I ended up doing. As far as I can tell, it's working: no more muforce hit, and VBR is getting a non-zero number (and music still plays). Code:
// get VBR value that PTPlayer requires // this code is based on code provided by AmigaGeek (on EAB): // https://github.com/amigageek/modsurfer/blob/4bdebbdc6162cc79af394c3caee40d5867808401/system.c#L391 // Supervisor() is not available in VBCC KS 1.3, so trying with SuperState() and UserState(). static ULONG App_GetVBR(void) { // VBR is 0 on 68000, supervisor register on 68010+. ULONG vbr = 0; LONG userstack; if (SysBase->AttnFlags & (1U << AFB_68010)) { // enter supervisor mode and get user stack userstack = SuperState(); vbr = mt_get_vbr(); // restore user stack UserState((char*)userstack); } return vbr; } added a mini function to the ptplayer.asm file: Code:
; lich king hack ; little hack function to return VBR value ;unsigned long ASM mt_get_vbr(void); xdef _mt_get_vbr _mt_get_vbr: movec vbr,d0 rts ; end lich king hack |
12 January 2024, 17:15 | #14 | ||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,499
|
Quote:
Supervisor()was in exec.library since the beginning. The problem is the exec_lib.fdfrom the 1.3 NDK, which I used to generate vbcc's system headers and inlines (using fd2pragma). This old FD file declares Supervisor()as ##private, while it is ##publicin later NDKs. One of the last vbcc udpates for m68k-kick13 fixed that. Quote:
And there will be more to come! I have already some m68k-kick13 changes for the next release in our source repository. |
||
12 January 2024, 19:25 | #15 | |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Quote:
From my POV, we exist in a golden age: people are actively updating an OS from the 1980s; people are actively making brand new games for olde timey computers; and people are out there making and improving dev tools for our old computers. Not to mention all the amazing new hardware people make. Is there a job where I can work 12 hours a day at retro stuff, get paid something? Clearly I should have been a stock broker or something in my 20s so I could be retired now. |
|
13 January 2024, 08:39 | #16 |
Registered User
Join Date: Sep 2019
Location: Finland
Posts: 363
|
Rewriting the level 6 interrupt vector is not very system friendly
cia.resource should be used for CIA based timers (as well as audio.resource for reserving the audio channels). CIA timer is needed for Protracker modules to support the tempo command properly. Alternatively one could run the music using the VBlank interrupt which is much easier to set up, but then again this will not sound correct if VBlank is not 50Hz (depends on the active screen mode). |
13 January 2024, 15:21 | #17 | ||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,499
|
Quote:
Quote:
NO_TIMERS. Then it no longer writes interrupt vectors or timer registers. From the source: Code:
; Setting NO_TIMERS disables the use of both CIA-B timers completely, which ; means that the player doesn't depend on level-6 EXTER interrupts anymore. ; NO_TIMERS=1 automatically includes VBLANK_MUSIC=1 (see below). ; With NO_TIMERS set, your main program has to call all music subroutines ; itself. The typical procedure in a VERTB-based main loop would be: ; 1. call _mt_music ; 2. wait at least 550 ticks, then call _mt_dmaon ; 3. wait at least 550 ticks again, then call _mt_setrep ; The last two steps could for example be done by Copper interrupts. |
||
13 January 2024, 15:35 | #18 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Well, thanks to you for implementing it!
I needed it to implement a player completely handled via Copper, and yup, it worked like a charm |
13 January 2024, 15:49 | #19 |
Registered User
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
|
Just out of like, curiosity, what kind of bad behavior should any user foolish enough to run this program expect, if I just like went ahead with using it the way it is? Like, HOW un-system-friendly is using the level 6 interrupts? Is it more than music will lag sometimes, or will it break some piece of system software that was depending on not having the interrupts diverted?
Not that I'm surrendering before trying, but I'm thinking I'm probably not going to do a very good job at writing my own interrupt code. I've only ever done that for 6502 machines, and the Amiga is a whole other beast. |
13 January 2024, 16:35 | #20 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Quote:
Some software, especially old ones, simply diverted the vector and ignored the TOD bit on IRQ handling code, therefore the IRQ6 through the timers worked without problems for the audio player... but expect somewhere side effects... I remember nasty bug due to bad CIA setup/handling code. So be polite: request its use (allocate CIA/IRQs appropriately) if your software is system friendly and don't violate the rules. If you take control of the system, do whatever you want with it |
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Ptplayer sfx problem | sandruzzo | Coders. General | 4 | 09 October 2022 13:37 |
Ptplayer question | sandruzzo | Coders. General | 11 | 06 October 2022 05:47 |
Amiblitz 3 and PtPlayer | Nightshft | Coders. Blitz Basic | 4 | 14 November 2021 00:28 |
CacheControl and VBR from bootblock | h0ffman | Coders. Asm / Hardware | 11 | 26 May 2021 17:57 |
Problem with ptplayer | MacSpain | support.Other | 2 | 23 January 2020 19:52 |
|
|