Method: CHD::CD#read_sector

Defined in:
lib/chd/cd.rb

#read_sector(lbasector, datatype = nil, phys = false) ⇒ String

Read one or more sectors from a CD-ROM

Parameters:

  • lbasector (Integer)

    sector number

  • datatype (Symbol) (defaults to: nil)

    type of data

Returns:

  • (String)


151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/chd/cd.rb', line 151

def read_sector(lbasector, datatype = nil, phys = false)
    # Compute CHD sector and track index
    frame_ofs_type = phys ? :physframeofs : :logframeofs
    chdsector      = lbasector
    trackidx       = 0
    @mapping.each_cons(2).with_index do |(cur, nxt), idx|
        if lbasector < nxt[frame_ofs_type]
            chdsector = lbasector - cur[frame_ofs_type] + cur[:chdframeofs]
            trackidx = idx
            break
        end
    end


    trackinfo = @toc[trackidx];
  tracktype = trackinfo[:trktype]

  offset, length, header =
         # return same type or don't care
         if (datatype == tracktype) || datatype.nil?
             [ 0,  trackinfo[:datasize] ]
             
  # return 2048 bytes of MODE1 data
         #   from a 2352 byte MODE1 RAW sector
  elsif (datatype  == :MODE1    ) &&
               (tracktype == :MODE1_RAW)
      [ 16, 2048 ]
             
  # return 2352 byte MODE1 RAW sector
         #  from 2048 bytes of MODE1 data
  elsif (datatype  == :MODE1_RAW) &&
               (tracktype == :MODE1    )
      warn "promotion of MODE1/FORM1 sector to MODE1 RAW is incomplete"
             m, sf = lba.divmod(60 * 75);
             s, f  = sf.divmod(75)
             hdr   = SYNCBYTES + [
          ((m / 10) << 4) | ((m % 10) << 0), # M
          ((s / 10) << 4) | ((s % 10) << 0), # S
          ((f / 10) << 4) | ((f % 10) << 0), # F
                 1                                  # MODE1
             ].pack('C*') # MSF + MODE1
             
             [ 0, 2048, hdr ]
             
  # return 2048 bytes of MODE1 data
         #   from a MODE2 FORM1 or RAW sector
         elsif (datatype  == :MODE1      ) &&
              ((tracktype == :MODE2_FORM1) || (tracktype == :MODE2_RAW  ))
      [ 24, 2048 ]
             
  # return 2048 bytes of MODE1 data
         #   from a MODE2 FORM2 or XA sector
  elsif (datatype  == :MODE1         ) &&
               (tracktype == :MODE2_FORM_MIX)
      [  8, 2048 ]
             
         # return MODE2 2336 byte data
         #   from a 2352 byte MODE1 or MODE2 RAW sector (skip the header)
  elsif (datatype  == :MODE2) &&
              ((tracktype == :MODE1_RAW) || (tracktype == :MODE2_RAW))
      [ 16, 2336 ]
             
         # Not supported
         else
             raise NotSupported,
                   "conversion from type %s to type %s not supported" % [
                       tracktype, datatype ]
  end

    # Read data
  unless phys 
 if ! trackinfo[:pgdatasize].zero?
    # chdman (phys=true) relies on chdframeofs to point
            # to index 0 instead of index 1 for extractcd.
    # Actually playing CDs requires it to point
            # to index 1 instead of index 0,
            # so adjust the offset when phys=false.
    chdsector += trackinfo[:pregap]
        elsif  lbasector < trackinfo[:logframeofs]
     # if this is pregap info that isn't actually in the file,
            # just return blank data
            return '\0' * length
 end
  end

    data = @chd.read_bytes(chdsector * FRAME_SIZE + offset, length)
    data = header + data if header
    data
end