Search
lxdream.org :: lxdream/src/maple/vmu.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/vmu.c
changeset 1035:e3093fd7d1da
prev1034:7044e01148f0
next1072:d82e04e6d497
author nkeynes
date Fri Jun 26 05:47:04 2009 +0000 (14 years ago)
permissions -rw-r--r--
last change Refactor path operations into lxpaths.[ch]
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Implementation of the SEGA VMU device
     5  * Part No. HKT-7000
     6  * 
     7  * The standard VMU implements 3 functions - Clock, LCD, and memory card, 
     8  * in addition to having it's own little CPU, buttons, etc. The CPU isn't
     9  * implemented just yet.   
    10  *
    11  * Copyright (c) 2009 Nathan Keynes.
    12  *
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  */
    24 #include <assert.h>
    25 #include <stdlib.h>
    26 #include <stdio.h>
    27 #include <string.h>
    28 #include <errno.h>
    29 #include <sys/mman.h>
    30 #include <fcntl.h>
    31 #include "display.h"
    32 #include "maple/maple.h"
    33 #include "vmu/vmuvol.h"
    34 #include "vmu/vmulist.h"
    36 #define VMU_LCD_SIZE (48*4)
    37 #define VMU_BLOCK_COUNT 256
    38 #define VMU_BLOCK_SIZE 512
    39 #define VMU_PHASE_SIZE 128
    40 #define VMU_CONFIG_ENTRIES 1
    42 #define VMU_IDENT {          0x00, 0x00, 0x00, 0x0E,  0x7E, 0x7E, 0x3F, 0x40,  0x00, 0x05, 0x10, 0x00, \
    43 	0x00, 0x0F, 0x41, 0x00,  0xFF, 0x00, 0x56, 0x69,  0x73, 0x75, 0x61, 0x6C,  0x20, 0x4D, 0x65, 0x6D, \
    44 	0x6F, 0x72, 0x79, 0x20,  0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x20, 0x20, \
    45 	0x20, 0x20, 0x20, 0x20,  0x50, 0x72, 0x6F, 0x64,  0x75, 0x63, 0x65, 0x64,  0x20, 0x42, 0x79, 0x20, \
    46 	0x6F, 0x72, 0x20, 0x55,  0x6E, 0x64, 0x65, 0x72,  0x20, 0x4C, 0x69, 0x63,  0x65, 0x6E, 0x73, 0x65, \
    47 	0x20, 0x46, 0x72, 0x6F,  0x6D, 0x20, 0x53, 0x45,  0x47, 0x41, 0x20, 0x45,  0x4E, 0x54, 0x45, 0x52, \
    48 	0x50, 0x52, 0x49, 0x53,  0x45, 0x53, 0x2C, 0x4C,  0x54, 0x44, 0x2E, 0x20,  0x20, 0x20, 0x20, 0x20, \
    49 	0x7C, 0x00, 0x82, 0x00 }
    50 #define VMU_VERSION {        0x56, 0x65, 0x72, 0x73,  0x69, 0x6F, 0x6E, 0x20,  0x31, 0x2E, 0x30, 0x30, \
    51 	0x35, 0x2C, 0x31, 0x39,  0x39, 0x39, 0x2F, 0x30,  0x34, 0x2F, 0x31, 0x35,  0x2C, 0x33, 0x31, 0x35, \
    52 	0x2D, 0x36, 0x32, 0x30,  0x38, 0x2D, 0x30, 0x33,  0x2C, 0x53, 0x45, 0x47,  0x41, 0x20, 0x56, 0x69, \
    53 	0x73, 0x75, 0x61, 0x6C,  0x20, 0x4D, 0x65, 0x6D,  0x6F, 0x72, 0x79, 0x20,  0x53, 0x79, 0x73, 0x74, \
    54 	0x65, 0x6D, 0x20, 0x42,  0x49, 0x4F, 0x53, 0x20,  0x50, 0x72, 0x6F, 0x64,  0x75, 0x63, 0x65, 0x64, \
    55 	0x20, 0x62, 0x79, 0x20 }
    57 static void vmu_destroy( maple_device_t dev );
    58 static maple_device_t vmu_clone( maple_device_t dev );
    59 static maple_device_t vmu_new();
    60 static lxdream_config_entry_t vmu_get_config( maple_device_t dev );
    61 static void vmu_set_config_value( maple_device_t dev, unsigned int key, const gchar *value );
    62 static int vmu_get_condition( maple_device_t dev, int function, unsigned char *outbuf,
    63                               unsigned int *outlen );
    64 static int vmu_get_meminfo( maple_device_t dev, int function, unsigned int pt, 
    65                             unsigned char *outbuf, unsigned int *outlen );
    66 static void vmu_attach(struct maple_device *dev);
    67 static void vmu_detach(struct maple_device *dev);
    68 static int vmu_read_block(struct maple_device *dev, int function, unsigned int pt,
    69                    uint32_t block, unsigned int phase, 
    70                    unsigned char *outbuf, unsigned int *buflen);
    71 static int vmu_write_block(struct maple_device *dev, int function, unsigned int pt,
    72                     uint32_t block, unsigned int phase, 
    73                     unsigned char *inbuf, unsigned int buflen);
    75 typedef struct vmu_device {
    76     struct maple_device dev;
    77     vmu_volume_t vol;
    78     char lcd_bitmap[VMU_LCD_SIZE]; /* 48x32 bitmap */
    79     struct lxdream_config_entry config[VMU_CONFIG_ENTRIES+1];
    80 } *vmu_device_t;
    82 struct maple_device_class vmu_class = { "Sega VMU", MAPLE_GRAB_DONTCARE, vmu_new };
    84 static struct vmu_device base_vmu = {
    85         { MAPLE_DEVICE_TAG, &vmu_class,
    86           VMU_IDENT, VMU_VERSION, 
    87           vmu_get_config, vmu_set_config_value, 
    88           vmu_attach, vmu_detach, vmu_destroy,
    89           vmu_clone, NULL, NULL, vmu_get_condition, NULL,
    90           vmu_get_meminfo, vmu_read_block, vmu_write_block, NULL, NULL },
    91           NULL, {0}, 
    92           {{ "volume", N_("Volume"), CONFIG_TYPE_FILE },
    93            { NULL, CONFIG_TYPE_NONE }} };
    95 static maple_device_t vmu_new( )
    96 {
    97     vmu_device_t dev = malloc( sizeof(struct vmu_device) );
    98     memcpy( dev, &base_vmu, sizeof(base_vmu) );
    99     return MAPLE_DEVICE(dev);
   100 }
   102 static maple_device_t vmu_clone( maple_device_t srcdevice )
   103 {
   104     vmu_device_t src = (vmu_device_t)srcdevice;
   105     vmu_device_t dev = (vmu_device_t)vmu_new();
   106     lxdream_copy_config_list( dev->config, src->config );
   107     return MAPLE_DEVICE(dev);
   108 }
   110 static lxdream_config_entry_t vmu_get_config( maple_device_t mdev )
   111 {
   112     vmu_device_t dev = (vmu_device_t)mdev;
   113     return dev->config;
   114 }
   116 static void vmu_set_config_value( maple_device_t dev, unsigned int key, const gchar *value )
   117 {
   118     vmu_device_t vmu = (vmu_device_t)dev;
   119     assert( key < VMU_CONFIG_ENTRIES );
   121     if( value == vmu->config[key].value ||
   122         value != NULL && vmu->config[key].value != NULL && strcmp(vmu->config[key].value, value) == 0 ) {
   123         return; /* Unchanged */
   124     }
   126     if( vmu->vol != NULL ) {
   127         vmulist_detach_vmu(vmu->vol);
   128     }
   129     lxdream_set_config_value( &vmu->config[key], value );
   130     vmu->vol = vmulist_get_vmu_by_filename( value );
   131     if( vmu->vol != NULL ) {
   132         vmulist_attach_vmu(vmu->vol, "MAPLE");
   133     }
   134 }
   136 void vmu_attach(struct maple_device *dev)
   137 {
   138     vmu_device_t vmu = (vmu_device_t)dev;
   139     if( vmu->config[0].value != NULL ) {
   140         vmu->vol = vmulist_get_vmu_by_filename(vmu->config[0].value);
   141         if( vmu->vol != NULL ) {
   142             vmulist_attach_vmu(vmu->vol, "MAPLE");
   143         }
   144     }
   145 }
   147 static void vmu_detach(struct maple_device *dev)
   148 {
   149     vmu_device_t vmu = (vmu_device_t)dev;
   150     if( vmu->vol != NULL ) {
   151         vmulist_detach_vmu(vmu->vol);
   152         vmu->vol = NULL;
   153     }
   154 }
   156 static void vmu_destroy( maple_device_t dev )
   157 {
   158     vmu_device_t vmu = (vmu_device_t)dev;
   159     free( dev );
   160 }
   162 static int vmu_get_condition(struct maple_device *dev, int function, 
   163                       unsigned char *outbuf, unsigned int *buflen)
   164 {
   165 }
   166 static int vmu_set_condition(struct maple_device *dev, int function, 
   167                       unsigned char *inbuf, unsigned int buflen)
   168 {
   169     return MAPLE_ERR_NO_RESPONSE; /* CHECKME */
   170 }
   172 static int vmu_get_meminfo(struct maple_device *dev, int function, unsigned int pt, 
   173                            unsigned char *outbuf, unsigned int *buflen)
   174 {
   175     struct vmu_device *vmu = (struct vmu_device *)dev;
   176     switch(function) {
   177     case MAPLE_FUNC_MEMORY:
   178         if( vmu->vol != NULL ) {
   179             const struct vmu_volume_metadata *md = vmu_volume_get_metadata( vmu->vol, pt ); 
   180             memcpy( outbuf, md, sizeof(struct vmu_volume_metadata) );
   181             *buflen = sizeof(struct vmu_volume_metadata);
   182             return 0;
   183         } // Else fallthrough 
   184     case MAPLE_FUNC_LCD:
   185     case MAPLE_FUNC_CLOCK:
   186         return MAPLE_ERR_NO_RESPONSE;
   187     default:
   188         return MAPLE_ERR_FUNC_UNSUP;
   189     }
   191 }
   192 static int vmu_read_block(struct maple_device *dev, int function, unsigned int pt,
   193                    uint32_t block, unsigned int phase, 
   194                    unsigned char *outbuf, unsigned int *buflen)
   195 {
   196     struct vmu_device *vmu = (struct vmu_device *)dev;
   197     switch( function ) {
   198     case MAPLE_FUNC_LCD:
   199         if( pt == 0 && block == 0 ) {
   200             *buflen = VMU_LCD_SIZE/4;
   201             memcpy( outbuf, vmu->lcd_bitmap, VMU_LCD_SIZE/4 );
   202         }
   203         return 0;
   204         break;
   205     case MAPLE_FUNC_MEMORY:
   206         if( vmu->vol != NULL ) {
   207             vmu_volume_read_block( vmu->vol, pt, block, outbuf );
   208             return 0;
   209         }
   210         // Else fallthrough for now
   211     case MAPLE_FUNC_CLOCK:
   212         return MAPLE_ERR_NO_RESPONSE; /* CHECKME */
   213     default:
   214         return MAPLE_ERR_FUNC_UNSUP;
   215     }
   216 }
   218 static int vmu_write_block(struct maple_device *dev, int function, unsigned int pt,
   219                     uint32_t block, unsigned int phase, 
   220                     unsigned char *inbuf, unsigned int buflen)
   221 {
   222     struct vmu_device *vmu = (struct vmu_device *)dev;
   223     switch( function ) {
   224     case MAPLE_FUNC_LCD:
   225         if( pt == 0 && block == 0 && buflen == (VMU_LCD_SIZE/4) ) {
   226             memcpy( vmu->lcd_bitmap, inbuf, VMU_LCD_SIZE );
   227         }
   228         return 0;
   229         break;
   230     case MAPLE_FUNC_MEMORY:
   231         if( vmu->vol != NULL && buflen == (VMU_PHASE_SIZE/4) ) {
   232             vmu_volume_write_phase( vmu->vol, pt, block, phase, inbuf );
   233             return 0;
   234         } 
   235         // Else fallthrough for now
   236     case MAPLE_FUNC_CLOCK:
   237         return MAPLE_ERR_NO_RESPONSE; /* CHECKME */
   238     default:
   239         return MAPLE_ERR_FUNC_UNSUP;
   240     }
   241 }
.