Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

520 lines
15 KiB

  1. /*
  2. NXCűʃwb_[t@C
  3. iNP2)@Sachiko Yasukawa
  4. */
  5. // Date | Author | Description
  6. // -----------+--------------+--------------------------------------------
  7. // 1998.03.27 | Hideki Yagi | Change the specification about GetSTC().
  8. // | | Change the specification about
  9. // | | Get***Property().
  10. //
  11. #define ISMIXSTREAM(type) ((type == Dvd || type == VideoCD) ? TRUE : FALSE)
  12. typedef enum{
  13. Video,
  14. Audio,
  15. Subpicture,
  16. Dvd,
  17. VideoCD,
  18. } STREAMTYPE;
  19. class CBaseStream;
  20. class IMPEGBoardBaseState
  21. {
  22. public:
  23. virtual BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *)=0;
  24. virtual BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *)=0;
  25. virtual BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *)=0;
  26. virtual BOOL ChangePause(IClassLibHAL *, IHALStreamControl *)=0;
  27. virtual BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *)=0;
  28. virtual BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *)=0;
  29. virtual BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *)=0;
  30. };
  31. class CPowerOffState : public IMPEGBoardBaseState
  32. {
  33. public:
  34. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  35. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  36. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  37. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  38. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  39. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  40. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  41. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  42. private:
  43. IMPEGBoardState *m_pMPEGBoardState;
  44. };
  45. class CStopState : public IMPEGBoardBaseState
  46. {
  47. public:
  48. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  49. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  50. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  51. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  52. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  53. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  54. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  55. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  56. private:
  57. IMPEGBoardState *m_pMPEGBoardState;
  58. };
  59. class CPlayState : public IMPEGBoardBaseState
  60. {
  61. public:
  62. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  63. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  64. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  65. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  66. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  67. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  68. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  69. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  70. private:
  71. IMPEGBoardState *m_pMPEGBoardState;
  72. };
  73. class CPauseState : public IMPEGBoardBaseState
  74. {
  75. public:
  76. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  77. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  78. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  79. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  80. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  81. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  82. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  83. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  84. private:
  85. IMPEGBoardState *m_pMPEGBoardState;
  86. };
  87. class CSlowState : public IMPEGBoardBaseState
  88. {
  89. public:
  90. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  91. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  92. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  93. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  94. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  95. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  96. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  97. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  98. private:
  99. IMPEGBoardState *m_pMPEGBoardState;
  100. };
  101. class CScanState : public IMPEGBoardBaseState
  102. {
  103. public:
  104. void Init(IMPEGBoardState *pMPEGBoardState){m_pMPEGBoardState = pMPEGBoardState;};
  105. BOOL ChangePowerOff(IClassLibHAL *, IHALStreamControl *);
  106. BOOL ChangeStop(IClassLibHAL *, IHALStreamControl *, CBaseStream *);
  107. BOOL ChangePlay(IClassLibHAL *, IHALStreamControl *);
  108. BOOL ChangePause(IClassLibHAL *, IHALStreamControl *);
  109. BOOL ChangePauseViaSingleStep(IClassLibHAL *, IHALStreamControl *);
  110. BOOL ChangeSlow(DWORD, IClassLibHAL *, IHALStreamControl *);
  111. BOOL ChangeScan(DWORD, IClassLibHAL *, IHALStreamControl *);
  112. private:
  113. IMPEGBoardState *m_pMPEGBoardState;
  114. };
  115. class CMPEGBoardState : public IMPEGBoardState
  116. {
  117. friend class CMPEGBoard;
  118. friend class CBaseStream;
  119. public:
  120. BOOL Init(){ m_pStateObject = (IMPEGBoardBaseState *)&m_PowerOffState; m_State = PowerOff;
  121. m_PowerOffState.Init(this); m_StopState.Init(this); m_PauseState.Init(this); m_PlayState.Init(this);
  122. m_ScanState.Init(this); m_SlowState.Init(this); return TRUE;};
  123. //�Ǝ�
  124. CMPEGBoardState(){Init();};
  125. IMPEGBoardBaseState *GetMPEGBoardState(){return m_pStateObject;};
  126. LIBSTATE GetState(){ return m_State;};
  127. void SetState(LIBSTATE);
  128. private:
  129. //IMPEGBoardState *m_this;
  130. IMPEGBoardBaseState *m_pStateObject;
  131. CPowerOffState m_PowerOffState;
  132. CStopState m_StopState;
  133. CPauseState m_PauseState;
  134. CPlayState m_PlayState;
  135. CSlowState m_SlowState;
  136. CScanState m_ScanState;
  137. LIBSTATE m_State;
  138. };
  139. class CTransfer;
  140. class CClassLibEvent : public IMPEGBoardEvent
  141. {
  142. public:
  143. void Advice(PVOID);
  144. HALEVENTTYPE GetEventType(){return m_Type;};
  145. IMBoardListItem* GetNext( void ){ return m_pNextEvent;};
  146. void SetNext( IMBoardListItem *Item ){ m_pNextEvent = Item;};
  147. CClassLibEvent(){m_pNextEvent = NULL; m_pTransfer = NULL; m_Type = ClassLibEvent_SendData;};
  148. void SetTransfer(CTransfer *pTransfer){m_pTransfer = pTransfer;};
  149. void SetEventType(HALEVENTTYPE type){ m_Type = type;};
  150. private:
  151. HALEVENTTYPE m_Type;
  152. IMBoardListItem *m_pNextEvent;
  153. CTransfer *m_pTransfer;
  154. };
  155. class CBaseStream : public IBaseStream
  156. {
  157. friend class CMPEGBoard;
  158. public:
  159. //IBaseStream����
  160. BOOL Init();
  161. BOOL Play();
  162. BOOL Stop();
  163. BOOL Pause();
  164. BOOL Slow(DWORD);
  165. BOOL Scan(DWORD);
  166. BOOL SingleStep();
  167. LIBSTATE GetState();
  168. BOOL SendData(IMPEGBuffer *);
  169. BOOL SetStateObject(IMPEGBoardState *pMPEGBoardStateObject);
  170. BOOL SetTransferObject(ITransfer *pTransfer);
  171. BOOL SetTransferMode(HALSTREAMMODE);
  172. BOOL SetDataDirection(DirectionType type );
  173. BOOL GetDataDirection(DirectionType *ptype );
  174. //�Ǝ�
  175. CBaseStream();
  176. IMPEGBoardBaseState *GetStateObject();
  177. IClassLibHAL *GetClassLibHAL(){return m_pIHAL;};
  178. IHALStreamControl *GetHALStreamControl(){return m_pIStreamHAL;};
  179. IMPEGBoardBaseState *GetIMPEGBoardState(){ return (((CMPEGBoardState *)m_pMPEGBoardStateObject)->GetMPEGBoardState());};
  180. void FlushTransferBuffer();
  181. IBaseStream *GetNextStream(){return m_pNextStreamObject;};
  182. IBaseStream *GetPrevStream(){return m_pPrevStreamObject;};
  183. void SetNextStream(IBaseStream *pNextStreamObject){m_pNextStreamObject = (CBaseStream *)pNextStreamObject;};
  184. void SetPrevStream(IBaseStream *pPrevStreamObject){m_pPrevStreamObject = (CBaseStream *)pPrevStreamObject;};
  185. BOOL ISMIXSTREAMTYPE(STREAMTYPE StreamType){return (StreamType == VideoCD) ? TRUE : ((StreamType == Dvd) ? TRUE : FALSE);};
  186. protected:
  187. CBaseStream *m_pNextStreamObject;
  188. CBaseStream *m_pPrevStreamObject;
  189. STREAMTYPE m_StreamType;
  190. IMPEGBoardState *m_pMPEGBoardStateObject;
  191. IClassLibHAL *m_pIHAL;
  192. IHALStreamControl *m_pIStreamHAL;
  193. ITransfer *m_pTransfer;
  194. UCHAR m_DriveChlgKey[10];
  195. UCHAR m_DecoderChlgKey[10];
  196. UCHAR m_DriveResKey[5];
  197. UCHAR m_DecoderResKey[5];
  198. };
  199. class CVideoStream : public CBaseStream, public IVideoProperty, public ICopyProtectProperty
  200. {
  201. public:
  202. BOOL CppInit();
  203. BOOL GetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  204. BOOL SetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  205. BOOL SetChlgKey(UCHAR *);
  206. BOOL GetChlgKey(UCHAR *);
  207. BOOL SetDVDKey1(UCHAR *);
  208. BOOL GetDVDKey2(UCHAR *);
  209. BOOL SetTitleKey(UCHAR *);
  210. BOOL SetDiscKey(UCHAR *);
  211. CVideoStream(){m_StreamType = Video;};
  212. };
  213. class CAudioStream : public CBaseStream, public IAudioProperty, public ICopyProtectProperty
  214. {
  215. public:
  216. BOOL CppInit();
  217. BOOL GetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  218. BOOL SetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  219. BOOL SetChlgKey(UCHAR *);
  220. BOOL GetChlgKey(UCHAR *);
  221. BOOL SetDVDKey1(UCHAR *);
  222. BOOL GetDVDKey2(UCHAR *);
  223. BOOL SetTitleKey(UCHAR *);
  224. BOOL SetDiscKey(UCHAR *);
  225. CAudioStream(){m_StreamType = Audio;};
  226. };
  227. class CSubpicStream : public CBaseStream, public ISubpicProperty, public ICopyProtectProperty
  228. {
  229. public:
  230. BOOL CppInit();
  231. BOOL GetSubpicProperty(SUBPICPROPTYPE PropertyType, PVOID pProperty);
  232. BOOL SetSubpicProperty(SUBPICPROPTYPE PropertyType, PVOID pProperty);
  233. BOOL SetChlgKey(UCHAR *);
  234. BOOL GetChlgKey(UCHAR *);
  235. BOOL SetDVDKey1(UCHAR *);
  236. BOOL GetDVDKey2(UCHAR *);
  237. BOOL SetTitleKey(UCHAR *);
  238. BOOL SetDiscKey(UCHAR *);
  239. CSubpicStream(){m_StreamType = Subpicture;};
  240. };
  241. class CVideoCDStream : public CBaseStream, public IVideoProperty, public IAudioProperty, public ICopyProtectProperty
  242. {
  243. public:
  244. BOOL CppInit();
  245. BOOL GetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  246. BOOL SetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  247. BOOL GetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  248. BOOL SetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  249. BOOL SetChlgKey(UCHAR *);
  250. BOOL GetChlgKey(UCHAR *);
  251. BOOL SetDVDKey1(UCHAR *);
  252. BOOL GetDVDKey2(UCHAR *);
  253. BOOL SetTitleKey(UCHAR *);
  254. BOOL SetDiscKey(UCHAR *);
  255. CVideoCDStream(){ m_StreamType = VideoCD;};
  256. };
  257. class CDVDStream : public CBaseStream, public IVideoProperty, public IAudioProperty,public ISubpicProperty, public ICopyProtectProperty
  258. {
  259. public:
  260. BOOL CppInit();
  261. BOOL GetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  262. BOOL SetVideoProperty(VIDEOPROPTYPE PropertyType, PVOID pProperty);
  263. BOOL GetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  264. BOOL SetAudioProperty(AUDIOPROPTYPE PropertyType, PVOID pProperty);
  265. BOOL GetSubpicProperty(SUBPICPROPTYPE PropertyType, PVOID pProperty);
  266. BOOL SetSubpicProperty(SUBPICPROPTYPE PropertyType, PVOID pProperty);
  267. BOOL SetChlgKey(UCHAR *);
  268. BOOL GetChlgKey(UCHAR *);
  269. BOOL SetDVDKey1(UCHAR *);
  270. BOOL GetDVDKey2(UCHAR *);
  271. BOOL SetTitleKey(UCHAR *);
  272. BOOL SetDiscKey(UCHAR *);
  273. BOOL GetCapability( CAPSTYPE PropType, DWORD *pPropType ); // H.Yagi
  274. CDVDStream(){m_StreamType = Dvd;};
  275. };
  276. class CClassLibBuffer : public IHALBuffer
  277. {
  278. public:
  279. DWORD GetSize();
  280. DWORD Flags();
  281. BYTE *GetBuffPointer();
  282. BYTE *GetLinBuffPointer();
  283. IMBoardListItem* GetNext(){ return m_pNext; };
  284. void SetNext( IMBoardListItem *Item ){ m_pNext = Item; };
  285. PVOID GetIMPEGBuffer(){ return m_pMPEGBoardBuffer;};
  286. CBaseStream *GetStream(){ return m_pStream;};
  287. CClassLibBuffer( void );
  288. CClassLibBuffer(IMBoardListItem *pBuffer, CBaseStream *pStream, DWORD PageNum);
  289. CClassLibBuffer(IMBoardListItem *pBuffer, CBaseStream *pStream, DWORD PageNum, DWORD Size, DWORD Add, DWORD LinAdd, DWORD flag);
  290. void SetParam(IMBoardListItem *pBuffer, CBaseStream *pStream, DWORD PageNum, DWORD Size, DWORD Add, DWORD LinAdd, DWORD flag);
  291. private:
  292. IMBoardListItem *m_pNext;
  293. DWORD m_PageNum;
  294. DWORD m_Size;
  295. DWORD m_flag;
  296. UCHAR *m_Add;
  297. UCHAR *m_LinAdd;
  298. CBaseStream *m_pStream;
  299. IMPEGBuffer *m_pMPEGBoardBuffer;
  300. public:
  301. BOOL m_fEnd;
  302. };
  303. #define MAXCLIBBUFF (20)
  304. class CMemoryAllocator
  305. {
  306. private:
  307. CClassLibBuffer Buff[MAXCLIBBUFF];
  308. int TopFreePoint;
  309. int LastFreePoint;
  310. int FreeBuffNum;
  311. public:
  312. CMemoryAllocator(){
  313. TopFreePoint = 0;
  314. LastFreePoint = 0;
  315. FreeBuffNum = MAXCLIBBUFF;
  316. for( int i = 0; i < MAXCLIBBUFF ; i ++ )
  317. Buff[i].SetNext( NULL );
  318. };
  319. ~CMemoryAllocator(){
  320. };
  321. CClassLibBuffer *Alloc(IMBoardListItem *pBuffer, CBaseStream *pStream, DWORD PageNum, DWORD Size, DWORD Add, DWORD LinAdd, DWORD flag)
  322. {
  323. CClassLibBuffer *pNewBuffer;
  324. if( FreeBuffNum == 0 )
  325. return NULL;
  326. pNewBuffer = &Buff[TopFreePoint];
  327. pNewBuffer->SetParam(pBuffer, pStream, PageNum, Size, Add, LinAdd, flag);
  328. FreeBuffNum--;
  329. TopFreePoint++;
  330. if( TopFreePoint == MAXCLIBBUFF )
  331. TopFreePoint = 0;
  332. return pNewBuffer;
  333. };
  334. void Free(CClassLibBuffer *pBuffer)
  335. {
  336. ASSERT( pBuffer == &Buff[LastFreePoint] );
  337. ASSERT( FreeBuffNum != MAXCLIBBUFF );
  338. LastFreePoint ++;
  339. if( LastFreePoint == MAXCLIBBUFF )
  340. LastFreePoint = 0;
  341. FreeBuffNum ++;
  342. pBuffer->SetNext(NULL);
  343. };
  344. int GetMaxBuffNum( void )
  345. {
  346. return MAXCLIBBUFF;
  347. };
  348. void Flush( void )
  349. {
  350. TopFreePoint = 0;
  351. LastFreePoint = 0;
  352. FreeBuffNum = MAXCLIBBUFF;
  353. for( int i = 0; i < MAXCLIBBUFF ; i ++ )
  354. Buff[i].SetNext( NULL );
  355. };
  356. };
  357. class CTransferStreamList : public IMBoardListItem
  358. {
  359. public:
  360. CTransferStreamList(){m_pNextItem = NULL; m_pBaseStream = NULL;};
  361. CTransferStreamList(CBaseStream *pStream){m_pNextItem = NULL; m_pBaseStream = pStream;};
  362. //378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
  363. void Init(CBaseStream *pStream){m_pNextItem = NULL; m_pBaseStream = pStream;};
  364. //378742
  365. IMBoardListItem* GetNext( void ){ return (IMBoardListItem *)m_pNextItem;};
  366. void SetNext( IMBoardListItem *Item ){ m_pNextItem = (CTransferStreamList *)Item;};
  367. CBaseStream *GetBaseStream(void){ return m_pBaseStream;};
  368. void SetBaseStream (CBaseStream *pStream){ m_pBaseStream = pStream;};
  369. private:
  370. CBaseStream *m_pBaseStream;
  371. CTransferStreamList *m_pNextItem;
  372. };
  373. class CTransfer : public ITransfer
  374. {
  375. friend class CMPEGBoard;
  376. #ifdef TEST
  377. friend class CMBoardAppDlg;
  378. #endif
  379. public:
  380. BOOL EnQueue( IMPEGBuffer *Buff);
  381. BOOL Init();
  382. BOOL SetSink(IMPEGBoardEvent *pEvent);
  383. BOOL UnSetSink(IMPEGBoardEvent *pEvent);
  384. BOOL SetDMABuffer(DWORD size, BYTE* LinerAdd, BYTE *PhysAdd);
  385. //�Ǝ�
  386. CTransfer(){Init();};
  387. ~CTransfer();
  388. BOOL DeQueue();
  389. BOOL AddStreamObject(IBaseStream *);
  390. BOOL ReleaseStreamObject(IBaseStream *);
  391. BOOL EndOfTransfer(CClassLibBuffer *);
  392. void Flush();
  393. private:
  394. CTransferStreamList *m_pStreamObject;
  395. //378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
  396. CTransferStreamList m_pNewTransferStreamList;
  397. //378742
  398. IMBoardListItem *m_pTopEventList, *m_pLastEventList;
  399. BYTE *m_LinerAdd;
  400. BYTE *m_PhysAdd;
  401. DWORD m_DMABufferSize;
  402. CClassLibEvent m_EndOfTransferEvent;
  403. IClassLibHAL *m_pIHAL;
  404. CMemoryAllocator m_Mem;
  405. IMPEGBuffer *m_pTopQueuedMPEGBuffer;
  406. IMPEGBuffer *m_pLastQueuedMPEGBuffer;
  407. IMPEGBuffer *m_pNextTransferMPEGBuffer;
  408. DWORD m_TopPagePoint;
  409. DWORD m_LastPagePoint;
  410. BOOL HasQueuedBuffer( void );
  411. BOOL GetNextTransferPoint( IMPEGBuffer **Point, DWORD *Page );
  412. BOOL FreeTopTransferPoint( IMPEGBuffer **Free );
  413. //�f�o�b�O�p
  414. int BufCount;
  415. DWORD StreamCount;
  416. };
  417. class CMPEGBoard : public IMPEGBoard
  418. {
  419. public:
  420. //IMPEGBoard����
  421. BOOL Init();
  422. BOOL AddStreamObjectInterface(IBaseStream *);
  423. BOOL ReleaseStreamObjectInterface(IBaseStream *);
  424. BOOL PowerOn();
  425. BOOL PowerOff();
  426. BOOL SetSTC(DWORD);
  427. BOOL GetSTC(DWORD *); // 98.03.27 H.Yagi
  428. BOOL SetHALObjectInterface(IClassLibHAL *);
  429. //�Ǝ�
  430. CMPEGBoard(){Init();};
  431. BOOL ChangePower(POWERSTATE);
  432. BOOL ISPOWEROFF(); //HAL���ݒ肳���Ă����‚�������
  433. BOOL SetHALStream(CBaseStream *, IClassLibHAL *);
  434. private:
  435. CBaseStream *m_pBaseStreamObject;//�Ǘ����ׂ��X�g���[���̃`�F�[���̐擪
  436. IClassLibHAL *m_pIHAL;//�n���C���^�t�F�[�X�ւ̃|�C���^
  437. };