Previous 15994 Revisions Next

r4522 Sunday 19th April, 2009 at 16:14:54 UTC by Justin Kerk
Fix SVN props
[docs]config.txt
[src/mess/drivers]tec1.c
[src/mess/layout]mpf1.lay tec1.lay z80ne.lay z80net.lay z80netb.lay
[src/mess/machine]ataricrt.c ataridev.h z80ne.c
[src/mess/tools/castool]castool.mak main.c stubs.c
[src/mess/video]upd7220.c upd7220.h

src/mess/tools/castool/stubs.c
r4521r4522
1#include "driver.h"
2#include <ctype.h>
3#include <stdarg.h>
4 
5/* Variables to hold the status of various game options */
6static FILE *errorlog;
7 
8const game_driver *const drivers[1];
9int rompath_extra;
10int history_filename;
11int mameinfo_filename;
12 
13void CLIB_DECL logerror(const char *text,...)
14{
15   va_list arg;
16   va_start(arg,text);
17   if (errorlog)
18      vfprintf(errorlog,text,arg);
19   va_end(arg);
20}
21 
22/* ----------------------------------------------------------------------- */
23/* total hack */
24 
25file_error mame_fopen(const char *searchpath, const char *filename, UINT32 openflags, mame_file **file)
26{
27   char buffer[2048];
28   snprintf(buffer, sizeof(buffer), "crc/%s", filename);
29   *file = (mame_file *) fopen(buffer, "r");
30   return FILERR_NONE;
31}
32 
33char *mame_fgets(char *s, int n, mame_file *file)
34{
35   return fgets(s, n, (FILE *) file);
36}
37 
38UINT32 mame_fwrite(mame_file *file, const void *buffer, UINT32 length)
39{
40   return fwrite(buffer, 1, length, (FILE *) file);
41}
42 
43void mame_fclose(mame_file *file)
44{
45   fclose((FILE *) file);
46}
47 
48int CLIB_DECL mame_fprintf(mame_file *f, const char *fmt, ...)
49{
50   int rc;
51   va_list va;
52   va_start(va, fmt);
53   rc = vfprintf(stderr, fmt, va);
54   va_end(va);
55   return rc;
56}
57 
58void mame_printf_error(const char *format, ...)
59{
60}
61 
62void mame_printf_warning(const char *format, ...)
63{
64}
65 
66void mame_printf_info(const char *format, ...)
67{
68}
69 
70void mame_printf_debug(const char *format, ...)
71{
72}
73 
74 
75 
76/***************************************************************************
77    TYPE DEFINITIONS
78***************************************************************************/
79 
80enum _memory_block_overlap
81{
82   OVERLAP_NONE,
83   OVERLAP_PARTIAL,
84   OVERLAP_FULL
85};
86typedef enum _memory_block_overlap memory_block_overlap;
87 
88 
89 
90/***************************************************************************
91    GLOBAL VARIABLES
92***************************************************************************/
93 
94/* pool list */
95static object_pool *pools[64];
96 
97/* resource tracking */
98int resource_tracking_tag = 0;
99 
100 
101 
102/***************************************************************************
103    PROTOTYPES
104***************************************************************************/
105 
106static void astring_destructor(void *object, size_t size);
107static void bitmap_destructor(void *object, size_t size);
108 
109 
110/***************************************************************************
111    CORE IMPLEMENTATION
112***************************************************************************/
113 
114/*-------------------------------------------------
115    init_resource_tracking - initialize the
116    resource tracking system
117-------------------------------------------------*/
118 
119void init_resource_tracking(void)
120{
121   resource_tracking_tag = 0;
122}
123 
124 
125/*-------------------------------------------------
126    exit_resource_tracking - tear down the
127    resource tracking system
128-------------------------------------------------*/
129 
130void exit_resource_tracking(void)
131{
132   while (resource_tracking_tag != 0)
133      end_resource_tracking();
134}
135 
136 
137/*-------------------------------------------------
138    memory_error - report a memory error
139-------------------------------------------------*/
140 
141static void memory_error(const char *message)
142{
143   fatalerror("%s", message);
144}
145 
146 
147/*-------------------------------------------------
148    begin_resource_tracking - start tracking
149    resources
150-------------------------------------------------*/
151 
152void begin_resource_tracking(void)
153{
154   object_pool *new_pool;
155 
156   /* sanity check */
157   assert_always(resource_tracking_tag < ARRAY_LENGTH(pools), "Too many memory pools");
158 
159   /* create a new pool */
160   new_pool = pool_alloc(memory_error);
161   if (!new_pool)
162      fatalerror("Failed to allocate new memory pool");
163   pools[resource_tracking_tag] = new_pool;
164 
165   /* add resource types */
166   pool_type_register(new_pool, OBJTYPE_ASTRING, "String", astring_destructor);
167   pool_type_register(new_pool, OBJTYPE_BITMAP, "Bitmap", bitmap_destructor);
168   //pool_type_register(new_pool, OBJTYPE_TIMER, "Timer", timer_destructor);
169   //pool_type_register(new_pool, OBJTYPE_STATEREG, "Save State Registration", state_destructor);
170 
171   /* increment the tag counter */
172   resource_tracking_tag++;
173}
174 
175 
176/*-------------------------------------------------
177    end_resource_tracking - stop tracking
178    resources
179-------------------------------------------------*/
180 
181void end_resource_tracking(void)
182{
183   /* decrement the tag counter */
184   resource_tracking_tag--;
185 
186   /* free the memory pool */
187   pool_free(pools[resource_tracking_tag]);
188   pools[resource_tracking_tag] = NULL;
189}
190 
191 
192/*-------------------------------------------------
193    current_pool - identifies the current memory
194    pool
195-------------------------------------------------*/
196 
197static object_pool *current_pool(void)
198{
199   object_pool *pool;
200   assert_always((resource_tracking_tag > 0) && (resource_tracking_tag <= ARRAY_LENGTH(pools)), "Invalid resource_tracking_tag");
201   pool = pools[resource_tracking_tag - 1];
202   assert_always(pool != NULL, "current_pool() is NULL");
203   return pool;
204}
205 
206 
207/*-------------------------------------------------
208    restrack_register_object - registers an
209    object with the current pool
210-------------------------------------------------*/
211 
212void *restrack_register_object(object_type type, void *ptr, size_t size, const char *file, int line)
213{
214   return pool_object_add_file_line(current_pool(), type, ptr, size, file, line);
215}
216 
217 
218/*-------------------------------------------------
219    auto_malloc_file_line - allocate auto-
220    freeing memory
221-------------------------------------------------*/
222 
223void *auto_malloc_file_line(size_t size, const char *file, int line)
224{
225   void *result = pool_malloc_file_line(current_pool(), size, file, line);
226#ifdef MAME_DEBUG
227   rand_memory(result, size);
228#endif
229   return result;
230}
231 
232 
233/*-------------------------------------------------
234    auto_realloc_file_line - reallocate auto-
235    freeing memory
236-------------------------------------------------*/
237 
238void *auto_realloc_file_line(void *ptr, size_t size, const char *file, int line)
239{
240   object_pool *pool = current_pool();
241   if (ptr != NULL)
242   {
243      int tag = resource_tracking_tag;
244      for (; tag > 0; tag--)
245      {
246         pool = pools[tag - 1];
247         if (pool_object_exists(pool, OBJTYPE_MEMORY, ptr))
248            break;
249      }
250      assert_always(tag > 0, "Failed to find alloc in pool");
251   }
252 
253   return pool_realloc_file_line(pool, ptr, size, file, line);
254}
255 
256 
257/*-------------------------------------------------
258    auto_strdup_file_line - allocate auto-freeing
259    string
260-------------------------------------------------*/
261 
262char *auto_strdup_file_line(const char *str, const char *file, int line)
263{
264   return pool_strdup_file_line(current_pool(), str, file, line);
265}
266 
267 
268/*-------------------------------------------------
269    auto_strdup_allow_null_file_line - allocate
270    auto-freeing string if str is null
271-------------------------------------------------*/
272 
273char *auto_strdup_allow_null_file_line(const char *str, const char *file, int line)
274{
275   return (str != NULL) ? auto_strdup_file_line(str, file, line) : NULL;
276}
277 
278 
279/*-------------------------------------------------
280    auto_astring_alloc_file_line - allocate
281    auto-freeing astring
282-------------------------------------------------*/
283 
284astring *auto_astring_alloc_file_line(const char *file, int line)
285{
286   return (astring *)restrack_register_object(OBJTYPE_ASTRING, astring_alloc(), 0, file, line);
287}
288 
289 
290 
291/*-------------------------------------------------
292    astring_destructor - destructor for astring
293    objects
294-------------------------------------------------*/
295 
296static void astring_destructor(void *object, size_t size)
297{
298   astring_free((astring *)object);
299}
300 
301 
302/*-------------------------------------------------
303    bitmap_destructor - destructor for bitmap
304    objects
305-------------------------------------------------*/
306 
307static void bitmap_destructor(void *object, size_t size)
308{
309   bitmap_free((bitmap_t *)object);
310}
311 
312 
1#include "driver.h"
2#include <ctype.h>
3#include <stdarg.h>
4
5/* Variables to hold the status of various game options */
6static FILE *errorlog;
7
8const game_driver *const drivers[1];
9int rompath_extra;
10int history_filename;
11int mameinfo_filename;
12
13void CLIB_DECL logerror(const char *text,...)
14{
15   va_list arg;
16   va_start(arg,text);
17   if (errorlog)
18      vfprintf(errorlog,text,arg);
19   va_end(arg);
20}
21
22/* ----------------------------------------------------------------------- */
23/* total hack */
24
25file_error mame_fopen(const char *searchpath, const char *filename, UINT32 openflags, mame_file **file)
26{
27   char buffer[2048];
28   snprintf(buffer, sizeof(buffer), "crc/%s", filename);
29   *file = (mame_file *) fopen(buffer, "r");
30   return FILERR_NONE;
31}
32
33char *mame_fgets(char *s, int n, mame_file *file)
34{
35   return fgets(s, n, (FILE *) file);
36}
37
38UINT32 mame_fwrite(mame_file *file, const void *buffer, UINT32 length)
39{
40   return fwrite(buffer, 1, length, (FILE *) file);
41}
42
43void mame_fclose(mame_file *file)
44{
45   fclose((FILE *) file);
46}
47
48int CLIB_DECL mame_fprintf(mame_file *f, const char *fmt, ...)
49{
50   int rc;
51   va_list va;
52   va_start(va, fmt);
53   rc = vfprintf(stderr, fmt, va);
54   va_end(va);
55   return rc;
56}
57
58void mame_printf_error(const char *format, ...)
59{
60}
61
62void mame_printf_warning(const char *format, ...)
63{
64}
65
66void mame_printf_info(const char *format, ...)
67{
68}
69
70void mame_printf_debug(const char *format, ...)
71{
72}
73
74
75
76/***************************************************************************
77    TYPE DEFINITIONS
78***************************************************************************/
79
80enum _memory_block_overlap
81{
82   OVERLAP_NONE,
83   OVERLAP_PARTIAL,
84   OVERLAP_FULL
85};
86typedef enum _memory_block_overlap memory_block_overlap;
87
88
89
90/***************************************************************************
91    GLOBAL VARIABLES
92***************************************************************************/
93
94/* pool list */
95static object_pool *pools[64];
96
97/* resource tracking */
98int resource_tracking_tag = 0;
99
100
101
102/***************************************************************************
103    PROTOTYPES
104***************************************************************************/
105
106static void astring_destructor(void *object, size_t size);
107static void bitmap_destructor(void *object, size_t size);
108
109
110/***************************************************************************
111    CORE IMPLEMENTATION
112***************************************************************************/
113
114/*-------------------------------------------------
115    init_resource_tracking - initialize the
116    resource tracking system
117-------------------------------------------------*/
118
119void init_resource_tracking(void)
120{
121   resource_tracking_tag = 0;
122}
123
124
125/*-------------------------------------------------
126    exit_resource_tracking - tear down the
127    resource tracking system
128-------------------------------------------------*/
129
130void exit_resource_tracking(void)
131{
132   while (resource_tracking_tag != 0)
133      end_resource_tracking();
134}
135
136
137/*-------------------------------------------------
138    memory_error - report a memory error
139-------------------------------------------------*/
140
141static void memory_error(const char *message)
142{
143   fatalerror("%s", message);
144}
145
146
147/*-------------------------------------------------
148    begin_resource_tracking - start tracking
149    resources
150-------------------------------------------------*/
151
152void begin_resource_tracking(void)
153{
154   object_pool *new_pool;
155
156   /* sanity check */
157   assert_always(resource_tracking_tag < ARRAY_LENGTH(pools), "Too many memory pools");
158
159   /* create a new pool */
160   new_pool = pool_alloc(memory_error);
161   if (!new_pool)
162      fatalerror("Failed to allocate new memory pool");
163   pools[resource_tracking_tag] = new_pool;
164
165   /* add resource types */
166   pool_type_register(new_pool, OBJTYPE_ASTRING, "String", astring_destructor);
167   pool_type_register(new_pool, OBJTYPE_BITMAP, "Bitmap", bitmap_destructor);
168   //pool_type_register(new_pool, OBJTYPE_TIMER, "Timer", timer_destructor);
169   //pool_type_register(new_pool, OBJTYPE_STATEREG, "Save State Registration", state_destructor);
170
171   /* increment the tag counter */
172   resource_tracking_tag++;
173}
174
175
176/*-------------------------------------------------
177    end_resource_tracking - stop tracking
178    resources
179-------------------------------------------------*/
180
181void end_resource_tracking(void)
182{
183   /* decrement the tag counter */
184   resource_tracking_tag--;
185
186   /* free the memory pool */
187   pool_free(pools[resource_tracking_tag]);
188   pools[resource_tracking_tag] = NULL;
189}
190
191
192/*-------------------------------------------------
193    current_pool - identifies the current memory
194    pool
195-------------------------------------------------*/
196
197static object_pool *current_pool(void)
198{
199   object_pool *pool;
200   assert_always((resource_tracking_tag > 0) && (resource_tracking_tag <= ARRAY_LENGTH(pools)), "Invalid resource_tracking_tag");
201   pool = pools[resource_tracking_tag - 1];
202   assert_always(pool != NULL, "current_pool() is NULL");
203   return pool;
204}
205
206
207/*-------------------------------------------------
208    restrack_register_object - registers an
209    object with the current pool
210-------------------------------------------------*/
211
212void *restrack_register_object(object_type type, void *ptr, size_t size, const char *file, int line)
213{
214   return pool_object_add_file_line(current_pool(), type, ptr, size, file, line);
215}
216
217
218/*-------------------------------------------------
219    auto_malloc_file_line - allocate auto-
220    freeing memory
221-------------------------------------------------*/
222
223void *auto_malloc_file_line(size_t size, const char *file, int line)
224{
225   void *result = pool_malloc_file_line(current_pool(), size, file, line);
226#ifdef MAME_DEBUG
227   rand_memory(result, size);
228#endif
229   return result;
230}
231
232
233/*-------------------------------------------------
234    auto_realloc_file_line - reallocate auto-
235    freeing memory
236-------------------------------------------------*/
237
238void *auto_realloc_file_line(void *ptr, size_t size, const char *file, int line)
239{
240   object_pool *pool = current_pool();
241   if (ptr != NULL)
242   {
243      int tag = resource_tracking_tag;
244      for (; tag > 0; tag--)
245      {
246         pool = pools[tag - 1];
247         if (pool_object_exists(pool, OBJTYPE_MEMORY, ptr))
248            break;
249      }
250      assert_always(tag > 0, "Failed to find alloc in pool");
251   }
252
253   return pool_realloc_file_line(pool, ptr, size, file, line);
254}
255
256
257/*-------------------------------------------------
258    auto_strdup_file_line - allocate auto-freeing
259    string
260-------------------------------------------------*/
261
262char *auto_strdup_file_line(const char *str, const char *file, int line)
263{
264   return pool_strdup_file_line(current_pool(), str, file, line);
265}
266
267
268/*-------------------------------------------------
269    auto_strdup_allow_null_file_line - allocate
270    auto-freeing string if str is null
271-------------------------------------------------*/
272
273char *auto_strdup_allow_null_file_line(const char *str, const char *file, int line)
274{
275   return (str != NULL) ? auto_strdup_file_line(str, file, line) : NULL;
276}
277
278
279/*-------------------------------------------------
280    auto_astring_alloc_file_line - allocate
281    auto-freeing astring
282-------------------------------------------------*/
283
284astring *auto_astring_alloc_file_line(const char *file, int line)
285{
286   return (astring *)restrack_register_object(OBJTYPE_ASTRING, astring_alloc(), 0, file, line);
287}
288
289
290
291/*-------------------------------------------------
292    astring_destructor - destructor for astring
293    objects
294-------------------------------------------------*/
295
296static void astring_destructor(void *object, size_t size)
297{
298   astring_free((astring *)object);
299}
300
301
302/*-------------------------------------------------
303    bitmap_destructor - destructor for bitmap
304    objects
305-------------------------------------------------*/
306
307static void bitmap_destructor(void *object, size_t size)
308{
309   bitmap_free((bitmap_t *)object);
310}
311
312
src/mess/tools/castool/main.c
r4521r4522
1/***************************************************************************
2 
3   main.c
4 
5   Castool command line front end
6   
7   27/03/2009 Initial version by Miodrag Milanovic
8 
9***************************************************************************/
10 
11#include <stdio.h>
12#include <string.h>
13#include <ctype.h>
14#include <stdlib.h>
15#include <time.h>
16#include <assert.h>
17 
18#include "mame.h"
19#include "mess.h"
20#include "fileio.h"
21#ifdef WIN32
22#include "winutils.h"
23#endif
24 
25#include "devices/cassette.h"
26 
27#include "formats/a26_cas.h" 
28#include "formats/apf_apt.h" 
29#include "formats/cbm_tap.h" 
30#include "formats/cgen_cas.h" 
31#include "formats/coco_cas.h" 
32#include "formats/csw_cas.h" 
33#include "formats/fmsx_cas.h" 
34#include "formats/gtp_cas.h" 
35#include "formats/jupi_tap.h" 
36#include "formats/kim1_cas.h" 
37#include "formats/lviv_lvt.h" 
38#include "formats/mz_cas.h" 
39#include "formats/orao_cas.h" 
40#include "formats/oric_tap.h" 
41#include "formats/pmd_pmd.h" 
42#include "formats/primoptp.h" 
43#include "formats/rk_cas.h" 
44#include "formats/sord_cas.h" 
45#include "formats/svi_cas.h" 
46#include "formats/trs_cas.h" 
47#include "formats/tzx_cas.h" 
48#include "formats/uef_cas.h" 
49#include "formats/vt_cas.h" 
50#include "formats/zx81_p.h" 
51 
52struct SupportedCassetteFormats
53{
54   const char *name;
55   const struct CassetteFormat * const *formats;
56   const char *desc;
57};
58 
59const struct SupportedCassetteFormats formats[] = {   
60   {"a26", a26_cassette_formats               ,"Atari 2600"},
61   {"apf", apf_cassette_formats               ,"APF Imagination Machine"},
62   {"cbm", cbm_cassette_formats               ,"Commodore"},
63   {"cgenie", cgenie_cassette_formats         ,"Colour Genie"},
64   {"coco", coco_cassette_formats             ,"TRS-80 Radio Shack Color Computer Family"},
65   {"csw", csw_cassette_formats               ,"Compressed Square Wave"},
66   {"bbc", bbc_cassette_formats               ,"BBC"},
67   {"fmxs", fmsx_cassette_formats             ,"MSX"},
68   {"gtp", gtp_cassette_formats               ,"Galaksija"},
69   {"jupiter", jupiter_cassette_formats       ,"Jupiter"},
70   {"kim1", kim1_cassette_formats             ,"KIM-1"},
71   {"lviv", lviv_lvt_format                   ,"Lviv"},
72   {"mz", mz700_cassette_formats              ,"Sharp MZ"},
73   {"orao", orao_cassette_formats             ,"Orao"},
74   {"oric", oric_cassette_formats             ,"Oric"},
75   {"pmd85", pmd85_pmd_format                 ,"PMD-85"},
76   {"primo", primo_ptp_format                 ,"Primo"},
77   {"rku", rku_cassette_formats               ,"UT-88"},
78   {"rk8", rk8_cassette_formats               ,"Mikro-80"},
79   {"rks", rks_cassette_formats               ,"Specialist"},
80   {"rko", rko_cassette_formats               ,"Orion"},
81   {"rkr", rkr_cassette_formats               ,"Radio-86RK"},
82   {"rka", rka_cassette_formats               ,"Apogee"},
83   {"rkm", rkm_cassette_formats               ,"Mikrosha"},
84   {"rkp", rkp_cassette_formats               ,"Partner"},
85   {"sord5m", sordm5_cassette_formats         ,"Sord-5M"},
86   {"svi", svi_cassette_formats               ,"SVI"},
87   {"trs80l2", trs80l2_cassette_formats       ,"TRS-80 Level 2"},
88   {"tzx", tzx_cassette_formats               ,"ZX Spectrum"},
89   {"cdt", cdt_cassette_formats               ,"Amstrad CPC"},
90   {"uef", uef_cassette_formats               ,"Acorn Electron"},
91   {"vtech1", vtech1_cassette_formats         ,"Video Technology Laser 110-310"},
92   {"vtech2", vtech2_cassette_formats         ,"Video Technology Laser 350-700"},
93   {"zx81_p", zx81_p_format                   ,"Sinclair ZX81"},
94   {"zx80_o", zx80_o_format                   ,"Sinclair ZX80"},
95   {NULL,NULL,NULL}
96};   
97 
98 
99const char *get_extension(const char *name)
100{
101   const char *s;
102   s = name;
103   if (s != NULL)
104      s = strrchr(s, '.');
105   return s ? s+1 : NULL;
106}
107 
108void display_usage(void)
109{
110   fprintf(stderr, "Usage: \n");
111   fprintf(stderr, "      castool.exe convert <format> <inputfile> <outputfile.wav>\n");
112}
113 
114void display_formats(void)
115{
116   int i,j;
117   fprintf(stderr, "Supported formats:\n\n");
118   for (i = 0; formats[i].name; i++) {
119      fprintf(stderr, "%10s - %s\n",formats[i].name,formats[i].desc);
120      for (j = 1; formats[i].formats[j]; j++) {
121         fprintf(stderr, "%15s %s\n","",formats[i].formats[j]->extensions);
122      }
123   }
124}
125 
126#ifdef WIN32
127int CLIB_DECL utf8_main(int argc, char *argv[])
128#else
129int CLIB_DECL main(int argc, char *argv[])
130#endif
131{   
132   int i;
133   int found =0;
134   const struct CassetteFormat * const *selected_formats = NULL;
135   cassette_image *cassette;
136   FILE *f;
137#ifdef WIN32
138   win_expand_wildcards(&argc, &argv);
139#endif /* WIN32 */
140 
141 
142   init_resource_tracking();   
143   begin_resource_tracking();
144 
145   if (argc > 1)
146   {
147      if (!mame_stricmp("convert", argv[1]))
148      {
149         // convert command
150         if (argc!=5) {
151            fprintf(stderr, "Wrong parameter number.\n\n");
152            display_usage();
153            return -1;
154         } else {
155            for (i = 0; formats[i].name; i++) {
156               if (mame_stricmp(formats[i].name,argv[2])==0) {
157                  selected_formats = formats[i].formats;
158                  found = 1;
159               }               
160            }
161            if (found==0) {
162               fprintf(stderr, "Wrong format name.\n\n");
163               display_usage();
164               fprintf(stderr, "\n");
165               display_formats();
166               return -1;               
167            }             
168             
169            f = fopen(argv[3], "rb");   
170            if (!f) {
171               fprintf(stderr, "File %s not found.\n",argv[3]);
172               return -1;
173            }
174   
175            if (cassette_open_choices(f, &stdio_ioprocs, get_extension(argv[3]), selected_formats, CASSETTE_FLAG_READONLY, &cassette))   {
176               fprintf(stderr, "Invalid format of input file.\n");               
177               return -1;
178            }
179         
180            cassette_dump(cassette,argv[4]);
181            cassette_close(cassette);
182            goto theend;
183         }
184      }
185   } 
186 
187   /* Usage */
188   fprintf(stderr, "castool - Generic cassette manipulation tool for use with MESS\n\n");
189   display_usage();
190   fprintf(stderr, "\n");
191   display_formats();
192   fprintf(stderr, "\nExample usage:\n");
193   fprintf(stderr, "        castool.exe convert tzx game.tzx game.wav\n\n");   
194 
195theend :
196   /* clean up our tracked resources */
197   exit_resource_tracking();
198 
199   return 0;
200}
1/***************************************************************************
2
3   main.c
4
5   Castool command line front end
6   
7   27/03/2009 Initial version by Miodrag Milanovic
8
9***************************************************************************/
10
11#include <stdio.h>
12#include <string.h>
13#include <ctype.h>
14#include <stdlib.h>
15#include <time.h>
16#include <assert.h>
17
18#include "mame.h"
19#include "mess.h"
20#include "fileio.h"
21#ifdef WIN32
22#include "winutils.h"
23#endif
24
25#include "devices/cassette.h"
26
27#include "formats/a26_cas.h"
28#include "formats/apf_apt.h"
29#include "formats/cbm_tap.h"
30#include "formats/cgen_cas.h"
31#include "formats/coco_cas.h"
32#include "formats/csw_cas.h"
33#include "formats/fmsx_cas.h"
34#include "formats/gtp_cas.h"
35#include "formats/jupi_tap.h"
36#include "formats/kim1_cas.h"
37#include "formats/lviv_lvt.h"
38#include "formats/mz_cas.h"
39#include "formats/orao_cas.h"
40#include "formats/oric_tap.h"
41#include "formats/pmd_pmd.h"
42#include "formats/primoptp.h"
43#include "formats/rk_cas.h"
44#include "formats/sord_cas.h"
45#include "formats/svi_cas.h"
46#include "formats/trs_cas.h"
47#include "formats/tzx_cas.h"
48#include "formats/uef_cas.h"
49#include "formats/vt_cas.h"
50#include "formats/zx81_p.h"
51
52struct SupportedCassetteFormats
53{
54   const char *name;
55   const struct CassetteFormat * const *formats;
56   const char *desc;
57};
58
59const struct SupportedCassetteFormats formats[] = {   
60   {"a26", a26_cassette_formats               ,"Atari 2600"},
61   {"apf", apf_cassette_formats               ,"APF Imagination Machine"},
62   {"cbm", cbm_cassette_formats               ,"Commodore"},
63   {"cgenie", cgenie_cassette_formats         ,"Colour Genie"},
64   {"coco", coco_cassette_formats             ,"TRS-80 Radio Shack Color Computer Family"},
65   {"csw", csw_cassette_formats               ,"Compressed Square Wave"},
66   {"bbc", bbc_cassette_formats               ,"BBC"},
67   {"fmxs", fmsx_cassette_formats             ,"MSX"},
68   {"gtp", gtp_cassette_formats               ,"Galaksija"},
69   {"jupiter", jupiter_cassette_formats       ,"Jupiter"},
70   {"kim1", kim1_cassette_formats             ,"KIM-1"},
71   {"lviv", lviv_lvt_format                   ,"Lviv"},
72   {"mz", mz700_cassette_formats              ,"Sharp MZ"},
73   {"orao", orao_cassette_formats             ,"Orao"},
74   {"oric", oric_cassette_formats             ,"Oric"},
75   {"pmd85", pmd85_pmd_format                 ,"PMD-85"},
76   {"primo", primo_ptp_format                 ,"Primo"},
77   {"rku", rku_cassette_formats               ,"UT-88"},
78   {"rk8", rk8_cassette_formats               ,"Mikro-80"},
79   {"rks", rks_cassette_formats               ,"Specialist"},
80   {"rko", rko_cassette_formats               ,"Orion"},
81   {"rkr", rkr_cassette_formats               ,"Radio-86RK"},
82   {"rka", rka_cassette_formats               ,"Apogee"},
83   {"rkm", rkm_cassette_formats               ,"Mikrosha"},
84   {"rkp", rkp_cassette_formats               ,"Partner"},
85   {"sord5m", sordm5_cassette_formats         ,"Sord-5M"},
86   {"svi", svi_cassette_formats               ,"SVI"},
87   {"trs80l2", trs80l2_cassette_formats       ,"TRS-80 Level 2"},
88   {"tzx", tzx_cassette_formats               ,"ZX Spectrum"},
89   {"cdt", cdt_cassette_formats               ,"Amstrad CPC"},
90   {"uef", uef_cassette_formats               ,"Acorn Electron"},
91   {"vtech1", vtech1_cassette_formats         ,"Video Technology Laser 110-310"},
92   {"vtech2", vtech2_cassette_formats         ,"Video Technology Laser 350-700"},
93   {"zx81_p", zx81_p_format                   ,"Sinclair ZX81"},
94   {"zx80_o", zx80_o_format                   ,"Sinclair ZX80"},
95   {NULL,NULL,NULL}
96}; 
97
98
99const char *get_extension(const char *name)
100{
101   const char *s;
102   s = name;
103   if (s != NULL)
104      s = strrchr(s, '.');
105   return s ? s+1 : NULL;
106}
107
108void display_usage(void)
109{
110   fprintf(stderr, "Usage: \n");
111   fprintf(stderr, "      castool.exe convert <format> <inputfile> <outputfile.wav>\n");
112}
113
114void display_formats(void)
115{
116   int i,j;
117   fprintf(stderr, "Supported formats:\n\n");
118   for (i = 0; formats[i].name; i++) {
119      fprintf(stderr, "%10s - %s\n",formats[i].name,formats[i].desc);
120      for (j = 1; formats[i].formats[j]; j++) {
121         fprintf(stderr, "%15s %s\n","",formats[i].formats[j]->extensions);
122      }
123   }
124}
125
126#ifdef WIN32
127int CLIB_DECL utf8_main(int argc, char *argv[])
128#else
129int CLIB_DECL main(int argc, char *argv[])
130#endif
131{   
132   int i;
133   int found =0;
134   const struct CassetteFormat * const *selected_formats = NULL;
135   cassette_image *cassette;
136   FILE *f;
137#ifdef WIN32
138   win_expand_wildcards(&argc, &argv);
139#endif /* WIN32 */
140
141
142   init_resource_tracking();   
143   begin_resource_tracking();
144
145   if (argc > 1)
146   {
147      if (!mame_stricmp("convert", argv[1]))
148      {
149         // convert command
150         if (argc!=5) {
151            fprintf(stderr, "Wrong parameter number.\n\n");
152            display_usage();
153            return -1;
154         } else {
155            for (i = 0; formats[i].name; i++) {
156               if (mame_stricmp(formats[i].name,argv[2])==0) {
157                  selected_formats = formats[i].formats;
158                  found = 1;
159               }               
160            }
161            if (found==0) {
162               fprintf(stderr, "Wrong format name.\n\n");
163               display_usage();
164               fprintf(stderr, "\n");
165               display_formats();
166               return -1;               
167            }           
168           
169            f = fopen(argv[3], "rb");   
170            if (!f) {
171               fprintf(stderr, "File %s not found.\n",argv[3]);
172               return -1;
173            }
174   
175            if (cassette_open_choices(f, &stdio_ioprocs, get_extension(argv[3]), selected_formats, CASSETTE_FLAG_READONLY, &cassette))   {
176               fprintf(stderr, "Invalid format of input file.\n");               
177               return -1;
178            }
179         
180            cassette_dump(cassette,argv[4]);
181            cassette_close(cassette);
182            goto theend;
183         }
184      }
185   }
186
187   /* Usage */
188   fprintf(stderr, "castool - Generic cassette manipulation tool for use with MESS\n\n");
189   display_usage();
190   fprintf(stderr, "\n");
191   display_formats();
192   fprintf(stderr, "\nExample usage:\n");
193   fprintf(stderr, "        castool.exe convert tzx game.tzx game.wav\n\n");   
194
195theend :
196   /* clean up our tracked resources */
197   exit_resource_tracking();
198
199   return 0;
200}
src/mess/tools/castool/castool.mak
r4521r4522
1###########################################################################
2#
3#   castool.mak
4#
5#   MESS castool makefile
6#
7###########################################################################
8 
9 
10# castool executable name
11CASTOOL = castool$(EXE)
12 
13# add path to castool headers
14CFLAGS += -I$(SRC)/$(TARGET)/tools/castool
15 
16# castool directories
17CASTOOLOBJ = $(MESSOBJ)/tools/castool
18 
19 
20 
21#-------------------------------------------------
22# castool objects
23#-------------------------------------------------
24 
25OBJDIRS += \
26   $(CASTOOLOBJ)
27 
28LIBCASTOOL = $(OBJ)/libcastool.a
29 
30# castool lib objects
31CASTOOL_LIB_OBJS =                  \
32   $(OBJ)/version.o               \
33   $(EMUOBJ)/mamecore.o            \
34   $(MESSOBJ)/tagpool.o            \
35   $(MESSOBJ)/utils.o               \
36   $(MESSOBJ)/tagpool.o            \
37   $(MESSOBJ)/opresolv.o            \
38   $(MESS_FORMATS)/a26_cas.o           \
39   $(MESS_FORMATS)/apf_apt.o           \
40   $(MESS_FORMATS)/cbm_tap.o           \
41   $(MESS_FORMATS)/cgen_cas.o          \
42   $(MESS_FORMATS)/coco_cas.o          \
43   $(MESS_FORMATS)/csw_cas.o           \
44   $(MESS_FORMATS)/fmsx_cas.o          \
45   $(MESS_FORMATS)/gtp_cas.o           \
46   $(MESS_FORMATS)/jupi_tap.o          \
47   $(MESS_FORMATS)/kim1_cas.o          \
48   $(MESS_FORMATS)/lviv_lvt.o          \
49   $(MESS_FORMATS)/mz_cas.o            \
50   $(MESS_FORMATS)/orao_cas.o          \
51   $(MESS_FORMATS)/oric_tap.o          \
52   $(MESS_FORMATS)/pmd_pmd.o           \
53   $(MESS_FORMATS)/primoptp.o          \
54   $(MESS_FORMATS)/rk_cas.o            \
55   $(MESS_FORMATS)/sord_cas.o          \
56   $(MESS_FORMATS)/svi_cas.o           \
57   $(MESS_FORMATS)/trs_cas.o           \
58   $(MESS_FORMATS)/tzx_cas.o           \
59   $(MESS_FORMATS)/uef_cas.o           \
60   $(MESS_FORMATS)/vt_cas.o            \
61   $(MESS_FORMATS)/zx81_p.o          \
62   $(MESS_FORMATS)/ioprocs.o         \
63   $(MESS_FORMATS)/cassimg.o         \
64   $(MESS_FORMATS)/wavfile.o         \
65   
66 
67$(LIBCASTOOL): $(CASTOOL_LIB_OBJS)
68 
69CASTOOL_OBJS = \
70   $(CASTOOLOBJ)/main.o \
71   $(CASTOOLOBJ)/stubs.o \
72   $(MESSOBJ)/toolerr.o
73 
74 
75 
76#-------------------------------------------------
77# rules to build the castool executable
78#-------------------------------------------------
79 
80$(CASTOOL): $(CASTOOL_OBJS) $(LIBCASTOOL) $(LIBUTIL) $(EXPAT) $(ZLIB) $(LIBOCORE)
81   @echo Linking $@...
82   $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
1###########################################################################
2#
3#   castool.mak
4#
5#   MESS castool makefile
6#
7###########################################################################
8
9
10# castool executable name
11CASTOOL = castool$(EXE)
12
13# add path to castool headers
14CFLAGS += -I$(SRC)/$(TARGET)/tools/castool
15
16# castool directories
17CASTOOLOBJ = $(MESSOBJ)/tools/castool
18
19
20
21#-------------------------------------------------
22# castool objects
23#-------------------------------------------------
24
25OBJDIRS += \
26   $(CASTOOLOBJ)
27
28LIBCASTOOL = $(OBJ)/libcastool.a
29
30# castool lib objects
31CASTOOL_LIB_OBJS =                  \
32   $(OBJ)/version.o               \
33   $(EMUOBJ)/mamecore.o            \
34   $(MESSOBJ)/tagpool.o            \
35   $(MESSOBJ)/utils.o               \
36   $(MESSOBJ)/tagpool.o            \
37   $(MESSOBJ)/opresolv.o            \
38   $(MESS_FORMATS)/a26_cas.o           \
39   $(MESS_FORMATS)/apf_apt.o           \
40   $(MESS_FORMATS)/cbm_tap.o           \
41   $(MESS_FORMATS)/cgen_cas.o          \
42   $(MESS_FORMATS)/coco_cas.o          \
43   $(MESS_FORMATS)/csw_cas.o           \
44   $(MESS_FORMATS)/fmsx_cas.o          \
45   $(MESS_FORMATS)/gtp_cas.o           \
46   $(MESS_FORMATS)/jupi_tap.o          \
47   $(MESS_FORMATS)/kim1_cas.o          \
48   $(MESS_FORMATS)/lviv_lvt.o          \
49   $(MESS_FORMATS)/mz_cas.o            \
50   $(MESS_FORMATS)/orao_cas.o          \
51   $(MESS_FORMATS)/oric_tap.o          \
52   $(MESS_FORMATS)/pmd_pmd.o           \
53   $(MESS_FORMATS)/primoptp.o          \
54   $(MESS_FORMATS)/rk_cas.o            \
55   $(MESS_FORMATS)/sord_cas.o          \
56   $(MESS_FORMATS)/svi_cas.o           \
57   $(MESS_FORMATS)/trs_cas.o           \
58   $(MESS_FORMATS)/tzx_cas.o           \
59   $(MESS_FORMATS)/uef_cas.o           \
60   $(MESS_FORMATS)/vt_cas.o            \
61   $(MESS_FORMATS)/zx81_p.o          \
62   $(MESS_FORMATS)/ioprocs.o         \
63   $(MESS_FORMATS)/cassimg.o         \
64   $(MESS_FORMATS)/wavfile.o         \
65   
66
67$(LIBCASTOOL): $(CASTOOL_LIB_OBJS)
68
69CASTOOL_OBJS = \
70   $(CASTOOLOBJ)/main.o \
71   $(CASTOOLOBJ)/stubs.o \
72   $(MESSOBJ)/toolerr.o
73
74
75
76#-------------------------------------------------
77# rules to build the castool executable
78#-------------------------------------------------
79
80$(CASTOOL): $(CASTOOL_OBJS) $(LIBCASTOOL) $(LIBUTIL) $(EXPAT) $(ZLIB) $(LIBOCORE)
81   @echo Linking $@...
82   $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
src/mess/video/upd7220.c
r4521r4522
1#include "driver.h"
2#include "upd7220.h"
3 
4/***************************************************************************
5    PARAMETERS
6***************************************************************************/
7 
8#define UPD7220_COMMAND_RESET   0x00
9#define UPD7220_COMMAND_SYNC   0x0e // & 0xfe
10#define UPD7220_COMMAND_VSYNC   0x6e // & 0xfe
11#define UPD7220_COMMAND_CCHAR   0x4b
12#define UPD7220_COMMAND_START   0x6b
13#define UPD7220_COMMAND_BCTRL   0x0c // & 0xfe
14#define UPD7220_COMMAND_ZOOM   0x46
15#define UPD7220_COMMAND_CURS   0x49
16#define UPD7220_COMMAND_PRAM   0x70 // & 0xf0
17#define UPD7220_COMMAND_PITCH   0x47
18#define UPD7220_COMMAND_WDAT   0x20 // & 0xe4
19#define UPD7220_COMMAND_MASK   0x4a
20#define UPD7220_COMMAND_FIGS   0x4c
21#define UPD7220_COMMAND_FIGD   0x6c
22#define UPD7220_COMMAND_GCHRD   0x68
23#define UPD7220_COMMAND_RDAT   0xa0 // & 0xe4
24#define UPD7220_COMMAND_CURD   0xe0
25#define UPD7220_COMMAND_LPRD   0xc0
26#define UPD7220_COMMAND_DMAR   0xa4 // & 0xe4
27#define UPD7220_COMMAND_DMAW   0x24 // & 0xe4
28 
29#define UPD7220_SR_DATA_READY         0x01
30#define UPD7220_SR_FIFO_FULL         0x02
31#define UPD7220_SR_FIFO_EMPTY         0x04
32#define UPD7220_SR_DRAWING_IN_PROGRESS   0x08
33#define UPD7220_SR_DMA_EXECUTE         0x10
34#define UPD7220_SR_VSYNC_ACTIVE         0x20
35#define UPD7220_SR_HBLANK_ACTIVE      0x40
36#define UPD7220_SR_LIGHT_PEN_DETECT      0x80
37 
38/***************************************************************************
39    TYPE DEFINITIONS
40***************************************************************************/
41 
42typedef struct _upd7220_t upd7220_t;
43struct _upd7220_t
44{
45   devcb_resolved_read8      in_data_func;
46   devcb_resolved_write8      out_data_func;
47   devcb_resolved_write_line   out_drq_func;
48   devcb_resolved_write_line   out_hsync_func;
49   devcb_resolved_write_line   out_vsync_func;
50   devcb_resolved_write_line   out_blank_func;
51 
52   int clock;                   
53 
54   UINT8 ra[16];               /* parameter RAM */
55 
56   UINT8 sr;                  /* status register */
57   UINT8 mode;                  /* mode of operation */
58 
59   int de;                     /* display enabled */
60   int aw;                     /* active display words per line - 2 (must be even number with bit 0 = 0) */
61   int al;                     /* active display lines per video field */
62   int vs;                     /* vertical sync width - 1 */
63   int vfp;                  /* vertical front porch width - 1 */
64   int vbp;                  /* vertical back porch width - 1 */
65   int hs;                     /* horizontal sync width - 1 */
66   int hfp;                  /* horizontal front porch width - 1 */
67   int hbp;                  /* horizontal back porch width - 1 */
68   int m;                     /* 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode) */
69 
70   int dc;                     /* display cursor */
71   int sc;                     /* 0 = blinking cursor / 1 = steady cursor */
72   int br;                     /* blink rate */
73   int lr;                     /* lines per character row - 1 */
74   int ctop;                  /* cursor top line number in the row */
75   int cbot;                  /* cursor bottom line number in the row (CBOT < LR) */
76   UINT32 ead;                  /* execute word address */
77   UINT16 dad;                  /* dot address within the word */
78   UINT32 lad;                  /* light pen address */
79   
80   int disp;                  /* display zoom factor */
81   int gchr;                  /* zoom factor for graphics character writing and area filling */
82   UINT16 mask;               /* mask register */
83   UINT8 pitch;               /* number of word addresses in display memory in the horizontal direction */
84 
85   /* timers */
86   emu_timer *vsync_timer;         /* vertical sync timer */
87   emu_timer *hsync_timer;         /* horizontal sync timer */
88   emu_timer *blank_timer;         /* CRT blanking timer */
89 
90   const device_config *screen;   /* screen */
91};
92 
93/***************************************************************************
94    INLINE FUNCTIONS
95***************************************************************************/
96 
97INLINE upd7220_t *get_safe_token(const device_config *device)
98{
99   assert(device != NULL);
100   assert(device->token != NULL);
101   return (upd7220_t *)device->token;
102}
103 
104INLINE const upd7220_interface *get_interface(const device_config *device)
105{
106   assert(device != NULL);
107   assert((device->type == UPD7220));
108   return (const upd7220_interface *) device->static_config;
109}
110 
111INLINE void queue(upd7220_t *upd7220, UINT8 data, int command)
112{
113}
114 
115INLINE UINT16 dequeue(upd7220_t *upd7220)
116{
117   return 0;
118}
119 
120/***************************************************************************
121    IMPLEMENTATION
122***************************************************************************/
123 
124/*-------------------------------------------------
125    recompute_parameters - 
126-------------------------------------------------*/
127#ifdef UNUSED_FUNCTION
128static void recompute_parameters(upd7220_t *upd7220)
129{
130   rectangle visarea;
131 
132   int horiz_pix_total;
133   int vert_pix_total;
134 
135   attoseconds_t refresh = HZ_TO_ATTOSECONDS(upd7220->clock) * (upd7220->aw + 2) * upd7220->al;
136 
137   visarea.min_x = upd7220->hs + upd7220->hbp + 1;
138   visarea.min_y = upd7220->vs + upd7220->vbp + 1;
139   visarea.max_x = 0;
140   visarea.max_y = upd7220->al + 2 - upd7220->vfp;
141 
142   video_screen_configure(upd7220->screen, horiz_pix_total, vert_pix_total, &visarea, refresh);
143}
144#endif
145/*-------------------------------------------------
146    update_vsync_timer - 
147-------------------------------------------------*/
148 
149static void update_vsync_timer(upd7220_t *upd7220, int state)
150{
151   int next_y = state ? (upd7220->vs + 1) : 0;
152 
153   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, 0);
154 
155   timer_adjust_oneshot(upd7220->vsync_timer, duration, !state);
156}
157 
158/*-------------------------------------------------
159    TIMER_CALLBACK( vsync_tick )
160-------------------------------------------------*/
161 
162static TIMER_CALLBACK( vsync_tick )
163{
164   const device_config *device = ptr;
165   upd7220_t *upd7220 = get_safe_token(device);
166 
167   devcb_call_write_line(&upd7220->out_vsync_func, param);
168 
169   update_vsync_timer(upd7220, param);
170}
171 
172/*-------------------------------------------------
173    update_hsync_timer - 
174-------------------------------------------------*/
175 
176static void update_hsync_timer(upd7220_t *upd7220, int state)
177{
178   int y = video_screen_get_vpos(upd7220->screen);
179 
180   int next_x = state ? upd7220->hs : 0;
181   int next_y = state ? y : ((y + 1) % upd7220->al);
182 
183   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
184 
185   timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
186}
187 
188/*-------------------------------------------------
189    TIMER_CALLBACK( hsync_tick )
190-------------------------------------------------*/
191 
192static TIMER_CALLBACK( hsync_tick )
193{
194   const device_config *device = ptr;
195   upd7220_t *upd7220 = get_safe_token(device);
196 
197   devcb_call_write_line(&upd7220->out_hsync_func, param);
198 
199   update_hsync_timer(upd7220, param);
200}
201 
202/*-------------------------------------------------
203    update_blank_timer - 
204-------------------------------------------------*/
205 
206static void update_blank_timer(upd7220_t *upd7220, int state)
207{
208   int y = video_screen_get_vpos(upd7220->screen);
209 
210   int next_x = state ? (upd7220->hs + upd7220->hbp + 1) : 0;
211   int next_y = state ? y : ((y + 1) % upd7220->al);
212 
213   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
214 
215   timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
216}
217 
218/*-------------------------------------------------
219    TIMER_CALLBACK( blank_tick )
220-------------------------------------------------*/
221 
222static TIMER_CALLBACK( blank_tick )
223{
224   const device_config *device = ptr;
225   upd7220_t *upd7220 = get_safe_token(device);
226 
227   devcb_call_write_line(&upd7220->out_blank_func, param);
228 
229   update_blank_timer(upd7220, param);
230}
231 
232/*-------------------------------------------------
233    process_command - process command
234-------------------------------------------------*/
235 
236#ifdef UNUSED_CODE
237static void process_command(upd7220_t *upd7220, UINT8 data)
238{
239   switch (data)
240   {
241   case UPD7220_COMMAND_RESET:
242      break;
243   case UPD7220_COMMAND_CCHAR:
244      break;
245   case UPD7220_COMMAND_START:
246      break;
247   case UPD7220_COMMAND_ZOOM:
248      break;
249   case UPD7220_COMMAND_CURS:
250      break;
251   case UPD7220_COMMAND_PITCH:
252      break;
253   case UPD7220_COMMAND_MASK:
254      break;
255   case UPD7220_COMMAND_FIGS:
256      break;
257   case UPD7220_COMMAND_FIGD:
258      break;
259   case UPD7220_COMMAND_CURD:
260      break;
261   case UPD7220_COMMAND_LPRD:
262      break;
263   default:
264      switch (data & 0xfe)
265      {
266      case UPD7220_COMMAND_SYNC:
267         break;
268      case UPD7220_COMMAND_VSYNC:
269         break;
270      case UPD7220_COMMAND_BCTRL:
271         break;
272      default:
273         switch (data & 0xf0)
274         {
275         case UPD7220_COMMAND_PRAM:
276         default:
277            switch (data & 0xe4)
278            {
279            case UPD7220_COMMAND_WDAT:
280               break;
281            case UPD7220_COMMAND_RDAT:
282               break;
283            case UPD7220_COMMAND_DMAR:
284               break;
285            case UPD7220_COMMAND_DMAW:
286               break;
287            default:
288               logerror("Invalid command %02x\n", data);
289            }
290         }
291      }
292   }
293}
294#endif
295 
296/*-------------------------------------------------
297    upd7220_r - register read
298-------------------------------------------------*/
299 
300READ8_DEVICE_HANDLER( upd7220_r )
301{
302   upd7220_t *upd7220 = get_safe_token(device);
303 
304   UINT8 data;
305 
306   if (offset & 1)
307   {
308      /* FIFO read */
309      data = dequeue(upd7220);
310   }
311   else
312   {
313      /* status register */
314      data = upd7220->sr;
315   }
316 
317   return data;
318}
319 
320/*-------------------------------------------------
321    upd7220_w - register write
322-------------------------------------------------*/
323 
324WRITE8_DEVICE_HANDLER( upd7220_w )
325{
326   upd7220_t *upd7220 = get_safe_token(device);
327 
328   if (offset & 1)
329   {
330      /* command into FIFO */
331      queue(upd7220, data, 1);
332   }
333   else
334   {
335      /* parameter into FIFO */
336      queue(upd7220, data, 0);
337   }
338}
339 
340/*-------------------------------------------------
341    upd7220_dack_w - DMA acknowledge w/data
342-------------------------------------------------*/
343 
344WRITE8_DEVICE_HANDLER( upd7220_dack_w )
345{
346}
347 
348/*-------------------------------------------------
349    upd7220_lpen_w - light pen strobe
350-------------------------------------------------*/
351 
352void upd7220_lpen_w(const device_config *device, int state)
353{
354}
355 
356/*-------------------------------------------------
357    ROM( upd7220 )
358-------------------------------------------------*/
359 
360ROM_START( upd7220 )
361   ROM_REGION( 0x100, "upd7220", ROMREGION_LOADBYNAME )
362   ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP ) /* internal 128x14 control ROM */
363ROM_END
364 
365/*-------------------------------------------------
366    DEVICE_START( upd7220 )
367-------------------------------------------------*/
368 
369static DEVICE_START( upd7220 )
370{
371   upd7220_t *upd7220 = get_safe_token(device);
372   const upd7220_interface *intf = get_interface(device);
373 
374   /* resolve callbacks */
375   devcb_resolve_read8(&upd7220->in_data_func, &intf->in_data_func, device);
376   devcb_resolve_write8(&upd7220->out_data_func, &intf->out_data_func, device);
377   devcb_resolve_write_line(&upd7220->out_drq_func, &intf->out_drq_func, device);
378   devcb_resolve_write_line(&upd7220->out_hsync_func, &intf->out_hsync_func, device);
379   devcb_resolve_write_line(&upd7220->out_vsync_func, &intf->out_vsync_func, device);
380 
381   /* get the screen device */
382   upd7220->screen = devtag_get_device(device->machine, intf->screen_tag);
383   assert(upd7220->screen != NULL);
384 
385   /* create the timers */
386   upd7220->vsync_timer = timer_alloc(device->machine, vsync_tick, (void *)device);
387   upd7220->hsync_timer = timer_alloc(device->machine, hsync_tick, (void *)device);
388   upd7220->blank_timer = timer_alloc(device->machine, blank_tick, (void *)device);
389 
390   /* register for state saving */
391   state_save_register_device_item_array(device, 0, upd7220->ra);
392   state_save_register_device_item(device, 0, upd7220->sr);
393   state_save_register_device_item(device, 0, upd7220->mode);
394   state_save_register_device_item(device, 0, upd7220->de);
395   state_save_register_device_item(device, 0, upd7220->aw);
396   state_save_register_device_item(device, 0, upd7220->al);
397   state_save_register_device_item(device, 0, upd7220->vs);
398   state_save_register_device_item(device, 0, upd7220->vfp);
399   state_save_register_device_item(device, 0, upd7220->vbp);
400   state_save_register_device_item(device, 0, upd7220->hs);
401   state_save_register_device_item(device, 0, upd7220->hfp);
402   state_save_register_device_item(device, 0, upd7220->hbp);
403   state_save_register_device_item(device, 0, upd7220->m);
404   state_save_register_device_item(device, 0, upd7220->dc);
405   state_save_register_device_item(device, 0, upd7220->sc);
406   state_save_register_device_item(device, 0, upd7220->br);
407   state_save_register_device_item(device, 0, upd7220->lr);
408   state_save_register_device_item(device, 0, upd7220->ctop);
409   state_save_register_device_item(device, 0, upd7220->cbot);
410   state_save_register_device_item(device, 0, upd7220->ead);
411   state_save_register_device_item(device, 0, upd7220->dad);
412   state_save_register_device_item(device, 0, upd7220->lad);
413   state_save_register_device_item(device, 0, upd7220->disp);
414   state_save_register_device_item(device, 0, upd7220->gchr);
415   state_save_register_device_item(device, 0, upd7220->mask);
416   state_save_register_device_item(device, 0, upd7220->pitch);
417}
418 
419/*-------------------------------------------------
420    DEVICE_RESET( upd7220 )
421-------------------------------------------------*/
422 
423static DEVICE_RESET( upd7220 )
424{
425   upd7220_t *upd7220 = get_safe_token(device);
426 
427   devcb_call_write_line(&upd7220->out_drq_func, CLEAR_LINE);
428}
429 
430/*-------------------------------------------------
431    DEVICE_SET_INFO( upd7220 )
432-------------------------------------------------*/
433 
434static DEVICE_SET_INFO( upd7220 )
435{
436   switch (state)
437   {
438      /* no parameters to set */
439   }
440}
441 
442/*-------------------------------------------------
443    DEVICE_GET_INFO( upd7220 )
444-------------------------------------------------*/
445 
446DEVICE_GET_INFO( upd7220 )
447{
448   switch (state)
449   {
450      /* --- the following bits of info are returned as 64-bit signed integers --- */
451      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(upd7220_t);                  break;
452      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                              break;
453      case DEVINFO_INT_CLASS:                     info->i = DEVICE_CLASS_PERIPHERAL;               break;
454 
455      /* --- the following bits of info are returned as pointers --- */
456      case DEVINFO_PTR_ROM_REGION:               info->romregion = ROM_NAME(upd7220);            break;
457 
458      /* --- the following bits of info are returned as pointers to data or functions --- */
459      case DEVINFO_FCT_SET_INFO:                  info->set_info = DEVICE_SET_INFO_NAME(upd7220);      break;
460      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(upd7220);         break;
461      case DEVINFO_FCT_STOP:                     /* Nothing */                              break;
462      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(upd7220);         break;
463 
464      /* --- the following bits of info are returned as NULL-terminated strings --- */
465      case DEVINFO_STR_NAME:                     strcpy(info->s, "NEC uPD7220");                  break;
466      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "NEC uPD7220");                  break;
467      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                        break;
468      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                     break;
469      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright MESS Team");            break;
470   }
471}
1#include "driver.h"
2#include "upd7220.h"
3
4/***************************************************************************
5    PARAMETERS
6***************************************************************************/
7
8#define UPD7220_COMMAND_RESET   0x00
9#define UPD7220_COMMAND_SYNC   0x0e // & 0xfe
10#define UPD7220_COMMAND_VSYNC   0x6e // & 0xfe
11#define UPD7220_COMMAND_CCHAR   0x4b
12#define UPD7220_COMMAND_START   0x6b
13#define UPD7220_COMMAND_BCTRL   0x0c // & 0xfe
14#define UPD7220_COMMAND_ZOOM   0x46
15#define UPD7220_COMMAND_CURS   0x49
16#define UPD7220_COMMAND_PRAM   0x70 // & 0xf0
17#define UPD7220_COMMAND_PITCH   0x47
18#define UPD7220_COMMAND_WDAT   0x20 // & 0xe4
19#define UPD7220_COMMAND_MASK   0x4a
20#define UPD7220_COMMAND_FIGS   0x4c
21#define UPD7220_COMMAND_FIGD   0x6c
22#define UPD7220_COMMAND_GCHRD   0x68
23#define UPD7220_COMMAND_RDAT   0xa0 // & 0xe4
24#define UPD7220_COMMAND_CURD   0xe0
25#define UPD7220_COMMAND_LPRD   0xc0
26#define UPD7220_COMMAND_DMAR   0xa4 // & 0xe4
27#define UPD7220_COMMAND_DMAW   0x24 // & 0xe4
28
29#define UPD7220_SR_DATA_READY         0x01
30#define UPD7220_SR_FIFO_FULL         0x02
31#define UPD7220_SR_FIFO_EMPTY         0x04
32#define UPD7220_SR_DRAWING_IN_PROGRESS   0x08
33#define UPD7220_SR_DMA_EXECUTE         0x10
34#define UPD7220_SR_VSYNC_ACTIVE         0x20
35#define UPD7220_SR_HBLANK_ACTIVE      0x40
36#define UPD7220_SR_LIGHT_PEN_DETECT      0x80
37
38/***************************************************************************
39    TYPE DEFINITIONS
40***************************************************************************/
41
42typedef struct _upd7220_t upd7220_t;
43struct _upd7220_t
44{
45   devcb_resolved_read8      in_data_func;
46   devcb_resolved_write8      out_data_func;
47   devcb_resolved_write_line   out_drq_func;
48   devcb_resolved_write_line   out_hsync_func;
49   devcb_resolved_write_line   out_vsync_func;
50   devcb_resolved_write_line   out_blank_func;
51
52   int clock;                 
53
54   UINT8 ra[16];               /* parameter RAM */
55
56   UINT8 sr;                  /* status register */
57   UINT8 mode;                  /* mode of operation */
58
59   int de;                     /* display enabled */
60   int aw;                     /* active display words per line - 2 (must be even number with bit 0 = 0) */
61   int al;                     /* active display lines per video field */
62   int vs;                     /* vertical sync width - 1 */
63   int vfp;                  /* vertical front porch width - 1 */
64   int vbp;                  /* vertical back porch width - 1 */
65   int hs;                     /* horizontal sync width - 1 */
66   int hfp;                  /* horizontal front porch width - 1 */
67   int hbp;                  /* horizontal back porch width - 1 */
68   int m;                     /* 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode) */
69
70   int dc;                     /* display cursor */
71   int sc;                     /* 0 = blinking cursor / 1 = steady cursor */
72   int br;                     /* blink rate */
73   int lr;                     /* lines per character row - 1 */
74   int ctop;                  /* cursor top line number in the row */
75   int cbot;                  /* cursor bottom line number in the row (CBOT < LR) */
76   UINT32 ead;                  /* execute word address */
77   UINT16 dad;                  /* dot address within the word */
78   UINT32 lad;                  /* light pen address */
79   
80   int disp;                  /* display zoom factor */
81   int gchr;                  /* zoom factor for graphics character writing and area filling */
82   UINT16 mask;               /* mask register */
83   UINT8 pitch;               /* number of word addresses in display memory in the horizontal direction */
84
85   /* timers */
86   emu_timer *vsync_timer;         /* vertical sync timer */
87   emu_timer *hsync_timer;         /* horizontal sync timer */
88   emu_timer *blank_timer;         /* CRT blanking timer */
89
90   const device_config *screen;   /* screen */
91};
92
93/***************************************************************************
94    INLINE FUNCTIONS
95***************************************************************************/
96
97INLINE upd7220_t *get_safe_token(const device_config *device)
98{
99   assert(device != NULL);
100   assert(device->token != NULL);
101   return (upd7220_t *)device->token;
102}
103
104INLINE const upd7220_interface *get_interface(const device_config *device)
105{
106   assert(device != NULL);
107   assert((device->type == UPD7220));
108   return (const upd7220_interface *) device->static_config;
109}
110
111INLINE void queue(upd7220_t *upd7220, UINT8 data, int command)
112{
113}
114
115INLINE UINT16 dequeue(upd7220_t *upd7220)
116{
117   return 0;
118}
119
120/***************************************************************************
121    IMPLEMENTATION
122***************************************************************************/
123
124/*-------------------------------------------------
125    recompute_parameters -
126-------------------------------------------------*/
127#ifdef UNUSED_FUNCTION
128static void recompute_parameters(upd7220_t *upd7220)
129{
130   rectangle visarea;
131
132   int horiz_pix_total;
133   int vert_pix_total;
134
135   attoseconds_t refresh = HZ_TO_ATTOSECONDS(upd7220->clock) * (upd7220->aw + 2) * upd7220->al;
136
137   visarea.min_x = upd7220->hs + upd7220->hbp + 1;
138   visarea.min_y = upd7220->vs + upd7220->vbp + 1;
139   visarea.max_x = 0;
140   visarea.max_y = upd7220->al + 2 - upd7220->vfp;
141
142   video_screen_configure(upd7220->screen, horiz_pix_total, vert_pix_total, &visarea, refresh);
143}
144#endif
145/*-------------------------------------------------
146    update_vsync_timer -
147-------------------------------------------------*/
148
149static void update_vsync_timer(upd7220_t *upd7220, int state)
150{
151   int next_y = state ? (upd7220->vs + 1) : 0;
152
153   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, 0);
154
155   timer_adjust_oneshot(upd7220->vsync_timer, duration, !state);
156}
157
158/*-------------------------------------------------
159    TIMER_CALLBACK( vsync_tick )
160-------------------------------------------------*/
161
162static TIMER_CALLBACK( vsync_tick )
163{
164   const device_config *device = ptr;
165   upd7220_t *upd7220 = get_safe_token(device);
166
167   devcb_call_write_line(&upd7220->out_vsync_func, param);
168
169   update_vsync_timer(upd7220, param);
170}
171
172/*-------------------------------------------------
173    update_hsync_timer -
174-------------------------------------------------*/
175
176static void update_hsync_timer(upd7220_t *upd7220, int state)
177{
178   int y = video_screen_get_vpos(upd7220->screen);
179
180   int next_x = state ? upd7220->hs : 0;
181   int next_y = state ? y : ((y + 1) % upd7220->al);
182
183   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
184
185   timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
186}
187
188/*-------------------------------------------------
189    TIMER_CALLBACK( hsync_tick )
190-------------------------------------------------*/
191
192static TIMER_CALLBACK( hsync_tick )
193{
194   const device_config *device = ptr;
195   upd7220_t *upd7220 = get_safe_token(device);
196
197   devcb_call_write_line(&upd7220->out_hsync_func, param);
198
199   update_hsync_timer(upd7220, param);
200}
201
202/*-------------------------------------------------
203    update_blank_timer -
204-------------------------------------------------*/
205
206static void update_blank_timer(upd7220_t *upd7220, int state)
207{
208   int y = video_screen_get_vpos(upd7220->screen);
209
210   int next_x = state ? (upd7220->hs + upd7220->hbp + 1) : 0;
211   int next_y = state ? y : ((y + 1) % upd7220->al);
212
213   attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
214
215   timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
216}
217
218/*-------------------------------------------------
219    TIMER_CALLBACK( blank_tick )
220-------------------------------------------------*/
221
222static TIMER_CALLBACK( blank_tick )
223{
224   const device_config *device = ptr;
225   upd7220_t *upd7220 = get_safe_token(device);
226
227   devcb_call_write_line(&upd7220->out_blank_func, param);
228
229   update_blank_timer(upd7220, param);
230}
231
232/*-------------------------------------------------
233    process_command - process command
234-------------------------------------------------*/
235
236#ifdef UNUSED_CODE
237static void process_command(upd7220_t *upd7220, UINT8 data)
238{
239   switch (data)
240   {
241   case UPD7220_COMMAND_RESET:
242      break;
243   case UPD7220_COMMAND_CCHAR:
244      break;
245   case UPD7220_COMMAND_START:
246      break;
247   case UPD7220_COMMAND_ZOOM:
248      break;
249   case UPD7220_COMMAND_CURS:
250      break;
251   case UPD7220_COMMAND_PITCH:
252      break;
253   case UPD7220_COMMAND_MASK:
254      break;
255   case UPD7220_COMMAND_FIGS:
256      break;
257   case UPD7220_COMMAND_FIGD:
258      break;
259   case UPD7220_COMMAND_CURD:
260      break;
261   case UPD7220_COMMAND_LPRD:
262      break;
263   default:
264      switch (data & 0xfe)
265      {
266      case UPD7220_COMMAND_SYNC:
267         break;
268      case UPD7220_COMMAND_VSYNC:
269         break;
270      case UPD7220_COMMAND_BCTRL:
271         break;
272      default:
273         switch (data & 0xf0)
274         {
275         case UPD7220_COMMAND_PRAM:
276         default:
277            switch (data & 0xe4)
278            {
279            case UPD7220_COMMAND_WDAT:
280               break;
281            case UPD7220_COMMAND_RDAT:
282               break;
283            case UPD7220_COMMAND_DMAR:
284               break;
285            case UPD7220_COMMAND_DMAW:
286               break;
287            default:
288               logerror("Invalid command %02x\n", data);
289            }
290         }
291      }
292   }
293}
294#endif
295
296/*-------------------------------------------------
297    upd7220_r - register read
298-------------------------------------------------*/
299
300READ8_DEVICE_HANDLER( upd7220_r )
301{
302   upd7220_t *upd7220 = get_safe_token(device);
303
304   UINT8 data;
305
306   if (offset & 1)
307   {
308      /* FIFO read */
309      data = dequeue(upd7220);
310   }
311   else
312   {
313      /* status register */
314      data = upd7220->sr;
315   }
316
317   return data;
318}
319
320/*-------------------------------------------------
321    upd7220_w - register write
322-------------------------------------------------*/
323
324WRITE8_DEVICE_HANDLER( upd7220_w )
325{
326   upd7220_t *upd7220 = get_safe_token(device);
327
328   if (offset & 1)
329   {
330      /* command into FIFO */
331      queue(upd7220, data, 1);
332   }
333   else
334   {
335      /* parameter into FIFO */
336      queue(upd7220, data, 0);
337   }
338}
339
340/*-------------------------------------------------
341    upd7220_dack_w - DMA acknowledge w/data
342-------------------------------------------------*/
343
344WRITE8_DEVICE_HANDLER( upd7220_dack_w )
345{
346}
347
348/*-------------------------------------------------
349    upd7220_lpen_w - light pen strobe
350-------------------------------------------------*/
351
352void upd7220_lpen_w(const device_config *device, int state)
353{
354}
355
356/*-------------------------------------------------
357    ROM( upd7220 )
358-------------------------------------------------*/
359
360ROM_START( upd7220 )
361   ROM_REGION( 0x100, "upd7220", ROMREGION_LOADBYNAME )
362   ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP ) /* internal 128x14 control ROM */
363ROM_END
364
365/*-------------------------------------------------
366    DEVICE_START( upd7220 )
367-------------------------------------------------*/
368
369static DEVICE_START( upd7220 )
370{
371   upd7220_t *upd7220 = get_safe_token(device);
372   const upd7220_interface *intf = get_interface(device);
373
374   /* resolve callbacks */
375   devcb_resolve_read8(&upd7220->in_data_func, &intf->in_data_func, device);
376   devcb_resolve_write8(&upd7220->out_data_func, &intf->out_data_func, device);
377   devcb_resolve_write_line(&upd7220->out_drq_func, &intf->out_drq_func, device);
378   devcb_resolve_write_line(&upd7220->out_hsync_func, &intf->out_hsync_func, device);
379   devcb_resolve_write_line(&upd7220->out_vsync_func, &intf->out_vsync_func, device);
380
381   /* get the screen device */
382   upd7220->screen = devtag_get_device(device->machine, intf->screen_tag);
383   assert(upd7220->screen != NULL);
384
385   /* create the timers */
386   upd7220->vsync_timer = timer_alloc(device->machine, vsync_tick, (void *)device);
387   upd7220->hsync_timer = timer_alloc(device->machine, hsync_tick, (void *)device);
388   upd7220->blank_timer = timer_alloc(device->machine, blank_tick, (void *)device);
389
390   /* register for state saving */
391   state_save_register_device_item_array(device, 0, upd7220->ra);
392   state_save_register_device_item(device, 0, upd7220->sr);
393   state_save_register_device_item(device, 0, upd7220->mode);
394   state_save_register_device_item(device, 0, upd7220->de);
395   state_save_register_device_item(device, 0, upd7220->aw);
396   state_save_register_device_item(device, 0, upd7220->al);
397   state_save_register_device_item(device, 0, upd7220->vs);
398   state_save_register_device_item(device, 0, upd7220->vfp);
399   state_save_register_device_item(device, 0, upd7220->vbp);
400   state_save_register_device_item(device, 0, upd7220->hs);
401   state_save_register_device_item(device, 0, upd7220->hfp);
402   state_save_register_device_item(device, 0, upd7220->hbp);
403   state_save_register_device_item(device, 0, upd7220->m);
404   state_save_register_device_item(device, 0, upd7220->dc);
405   state_save_register_device_item(device, 0, upd7220->sc);
406   state_save_register_device_item(device, 0, upd7220->br);
407   state_save_register_device_item(device, 0, upd7220->lr);
408   state_save_register_device_item(device, 0, upd7220->ctop);
409   state_save_register_device_item(device, 0, upd7220->cbot);
410   state_save_register_device_item(device, 0, upd7220->ead);
411   state_save_register_device_item(device, 0, upd7220->dad);
412   state_save_register_device_item(device, 0, upd7220->lad);
413   state_save_register_device_item(device, 0, upd7220->disp);
414   state_save_register_device_item(device, 0, upd7220->gchr);
415   state_save_register_device_item(device, 0, upd7220->mask);
416   state_save_register_device_item(device, 0, upd7220->pitch);
417}
418
419/*-------------------------------------------------
420    DEVICE_RESET( upd7220 )
421-------------------------------------------------*/
422
423static DEVICE_RESET( upd7220 )
424{
425   upd7220_t *upd7220 = get_safe_token(device);
426
427   devcb_call_write_line(&upd7220->out_drq_func, CLEAR_LINE);
428}
429
430/*-------------------------------------------------
431    DEVICE_SET_INFO( upd7220 )
432-------------------------------------------------*/
433
434static DEVICE_SET_INFO( upd7220 )
435{
436   switch (state)
437   {
438      /* no parameters to set */
439   }
440}
441
442/*-------------------------------------------------
443    DEVICE_GET_INFO( upd7220 )
444-------------------------------------------------*/
445
446DEVICE_GET_INFO( upd7220 )
447{
448   switch (state)
449   {
450      /* --- the following bits of info are returned as 64-bit signed integers --- */
451      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(upd7220_t);                  break;
452      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                              break;
453      case DEVINFO_INT_CLASS:                     info->i = DEVICE_CLASS_PERIPHERAL;               break;
454
455      /* --- the following bits of info are returned as pointers --- */
456      case DEVINFO_PTR_ROM_REGION:               info->romregion = ROM_NAME(upd7220);            break;
457
458      /* --- the following bits of info are returned as pointers to data or functions --- */
459      case DEVINFO_FCT_SET_INFO:                  info->set_info = DEVICE_SET_INFO_NAME(upd7220);      break;
460      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(upd7220);         break;
461      case DEVINFO_FCT_STOP:                     /* Nothing */                              break;
462      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(upd7220);         break;
463
464      /* --- the following bits of info are returned as NULL-terminated strings --- */
465      case DEVINFO_STR_NAME:                     strcpy(info->s, "NEC uPD7220");                  break;
466      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "NEC uPD7220");                  break;
467      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                        break;
468      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                     break;
469      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright MESS Team");            break;
470   }
471}
src/mess/video/upd7220.h
r4521r4522
1#ifndef __UPD7220__
2#define __UPD7220__
3 
4#include "devcb.h"
5 
6/***************************************************************************
7    MACROS / CONSTANTS
8***************************************************************************/
9 
10#define UPD7220      DEVICE_GET_INFO_NAME(upd7220)
11 
12#define MDRV_UPD7220_ADD(_tag, _clock, _config) \
13   MDRV_DEVICE_ADD(_tag, UPD7220, _clock) \
14   MDRV_DEVICE_CONFIG(_config)
15 
16#define UPD7220_INTERFACE(name) const upd7220_interface (name)=
17 
18/***************************************************************************
19    TYPE DEFINITIONS
20***************************************************************************/
21 
22typedef void (*upd7220_display_pixels_func)(const device_config *device, int y, int x, UINT16 ad, UINT8 lc, int atblink, int csr, int csr_image);
23#define UPD7220_DISPLAY_PIXELS(name) void name(const device_config *device, int y, int x, UINT16 ad, UINT8 lc, int atblink, int csr, int csr_image)
24 
25typedef struct _upd7220_interface upd7220_interface;
26struct _upd7220_interface
27{
28   const char *screen_tag;      /* screen we are acting on */
29 
30   int                  hpixels_per_column;
31 
32   upd7220_display_pixels_func   display;
33 
34   /* this gets called for every video memory read */
35   devcb_read8            in_data_func;
36 
37   /* this gets called for every video memory write */
38   devcb_write8         out_data_func;
39 
40   /* this gets called for every change of the DRQ pin (pin 7) */
41   devcb_write_line      out_drq_func;
42 
43   /* this gets called for every change of the HSYNC pin (pin 3) */
44   devcb_write_line      out_hsync_func;
45 
46   /* this gets called for every change of the VSYNC pin (pin 4) */
47   devcb_write_line      out_vsync_func;
48 
49   /* this gets called for every change of the BLANK pin (pin 5) */
50   devcb_write_line      out_blank_func;
51};
52 
53/***************************************************************************
54    PROTOTYPES
55***************************************************************************/
56 
57/* device interface */
58DEVICE_GET_INFO( upd7220 );
59 
60/* register read */
61READ8_DEVICE_HANDLER( upd7220_r );
62 
63/* register write */
64WRITE8_DEVICE_HANDLER( upd7220_w );
65 
66/* dma acknowledge with write */
67WRITE8_DEVICE_HANDLER( upd7220_dack_w );
68 
69/* light pen strobe */
70void upd7220_lpen_w(const device_config *device, int state);
71 
72/* screen update */
73void upd7220_update(const device_config *device, bitmap_t *bitmap, const rectangle *cliprect);
74 
75#endif
1#ifndef __UPD7220__
2#define __UPD7220__
3
4#include "devcb.h"
5
6/***************************************************************************
7    MACROS / CONSTANTS
8***************************************************************************/
9
10#define UPD7220      DEVICE_GET_INFO_NAME(upd7220)
11
12#define MDRV_UPD7220_ADD(_tag, _clock, _config) \
13   MDRV_DEVICE_ADD(_tag, UPD7220, _clock) \
14   MDRV_DEVICE_CONFIG(_config)
15
16#define UPD7220_INTERFACE(name) const upd7220_interface (name)=
17
18/***************************************************************************
19    TYPE DEFINITIONS
20***************************************************************************/
21
22typedef void (*upd7220_display_pixels_func)(const device_config *device, int y, int x, UINT16 ad, UINT8 lc, int atblink, int csr, int csr_image);
23#define UPD7220_DISPLAY_PIXELS(name) void name(const device_config *device, int y, int x, UINT16 ad, UINT8 lc, int atblink, int csr, int csr_image)
24
25typedef struct _upd7220_interface upd7220_interface;
26struct _upd7220_interface
27{
28   const char *screen_tag;      /* screen we are acting on */
29
30   int                  hpixels_per_column;
31
32   upd7220_display_pixels_func   display;
33
34   /* this gets called for every video memory read */
35   devcb_read8            in_data_func;
36
37   /* this gets called for every video memory write */
38   devcb_write8         out_data_func;
39
40   /* this gets called for every change of the DRQ pin (pin 7) */
41   devcb_write_line      out_drq_func;
42
43   /* this gets called for every change of the HSYNC pin (pin 3) */
44   devcb_write_line      out_hsync_func;
45
46   /* this gets called for every change of the VSYNC pin (pin 4) */
47   devcb_write_line      out_vsync_func;
48
49   /* this gets called for every change of the BLANK pin (pin 5) */
50   devcb_write_line      out_blank_func;
51};
52
53/***************************************************************************
54    PROTOTYPES
55***************************************************************************/
56
57/* device interface */
58DEVICE_GET_INFO( upd7220 );
59
60/* register read */
61READ8_DEVICE_HANDLER( upd7220_r );
62
63/* register write */
64WRITE8_DEVICE_HANDLER( upd7220_w );
65
66/* dma acknowledge with write */
67WRITE8_DEVICE_HANDLER( upd7220_dack_w );
68
69/* light pen strobe */
70void upd7220_lpen_w(const device_config *device, int state);
71
72/* screen update */
73void upd7220_update(const device_config *device, bitmap_t *bitmap, const rectangle *cliprect);
74
75#endif
src/mess/machine/z80ne.c
r4521r4522
1/***********************************************************************
2 
3   machine/z80ne.c
4 
5   Functions to emulate general aspects of the machine (RAM, ROM,
6   interrupts, I/O ports)
7 
8***********************************************************************/
9 
10/* Core includes */
11#include "driver.h"
12#include "devintrf.h"
13#include "includes/z80ne.h"
14 
15/* Components */
16#include "machine/ay31015.h"
17#include "machine/kr2376.h"
18#include "machine/wd17xx.h"
19#include "video/m6847.h"
20 
21/* Devices */
22#include "devices/basicdsk.h"
23#include "devices/cassette.h"
24 
25static UINT8 lx383_scan_counter;
26static UINT8 lx383_key[LX383_KEYS];
27static int   lx383_downsampler;
28static int   nmi_delay_counter;
29static const device_config *z80ne_ay31015;
30static UINT8 lx385_ctrl = 0x1f;
31static const device_config *lx388_kr2376;
32 
33 
34 
35/* timer to read cassette waveforms */
36static emu_timer *cassette_timer;
37 
38/* wave duration threshold */
39typedef enum
40{
41   TAPE_300BPS  = 300, /*  300 bps */
42   TAPE_600BPS  = 600, /*  600 bps */
43   TAPE_1200BPS = 1200 /* 1200 bps */
44} z80netape_speed;
45 
46static struct {
47   struct {
48      int length;      /* time cassette level is at input.level */
49      int level;      /* cassette level */
50      int bit;      /* bit being read */
51   } input;
52   struct {
53      int length;      /* time cassette level is at output.level */
54      int level;      /* cassette level */
55      int bit;      /* bit to to output */
56   } output;
57   z80netape_speed speed;         /* 300 - 600 - 1200 */
58   int wave_filter;
59   int wave_length;
60   int wave_short;
61   int wave_long;
62} cass_data;
63 
64static const device_config *cassette_device_image(running_machine *machine)
65{
66   if (lx385_ctrl & 0x08)
67      return devtag_get_device(machine, "cassetteb");
68   else
69      return devtag_get_device(machine, "cassettea");
70}
71 
72static TIMER_CALLBACK(z80ne_cassette_tc)
73{
74   UINT8 cass_ws = 0;
75   cass_data.input.length++;
76 
77   cass_ws = (cassette_input(cassette_device_image(machine)) > +0.02) ? 1 : 0;
78 
79   if ((cass_ws ^ cass_data.input.level) & cass_ws)
80   {
81      cass_data.input.level = cass_ws;
82      cass_data.input.bit = ((cass_data.input.length < cass_data.wave_filter) || (cass_data.input.length > 0x20)) ? 1 : 0;
83      cass_data.input.length = 0;
84      ay31015_set_input_pin( z80ne_ay31015, AY31015_SI, cass_data.input.bit );
85   }
86   cass_data.input.level = cass_ws;
87 
88   /* saving a tape - convert the serial stream from the uart */
89 
90   cass_data.output.length--;
91 
92   if (!(cass_data.output.length))
93   {
94      if (cass_data.output.level)
95         cass_data.output.level = 0;
96      else
97      {
98         cass_data.output.level=1;
99         cass_ws = ay31015_get_output_pin( z80ne_ay31015, AY31015_SO );
100         cass_data.wave_length = cass_ws ? cass_data.wave_short : cass_data.wave_long;
101      }
102      cassette_output(cassette_device_image(machine), cass_data.output.level ? -1.0 : +1.0);
103      cass_data.output.length = cass_data.wave_length;
104   }
105}
106 
107 
108DRIVER_INIT( z80ne )
109{
110   /* first two entries point to rom on reset */
111   UINT8 *RAM = memory_region(machine, "z80ne");
112   memory_configure_bank(machine, 1, 0, 2, &RAM[0x0000], 0x8000);
113}
114 
115DRIVER_INIT( z80net )
116{
117   DRIVER_INIT_CALL(z80ne);
118}
119 
120DRIVER_INIT( z80netb )
121{
122}
123 
124/* after the first 3 bytes have been read from ROM, switch the ram back in */
125static TIMER_CALLBACK(z80ne_reset_address_decoder)
126{
127   memory_set_bank(machine, 1, 0);
128}
129 
130static TIMER_CALLBACK( z80ne_kbd_scan )
131{
132   /*
133    * NE555 is connected to a 74LS93 binary counter
134    * 74LS93 output:
135    *   QA-QC: column index for LEDs and keyboard
136    *   QD:    keyboard row select
137    *
138    * Port F0 input bit assignment:
139    *   0   QA   bits 0..3 of row counter
140    *   1   QB
141    *   2   QC
142    *   3   QD
143    *   4   Control button pressed, active high
144    *   5  Always low
145    *   6  Always low
146    *   7  Selected button pressed, active low
147    *
148    *
149    */
150 
151   static UINT16 key_bits;
152   static UINT8 ctrl, rst;
153   static UINT8 i;
154 
155   // 4-bit counter
156   --lx383_scan_counter;
157   lx383_scan_counter &= 0x0f;
158 
159   if ( --lx383_downsampler == 0 )
160   {
161      lx383_downsampler = LX383_DOWNSAMPLING;
162      key_bits = (input_port_read(machine, "ROW1") << 8) | input_port_read(machine, "ROW0");
163      rst = input_port_read(machine, "RST");
164      ctrl = input_port_read(machine, "CTRL");
165 
166       for ( i = 0; i<LX383_KEYS; i++)
167      {
168         lx383_key[i] = ( i | (key_bits & 0x01 ? 0x80 : 0x00) | ~ctrl);
169         key_bits >>= 1;
170      }
171   }
172}
173 
174/*
175 * Handle NMI delay for single step instruction
176 */
177//static offs_t nmi_delay_count(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t address, direct_read_data *direct)
178static DIRECT_UPDATE_HANDLER( nmi_delay_count )
179{
180   nmi_delay_counter--;
181 
182   if (!nmi_delay_counter)
183   {
184      memory_set_direct_update_handler( space, NULL );
185      cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, PULSE_LINE);
186   }
187   return address;
188}
189 
190MACHINE_RESET(z80ne_base)
191{
192   int i;
193   const address_space *space = cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM);
194 
195   logerror("In MACHINE_RESET z80ne_base\n");
196 
197   for ( i=0; i<LX383_KEYS; i++)
198       lx383_key[i] = 0xf0 | i;
199    lx383_scan_counter = 0x0f;
200    lx383_downsampler = LX383_DOWNSAMPLING;
201    timer_pulse(machine,  ATTOTIME_IN_HZ(1000), NULL, 0, z80ne_kbd_scan );
202 
203   /* Initialize cassette interface */
204   switch(input_port_read(machine, "LX.385") & 0x07)
205   {
206   case 0x01:
207      cass_data.speed = TAPE_300BPS;
208      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 1600;
209      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
210      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (1200 * 2);
211      break;
212   case 0x02:
213      cass_data.speed = TAPE_600BPS;
214      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 3200;
215      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
216      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
217      break;
218   case 0x04:
219      cass_data.speed = TAPE_1200BPS;
220      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 6400;
221      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (9600 * 2);
222      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
223   }
224//   cass_data.output.length = 0;
225   cass_data.wave_length = cass_data.wave_short;
226   cass_data.output.length = cass_data.wave_length;
227   cass_data.output.level = 1;
228   cass_data.input.length = 0;
229   cass_data.input.bit = 1;
230 
231   z80ne_ay31015 = devtag_get_device(machine, "ay_3_1015");
232   ay31015_set_input_pin( z80ne_ay31015, AY31015_CS, 0 );
233   ay31015_set_input_pin( z80ne_ay31015, AY31015_NB1, 1 );
234   ay31015_set_input_pin( z80ne_ay31015, AY31015_NB2, 1 );
235   ay31015_set_input_pin( z80ne_ay31015, AY31015_TSB, 1 );
236   ay31015_set_input_pin( z80ne_ay31015, AY31015_EPS, 1 );
237   ay31015_set_input_pin( z80ne_ay31015, AY31015_NP, input_port_read(machine, "LX.385") & 0x80 ? 1 : 0 );
238   ay31015_set_input_pin( z80ne_ay31015, AY31015_CS, 1 );
239   ay31015_set_receiver_clock( z80ne_ay31015, cass_data.speed * 16.0);
240   ay31015_set_transmitter_clock( z80ne_ay31015, cass_data.speed * 16.0);
241 
242   memory_set_direct_update_handler( space, NULL );
243   nmi_delay_counter = 0;
244   lx385_ctrl_w(space, 0, 0);
245 
246}
247 
248MACHINE_RESET(z80ne)
249{
250//   UINT8 *RAM = memory_region(machine, "z80ne");
251//   memory_configure_bank(machine, 1, 0, 2, &RAM[0x0000], 0x8000);
252 
253   /* after the first 3 bytes have been read from ROM, switch the ram back in */
254   timer_set(machine, ATTOTIME_IN_USEC(6), NULL, 0, z80ne_reset_address_decoder);
255    memory_set_bank(machine, 1, 1);
256 
257   logerror("In MACHINE_RESET z80ne\n");
258   MACHINE_RESET_CALL( z80ne_base );
259}
260 
261MACHINE_RESET(z80net)
262{
263   MACHINE_RESET_CALL( z80ne );
264   logerror("In MACHINE_RESET z80net\n");
265 
266   lx388_kr2376 = devtag_get_device(machine, "lx388_kr2376");
267   kr2376_set_input_pin( lx388_kr2376, KR2376_DSII, 0);
268   kr2376_set_input_pin( lx388_kr2376, KR2376_PII, 0);
269}
270 
271MACHINE_RESET(z80netb)
272{
273   MACHINE_RESET_CALL( z80ne_base );
274   logerror("In MACHINE_RESET z80netb\n");
275 
276   lx388_kr2376 = devtag_get_device(machine, "lx388_kr2376");
277   kr2376_set_input_pin( lx388_kr2376, KR2376_DSII, 0);
278   kr2376_set_input_pin( lx388_kr2376, KR2376_PII, 0);
279}
280 
281INPUT_CHANGED( z80ne_reset )
282{
283   UINT8 rst;
284   rst = input_port_read(field->port->machine, "RST");
285 
286   if ( ! BIT(rst, 0))
287   {
288      running_machine *machine = field->port->machine;
289      //MACHINE_RESET_CALL(z80ne);
290      //device_reset(machine->cpu[0]);
291      mame_schedule_soft_reset(machine);
292   }
293}
294 
295INPUT_CHANGED( z80ne_nmi )
296{
297   UINT8 nmi;
298   nmi = input_port_read(field->port->machine, "LX388_BRK");
299 
300   if ( ! BIT(nmi, 0))
301   {
302      cpu_set_input_line(field->port->machine->cpu[0], INPUT_LINE_NMI, PULSE_LINE);
303   }
304}
305 
306MACHINE_START( z80ne )
307{
308   logerror("In MACHINE_START z80ne\n");
309   state_save_register_item( machine, "z80ne", NULL, 0, lx383_scan_counter );
310   state_save_register_item( machine, "z80ne", NULL, 0, lx383_downsampler );
311   state_save_register_item_array( machine, "z80ne", NULL, 0, lx383_key );
312   state_save_register_item( machine, "z80ne", NULL, 0, nmi_delay_counter );
313   cassette_timer = timer_alloc(machine, z80ne_cassette_tc, NULL);
314}
315 
316MACHINE_START( z80net )
317{
318   MACHINE_START_CALL( z80ne );
319   logerror("In MACHINE_START z80net\n");
320}
321 
322MACHINE_START( z80netb )
323{
324   MACHINE_START_CALL( z80net );
325   logerror("In MACHINE_START z80netb\n");
326}
327 
328/******************************************************************************
329 Drivers
330******************************************************************************/
331 
332/* LX.383 - LX.384 HEX keyboard and display */
333READ8_HANDLER( lx383_r )
334{
335   /*
336    * Keyboard scanning
337    *
338    * IC14 NE555 astable oscillator
339    * IC13 74LS93 binary counter
340    * IC5  74LS240 tri-state buffer
341    *
342    * l'oscillatore NE555 alimenta il clock del contatore 74LS93
343    *       D0 - Q(A) --\
344    *       D1 - Q(B)    |-- column
345    *       D2 - Q(C) --/
346    *       D3 - Q(D)        row
347    *      D4 - CTRL
348    *      D5 - 0
349    *      D6 - 0
350    *      D7 - ~KEY Pressed
351    */
352    return lx383_key[lx383_scan_counter];
353}
354 
355//#define ATTR_UNUSED __attribute__((__unused__))
356WRITE8_HANDLER( lx383_w )
357{
358   /*
359    * First 8 locations (F0-F7) are mapped to a dual-port 8-byte RAM
360    * The 1KHz NE-555 astable oscillator circuit drive
361    * a 4-bit 74LS93 binary counter.
362    * The 3 least sigificant bits of the counter are connected
363    * both to the read addres of the dual-port ram and to
364    * a 74LS156 3 to 8 binary decoder driving the cathode
365    * of 8 7-segments LEDS.
366    * The data output of the dual-port ram drive the anodes
367    * of the LEDS through 74LS07 buffers.
368    * LED segments - dual-port RAM bit:
369    *   A   0x01
370    *   B   0x02
371    *   C   0x04
372    *   D   0x08
373    *   E   0x10
374    *   F   0x20
375    *   G   0x40
376    *   P   0x80 (represented by DP in original schematics)
377    *
378    *   A write in the range F0-FF starts a 74LS90 counter
379    *   that trigger the NMI line of the CPU afther 2 instruction
380    *   fetch cycles for single step execution.
381    */
382 
383   if ( offset < 8 )
384       output_set_digit_value( offset, data ^ 0xff );
385    else
386       /* after writing to port 0xF8 and the first ~M1 cycles strike a NMI for single step execution */
387       nmi_delay_counter = 1;
388       memory_set_direct_update_handler(cpu_get_address_space(space->machine->cpu[0], ADDRESS_SPACE_PROGRAM),nmi_delay_count);
389}
390 
391 
392/* LX.385 Cassette tape interface */
393/*
394 * NE555 is connected to a 74LS93 binary counter
395 * 74LS93 output:
396 *   QA-QC: colum index for LEDs and keyboard
397 *   QD:    keyboard row select
398 *
399 * Port EE: UART Data Read/Write
400 * Port EF: Status/Control
401 *     read, UART status bits read
402 *         0 OR   Overrun
403 *         1 FE   Framing Error
404 *         2 PE   Parity Error
405 *         3 TBMT Transmitter Buffer Empty
406 *         4 DAV  Data Available
407 *         5 EOC  End Of Character
408 *         6 1
409 *         7 1
410 *     write, UART control bits / Tape Unit select / Modulation control
411 *         0 bit1=0, bit0=0   UART Reset pulse
412 *         1 bit1=0, bit0=1   UART RDAV (Reset Data Available) pulse
413 *         2 Tape modulation enable
414 *         3 *TAPEA Enable (active low) (at reset: low)
415 *         4 *TAPEB Enable (active low) (at reset: low)
416 *  Cassette is connected to the uart data input and output via the cassette
417 *  interface hardware.
418 *
419 *  The cassette interface hardware converts square-wave pulses into bits which the uart receives.
420 *
421 *  1. the cassette format: "frequency shift" is converted
422    into the uart data format "non-return to zero"
423 
424    2. on cassette a 1 data bit is stored as 8 2400 Hz pulses
425    and a 0 data bit as 4 1200 Hz pulses
426    - At 1200 baud, a logic 1 is 1 cycle of 1200 Hz and a logic 0 is 1/2 cycle of 600 Hz.
427    - At 300 baud, a logic 1 is 8 cycles of 2400 Hz and a logic 0 is 4 cycles of 1200 Hz.
428 
429    Attenuation is applied to the signal and the square wave edges are rounded.
430 
431    A manchester encoder is used. A flip-flop synchronises input
432    data on the positive-edge of the clock pulse.
433 *
434 */
435READ8_HANDLER(lx385_data_r)
436{
437   return ay31015_get_received_data( z80ne_ay31015 );
438}
439 
440READ8_HANDLER(lx385_ctrl_r)
441{
442   /* set unused bits high */
443   UINT8 data = 0xc0;
444//   UINT8 olddata = 0xc0;
445 
446   ay31015_set_input_pin( z80ne_ay31015, AY31015_SWE, 0 );
447   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_OR   ) ? 0x01 : 0);
448   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_FE   ) ? 0x02 : 0);
449   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_PE   ) ? 0x04 : 0);
450   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_TBMT ) ? 0x08 : 0);
451   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_DAV  ) ? 0x10 : 0);
452   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_EOC  ) ? 0x20 : 0);
453   ay31015_set_input_pin( z80ne_ay31015, AY31015_SWE, 1 );
454 
455   return data;
456}
457WRITE8_HANDLER(lx385_data_w)
458{
459   ay31015_set_transmit_data( z80ne_ay31015, data );
460}
461 
462#define LX385_CASSETTE_MOTOR_MASK ((1<<3)|(1<<4))
463 
464WRITE8_HANDLER(lx385_ctrl_w)
465{
466   /* Translate data to control signals
467    *     0 bit1=0, bit0=0   UART Reset pulse
468    *     1 bit1=0, bit0=1   UART RDAV (Reset Data Available) pulse
469    *     2 UART Tx Clock Enable (active high)
470    *     3 *TAPEA Enable (active low) (at reset: low)
471    *     4 *TAPEB Enable (active low) (at reset: low)
472    */
473   UINT8 uart_reset, uart_rdav, uart_tx_clock;
474   UINT8 motor_a, motor_b;
475   UINT8 changed_bits = (lx385_ctrl ^ data) & 0x1C;
476   lx385_ctrl = data;
477 
478   uart_reset = ((data & 0x03) == 0x00);
479   uart_rdav  = ((data & 0x03) == 0x01);
480   uart_tx_clock = ((data & 0x04) == 0x04);
481   motor_a = ((data & 0x08) == 0x00);
482   motor_b = ((data & 0x10) == 0x00);
483 
484   /* UART Reset and RDAV */
485   if(uart_reset)
486   {
487      ay31015_set_input_pin( z80ne_ay31015, AY31015_XR, 1 );
488      ay31015_set_input_pin( z80ne_ay31015, AY31015_XR, 0 );
489   }
490 
491   if(uart_rdav)
492   {
493      ay31015_set_input_pin( z80ne_ay31015, AY31015_RDAV, 1 );
494      ay31015_set_input_pin( z80ne_ay31015, AY31015_RDAV, 0 );
495   }
496 
497   if (!changed_bits) return;
498 
499   /* UART Tx Clock enable/disable */
500   if(changed_bits & 0x04)
501      ay31015_set_transmitter_clock( z80ne_ay31015, uart_tx_clock ? cass_data.speed * 16.0 : 0.0);
502 
503   /* motors */
504   if(changed_bits & 0x18)
505   {
506      cassette_change_state(devtag_get_device(space->machine, "cassettea"),
507         (motor_a) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
508 
509      cassette_change_state(devtag_get_device(space->machine, "cassetteb"),
510         (motor_b) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
511 
512      if (motor_a || motor_b)
513         timer_adjust_periodic(cassette_timer, attotime_zero, 0, ATTOTIME_IN_HZ(LX385_TAPE_SAMPLE_FREQ));
514      else
515         timer_adjust_oneshot(cassette_timer, attotime_zero, 0);
516   }
517}
518 
519READ8_HANDLER(lx388_data_r)
520{
521   UINT8 data;
522 
523   data = kr2376_data_r(lx388_kr2376, 0) & 0x7f;
524   data |= kr2376_get_output_pin(lx388_kr2376, KR2376_SO) << 7;
525   return data;
526}
527 
528READ8_HANDLER(lx388_read_field_sync)
529{
530   UINT8 data;
531 
532   data = m6847_get_field_sync(space->machine) ? 0x00 : 0x80;
533   return data;
534}
1/***********************************************************************
2
3   machine/z80ne.c
4
5   Functions to emulate general aspects of the machine (RAM, ROM,
6   interrupts, I/O ports)
7
8***********************************************************************/
9
10/* Core includes */
11#include "driver.h"
12#include "devintrf.h"
13#include "includes/z80ne.h"
14
15/* Components */
16#include "machine/ay31015.h"
17#include "machine/kr2376.h"
18#include "machine/wd17xx.h"
19#include "video/m6847.h"
20
21/* Devices */
22#include "devices/basicdsk.h"
23#include "devices/cassette.h"
24
25static UINT8 lx383_scan_counter;
26static UINT8 lx383_key[LX383_KEYS];
27static int   lx383_downsampler;
28static int   nmi_delay_counter;
29static const device_config *z80ne_ay31015;
30static UINT8 lx385_ctrl = 0x1f;
31static const device_config *lx388_kr2376;
32
33
34
35/* timer to read cassette waveforms */
36static emu_timer *cassette_timer;
37
38/* wave duration threshold */
39typedef enum
40{
41   TAPE_300BPS  = 300, /*  300 bps */
42   TAPE_600BPS  = 600, /*  600 bps */
43   TAPE_1200BPS = 1200 /* 1200 bps */
44} z80netape_speed;
45
46static struct {
47   struct {
48      int length;      /* time cassette level is at input.level */
49      int level;      /* cassette level */
50      int bit;      /* bit being read */
51   } input;
52   struct {
53      int length;      /* time cassette level is at output.level */
54      int level;      /* cassette level */
55      int bit;      /* bit to to output */
56   } output;
57   z80netape_speed speed;         /* 300 - 600 - 1200 */
58   int wave_filter;
59   int wave_length;
60   int wave_short;
61   int wave_long;
62} cass_data;
63
64static const device_config *cassette_device_image(running_machine *machine)
65{
66   if (lx385_ctrl & 0x08)
67      return devtag_get_device(machine, "cassetteb");
68   else
69      return devtag_get_device(machine, "cassettea");
70}
71
72static TIMER_CALLBACK(z80ne_cassette_tc)
73{
74   UINT8 cass_ws = 0;
75   cass_data.input.length++;
76
77   cass_ws = (cassette_input(cassette_device_image(machine)) > +0.02) ? 1 : 0;
78
79   if ((cass_ws ^ cass_data.input.level) & cass_ws)
80   {
81      cass_data.input.level = cass_ws;
82      cass_data.input.bit = ((cass_data.input.length < cass_data.wave_filter) || (cass_data.input.length > 0x20)) ? 1 : 0;
83      cass_data.input.length = 0;
84      ay31015_set_input_pin( z80ne_ay31015, AY31015_SI, cass_data.input.bit );
85   }
86   cass_data.input.level = cass_ws;
87
88   /* saving a tape - convert the serial stream from the uart */
89
90   cass_data.output.length--;
91
92   if (!(cass_data.output.length))
93   {
94      if (cass_data.output.level)
95         cass_data.output.level = 0;
96      else
97      {
98         cass_data.output.level=1;
99         cass_ws = ay31015_get_output_pin( z80ne_ay31015, AY31015_SO );
100         cass_data.wave_length = cass_ws ? cass_data.wave_short : cass_data.wave_long;
101      }
102      cassette_output(cassette_device_image(machine), cass_data.output.level ? -1.0 : +1.0);
103      cass_data.output.length = cass_data.wave_length;
104   }
105}
106
107
108DRIVER_INIT( z80ne )
109{
110   /* first two entries point to rom on reset */
111   UINT8 *RAM = memory_region(machine, "z80ne");
112   memory_configure_bank(machine, 1, 0, 2, &RAM[0x0000], 0x8000);
113}
114
115DRIVER_INIT( z80net )
116{
117   DRIVER_INIT_CALL(z80ne);
118}
119
120DRIVER_INIT( z80netb )
121{
122}
123
124/* after the first 3 bytes have been read from ROM, switch the ram back in */
125static TIMER_CALLBACK(z80ne_reset_address_decoder)
126{
127   memory_set_bank(machine, 1, 0);
128}
129
130static TIMER_CALLBACK( z80ne_kbd_scan )
131{
132   /*
133    * NE555 is connected to a 74LS93 binary counter
134    * 74LS93 output:
135    *   QA-QC: column index for LEDs and keyboard
136    *   QD:    keyboard row select
137    *
138    * Port F0 input bit assignment:
139    *   0   QA   bits 0..3 of row counter
140    *   1   QB
141    *   2   QC
142    *   3   QD
143    *   4   Control button pressed, active high
144    *   5  Always low
145    *   6  Always low
146    *   7  Selected button pressed, active low
147    *
148    *
149    */
150
151   static UINT16 key_bits;
152   static UINT8 ctrl, rst;
153   static UINT8 i;
154
155   // 4-bit counter
156   --lx383_scan_counter;
157   lx383_scan_counter &= 0x0f;
158
159   if ( --lx383_downsampler == 0 )
160   {
161      lx383_downsampler = LX383_DOWNSAMPLING;
162      key_bits = (input_port_read(machine, "ROW1") << 8) | input_port_read(machine, "ROW0");
163      rst = input_port_read(machine, "RST");
164      ctrl = input_port_read(machine, "CTRL");
165
166       for ( i = 0; i<LX383_KEYS; i++)
167      {
168         lx383_key[i] = ( i | (key_bits & 0x01 ? 0x80 : 0x00) | ~ctrl);
169         key_bits >>= 1;
170      }
171   }
172}
173
174/*
175 * Handle NMI delay for single step instruction
176 */
177//static offs_t nmi_delay_count(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t address, direct_read_data *direct)
178static DIRECT_UPDATE_HANDLER( nmi_delay_count )
179{
180   nmi_delay_counter--;
181
182   if (!nmi_delay_counter)
183   {
184      memory_set_direct_update_handler( space, NULL );
185      cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, PULSE_LINE);
186   }
187   return address;
188}
189
190MACHINE_RESET(z80ne_base)
191{
192   int i;
193   const address_space *space = cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM);
194
195   logerror("In MACHINE_RESET z80ne_base\n");
196
197   for ( i=0; i<LX383_KEYS; i++)
198       lx383_key[i] = 0xf0 | i;
199    lx383_scan_counter = 0x0f;
200    lx383_downsampler = LX383_DOWNSAMPLING;
201    timer_pulse(machine,  ATTOTIME_IN_HZ(1000), NULL, 0, z80ne_kbd_scan );
202
203   /* Initialize cassette interface */
204   switch(input_port_read(machine, "LX.385") & 0x07)
205   {
206   case 0x01:
207      cass_data.speed = TAPE_300BPS;
208      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 1600;
209      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
210      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (1200 * 2);
211      break;
212   case 0x02:
213      cass_data.speed = TAPE_600BPS;
214      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 3200;
215      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
216      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
217      break;
218   case 0x04:
219      cass_data.speed = TAPE_1200BPS;
220      cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 6400;
221      cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (9600 * 2);
222      cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
223   }
224//   cass_data.output.length = 0;
225   cass_data.wave_length = cass_data.wave_short;
226   cass_data.output.length = cass_data.wave_length;
227   cass_data.output.level = 1;
228   cass_data.input.length = 0;
229   cass_data.input.bit = 1;
230
231   z80ne_ay31015 = devtag_get_device(machine, "ay_3_1015");
232   ay31015_set_input_pin( z80ne_ay31015, AY31015_CS, 0 );
233   ay31015_set_input_pin( z80ne_ay31015, AY31015_NB1, 1 );
234   ay31015_set_input_pin( z80ne_ay31015, AY31015_NB2, 1 );
235   ay31015_set_input_pin( z80ne_ay31015, AY31015_TSB, 1 );
236   ay31015_set_input_pin( z80ne_ay31015, AY31015_EPS, 1 );
237   ay31015_set_input_pin( z80ne_ay31015, AY31015_NP, input_port_read(machine, "LX.385") & 0x80 ? 1 : 0 );
238   ay31015_set_input_pin( z80ne_ay31015, AY31015_CS, 1 );
239   ay31015_set_receiver_clock( z80ne_ay31015, cass_data.speed * 16.0);
240   ay31015_set_transmitter_clock( z80ne_ay31015, cass_data.speed * 16.0);
241
242   memory_set_direct_update_handler( space, NULL );
243   nmi_delay_counter = 0;
244   lx385_ctrl_w(space, 0, 0);
245
246}
247
248MACHINE_RESET(z80ne)
249{
250//   UINT8 *RAM = memory_region(machine, "z80ne");
251//   memory_configure_bank(machine, 1, 0, 2, &RAM[0x0000], 0x8000);
252
253   /* after the first 3 bytes have been read from ROM, switch the ram back in */
254   timer_set(machine, ATTOTIME_IN_USEC(6), NULL, 0, z80ne_reset_address_decoder);
255    memory_set_bank(machine, 1, 1);
256
257   logerror("In MACHINE_RESET z80ne\n");
258   MACHINE_RESET_CALL( z80ne_base );
259}
260
261MACHINE_RESET(z80net)
262{
263   MACHINE_RESET_CALL( z80ne );
264   logerror("In MACHINE_RESET z80net\n");
265
266   lx388_kr2376 = devtag_get_device(machine, "lx388_kr2376");
267   kr2376_set_input_pin( lx388_kr2376, KR2376_DSII, 0);
268   kr2376_set_input_pin( lx388_kr2376, KR2376_PII, 0);
269}
270
271MACHINE_RESET(z80netb)
272{
273   MACHINE_RESET_CALL( z80ne_base );
274   logerror("In MACHINE_RESET z80netb\n");
275
276   lx388_kr2376 = devtag_get_device(machine, "lx388_kr2376");
277   kr2376_set_input_pin( lx388_kr2376, KR2376_DSII, 0);
278   kr2376_set_input_pin( lx388_kr2376, KR2376_PII, 0);
279}
280
281INPUT_CHANGED( z80ne_reset )
282{
283   UINT8 rst;
284   rst = input_port_read(field->port->machine, "RST");
285
286   if ( ! BIT(rst, 0))
287   {
288      running_machine *machine = field->port->machine;
289      //MACHINE_RESET_CALL(z80ne);
290      //device_reset(machine->cpu[0]);
291      mame_schedule_soft_reset(machine);
292   }
293}
294
295INPUT_CHANGED( z80ne_nmi )
296{
297   UINT8 nmi;
298   nmi = input_port_read(field->port->machine, "LX388_BRK");
299
300   if ( ! BIT(nmi, 0))
301   {
302      cpu_set_input_line(field->port->machine->cpu[0], INPUT_LINE_NMI, PULSE_LINE);
303   }
304}
305
306MACHINE_START( z80ne )
307{
308   logerror("In MACHINE_START z80ne\n");
309   state_save_register_item( machine, "z80ne", NULL, 0, lx383_scan_counter );
310   state_save_register_item( machine, "z80ne", NULL, 0, lx383_downsampler );
311   state_save_register_item_array( machine, "z80ne", NULL, 0, lx383_key );
312   state_save_register_item( machine, "z80ne", NULL, 0, nmi_delay_counter );
313   cassette_timer = timer_alloc(machine, z80ne_cassette_tc, NULL);
314}
315
316MACHINE_START( z80net )
317{
318   MACHINE_START_CALL( z80ne );
319   logerror("In MACHINE_START z80net\n");
320}
321
322MACHINE_START( z80netb )
323{
324   MACHINE_START_CALL( z80net );
325   logerror("In MACHINE_START z80netb\n");
326}
327
328/******************************************************************************
329 Drivers
330******************************************************************************/
331
332/* LX.383 - LX.384 HEX keyboard and display */
333READ8_HANDLER( lx383_r )
334{
335   /*
336    * Keyboard scanning
337    *
338    * IC14 NE555 astable oscillator
339    * IC13 74LS93 binary counter
340    * IC5  74LS240 tri-state buffer
341    *
342    * l'oscillatore NE555 alimenta il clock del contatore 74LS93
343    *       D0 - Q(A) --\
344    *       D1 - Q(B)    |-- column
345    *       D2 - Q(C) --/
346    *       D3 - Q(D)        row
347    *      D4 - CTRL
348    *      D5 - 0
349    *      D6 - 0
350    *      D7 - ~KEY Pressed
351    */
352    return lx383_key[lx383_scan_counter];
353}
354
355//#define ATTR_UNUSED __attribute__((__unused__))
356WRITE8_HANDLER( lx383_w )
357{
358   /*
359    * First 8 locations (F0-F7) are mapped to a dual-port 8-byte RAM
360    * The 1KHz NE-555 astable oscillator circuit drive
361    * a 4-bit 74LS93 binary counter.
362    * The 3 least sigificant bits of the counter are connected
363    * both to the read addres of the dual-port ram and to
364    * a 74LS156 3 to 8 binary decoder driving the cathode
365    * of 8 7-segments LEDS.
366    * The data output of the dual-port ram drive the anodes
367    * of the LEDS through 74LS07 buffers.
368    * LED segments - dual-port RAM bit:
369    *   A   0x01
370    *   B   0x02
371    *   C   0x04
372    *   D   0x08
373    *   E   0x10
374    *   F   0x20
375    *   G   0x40
376    *   P   0x80 (represented by DP in original schematics)
377    *
378    *   A write in the range F0-FF starts a 74LS90 counter
379    *   that trigger the NMI line of the CPU afther 2 instruction
380    *   fetch cycles for single step execution.
381    */
382
383   if ( offset < 8 )
384       output_set_digit_value( offset, data ^ 0xff );
385    else
386       /* after writing to port 0xF8 and the first ~M1 cycles strike a NMI for single step execution */
387       nmi_delay_counter = 1;
388       memory_set_direct_update_handler(cpu_get_address_space(space->machine->cpu[0], ADDRESS_SPACE_PROGRAM),nmi_delay_count);
389}
390
391
392/* LX.385 Cassette tape interface */
393/*
394 * NE555 is connected to a 74LS93 binary counter
395 * 74LS93 output:
396 *   QA-QC: colum index for LEDs and keyboard
397 *   QD:    keyboard row select
398 *
399 * Port EE: UART Data Read/Write
400 * Port EF: Status/Control
401 *     read, UART status bits read
402 *         0 OR   Overrun
403 *         1 FE   Framing Error
404 *         2 PE   Parity Error
405 *         3 TBMT Transmitter Buffer Empty
406 *         4 DAV  Data Available
407 *         5 EOC  End Of Character
408 *         6 1
409 *         7 1
410 *     write, UART control bits / Tape Unit select / Modulation control
411 *         0 bit1=0, bit0=0   UART Reset pulse
412 *         1 bit1=0, bit0=1   UART RDAV (Reset Data Available) pulse
413 *         2 Tape modulation enable
414 *         3 *TAPEA Enable (active low) (at reset: low)
415 *         4 *TAPEB Enable (active low) (at reset: low)
416 *  Cassette is connected to the uart data input and output via the cassette
417 *  interface hardware.
418 *
419 *  The cassette interface hardware converts square-wave pulses into bits which the uart receives.
420 *
421 *  1. the cassette format: "frequency shift" is converted
422    into the uart data format "non-return to zero"
423
424    2. on cassette a 1 data bit is stored as 8 2400 Hz pulses
425    and a 0 data bit as 4 1200 Hz pulses
426    - At 1200 baud, a logic 1 is 1 cycle of 1200 Hz and a logic 0 is 1/2 cycle of 600 Hz.
427    - At 300 baud, a logic 1 is 8 cycles of 2400 Hz and a logic 0 is 4 cycles of 1200 Hz.
428
429    Attenuation is applied to the signal and the square wave edges are rounded.
430
431    A manchester encoder is used. A flip-flop synchronises input
432    data on the positive-edge of the clock pulse.
433 *
434 */
435READ8_HANDLER(lx385_data_r)
436{
437   return ay31015_get_received_data( z80ne_ay31015 );
438}
439
440READ8_HANDLER(lx385_ctrl_r)
441{
442   /* set unused bits high */
443   UINT8 data = 0xc0;
444//   UINT8 olddata = 0xc0;
445
446   ay31015_set_input_pin( z80ne_ay31015, AY31015_SWE, 0 );
447   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_OR   ) ? 0x01 : 0);
448   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_FE   ) ? 0x02 : 0);
449   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_PE   ) ? 0x04 : 0);
450   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_TBMT ) ? 0x08 : 0);
451   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_DAV  ) ? 0x10 : 0);
452   data |= (ay31015_get_output_pin( z80ne_ay31015, AY31015_EOC  ) ? 0x20 : 0);
453   ay31015_set_input_pin( z80ne_ay31015, AY31015_SWE, 1 );
454
455   return data;
456}
457WRITE8_HANDLER(lx385_data_w)
458{
459   ay31015_set_transmit_data( z80ne_ay31015, data );
460}
461
462#define LX385_CASSETTE_MOTOR_MASK ((1<<3)|(1<<4))
463
464WRITE8_HANDLER(lx385_ctrl_w)
465{
466   /* Translate data to control signals
467    *     0 bit1=0, bit0=0   UART Reset pulse
468    *     1 bit1=0, bit0=1   UART RDAV (Reset Data Available) pulse
469    *     2 UART Tx Clock Enable (active high)
470    *     3 *TAPEA Enable (active low) (at reset: low)
471    *     4 *TAPEB Enable (active low) (at reset: low)
472    */
473   UINT8 uart_reset, uart_rdav, uart_tx_clock;
474   UINT8 motor_a, motor_b;
475   UINT8 changed_bits = (lx385_ctrl ^ data) & 0x1C;
476   lx385_ctrl = data;
477
478   uart_reset = ((data & 0x03) == 0x00);
479   uart_rdav  = ((data & 0x03) == 0x01);
480   uart_tx_clock = ((data & 0x04) == 0x04);
481   motor_a = ((data & 0x08) == 0x00);
482   motor_b = ((data & 0x10) == 0x00);
483
484   /* UART Reset and RDAV */
485   if(uart_reset)
486   {
487      ay31015_set_input_pin( z80ne_ay31015, AY31015_XR, 1 );
488      ay31015_set_input_pin( z80ne_ay31015, AY31015_XR, 0 );
489   }
490
491   if(uart_rdav)
492   {
493      ay31015_set_input_pin( z80ne_ay31015, AY31015_RDAV, 1 );
494      ay31015_set_input_pin( z80ne_ay31015, AY31015_RDAV, 0 );
495   }
496
497   if (!changed_bits) return;
498
499   /* UART Tx Clock enable/disable */
500   if(changed_bits & 0x04)
501      ay31015_set_transmitter_clock( z80ne_ay31015, uart_tx_clock ? cass_data.speed * 16.0 : 0.0);
502
503   /* motors */
504   if(changed_bits & 0x18)
505   {
506      cassette_change_state(devtag_get_device(space->machine, "cassettea"),
507         (motor_a) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
508
509      cassette_change_state(devtag_get_device(space->machine, "cassetteb"),
510         (motor_b) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
511
512      if (motor_a || motor_b)
513         timer_adjust_periodic(cassette_timer, attotime_zero, 0, ATTOTIME_IN_HZ(LX385_TAPE_SAMPLE_FREQ));
514      else
515         timer_adjust_oneshot(cassette_timer, attotime_zero, 0);
516   }
517}
518
519READ8_HANDLER(lx388_data_r)
520{
521   UINT8 data;
522
523   data = kr2376_data_r(lx388_kr2376, 0) & 0x7f;
524   data |= kr2376_get_output_pin(lx388_kr2376, KR2376_SO) << 7;
525   return data;
526}
527
528READ8_HANDLER(lx388_read_field_sync)
529{
530   UINT8 data;
531
532   data = m6847_get_field_sync(space->machine) ? 0x00 : 0x80;
533   return data;
534}
src/mess/drivers/tec1.c
r4521r4522
1/***************************************************************************
2 
3   TEC-1 driver, written by Robbbert in April, 2009 for MESS.
4 
5The TEC-1 was a single-board "computer" described in Talking Electronics
6magazine, issues number 10 and 11. Talking Electronics do not have dates on
7their issues, so the date is uncertain, although 1984 seems a reasonable
8guess. Talking Electronics operated from Cheltenham, a suburb of Melbourne.
9 
10The hardware is quite simple, consisting of a Z80 cpu, 2x 8212 8-bit latch,
1174C923 keyboard scanner, 20 push-button keys, 6-digit LED display, a speaker,
12a 2k EPROM and sundry parts.
13 
14The cpu speed could be adjusted by using a potentiometer, the range being
15250 kHz to 2MHz. This is a simple method of adjusting a game's difficulty.
16 
17We emulate the original version. Later enhancements included more RAM, speech
18synthesis and various attachments, however I have no information on these.
19 
20Keys:
210 to 9, A to F are on the key of the same name.
22AD (input an address) is the J key.
23+ and - (increment / decrement address) are the - and = keys.
24GO (execute program at current address) is the Enter key.
25Whenever a program listing mentions RESET, do a Soft Reset.
26 
27Each key causes a beep to be heard. You may need to press more than once
28to get it to register.
29 
30Inbuilt games - press the following sequence of keys:
31- Welcome: RESET D 1 + 0 2 AD 0 2 7 0 GO GO
32- Nim: RESET AD 3 E 0 GO GO
33- Invaders: RESET AD 3 2 0 GO GO
34- Luna Lander: RESET AD 4 9 0 GO GO
35 
36Not emulated / need to be checked:
37- The 74C923 code may need to be revisited to improve keyboard response.
38- The 10ms debounce is not emulated.
39- Artwork needs to be produced.
40 
41Thanks to Chris Schwartz who dumped his ROM for me way back in the old days.
42It's only taken 25 years to get around to emulating it...
43 
44***************************************************************************/
45 
46#include "driver.h"
47#include "cpu/z80/z80.h"
48#include "sound/speaker.h"
49#include "tec1.lh"
50 
51static emu_timer *tec1_kbd_timer;
52static UINT8 tec1_kbd=0;
53static UINT8 tec1_segment=0;
54static UINT8 tec1_digit=0;
55static const device_config *tec1_speaker;
56 
57 
58/***************************************************************************
59 
60   Display
61 
62***************************************************************************/
63 
64static void tec1_display(void)
65{
66   UINT8 i;
67   for (i = 0; i < 6; i++)
68      if (tec1_digit & (1 << i))
69         output_set_digit_value(5-i, tec1_segment);
70}
71 
72static WRITE8_HANDLER( tec1_segment_w )
73{
74/*   d7 segment d
75   d6 segment e
76   d5 segment c
77   d4 segment dot
78   d3 segment b
79   d2 segment g
80   d1 segment f
81   d0 segment a */
82 
83   tec1_segment = BITSWAP8(data, 4, 2, 1, 6, 7, 5, 3, 0);
84   if (tec1_digit) tec1_display();
85}
86 
87static WRITE8_HANDLER( tec1_digit_w )
88{
89/*    d7 speaker
90   d6 not used
91   d5 data digit 1
92   d4 data digit 2
93   d3 address digit 1
94   d2 address digit 2
95   d1 address digit 3
96   d0 address digit 4 */
97 
98   speaker_level_w(tec1_speaker, (data & 0x80) ? 1 : 0);
99 
100   tec1_digit = data & 0x3f;
101   if (tec1_digit) tec1_display();
102}
103 
104 
105/***************************************************************************
106 
107   Keyboard
108 
109***************************************************************************/
110 
111static READ8_HANDLER( tec1_kbd_r )
112{
113   cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, CLEAR_LINE);
114   return tec1_kbd;
115}
116   
117static UINT8 tec1_convert_col_to_bin( UINT8 col, UINT8 row )
118{
119   UINT8 data = row;
120 
121   if (col & 2)
122      data |= 4;
123   else
124   if (col & 4)
125      data |= 8;
126   else
127   if (col & 8)
128      data |= 12;
129   else
130   if (col & 16)
131      data |= 16;
132 
133   return data;
134}
135 
136 
137static const char *const keynames[] = { "LINE0", "LINE1", "LINE2", "LINE3" };
138 
139static TIMER_CALLBACK( tec1_kbd_callback )
140{
141/* 74C923 4 by 5 key encoder. */
142 
143 
144   static UINT8 row=0;
145 
146   /* if previous key is still held, bail out */
147   if (input_port_read(machine, keynames[row]))
148      if (tec1_convert_col_to_bin(input_port_read(machine, keynames[row]), row) == tec1_kbd)
149         return; 
150       
151   row++;
152   row &= 3;
153 
154   /* see if a key pressed */
155   if (input_port_read(machine, keynames[row]))
156   {
157      tec1_kbd = tec1_convert_col_to_bin(input_port_read(machine, keynames[row]), row);
158      cpu_set_input_line(machine->cpu[0], INPUT_LINE_NMI, HOLD_LINE);
159   }
160}
161 
162 
163/***************************************************************************
164 
165   Machine
166 
167***************************************************************************/
168 
169static MACHINE_RESET( tec1 )
170{
171   tec1_kbd_timer = timer_alloc(machine,  tec1_kbd_callback, NULL );
172   timer_adjust_periodic( tec1_kbd_timer, attotime_zero, 0, ATTOTIME_IN_HZ(500) );
173   tec1_speaker = devtag_get_device(machine, "speaker");
174}
175 
176 
177/***************************************************************************
178 
179   Address Map
180 
181***************************************************************************/
182 
183static ADDRESS_MAP_START( tec1_map, ADDRESS_SPACE_PROGRAM, 8 )
184   ADDRESS_MAP_GLOBAL_MASK(0x3fff)
185   AM_RANGE(0x0000, 0x07ff) AM_ROM
186   AM_RANGE(0x0800, 0x17ff) AM_RAM
187ADDRESS_MAP_END
188 
189static ADDRESS_MAP_START( tec1_io, ADDRESS_SPACE_IO, 8 )
190   ADDRESS_MAP_GLOBAL_MASK(0x07)
191   AM_RANGE(0x00, 0x00) AM_READ(tec1_kbd_r)
192   AM_RANGE(0x01, 0x01) AM_WRITE(tec1_digit_w)
193   AM_RANGE(0x02, 0x02) AM_WRITE(tec1_segment_w)
194ADDRESS_MAP_END
195 
196 
197/**************************************************************************
198 
199   Keyboard Layout
200 
201***************************************************************************/
202 
203static INPUT_PORTS_START( tec1 )
204   PORT_START("LINE0") /* KEY ROW 0 */
205   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)      PORT_CHAR('0')
206   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)      PORT_CHAR('4')
207   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)      PORT_CHAR('8')
208   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)      PORT_CHAR('C')
209   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("+") PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('=')
210 
211   PORT_START("LINE1") /* KEY ROW 1 */
212   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)      PORT_CHAR('1')
213   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5)      PORT_CHAR('5')
214   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)      PORT_CHAR('9')
215   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)      PORT_CHAR('D')
216   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
217 
218   PORT_START("LINE2") /* KEY ROW 2 */
219   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)      PORT_CHAR('2')
220   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)      PORT_CHAR('6')
221   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)      PORT_CHAR('A')
222   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)      PORT_CHAR('E')
223   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("GO") PORT_CODE(KEYCODE_ENTER)   PORT_CHAR(13)
224 
225   PORT_START("LINE3") /* KEY ROW 3 */
226   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)      PORT_CHAR('3')
227   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)      PORT_CHAR('7')
228   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)      PORT_CHAR('B')
229   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)      PORT_CHAR('F')
230   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("AD") PORT_CODE(KEYCODE_J)      PORT_CHAR('J')
231INPUT_PORTS_END
232 
233 
234/***************************************************************************
235 
236   Machine driver
237 
238***************************************************************************/
239 
240static MACHINE_DRIVER_START( tec1 )
241   /* basic machine hardware */
242   MDRV_CPU_ADD("maincpu", Z80, 500000)   /* speed can be varied between 250kHz and 2MHz */
243   MDRV_CPU_PROGRAM_MAP(tec1_map, 0)
244   MDRV_CPU_IO_MAP(tec1_io, 0)
245 
246   MDRV_MACHINE_RESET(tec1)
247 
248   /* video hardware */
249   MDRV_DEFAULT_LAYOUT(layout_tec1)
250 
251   /* sound hardware */
252   MDRV_SPEAKER_STANDARD_MONO("mono")
253   MDRV_SOUND_ADD("speaker", SPEAKER, 0)
254   MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
255MACHINE_DRIVER_END
256 
257 
258/***************************************************************************
259 
260   Game driver
261 
262***************************************************************************/
263 
264ROM_START(tec1)
265   ROM_REGION(0x10000, "maincpu", 0)
266   ROM_LOAD("tec1.rom",    0x0000, 0x0800, CRC(b3390c36) SHA1(18aabc68d473206b7fc4e365c6b57a4e218482c3) )
267//   ROM_SYSTEM_BIOS(0, "tec1", "TEC-1")
268//   ROMX_LOAD("tec1.rom",    0x0000, 0x0800, CRC(b3390c36) SHA1(18aabc68d473206b7fc4e365c6b57a4e218482c3), ROM_BIOS(1))
269//   ROM_SYSTEM_BIOS(1, "tec1a", "TEC-1A")
270//   ROMX_LOAD("tec1a.rom",   0x0000, 0x0800, CRC(60daea3c) SHA1(383b7e7f02e91fb18c87eb03c5949e31156771d4), ROM_BIOS(2))
271ROM_END
272 
273/*    YEAR  NAME      PARENT  COMPAT  MACHINE     INPUT    INIT      CONFIG       COMPANY  FULLNAME */
274COMP( 1984, tec1,     0,      0,      tec1,       tec1,    0,        0,      "Talking Electronics magazine",  "TEC-1" , 0 )
1/***************************************************************************
2
3   TEC-1 driver, written by Robbbert in April, 2009 for MESS.
4
5The TEC-1 was a single-board "computer" described in Talking Electronics
6magazine, issues number 10 and 11. Talking Electronics do not have dates on
7their issues, so the date is uncertain, although 1984 seems a reasonable
8guess. Talking Electronics operated from Cheltenham, a suburb of Melbourne.
9
10The hardware is quite simple, consisting of a Z80 cpu, 2x 8212 8-bit latch,
1174C923 keyboard scanner, 20 push-button keys, 6-digit LED display, a speaker,
12a 2k EPROM and sundry parts.
13
14The cpu speed could be adjusted by using a potentiometer, the range being
15250 kHz to 2MHz. This is a simple method of adjusting a game's difficulty.
16
17We emulate the original version. Later enhancements included more RAM, speech
18synthesis and various attachments, however I have no information on these.
19
20Keys:
210 to 9, A to F are on the key of the same name.
22AD (input an address) is the J key.
23+ and - (increment / decrement address) are the - and = keys.
24GO (execute program at current address) is the Enter key.
25Whenever a program listing mentions RESET, do a Soft Reset.
26
27Each key causes a beep to be heard. You may need to press more than once
28to get it to register.
29
30Inbuilt games - press the following sequence of keys:
31- Welcome: RESET D 1 + 0 2 AD 0 2 7 0 GO GO
32- Nim: RESET AD 3 E 0 GO GO
33- Invaders: RESET AD 3 2 0 GO GO
34- Luna Lander: RESET AD 4 9 0 GO GO
35
36Not emulated / need to be checked:
37- The 74C923 code may need to be revisited to improve keyboard response.
38- The 10ms debounce is not emulated.
39- Artwork needs to be produced.
40
41Thanks to Chris Schwartz who dumped his ROM for me way back in the old days.
42It's only taken 25 years to get around to emulating it...
43
44***************************************************************************/
45
46#include "driver.h"
47#include "cpu/z80/z80.h"
48#include "sound/speaker.h"
49#include "tec1.lh"
50
51static emu_timer *tec1_kbd_timer;
52static UINT8 tec1_kbd=0;
53static UINT8 tec1_segment=0;
54static UINT8 tec1_digit=0;
55static const device_config *tec1_speaker;
56
57
58/***************************************************************************
59
60   Display
61
62***************************************************************************/
63
64static void tec1_display(void)
65{
66   UINT8 i;
67   for (i = 0; i < 6; i++)
68      if (tec1_digit & (1 << i))
69         output_set_digit_value(5-i, tec1_segment);
70}
71
72static WRITE8_HANDLER( tec1_segment_w )
73{
74/*   d7 segment d
75   d6 segment e
76   d5 segment c
77   d4 segment dot
78   d3 segment b
79   d2 segment g
80   d1 segment f
81   d0 segment a */
82
83   tec1_segment = BITSWAP8(data, 4, 2, 1, 6, 7, 5, 3, 0);
84   if (tec1_digit) tec1_display();
85}
86
87static WRITE8_HANDLER( tec1_digit_w )
88{
89/*    d7 speaker
90   d6 not used
91   d5 data digit 1
92   d4 data digit 2
93   d3 address digit 1
94   d2 address digit 2
95   d1 address digit 3
96   d0 address digit 4 */
97
98   speaker_level_w(tec1_speaker, (data & 0x80) ? 1 : 0);
99
100   tec1_digit = data & 0x3f;
101   if (tec1_digit) tec1_display();
102}
103
104
105/***************************************************************************
106
107   Keyboard
108
109***************************************************************************/
110
111static READ8_HANDLER( tec1_kbd_r )
112{
113   cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, CLEAR_LINE);
114   return tec1_kbd;
115}
116   
117static UINT8 tec1_convert_col_to_bin( UINT8 col, UINT8 row )
118{
119   UINT8 data = row;
120
121   if (col & 2)
122      data |= 4;
123   else
124   if (col & 4)
125      data |= 8;
126   else
127   if (col & 8)
128      data |= 12;
129   else
130   if (col & 16)
131      data |= 16;
132
133   return data;
134}
135
136
137static const char *const keynames[] = { "LINE0", "LINE1", "LINE2", "LINE3" };
138
139static TIMER_CALLBACK( tec1_kbd_callback )
140{
141/* 74C923 4 by 5 key encoder. */
142
143
144   static UINT8 row=0;
145
146   /* if previous key is still held, bail out */
147   if (input_port_read(machine, keynames[row]))
148      if (tec1_convert_col_to_bin(input_port_read(machine, keynames[row]), row) == tec1_kbd)
149         return;
150     
151   row++;
152   row &= 3;
153
154   /* see if a key pressed */
155   if (input_port_read(machine, keynames[row]))
156   {
157      tec1_kbd = tec1_convert_col_to_bin(input_port_read(machine, keynames[row]), row);
158      cpu_set_input_line(machine->cpu[0], INPUT_LINE_NMI, HOLD_LINE);
159   }
160}
161
162
163/***************************************************************************
164
165   Machine
166
167***************************************************************************/
168
169static MACHINE_RESET( tec1 )
170{
171   tec1_kbd_timer = timer_alloc(machine,  tec1_kbd_callback, NULL );
172   timer_adjust_periodic( tec1_kbd_timer, attotime_zero, 0, ATTOTIME_IN_HZ(500) );
173   tec1_speaker = devtag_get_device(machine, "speaker");
174}
175
176
177/***************************************************************************
178
179   Address Map
180
181***************************************************************************/
182
183static ADDRESS_MAP_START( tec1_map, ADDRESS_SPACE_PROGRAM, 8 )
184   ADDRESS_MAP_GLOBAL_MASK(0x3fff)
185   AM_RANGE(0x0000, 0x07ff) AM_ROM
186   AM_RANGE(0x0800, 0x17ff) AM_RAM
187ADDRESS_MAP_END
188
189static ADDRESS_MAP_START( tec1_io, ADDRESS_SPACE_IO, 8 )
190   ADDRESS_MAP_GLOBAL_MASK(0x07)
191   AM_RANGE(0x00, 0x00) AM_READ(tec1_kbd_r)
192   AM_RANGE(0x01, 0x01) AM_WRITE(tec1_digit_w)
193   AM_RANGE(0x02, 0x02) AM_WRITE(tec1_segment_w)
194ADDRESS_MAP_END
195
196
197/**************************************************************************
198
199   Keyboard Layout
200
201***************************************************************************/
202
203static INPUT_PORTS_START( tec1 )
204   PORT_START("LINE0") /* KEY ROW 0 */
205   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)      PORT_CHAR('0')
206   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)      PORT_CHAR('4')
207   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)      PORT_CHAR('8')
208   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)      PORT_CHAR('C')
209   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("+") PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('=')
210
211   PORT_START("LINE1") /* KEY ROW 1 */
212   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)      PORT_CHAR('1')
213   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5)      PORT_CHAR('5')
214   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)      PORT_CHAR('9')
215   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)      PORT_CHAR('D')
216   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
217
218   PORT_START("LINE2") /* KEY ROW 2 */
219   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)      PORT_CHAR('2')
220   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)      PORT_CHAR('6')
221   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)      PORT_CHAR('A')
222   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)      PORT_CHAR('E')
223   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("GO") PORT_CODE(KEYCODE_ENTER)   PORT_CHAR(13)
224
225   PORT_START("LINE3") /* KEY ROW 3 */
226   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)      PORT_CHAR('3')
227   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)      PORT_CHAR('7')
228   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)      PORT_CHAR('B')
229   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)      PORT_CHAR('F')
230   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("AD") PORT_CODE(KEYCODE_J)      PORT_CHAR('J')
231INPUT_PORTS_END
232
233
234/***************************************************************************
235
236   Machine driver
237
238***************************************************************************/
239
240static MACHINE_DRIVER_START( tec1 )
241   /* basic machine hardware */
242   MDRV_CPU_ADD("maincpu", Z80, 500000)   /* speed can be varied between 250kHz and 2MHz */
243   MDRV_CPU_PROGRAM_MAP(tec1_map, 0)
244   MDRV_CPU_IO_MAP(tec1_io, 0)
245
246   MDRV_MACHINE_RESET(tec1)
247
248   /* video hardware */
249   MDRV_DEFAULT_LAYOUT(layout_tec1)
250
251   /* sound hardware */
252   MDRV_SPEAKER_STANDARD_MONO("mono")
253   MDRV_SOUND_ADD("speaker", SPEAKER, 0)
254   MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
255MACHINE_DRIVER_END
256
257
258/***************************************************************************
259
260   Game driver
261
262***************************************************************************/
263
264ROM_START(tec1)
265   ROM_REGION(0x10000, "maincpu", 0)
266   ROM_LOAD("tec1.rom",    0x0000, 0x0800, CRC(b3390c36) SHA1(18aabc68d473206b7fc4e365c6b57a4e218482c3) )
267//   ROM_SYSTEM_BIOS(0, "tec1", "TEC-1")
268//   ROMX_LOAD("tec1.rom",    0x0000, 0x0800, CRC(b3390c36) SHA1(18aabc68d473206b7fc4e365c6b57a4e218482c3), ROM_BIOS(1))
269//   ROM_SYSTEM_BIOS(1, "tec1a", "TEC-1A")
270//   ROMX_LOAD("tec1a.rom",   0x0000, 0x0800, CRC(60daea3c) SHA1(383b7e7f02e91fb18c87eb03c5949e31156771d4), ROM_BIOS(2))
271ROM_END
272
273/*    YEAR  NAME      PARENT  COMPAT  MACHINE     INPUT    INIT      CONFIG       COMPANY  FULLNAME */
274COMP( 1984, tec1,     0,      0,      tec1,       tec1,    0,        0,      "Talking Electronics magazine",  "TEC-1" , 0 )

Previous 15994 Revisions Next


© 1998-2018 The MESS Team