src/mess/tools/castool/stubs.c
| r4521 | r4522 | |
| 1 | | #include "driver.h"
|
| 2 | | #include <ctype.h>
|
| 3 | | #include <stdarg.h>
|
| 4 | | |
| 5 | | /* Variables to hold the status of various game options */
|
| 6 | | static FILE *errorlog;
|
| 7 | | |
| 8 | | const game_driver *const drivers[1];
|
| 9 | | int rompath_extra;
|
| 10 | | int history_filename;
|
| 11 | | int mameinfo_filename;
|
| 12 | | |
| 13 | | void 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 | | |
| 25 | | file_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 | | |
| 33 | | char *mame_fgets(char *s, int n, mame_file *file)
|
| 34 | | {
|
| 35 | | return fgets(s, n, (FILE *) file);
|
| 36 | | }
|
| 37 | | |
| 38 | | UINT32 mame_fwrite(mame_file *file, const void *buffer, UINT32 length)
|
| 39 | | {
|
| 40 | | return fwrite(buffer, 1, length, (FILE *) file);
|
| 41 | | }
|
| 42 | | |
| 43 | | void mame_fclose(mame_file *file)
|
| 44 | | {
|
| 45 | | fclose((FILE *) file);
|
| 46 | | }
|
| 47 | | |
| 48 | | int 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 | | |
| 58 | | void mame_printf_error(const char *format, ...)
|
| 59 | | {
|
| 60 | | }
|
| 61 | | |
| 62 | | void mame_printf_warning(const char *format, ...)
|
| 63 | | {
|
| 64 | | }
|
| 65 | | |
| 66 | | void mame_printf_info(const char *format, ...)
|
| 67 | | {
|
| 68 | | }
|
| 69 | | |
| 70 | | void mame_printf_debug(const char *format, ...)
|
| 71 | | {
|
| 72 | | }
|
| 73 | | |
| 74 | | |
| 75 | | |
| 76 | | /***************************************************************************
|
| 77 | | TYPE DEFINITIONS
|
| 78 | | ***************************************************************************/
|
| 79 | | |
| 80 | | enum _memory_block_overlap
|
| 81 | | {
|
| 82 | | OVERLAP_NONE,
|
| 83 | | OVERLAP_PARTIAL,
|
| 84 | | OVERLAP_FULL
|
| 85 | | };
|
| 86 | | typedef enum _memory_block_overlap memory_block_overlap;
|
| 87 | | |
| 88 | | |
| 89 | | |
| 90 | | /***************************************************************************
|
| 91 | | GLOBAL VARIABLES
|
| 92 | | ***************************************************************************/
|
| 93 | | |
| 94 | | /* pool list */
|
| 95 | | static object_pool *pools[64];
|
| 96 | | |
| 97 | | /* resource tracking */
|
| 98 | | int resource_tracking_tag = 0;
|
| 99 | | |
| 100 | | |
| 101 | | |
| 102 | | /***************************************************************************
|
| 103 | | PROTOTYPES
|
| 104 | | ***************************************************************************/
|
| 105 | | |
| 106 | | static void astring_destructor(void *object, size_t size);
|
| 107 | | static 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 | | |
| 119 | | void 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 | | |
| 130 | | void 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 | | |
| 141 | | static 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 | | |
| 152 | | void 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 | | |
| 181 | | void 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 | | |
| 197 | | static 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 | | |
| 212 | | void *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 | | |
| 223 | | void *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 | | |
| 238 | | void *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 | | |
| 262 | | char *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 | | |
| 273 | | char *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 | | |
| 284 | | astring *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 | | |
| 296 | | static 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 | | |
| 307 | | static 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 */ |
| 6 | static FILE *errorlog; |
| 7 | |
| 8 | const game_driver *const drivers[1]; |
| 9 | int rompath_extra; |
| 10 | int history_filename; |
| 11 | int mameinfo_filename; |
| 12 | |
| 13 | void 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 | |
| 25 | file_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 | |
| 33 | char *mame_fgets(char *s, int n, mame_file *file) |
| 34 | { |
| 35 | return fgets(s, n, (FILE *) file); |
| 36 | } |
| 37 | |
| 38 | UINT32 mame_fwrite(mame_file *file, const void *buffer, UINT32 length) |
| 39 | { |
| 40 | return fwrite(buffer, 1, length, (FILE *) file); |
| 41 | } |
| 42 | |
| 43 | void mame_fclose(mame_file *file) |
| 44 | { |
| 45 | fclose((FILE *) file); |
| 46 | } |
| 47 | |
| 48 | int 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 | |
| 58 | void mame_printf_error(const char *format, ...) |
| 59 | { |
| 60 | } |
| 61 | |
| 62 | void mame_printf_warning(const char *format, ...) |
| 63 | { |
| 64 | } |
| 65 | |
| 66 | void mame_printf_info(const char *format, ...) |
| 67 | { |
| 68 | } |
| 69 | |
| 70 | void mame_printf_debug(const char *format, ...) |
| 71 | { |
| 72 | } |
| 73 | |
| 74 | |
| 75 | |
| 76 | /*************************************************************************** |
| 77 | TYPE DEFINITIONS |
| 78 | ***************************************************************************/ |
| 79 | |
| 80 | enum _memory_block_overlap |
| 81 | { |
| 82 | OVERLAP_NONE, |
| 83 | OVERLAP_PARTIAL, |
| 84 | OVERLAP_FULL |
| 85 | }; |
| 86 | typedef enum _memory_block_overlap memory_block_overlap; |
| 87 | |
| 88 | |
| 89 | |
| 90 | /*************************************************************************** |
| 91 | GLOBAL VARIABLES |
| 92 | ***************************************************************************/ |
| 93 | |
| 94 | /* pool list */ |
| 95 | static object_pool *pools[64]; |
| 96 | |
| 97 | /* resource tracking */ |
| 98 | int resource_tracking_tag = 0; |
| 99 | |
| 100 | |
| 101 | |
| 102 | /*************************************************************************** |
| 103 | PROTOTYPES |
| 104 | ***************************************************************************/ |
| 105 | |
| 106 | static void astring_destructor(void *object, size_t size); |
| 107 | static 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 | |
| 119 | void 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 | |
| 130 | void 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 | |
| 141 | static 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 | |
| 152 | void 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 | |
| 181 | void 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 | |
| 197 | static 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 | |
| 212 | void *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 | |
| 223 | void *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 | |
| 238 | void *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 | |
| 262 | char *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 | |
| 273 | char *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 | |
| 284 | astring *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 | |
| 296 | static 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 | |
| 307 | static void bitmap_destructor(void *object, size_t size) |
| 308 | { |
| 309 | bitmap_free((bitmap_t *)object); |
| 310 | } |
| 311 | |
| 312 | |
src/mess/tools/castool/main.c
| r4521 | r4522 | |
| 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 | | |
| 52 | | struct SupportedCassetteFormats
|
| 53 | | {
|
| 54 | | const char *name;
|
| 55 | | const struct CassetteFormat * const *formats;
|
| 56 | | const char *desc;
|
| 57 | | };
|
| 58 | | |
| 59 | | const 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 | | |
| 99 | | const 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 | | |
| 108 | | void display_usage(void)
|
| 109 | | {
|
| 110 | | fprintf(stderr, "Usage: \n");
|
| 111 | | fprintf(stderr, " castool.exe convert <format> <inputfile> <outputfile.wav>\n");
|
| 112 | | }
|
| 113 | | |
| 114 | | void 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
|
| 127 | | int CLIB_DECL utf8_main(int argc, char *argv[])
|
| 128 | | #else
|
| 129 | | int 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 | | |
| 195 | | theend :
|
| 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 | |
| 52 | struct SupportedCassetteFormats |
| 53 | { |
| 54 | const char *name; |
| 55 | const struct CassetteFormat * const *formats; |
| 56 | const char *desc; |
| 57 | }; |
| 58 | |
| 59 | const 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 | |
| 99 | const 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 | |
| 108 | void display_usage(void) |
| 109 | { |
| 110 | fprintf(stderr, "Usage: \n"); |
| 111 | fprintf(stderr, " castool.exe convert <format> <inputfile> <outputfile.wav>\n"); |
| 112 | } |
| 113 | |
| 114 | void 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 |
| 127 | int CLIB_DECL utf8_main(int argc, char *argv[]) |
| 128 | #else |
| 129 | int 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 | |
| 195 | theend : |
| 196 | /* clean up our tracked resources */ |
| 197 | exit_resource_tracking(); |
| 198 | |
| 199 | return 0; |
| 200 | } |
src/mess/video/upd7220.c
| r4521 | r4522 | |
| 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 | | |
| 42 | | typedef struct _upd7220_t upd7220_t;
|
| 43 | | struct _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 | | |
| 97 | | INLINE 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 | | |
| 104 | | INLINE 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 | | |
| 111 | | INLINE void queue(upd7220_t *upd7220, UINT8 data, int command)
|
| 112 | | {
|
| 113 | | }
|
| 114 | | |
| 115 | | INLINE 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
|
| 128 | | static 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 | | |
| 149 | | static 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 | | |
| 162 | | static 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 | | |
| 176 | | static 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 | | |
| 192 | | static 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 | | |
| 206 | | static 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 | | |
| 222 | | static 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
|
| 237 | | static 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 | | |
| 300 | | READ8_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 | | |
| 324 | | WRITE8_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 | | |
| 344 | | WRITE8_DEVICE_HANDLER( upd7220_dack_w )
|
| 345 | | {
|
| 346 | | }
|
| 347 | | |
| 348 | | /*-------------------------------------------------
|
| 349 | | upd7220_lpen_w - light pen strobe
|
| 350 | | -------------------------------------------------*/
|
| 351 | | |
| 352 | | void upd7220_lpen_w(const device_config *device, int state)
|
| 353 | | {
|
| 354 | | }
|
| 355 | | |
| 356 | | /*-------------------------------------------------
|
| 357 | | ROM( upd7220 )
|
| 358 | | -------------------------------------------------*/
|
| 359 | | |
| 360 | | ROM_START( upd7220 )
|
| 361 | | ROM_REGION( 0x100, "upd7220", ROMREGION_LOADBYNAME )
|
| 362 | | ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP ) /* internal 128x14 control ROM */
|
| 363 | | ROM_END
|
| 364 | | |
| 365 | | /*-------------------------------------------------
|
| 366 | | DEVICE_START( upd7220 )
|
| 367 | | -------------------------------------------------*/
|
| 368 | | |
| 369 | | static 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 | | |
| 423 | | static 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 | | |
| 434 | | static 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 | | |
| 446 | | DEVICE_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 | |
| 42 | typedef struct _upd7220_t upd7220_t; |
| 43 | struct _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 | |
| 97 | INLINE 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 | |
| 104 | INLINE 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 | |
| 111 | INLINE void queue(upd7220_t *upd7220, UINT8 data, int command) |
| 112 | { |
| 113 | } |
| 114 | |
| 115 | INLINE 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 |
| 128 | static 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 | |
| 149 | static 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 | |
| 162 | static 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 | |
| 176 | static 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 | |
| 192 | static 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 | |
| 206 | static 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 | |
| 222 | static 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 |
| 237 | static 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 | |
| 300 | READ8_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 | |
| 324 | WRITE8_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 | |
| 344 | WRITE8_DEVICE_HANDLER( upd7220_dack_w ) |
| 345 | { |
| 346 | } |
| 347 | |
| 348 | /*------------------------------------------------- |
| 349 | upd7220_lpen_w - light pen strobe |
| 350 | -------------------------------------------------*/ |
| 351 | |
| 352 | void upd7220_lpen_w(const device_config *device, int state) |
| 353 | { |
| 354 | } |
| 355 | |
| 356 | /*------------------------------------------------- |
| 357 | ROM( upd7220 ) |
| 358 | -------------------------------------------------*/ |
| 359 | |
| 360 | ROM_START( upd7220 ) |
| 361 | ROM_REGION( 0x100, "upd7220", ROMREGION_LOADBYNAME ) |
| 362 | ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP ) /* internal 128x14 control ROM */ |
| 363 | ROM_END |
| 364 | |
| 365 | /*------------------------------------------------- |
| 366 | DEVICE_START( upd7220 ) |
| 367 | -------------------------------------------------*/ |
| 368 | |
| 369 | static 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 | |
| 423 | static 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 | |
| 434 | static 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 | |
| 446 | DEVICE_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/machine/z80ne.c
| r4521 | r4522 | |
| 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 | | |
| 25 | | static UINT8 lx383_scan_counter;
|
| 26 | | static UINT8 lx383_key[LX383_KEYS];
|
| 27 | | static int lx383_downsampler;
|
| 28 | | static int nmi_delay_counter;
|
| 29 | | static const device_config *z80ne_ay31015;
|
| 30 | | static UINT8 lx385_ctrl = 0x1f;
|
| 31 | | static const device_config *lx388_kr2376;
|
| 32 | | |
| 33 | | |
| 34 | | |
| 35 | | /* timer to read cassette waveforms */
|
| 36 | | static emu_timer *cassette_timer;
|
| 37 | | |
| 38 | | /* wave duration threshold */
|
| 39 | | typedef enum
|
| 40 | | {
|
| 41 | | TAPE_300BPS = 300, /* 300 bps */
|
| 42 | | TAPE_600BPS = 600, /* 600 bps */
|
| 43 | | TAPE_1200BPS = 1200 /* 1200 bps */
|
| 44 | | } z80netape_speed;
|
| 45 | | |
| 46 | | static 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 | | |
| 64 | | static 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 | | |
| 72 | | static 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 | | |
| 108 | | DRIVER_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 | | |
| 115 | | DRIVER_INIT( z80net )
|
| 116 | | {
|
| 117 | | DRIVER_INIT_CALL(z80ne);
|
| 118 | | }
|
| 119 | | |
| 120 | | DRIVER_INIT( z80netb )
|
| 121 | | {
|
| 122 | | }
|
| 123 | | |
| 124 | | /* after the first 3 bytes have been read from ROM, switch the ram back in */
|
| 125 | | static TIMER_CALLBACK(z80ne_reset_address_decoder)
|
| 126 | | {
|
| 127 | | memory_set_bank(machine, 1, 0);
|
| 128 | | }
|
| 129 | | |
| 130 | | static 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)
|
| 178 | | static 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 | | |
| 190 | | MACHINE_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 | | |
| 248 | | MACHINE_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 | | |
| 261 | | MACHINE_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 | | |
| 271 | | MACHINE_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 | | |
| 281 | | INPUT_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 | | |
| 295 | | INPUT_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 | | |
| 306 | | MACHINE_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 | | |
| 316 | | MACHINE_START( z80net )
|
| 317 | | {
|
| 318 | | MACHINE_START_CALL( z80ne );
|
| 319 | | logerror("In MACHINE_START z80net\n");
|
| 320 | | }
|
| 321 | | |
| 322 | | MACHINE_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 */
|
| 333 | | READ8_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__))
|
| 356 | | WRITE8_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 | | */
|
| 435 | | READ8_HANDLER(lx385_data_r)
|
| 436 | | {
|
| 437 | | return ay31015_get_received_data( z80ne_ay31015 );
|
| 438 | | }
|
| 439 | | |
| 440 | | READ8_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 | | }
|
| 457 | | WRITE8_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 | | |
| 464 | | WRITE8_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 | | |
| 519 | | READ8_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 | | |
| 528 | | READ8_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 | |
| 25 | static UINT8 lx383_scan_counter; |
| 26 | static UINT8 lx383_key[LX383_KEYS]; |
| 27 | static int lx383_downsampler; |
| 28 | static int nmi_delay_counter; |
| 29 | static const device_config *z80ne_ay31015; |
| 30 | static UINT8 lx385_ctrl = 0x1f; |
| 31 | static const device_config *lx388_kr2376; |
| 32 | |
| 33 | |
| 34 | |
| 35 | /* timer to read cassette waveforms */ |
| 36 | static emu_timer *cassette_timer; |
| 37 | |
| 38 | /* wave duration threshold */ |
| 39 | typedef enum |
| 40 | { |
| 41 | TAPE_300BPS = 300, /* 300 bps */ |
| 42 | TAPE_600BPS = 600, /* 600 bps */ |
| 43 | TAPE_1200BPS = 1200 /* 1200 bps */ |
| 44 | } z80netape_speed; |
| 45 | |
| 46 | static 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 | |
| 64 | static 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 | |
| 72 | static 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 | |
| 108 | DRIVER_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 | |
| 115 | DRIVER_INIT( z80net ) |
| 116 | { |
| 117 | DRIVER_INIT_CALL(z80ne); |
| 118 | } |
| 119 | |
| 120 | DRIVER_INIT( z80netb ) |
| 121 | { |
| 122 | } |
| 123 | |
| 124 | /* after the first 3 bytes have been read from ROM, switch the ram back in */ |
| 125 | static TIMER_CALLBACK(z80ne_reset_address_decoder) |
| 126 | { |
| 127 | memory_set_bank(machine, 1, 0); |
| 128 | } |
| 129 | |
| 130 | static 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) |
| 178 | static 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 | |
| 190 | MACHINE_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 | |
| 248 | MACHINE_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 | |
| 261 | MACHINE_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 | |
| 271 | MACHINE_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 | |
| 281 | INPUT_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 | |
| 295 | INPUT_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 | |
| 306 | MACHINE_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 | |
| 316 | MACHINE_START( z80net ) |
| 317 | { |
| 318 | MACHINE_START_CALL( z80ne ); |
| 319 | logerror("In MACHINE_START z80net\n"); |
| 320 | } |
| 321 | |
| 322 | MACHINE_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 */ |
| 333 | READ8_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__)) |
| 356 | WRITE8_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 | */ |
| 435 | READ8_HANDLER(lx385_data_r) |
| 436 | { |
| 437 | return ay31015_get_received_data( z80ne_ay31015 ); |
| 438 | } |
| 439 | |
| 440 | READ8_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 | } |
| 457 | WRITE8_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 | |
| 464 | WRITE8_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 | |
| 519 | READ8_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 | |
| 528 | READ8_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
| r4521 | r4522 | |
| 1 | | /***************************************************************************
|
| 2 | | |
| 3 | | TEC-1 driver, written by Robbbert in April, 2009 for MESS.
|
| 4 | | |
| 5 | | The TEC-1 was a single-board "computer" described in Talking Electronics
|
| 6 | | magazine, issues number 10 and 11. Talking Electronics do not have dates on
|
| 7 | | their issues, so the date is uncertain, although 1984 seems a reasonable
|
| 8 | | guess. Talking Electronics operated from Cheltenham, a suburb of Melbourne.
|
| 9 | | |
| 10 | | The hardware is quite simple, consisting of a Z80 cpu, 2x 8212 8-bit latch,
|
| 11 | | 74C923 keyboard scanner, 20 push-button keys, 6-digit LED display, a speaker,
|
| 12 | | a 2k EPROM and sundry parts.
|
| 13 | | |
| 14 | | The cpu speed could be adjusted by using a potentiometer, the range being
|
| 15 | | 250 kHz to 2MHz. This is a simple method of adjusting a game's difficulty.
|
| 16 | | |
| 17 | | We emulate the original version. Later enhancements included more RAM, speech
|
| 18 | | synthesis and various attachments, however I have no information on these.
|
| 19 | | |
| 20 | | Keys:
|
| 21 | | 0 to 9, A to F are on the key of the same name.
|
| 22 | | AD (input an address) is the J key.
|
| 23 | | + and - (increment / decrement address) are the - and = keys.
|
| 24 | | GO (execute program at current address) is the Enter key.
|
| 25 | | Whenever a program listing mentions RESET, do a Soft Reset.
|
| 26 | | |
| 27 | | Each key causes a beep to be heard. You may need to press more than once
|
| 28 | | to get it to register.
|
| 29 | | |
| 30 | | Inbuilt 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 | | |
| 36 | | Not 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 | | |
| 41 | | Thanks to Chris Schwartz who dumped his ROM for me way back in the old days.
|
| 42 | | It'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 | | |
| 51 | | static emu_timer *tec1_kbd_timer;
|
| 52 | | static UINT8 tec1_kbd=0;
|
| 53 | | static UINT8 tec1_segment=0;
|
| 54 | | static UINT8 tec1_digit=0;
|
| 55 | | static const device_config *tec1_speaker;
|
| 56 | | |
| 57 | | |
| 58 | | /***************************************************************************
|
| 59 | | |
| 60 | | Display
|
| 61 | | |
| 62 | | ***************************************************************************/
|
| 63 | | |
| 64 | | static 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 | | |
| 72 | | static 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 | | |
| 87 | | static 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 | | |
| 111 | | static 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 | |
|
| 117 | | static 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 | | |
| 137 | | static const char *const keynames[] = { "LINE0", "LINE1", "LINE2", "LINE3" };
|
| 138 | | |
| 139 | | static 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 | | |
| 169 | | static 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 | | |
| 183 | | static 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
|
| 187 | | ADDRESS_MAP_END
|
| 188 | | |
| 189 | | static 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)
|
| 194 | | ADDRESS_MAP_END
|
| 195 | | |
| 196 | | |
| 197 | | /**************************************************************************
|
| 198 | | |
| 199 | | Keyboard Layout
|
| 200 | | |
| 201 | | ***************************************************************************/
|
| 202 | | |
| 203 | | static 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')
|
| 231 | | INPUT_PORTS_END
|
| 232 | | |
| 233 | | |
| 234 | | /***************************************************************************
|
| 235 | | |
| 236 | | Machine driver
|
| 237 | | |
| 238 | | ***************************************************************************/
|
| 239 | | |
| 240 | | static 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)
|
| 255 | | MACHINE_DRIVER_END
|
| 256 | | |
| 257 | | |
| 258 | | /***************************************************************************
|
| 259 | | |
| 260 | | Game driver
|
| 261 | | |
| 262 | | ***************************************************************************/
|
| 263 | | |
| 264 | | ROM_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))
|
| 271 | | ROM_END
|
| 272 | | |
| 273 | | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME */
|
| 274 | | COMP( 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 | |
| 5 | The TEC-1 was a single-board "computer" described in Talking Electronics |
| 6 | magazine, issues number 10 and 11. Talking Electronics do not have dates on |
| 7 | their issues, so the date is uncertain, although 1984 seems a reasonable |
| 8 | guess. Talking Electronics operated from Cheltenham, a suburb of Melbourne. |
| 9 | |
| 10 | The hardware is quite simple, consisting of a Z80 cpu, 2x 8212 8-bit latch, |
| 11 | 74C923 keyboard scanner, 20 push-button keys, 6-digit LED display, a speaker, |
| 12 | a 2k EPROM and sundry parts. |
| 13 | |
| 14 | The cpu speed could be adjusted by using a potentiometer, the range being |
| 15 | 250 kHz to 2MHz. This is a simple method of adjusting a game's difficulty. |
| 16 | |
| 17 | We emulate the original version. Later enhancements included more RAM, speech |
| 18 | synthesis and various attachments, however I have no information on these. |
| 19 | |
| 20 | Keys: |
| 21 | 0 to 9, A to F are on the key of the same name. |
| 22 | AD (input an address) is the J key. |
| 23 | + and - (increment / decrement address) are the - and = keys. |
| 24 | GO (execute program at current address) is the Enter key. |
| 25 | Whenever a program listing mentions RESET, do a Soft Reset. |
| 26 | |
| 27 | Each key causes a beep to be heard. You may need to press more than once |
| 28 | to get it to register. |
| 29 | |
| 30 | Inbuilt 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 | |
| 36 | Not 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 | |
| 41 | Thanks to Chris Schwartz who dumped his ROM for me way back in the old days. |
| 42 | It'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 | |
| 51 | static emu_timer *tec1_kbd_timer; |
| 52 | static UINT8 tec1_kbd=0; |
| 53 | static UINT8 tec1_segment=0; |
| 54 | static UINT8 tec1_digit=0; |
| 55 | static const device_config *tec1_speaker; |
| 56 | |
| 57 | |
| 58 | /*************************************************************************** |
| 59 | |
| 60 | Display |
| 61 | |
| 62 | ***************************************************************************/ |
| 63 | |
| 64 | static 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 | |
| 72 | static 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 | |
| 87 | static 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 | |
| 111 | static 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 | |
| 117 | static 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 | |
| 137 | static const char *const keynames[] = { "LINE0", "LINE1", "LINE2", "LINE3" }; |
| 138 | |
| 139 | static 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 | |
| 169 | static 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 | |
| 183 | static 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 |
| 187 | ADDRESS_MAP_END |
| 188 | |
| 189 | static 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) |
| 194 | ADDRESS_MAP_END |
| 195 | |
| 196 | |
| 197 | /************************************************************************** |
| 198 | |
| 199 | Keyboard Layout |
| 200 | |
| 201 | ***************************************************************************/ |
| 202 | |
| 203 | static 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') |
| 231 | INPUT_PORTS_END |
| 232 | |
| 233 | |
| 234 | /*************************************************************************** |
| 235 | |
| 236 | Machine driver |
| 237 | |
| 238 | ***************************************************************************/ |
| 239 | |
| 240 | static 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) |
| 255 | MACHINE_DRIVER_END |
| 256 | |
| 257 | |
| 258 | /*************************************************************************** |
| 259 | |
| 260 | Game driver |
| 261 | |
| 262 | ***************************************************************************/ |
| 263 | |
| 264 | ROM_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)) |
| 271 | ROM_END |
| 272 | |
| 273 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME */ |
| 274 | COMP( 1984, tec1, 0, 0, tec1, tec1, 0, 0, "Talking Electronics magazine", "TEC-1" , 0 ) |