e9126d48d6b73ab0ae53fbe30f50b390fdfb4c82
[mercenary-reloaded.git] / src / libdisk / disk.c
1 /* disk access emulation
2  *
3  * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
4  * All Rights Reserved
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include "disk.h"
24
25 //#define DEBUG_DISK
26
27 #define CIAAPRA         0xbfe000
28 #define CIABPRB         0xbfd100
29 #define DSKPTH          0xdff020
30 #define DSKPTL          0xdff022
31 #define DSKLEN          0xdff024
32 #define INTREQR         0xdff01e
33
34 static uint16_t ciabprb = 0xffff;
35 static int track = 0;
36 static uint32_t dskptr = 0;
37 static uint16_t dsklen = 0;
38
39 /* NOTE: all CIA access is WORD access, so we use bits 8..15 for CIA-B */
40
41 uint16_t emulate_disk_read(uint32_t address)
42 {
43         uint16_t value = 0xffff;
44
45         switch (address) {
46         case CIAAPRA:
47                 /* /RDY (bit 5) is always 0, so disk is ready! */
48                 value &= 0xffdf;
49                 if (track == 0)
50                         value &= 0xffef;
51                 break;
52         case CIABPRB:
53                 /* return current bits from CIA-A PRB */
54                 value &= ciabprb;
55                 break;
56         case INTREQR:
57                 /* if disk dma is not on, don't process read/write */
58                 if (!(dsklen & 0x8000))
59                         break;
60
61                 if ((dsklen & 0x4000))
62                         disk_write(track, (ciabprb >> 10) & 1, dskptr, (dsklen & 0x3fff) << 1);
63                 else
64                         disk_read(track, (ciabprb >> 10) & 1, dskptr, (dsklen & 0x3fff) << 1);
65 #ifdef DEBUG_DISK
66                 printf("read from INTREQR: game asks for finished read/write\n");
67 #endif
68                 /* keep bit 2 set, so it indicated finished read/write */
69                 value &= 0xffff;
70                 break;
71         }
72
73         return value;
74 }
75
76 void emulate_disk_write(uint32_t address, uint16_t value)
77 {
78         switch (address) {
79         case CIABPRB:
80 #ifdef DEBUG_DISK
81                 printf("selected side %d\n", (value >> 10) & 1);
82 #endif
83                 if (((ciabprb >> 8) & 1) && !((value >> 8) & 1)) {
84                         if (!((value >> 9) & 1)) {
85                                 track++;
86                                 if (track > 84)
87                                         track = 84;
88 #ifdef DEBUG_DISK
89                                 printf("step forward to track %d\n", track);
90 #endif
91                         } else {
92                                 track--;
93                                 if (track < 0)
94                                         track = 0;
95 #ifdef DEBUG_DISK
96                                 printf("step backwards to track %d\n", track);
97 #endif
98                         }
99                 }
100                 ciabprb = value;
101                 break;
102         case DSKPTH:
103                 dskptr = (dskptr & 0x0000ffff) | (value << 16);
104                 break;
105         case DSKPTL:
106                 dskptr = (dskptr & 0xffff0000) | value;
107 #ifdef DEBUG_DISK
108                 printf("disk pointer set to 0x%06x\n", dskptr);
109 #endif
110                 break;
111         case DSKLEN:
112                 dsklen = value;
113 #ifdef DEBUG_DISK
114                 printf("DSKLEN: disk length set to 0x%04x, mode set to '%s', dma set to '%s'\n", dsklen & 0x3fff, (dsklen & 0x4000) ? "write" : "read", (dsklen & 0x8000) ? "on" : "off");
115 #endif
116                 break;
117         }
118 }
119
120 int get_disk_track(void)
121 {
122 #ifdef DEBUG_DISK
123         printf("disk drive is at track %d\n", track);
124 #endif
125         return track;
126 }
127