diff Plugins/Input/adplug/core/dro.cpp @ 428:15ca2ea93a30 trunk

[svn] Sync with upstream CVS. This implements RIX playback.
author chainsaw
date Sat, 14 Jan 2006 07:27:13 -0800
parents 8df427a314a8
children f12d7e208b43
line wrap: on
line diff
--- a/Plugins/Input/adplug/core/dro.cpp	Sat Jan 14 05:40:19 2006 -0800
+++ b/Plugins/Input/adplug/core/dro.cpp	Sat Jan 14 07:27:13 2006 -0800
@@ -1,6 +1,6 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,9 +18,12 @@
  *
  * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet@zophar.net>
  *
- * NOTES:
- * OPL3 and second opl2 writes are ignored
-  */
+ * upgraded by matthew gambrell <zeromus@zeromus.org>
+ * 
+ * NOTES: 3-oct-04: the DRO format is not yet finalized. beware.
+ */
+
+#include <stdio.h>
 
 #include "dro.h"
 
@@ -31,69 +34,96 @@
   return new CdroPlayer(newopl);
 }
 
+CdroPlayer::CdroPlayer(Copl *newopl)
+  : CPlayer(newopl), data(0)
+{
+  if(opl->gettype() == Copl::TYPE_OPL2)
+    opl3_mode = 0;
+  else
+    opl3_mode = 1;
+}
+
 bool CdroPlayer::load(const std::string &filename, const CFileProvider &fp)
 {
-	binistream *f = fp.open(filename); if(!f) return false;
-	char id[8];unsigned long i;
+  binistream *f = fp.open(filename); if(!f) return false;
+  char id[8];
+  unsigned long i;
 
-	// file validation section
-	f->readString(id, 8);
-	if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; }
+  // file validation section
+  f->readString(id, 8);
+  if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; }
+  int version = f->readInt(4);	// not very useful just yet
+  if(version != 0x10000) { fp.close(f); return false; }
 
-	// load section
-	mstotal = f->readInt(4);	// Total milliseconds in file
-	length = f->readInt(4);		// Total data bytes in file
-	mode = (OplMode)f->readInt(1);		// Type of opl data this can contain
-	data = new unsigned char [length];
-	for (i=0;i<length;i++) 
-		data[i]=f->readInt(1);
-	fp.close(f);
-	rewind(0);
-	return true;
+  // load section
+  mstotal = f->readInt(4);	// Total milliseconds in file
+  length = f->readInt(4);	// Total data bytes in file
+  f->ignore(1);			// Type of opl data this can contain - ignored
+  data = new unsigned char [length];
+  for (i=0;i<length;i++) 
+    data[i]=f->readInt(1);
+  fp.close(f);
+  rewind(0);
+  return true;
 }
 
 bool CdroPlayer::update()
 {
-	if (delay>500) {
-		delay-=500;
-		return true;
-	} else delay=0;
-	while (pos < length) 
-	{	
-		unsigned char cmd = data[pos++];
-		switch(cmd) {
-		case 0: 
-			delay = 1 + data[pos++];
-			return true;
-		case 1: 
-			delay = 1 + data[pos] + (data[pos+1]<<8);
-			pos+=2;
-			return true;
-		case 2:
-			index = 0;
-			break;
-		case 3:
-			index = 0;
-			break;
-		default:
-		  if(!index)
-		    opl->write(cmd,data[pos++]);
-		  break;
-		}
-	}
-	return pos<length;
+  if (delay>500) {
+    delay-=500;
+    return true;
+  } else
+    delay=0;
+
+  while (pos < length) {
+    unsigned char cmd = data[pos++];
+    switch(cmd) {
+    case 0: 
+      delay = 1 + data[pos++];
+      return true;
+    case 1: 
+      delay = 1 + data[pos] + (data[pos+1]<<8);
+      pos+=2;
+      return true;
+    case 2:
+      index = 0;
+      opl->setchip(0);
+      break;
+    case 3:
+      index = 1;
+      opl->setchip(1);
+      break;
+    default:
+      if(cmd==4) cmd = data[pos++]; //data override
+      if(index == 0 || opl3_mode)
+	opl->write(cmd,data[pos++]);
+      break;
+    }
+  }
+
+  return pos<length;
 }
 
 void CdroPlayer::rewind(int subsong)
 {
-	delay=1;
-	pos = index = 0; 
-	opl->init(); 
-	opl->write(1,32);	// go to OPL2 mode
+  delay=1; 
+  pos = index = 0; 
+  opl->init(); 
+
+  //dro assumes all registers are initialized to 0
+  //registers not initialized to 0 will be corrected
+  //in the data stream
+  for(int i=0;i<256;i++)
+    opl->write(i,0);
+	
+  opl->setchip(1);
+  for(int i=0;i<256;i++)
+    opl->write(i,0);
+  opl->setchip(0);
 }
 
 float CdroPlayer::getrefresh()
 {
-	if (delay > 500) return 1000 / 500;
-	else return 1000 / (double)delay;
+  if (delay > 500) return 1000 / 500;
+  else return 1000 / (double)delay;
 }