Previous 15994 Revisions Next

r14873 Sunday 8th April, 2012 at 18:57:35 UTC by Sandro Ronco
x07: Added cassette load/save. (nw)
[src/lib]lib.mak
[src/lib/formats]x07_cas.c* x07_cas.h*
[src/mess/drivers]x07.c
[src/mess/includes]x07.h

src/lib/formats/x07_cas.c
r0r14873
1/********************************************************************
2
3    Support for Canon X-07 cassette images
4
5********************************************************************/
6
7#include "x07_cas.h"
8
9#define WAVEENTRY_LOW  -32768
10#define WAVEENTRY_HIGH  32767
11
12#define X07_WAV_FREQUENCY   4800
13#define X07_TIMER_FREQUENCY   1200
14#define X07_BIT_LENGTH      (X07_WAV_FREQUENCY/X07_TIMER_FREQUENCY)
15#define X07_HEADER_BYTES   16
16
17// image size
18static int x07_image_size;
19
20static int x07_put_samples(INT16 *buffer, int sample_pos, int count, int level)
21{
22   if (buffer)
23   {
24      for (int i=0; i<count; i++)
25         buffer[sample_pos + i] = level;
26   }
27
28   return count;
29}
30
31static int x07_output_bit(INT16 *buffer, int sample_pos, UINT8 bit)
32{
33   int samples = 0;
34
35   if (bit)
36   {
37      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_HIGH);
38      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_LOW);
39      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_HIGH);
40      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_LOW);
41   }
42   else
43   {
44      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/2, WAVEENTRY_HIGH);
45      samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/2, WAVEENTRY_LOW);
46   }
47
48    return samples;
49}
50
51static int x07_output_byte(INT16 *buffer, int sample_pos, UINT8 byte)
52{
53   int samples = 0;
54
55   /* start */
56   samples += x07_output_bit (buffer, sample_pos + samples, 0);
57
58   /* data */
59   for (int i=0; i<8; i++)
60      samples += x07_output_bit(buffer,sample_pos + samples, (byte>>i) & 0x01);
61
62   /* stop */
63   samples += x07_output_bit (buffer, sample_pos + samples, 1);
64   samples += x07_output_bit (buffer, sample_pos + samples, 1);
65   samples += x07_output_bit (buffer, sample_pos + samples, 1);
66
67   return samples;
68}
69
70static int x07_handle_cassette(INT16 *buffer, const UINT8 *bytes)
71{
72   int sample_count = 0;
73   int img_start = 0;
74
75   /* start */
76   for (int i=0; i<X07_WAV_FREQUENCY; i++)
77      sample_count += x07_output_bit(buffer, sample_count, 1);
78
79   /* header */
80   if (bytes[0] == 0xd3 && bytes[1] == 0xd3 && bytes[2] == 0xd3 && bytes[3] == 0xd3)
81   {
82      // valid header
83      for (int i=0; i<X07_HEADER_BYTES; i++)
84         sample_count += x07_output_byte(buffer, sample_count, bytes[i]);
85
86      img_start = X07_HEADER_BYTES;
87   }
88   else
89   {
90      // remove the NULL chars at start
91      while (!bytes[img_start])
92         img_start++;
93
94      // insert 0xd3 bytes
95      for (int i=0; i<10; i++)
96         sample_count += x07_output_byte(buffer, sample_count, 0xd3);
97
98      // fake filename
99      for (int i=0; i<6; i++)
100         sample_count += x07_output_byte(buffer, sample_count, 'A');
101   }
102
103   /* pause */
104   for (int i=0; i<X07_WAV_FREQUENCY/16; i++)
105      sample_count += x07_output_bit(buffer, sample_count, 1);
106
107   /* data */
108   for (int i=img_start; i<x07_image_size; i++)
109      sample_count += x07_output_byte(buffer, sample_count, bytes[i]);
110
111   /* end */
112   for (int i=0; i<X07_WAV_FREQUENCY/8; i++)
113      sample_count += x07_output_bit(buffer, sample_count, 1);
114
115   return sample_count;
116}
117
118
119/*******************************************************************
120   Generate samples for the tape image
121********************************************************************/
122
123static int x07_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes)
124{
125   return x07_handle_cassette(buffer, bytes);
126}
127
128/*******************************************************************
129   Calculate the number of samples needed for this tape image
130********************************************************************/
131
132static int x07_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
133{
134   x07_image_size = length;
135
136   return x07_handle_cassette(NULL, bytes);
137}
138
139static const struct CassetteLegacyWaveFiller x07_legacy_fill_wave =
140{
141   x07_cassette_fill_wave,               /* fill_wave */
142   -1,                              /* chunk_size */
143   0,                              /* chunk_samples */
144   x07_cassette_calculate_size_in_samples,   /* chunk_sample_calc */
145   X07_WAV_FREQUENCY,                  /* sample_frequency */
146   0,                              /* header_samples */
147   0                              /* trailer_samples */
148};
149
150static casserr_t x07_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts)
151{
152   return cassette_legacy_identify(cassette, opts, &x07_legacy_fill_wave);
153}
154
155static casserr_t x07_cassette_load(cassette_image *cassette)
156{
157   return cassette_legacy_construct(cassette, &x07_legacy_fill_wave);
158}
159
160static const struct CassetteFormat x07_cassette_image_format =
161{
162   "k7,lst,cas",
163   x07_cassette_identify,
164   x07_cassette_load,
165   NULL
166};
167
168CASSETTE_FORMATLIST_START(x07_cassette_formats)
169   CASSETTE_FORMAT(x07_cassette_image_format)
170CASSETTE_FORMATLIST_END
src/lib/formats/x07_cas.h
r0r14873
1/*********************************************************************
2
3    x07_cas.h
4
5    Format code for Canon X-07 casette images
6
7*********************************************************************/
8
9#ifndef X07_CAS_H
10#define X07_CAS_H
11
12#include "cassimg.h"
13
14CASSETTE_FORMATLIST_EXTERN(x07_cassette_formats);
15
16#endif /* X07_CAS_H */
src/lib/lib.mak
r14872r14873
162162   $(LIBOBJ)/formats/vt_dsk.o      \
163163   $(LIBOBJ)/formats/vtech1_dsk.o   \
164164   $(LIBOBJ)/formats/wavfile.o      \
165   $(LIBOBJ)/formats/x07_cas.o      \
165166   $(LIBOBJ)/formats/x1_tap.o      \
166167   $(LIBOBJ)/formats/z80ne_dsk.o   \
167168   $(LIBOBJ)/formats/zx81_p.o      \
src/mess/includes/x07.h
r14872r14873
44
55*********************************************************************/
66
7#include "emu.h"
8#include "cpu/z80/z80.h"
9#include "sound/beep.h"
710#include "machine/ram.h"
11#include "sound/wave.h"
12#include "imagedev/cartslot.h"
13#include "imagedev/cassette.h"
814#include "imagedev/printer.h"
15#include "formats/x07_cas.h"
16#include "rendlay.h"
917
1018//default value for user defined keys, taken for official documentation
1119static const char *const udk_ini[12] = {
r14872r14873
153161        m_maincpu(*this, "maincpu"),
154162        m_printer(*this, "printer"),
155163        m_beep(*this, BEEPER_TAG),
156        m_ram(*this, RAM_TAG)
164        m_ram(*this, RAM_TAG),
165        m_cassette(*this, CASSETTE_TAG)
157166   { }
158167
159168   required_device<cpu_device> m_maincpu;
160169   required_device<printer_image_device> m_printer;
161170   required_device<device_t> m_beep;
162171   required_device<ram_device> m_ram;
172   required_device<cassette_image_device> m_cassette;
163173
164174   void machine_start();
165175   void machine_reset();
r14872r14873
179189   void cassette_r();
180190   void printer_w();
181191   void kb_irq();
192   void cassette_load();
193   void cassette_save();
194   void receive_bit(int bit);
182195
183196   inline UINT8 get_char(UINT16 pos);
184197   inline UINT8 kb_get_index(UINT8 char_code);
r14872r14873
233246   UINT8 m_kb_size;
234247
235248   /* cassette */
236   emu_timer *m_k7irq;
237   UINT8  m_k7on;
238   UINT8 *m_k7data;
239   UINT32 m_k7size;
240   UINT32 m_k7pos;
249   UINT8  m_cass_motor;
250   UINT8  m_cass_data;
251   UINT32 m_cass_clk;
252   UINT8  m_bit_count;
253   int    m_cass_state;
254   emu_timer *m_cass_poll;
255   emu_timer *m_cass_tick;
241256
242257   /* printer */
243258   UINT8 m_prn_sendbit;
src/mess/drivers/x07.c
r14872r14873
99    - better emulation of the i/o ports
1010    - external video (need X-720 dump)
1111    - serial port
12    - load/save cassette in wav format
1312
1413    Memory Map
1514
r14872r14873
2827****************************************************************************/
2928
3029
31#include "emu.h"
32#include "cpu/z80/z80.h"
33#include "sound/beep.h"
3430#include "includes/x07.h"
35#include "imagedev/printer.h"
36#include "imagedev/cartslot.h"
37#include "machine/ram.h"
38#include "rendlay.h"
3931
4032/***************************************************************************
4133    T6834 IMPLEMENTATION
r14872r14873
663655   }
664656}
665657
666
667658void x07_state::cassette_r()
668659{
669   if (m_k7size && m_k7on && (m_k7pos<m_k7size))
660   m_regs_r[6] &= ~2;
661}
662
663void x07_state::cassette_w()
664{
665   m_regs_r[6] &= ~1;
666   m_cass_data = m_regs_w[7];
667}
668
669static TIMER_CALLBACK( cassette_tick )
670{
671   x07_state *state = machine.driver_data<x07_state>();
672   state->m_cass_clk++;
673}
674
675static TIMER_CALLBACK( cassette_poll )
676{
677   x07_state *state = machine.driver_data<x07_state>();
678
679   if ((state->m_cassette->get_state() & 0x03) == CASSETTE_PLAY)
680      state->cassette_load();
681   else if ((state->m_cassette->get_state() & 0x03) == CASSETTE_RECORD)
682      state->cassette_save();
683}
684
685void x07_state::cassette_load()
686{
687   int cass = (m_cassette->input() >= 0) ? +1 : -1;
688   if (cass > 0 && m_cass_state < 0)
670689   {
671      m_regs_r[6] |= 2;
672      m_regs_r[7] = m_k7data[m_k7pos++];
690      if ((m_cass_clk & 0x7f) >= 4 && (m_cass_clk & 0x7f) <= 6)
691      {
692         if (m_cass_clk & 0x80)
693         {
694            m_cass_clk = 0;
695            receive_bit(1);
696         }
697         else
698         {
699            m_cass_clk = 0x80;
700         }
701      }
702      else if ((m_cass_clk & 0x7f) >= 9 && (m_cass_clk & 0x7f) <= 11)
703      {
704         m_cass_clk = 0;
705         receive_bit(0);
706      }
707      else
708      {
709         m_cass_clk = 0;
710         logerror("Invalid data: %d %f\n", (m_cass_clk & 0x7f), m_cassette->get_position());
711      }
673712
674      popmessage("%04x//%04x", m_k7pos, m_k7size);
713      m_cass_tick->adjust(attotime::from_hz(12000), 0, attotime::from_hz(12000));
714   }
675715
676      m_k7irq->adjust(attotime::from_msec(2));
677   }
716   m_cass_state = cass;
678717}
679718
680719
681void x07_state::cassette_w()
720void x07_state::cassette_save()
682721{
683   //TODO
722   int cass = m_cass_state;
723
724   if (m_cass_clk % 10 == 0)
725   {
726
727      if (m_bit_count < 4)
728      {
729         switch (m_bit_count & 3)
730         {
731            case 0:    case 1:    cass = +1;   break;
732            case 2:    case 3:    cass = -1;   break;
733         }
734
735         m_bit_count++;
736      }
737      else if (m_bit_count < 36)
738      {
739         switch (m_bit_count & 3)
740         {
741            case 0:    cass = +1;   break;
742            case 1:    cass = (m_cass_data & 1) ? -1 : +1;   break;
743            case 2:    cass = (m_cass_data & 1) ? +1 : -1;   break;
744            case 3:    cass = -1;   m_cass_data >>= 1;      break;
745         }
746
747         m_bit_count++;
748      }
749      else if (m_bit_count < 48)
750      {
751         switch (m_bit_count & 3)
752         {
753            case 0:    case 2:    cass = +1;   break;
754            case 1:    case 3:    cass = -1;   break;
755         }
756
757         if (m_bit_count == 47)
758            m_regs_r[6] |= 1;
759
760         m_bit_count++;
761      }
762      else
763      {
764         cass = (m_cass_state > 0) ? -1 : +1;
765      }
766
767      m_cassette->output( cass );
768   }
769
770   // finish the current cycle before start the next
771   if ((m_cass_state <= 0) && !(m_regs_r[6] & 1) && m_bit_count >= 48)
772      m_bit_count = 0;
773
774   m_cass_state = cass;
775   m_cass_clk++;
684776}
685777
778void x07_state::receive_bit(int bit)
779{
780   if (m_bit_count == 0)
781   {
782      // wait for start bit
783      if (bit == 0)
784         m_bit_count++;
785   }
786   else if (m_bit_count < 9)
787   {
788      m_cass_data = (m_cass_data>>1) | (bit<<7);
789      m_bit_count++;
790   }
791   else if (m_bit_count < 12)
792   {
793      if (bit != 1)
794         logerror("Invalid stop bit: %f\n", m_cassette->get_position());
686795
796      m_bit_count++;
797   }
798
799   // every byte take 12 bit
800   if (m_bit_count == 12)
801   {
802      //printf("data: %02x %f\n", m_cass_data, m_cassette->get_position());
803      m_regs_r[6] |= 2;
804      m_regs_r[7] = m_cass_data;
805      m_cass_data = 0;
806      m_bit_count = 0;
807
808      device_set_input_line(m_maincpu, NSC800_RSTB, ASSERT_LINE);
809      m_rstb_clear->adjust(attotime::from_usec(200));
810
811   }
812}
813
814
687815/****************************************************
688816    this function emulate the color printer X-710
689817    only the text functions are emulated
r14872r14873
9101038      }
9111039}
9121040
913
914static DEVICE_IMAGE_LOAD( x07_cass )
915{
916   running_machine &machine = image.device().machine();
917   x07_state *state = machine.driver_data<x07_state>();
918   UINT8 *tmp_data;
919   UINT32 image_size;
920   char *basename = (char*)image.basename();
921
922   if (image.software_entry() == NULL)
923   {
924      image_size = image.length();
925      tmp_data = auto_alloc_array(machine, UINT8, image_size);
926      image.fread(tmp_data, image_size);
927   }
928   else
929   {
930      image_size = image.get_software_region_length("k7");
931      tmp_data = auto_alloc_array(machine, UINT8, image_size);
932      memcpy(tmp_data, image.get_software_region("k7"), image_size);
933   }
934
935   if (tmp_data[0] == 0xd3 && tmp_data[1] == 0xd3)
936   {
937      //image should be valid
938      state->m_k7data = auto_alloc_array(machine, UINT8, image_size);
939      memcpy(state->m_k7data, tmp_data, image_size);
940      state->m_k7size = image_size;
941   }
942   else
943   {
944      UINT8 *img_data = tmp_data;
945
946      //remove the NULL chars at start
947      while (!img_data[0])
948      {
949         image_size--;
950         img_data++;
951      }
952
953      //allocate the required space
954      state->m_k7data = auto_alloc_array(machine, UINT8, image_size + 0x10);
955
956      //insert the sync bytes
957      for(int i=0; i<10; i++)
958         state->m_k7data[i] = 0xd3;
959
960      //empty the name area
961      memset(state->m_k7data + 0x0a, 0x00, 6);
962
963      //copy basename in the name area
964      for(int i=0; i<6; i++)
965      {
966         if (basename[i] == 0 || basename[i] == '.')
967            break;
968         state->m_k7data[10 + i] = basename[i];
969      }
970
971      memcpy(state->m_k7data + 0x10, img_data, image_size);
972      state->m_k7size = image_size + 0x10;
973   }
974
975   state->m_k7pos = 0;
976   auto_free(machine, tmp_data);
977   return IMAGE_INIT_PASS;
978}
979
980
981static DEVICE_IMAGE_UNLOAD( x07_cass )
982{
983   running_machine &machine = image.device().machine();
984   x07_state *state = machine.driver_data<x07_state>();
985
986   auto_free(machine, state->m_k7data);
987   state->m_k7size = state->m_k7pos = 0;
988}
989
990
9911041static DEVICE_IMAGE_LOAD( x07_card )
9921042{
9931043   running_machine &machine = image.device().machine();
r14872r14873
10811131      data = 0x00;
10821132      break;
10831133   case 0xf6:
1084      if (m_k7on)   m_regs_r[6] |= 5;
1134      if (m_cass_motor)   m_regs_r[6] |= 4;
10851135      //fall through
10861136   case 0xf0:
10871137   case 0xf1:
r14872r14873
11241174
11251175   case 0xf4:
11261176      m_regs_r[4] = m_regs_w[4] = data;
1127      m_k7on = ((data & 0x0c) == 0x08) ? 1 : 0;
1177      m_cass_motor = ((data & 0x0d) == 0x09) ? 1 : 0;
11281178
1179      if (m_cass_motor)
1180      {
1181         m_cassette->change_state(CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR);
1182         m_cass_poll->adjust(attotime::from_hz(48000), 0, attotime::from_hz(48000));
1183      }
1184      else
1185      {
1186         m_cassette->change_state(CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
1187         m_cass_poll->reset();
1188         m_cass_tick->reset();
1189      }
1190
11291191#if(1)
11301192      if((data & 0x0e) == 0x0e)
11311193      {
r14872r14873
13271389   beep_set_state(state->m_beep, 0);
13281390}
13291391
1330static TIMER_CALLBACK( k7_irq )
1331{
1332   x07_state *state = machine.driver_data<x07_state>();
1333
1334   device_set_input_line(state->m_maincpu, NSC800_RSTB, ASSERT_LINE);
1335
1336   state->m_rstb_clear->adjust(attotime::from_usec(200));
1337}
1338
13391392static const gfx_layout x07_charlayout =
13401393{
13411394   6, 8,               /* 6 x 8 characters */
r14872r14873
13561409   m_rsta_clear = machine().scheduler().timer_alloc(FUNC(rsta_clear));
13571410   m_rstb_clear = machine().scheduler().timer_alloc(FUNC(rstb_clear));
13581411   m_beep_stop = machine().scheduler().timer_alloc(FUNC(beep_stop));
1359   m_k7irq = machine().scheduler().timer_alloc(FUNC(k7_irq));
1412   m_cass_poll = machine().scheduler().timer_alloc(FUNC(cassette_poll));
1413   m_cass_tick = machine().scheduler().timer_alloc(FUNC(cassette_tick));
13601414
13611415   /* Save State */
13621416   save_item(NAME(m_sleep));
r14872r14873
13751429   save_item(NAME(m_prn_sendbit));
13761430   save_item(NAME(m_prn_char_code));
13771431   save_item(NAME(m_prn_size));
1378   save_item(NAME(m_k7on));
1379   save_item(NAME(m_k7size));
1380   save_item(NAME(m_k7pos));
1432   save_item(NAME(m_cass_motor));
1433   save_item(NAME(m_cass_data));
1434   save_item(NAME(m_cass_clk));
1435   save_item(NAME(m_cass_state));
1436   save_item(NAME(m_bit_count));
13811437   save_item(NAME(m_t6834_ram));
13821438   save_item(NAME(m_regs_r));
13831439   save_item(NAME(m_regs_w));
13841440   save_item(NAME(m_alarm));
13851441   save_item(NAME(m_lcd_map));
13861442   save_item(NAME(m_prn_buffer));
1387   save_pointer(NAME(m_k7data), m_k7size);
13881443   save_item(NAME(m_in.read));
13891444   save_item(NAME(m_in.write));
13901445   save_item(NAME(m_in.data));
r14872r14873
14371492   cpu_set_reg(m_maincpu, Z80_PC, 0xc3c3);
14381493}
14391494
1495static const cassette_interface x07_cassette_interface =
1496{
1497   x07_cassette_formats,
1498   NULL,
1499   (cassette_state)(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED),
1500   "x07_cass",
1501   NULL
1502};
1503
14401504static MACHINE_CONFIG_START( x07, x07_state )
14411505
14421506   /* basic machine hardware */
r14872r14873
14591523   /* sound hardware */
14601524   MCFG_SPEAKER_STANDARD_MONO( "mono" )
14611525   MCFG_SOUND_ADD( BEEPER_TAG, BEEP, 0 )
1462   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "mono", 1.00 )
1526   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "mono", 0.50 )
1527   MCFG_SOUND_WAVE_ADD(WAVE_TAG, CASSETTE_TAG)
1528   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
14631529
14641530   /* printer */
14651531   MCFG_PRINTER_ADD("printer")
r14872r14873
14861552   MCFG_CARTSLOT_INTERFACE("x07_card")
14871553
14881554   /* cassette */
1489   MCFG_CARTSLOT_ADD("cassette")
1490   MCFG_CARTSLOT_EXTENSION_LIST("k7,cas,lst")
1491   MCFG_CARTSLOT_NOT_MANDATORY
1492   MCFG_CARTSLOT_LOAD(x07_cass)
1493   MCFG_CARTSLOT_UNLOAD(x07_cass)
1494   MCFG_CARTSLOT_INTERFACE("x07_cass")
1555   MCFG_CASSETTE_ADD( CASSETTE_TAG, x07_cassette_interface )
14951556
14961557   /* Software lists */
14971558   MCFG_SOFTWARE_LIST_ADD("card_list", "x07_card")

Previous 15994 Revisions Next


© 1998-2018 The MESS Team