English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 11 January 2024, 03:46   #1
Warty
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
docs:
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).
I'm targeting 68000 machines running 1.3 up through 680x0 running 3.2.2. (I can't test other combinations than that).

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.
So hopefully there's a way I can do whatever detection I need to without doing bad things to the system.

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).
Warty is offline  
Old 11 January 2024, 03:55   #2
R4M
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.
R4M is offline  
Old 11 January 2024, 04:11   #3
arcanist
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
arcanist is online now  
Old 11 January 2024, 05:07   #4
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Quote:
Originally Posted by arcanist View Post
Thanks @arcanist!

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:
The MC68000 has two stacks, the user stack (USP) and supervisor stack (SSP). As of the MC68020 there are two supervisor stacks, the interrupt stack pointer (ISP) and the master stack pointer (MSP). The SuperState() function allows you to enter supervisor mode with the USP used as SSP. The function returns the SSP, which will be the MSP, if an MC68020 or greater is used. Returning to user mode is done with the UserState() function. This function takes the SSP as argument, which must be saved when SuperState() is called. Because of possible problems with stack size, Supervisor() is to be preferred over SuperState().
http://wiki.amigaspirit.hu/index.php...age_(Chapter_8)

Googling for some SuperState() examples...
Warty is offline  
Old 11 January 2024, 05:20   #5
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Oh, no...

Quote:
BUGS
This function is broken in V33/34 Kickstart. Fixed in V1.31 setpatch.
http://amigadev.elowar.com/read/ADCD.../node0244.html
Warty is offline  
Old 11 January 2024, 10:08   #6
hooverphonique
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.
hooverphonique is offline  
Old 11 January 2024, 10:28   #7
nogginthenog
Amigan
 
Join Date: Feb 2012
Location: London
Posts: 1,311
Quote:
Originally Posted by hooverphonique View Post
If you're not taking over the hardware, you should probably use OS functions to install your ISR.
This is the way. Look at AddIntServer(INTB_VERTB, &myint);

http://amigadev.elowar.com/read/ADCD.../node0326.html
nogginthenog is offline  
Old 11 January 2024, 16:19   #8
arcanist
Registered User
 
Join Date: Dec 2017
Location: Austin, TX
Age: 41
Posts: 406
Quote:
Originally Posted by Warty View Post
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.
I don't see a minimum version note in the Autodoc. The prototype is in VBCC's m68k-kick13 target too.

I guess try it and see.
arcanist is online now  
Old 11 January 2024, 16:46   #9
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
Quote:
Originally Posted by nogginthenog View Post
This is the way. Look at AddIntServer(INTB_VERTB, &myint);

http://amigadev.elowar.com/read/ADCD.../node0326.html

Yes, except that he isn't trying to add a VERTB ISR
To add a cia ISR, use cia.resource AddICRVector()
hooverphonique is offline  
Old 11 January 2024, 18:13   #10
nogginthenog
Amigan
 
Join Date: Feb 2012
Location: London
Posts: 1,311
Quote:
Originally Posted by hooverphonique View Post
Yes, except that he isn't trying to add a VERTB ISR
To add a cia ISR, use cia.resource AddICRVector()
Ah I read VBR as VB. Just testing
nogginthenog is offline  
Old 12 January 2024, 02:20   #11
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Quote:
Originally Posted by arcanist View Post
I don't see a minimum version note in the Autodoc. The prototype is in VBCC's m68k-kick13 target too.

I guess try it and see.
Are you sure about that? This is the exec_protos.h from m68k-kick13.

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 *);
It doesn't compile.

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  */
Warty is offline  
Old 12 January 2024, 03:24   #12
arcanist
Registered User
 
Join Date: Dec 2017
Location: Austin, TX
Age: 41
Posts: 406
Quote:
Originally Posted by Warty View Post
Are you sure about that? This is the exec_protos.h from m68k-kick13.
This is the current version on VBCC's website:

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))
arcanist is online now  
Old 12 January 2024, 06:05   #13
Warty
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
Warty is offline  
Old 12 January 2024, 17:15   #14
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,499
Quote:
Originally Posted by Warty View Post
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.
Supervisor()
was in exec.library since the beginning. The problem is the
exec_lib.fd
from 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
##public
in later NDKs.
One of the last vbcc udpates for m68k-kick13 fixed that.

Quote:
Originally Posted by Warty View Post
Well shiver me timbers. I never thought VBCC's 1.3 target would be getting updates.
Why not? We are not perfect.
And there will be more to come! I have already some m68k-kick13 changes for the next release in our source repository.
phx is offline  
Old 12 January 2024, 19:25   #15
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Quote:
Originally Posted by phx View Post
Why not? We are not perfect.
And there will be more to come! I have already some m68k-kick13 changes for the next release in our source repository.
Thank you for the updates! I picked up 0.9h patch 3 targets last night and rebuilt. I need to rebuild my vbbc binaries, I'm still using something from 2017.

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.
Warty is offline  
Old 13 January 2024, 08:39   #16
koobo
Registered User
 
koobo's Avatar
 
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).
koobo is offline  
Old 13 January 2024, 15:21   #17
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,499
Quote:
Originally Posted by koobo View Post
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).
Exactly. That's why I don't recommend my player for system friendly software. Maybe I should add support for it, some day, but I never needed it myself and nobody has beaten me to it yet.

Quote:
Alternatively one could run the music using the VBlank interrupt
Yes. That could be a good, system-friendly alternative for Warty, if he also reserves audio channels in his own code. ptplayer can switch to VBlank-only by defining
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.
Thanks to Ross, BTW, who urged me to implement it.
phx is offline  
Old 13 January 2024, 15:35   #18
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
Quote:
Originally Posted by phx View Post
[/code]Thanks to Ross, BTW, who urged me to implement it.
Well, thanks to you for implementing it!

Quote:
Originally Posted by phx View Post
; The last two steps could for example be done by Copper interrupts.
I needed it to implement a player completely handled via Copper, and yup, it worked like a charm
ross is online now  
Old 13 January 2024, 15:49   #19
Warty
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.
Warty is offline  
Old 13 January 2024, 16:35   #20
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
Quote:
Originally Posted by Warty View Post
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.
If I'm not wrong, the graphics.library uses the CIAB TOD in certain situations (and set the IRQ mask for the relative bit), so it wouldn't be appropriate to use the IRQ6 directly.

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
ross is online now  
 


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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 19:02.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10568 seconds with 13 queries