Changeset b412168 in mainline for uspace/lib
- Timestamp:
- 2014-11-17T03:25:04Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6069061
- Parents:
- ef3da5a (diff), 5042706 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib
- Files:
-
- 12 added
- 14 edited
-
c/generic/stats.c (modified) (2 diffs)
-
c/generic/time.c (modified) (28 diffs)
-
c/include/fourcc.h (modified) (1 diff)
-
c/include/stats.h (modified) (1 diff)
-
c/include/stddef.h (modified) (1 diff)
-
c/include/sys/time.h (modified) (3 diffs)
-
compress/Makefile (added)
-
compress/gzip.c (added)
-
compress/gzip.h (added)
-
compress/inflate.c (added)
-
compress/inflate.h (added)
-
draw/Makefile (modified) (1 diff)
-
draw/codec/tga.c (modified) (3 diffs)
-
draw/codec/tga.gz.c (added)
-
draw/codec/tga.gz.h (added)
-
draw/codec/webp.c (added)
-
draw/codec/webp.h (added)
-
trackmod/Makefile (modified) (1 diff)
-
trackmod/protracker.c (modified) (4 diffs)
-
trackmod/trackmod.c (modified) (26 diffs)
-
trackmod/trackmod.h (modified) (2 diffs)
-
trackmod/types/protracker.h (modified) (1 diff)
-
trackmod/types/trackmod.h (modified) (6 diffs)
-
trackmod/types/xm.h (added)
-
trackmod/xm.c (added)
-
trackmod/xm.h (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/stats.c
ref3da5a rb412168 291 291 } 292 292 293 /** Get system uptime294 *295 * @return System uptime (in seconds).296 *297 */298 sysarg_t stats_get_uptime(void)299 {300 sysarg_t uptime;301 if (sysinfo_get_value("system.uptime", &uptime) != EOK)302 uptime = 0;303 304 return uptime;305 }306 307 293 /** Print load fixed-point value 308 294 * … … 316 302 void stats_print_load_fragment(load_t upper, unsigned int dec_length) 317 303 { 318 /* Magic value from BSD */319 load_t lower = 65536;320 321 304 /* Print the whole part */ 322 printf("%u.", upper / lower);323 324 load_t rest = (upper % lower) * 10;305 printf("%u.", upper / LOAD_UNIT); 306 307 load_t rest = (upper % LOAD_UNIT) * 10; 325 308 326 309 unsigned int i; 327 310 for (i = 0; i < dec_length; i++) { 328 printf("%u", rest / lower);329 rest = (rest % lower) * 10;311 printf("%u", rest / LOAD_UNIT); 312 rest = (rest % LOAD_UNIT) * 10; 330 313 } 331 314 } -
uspace/lib/c/generic/time.c
ref3da5a rb412168 54 54 #include <malloc.h> 55 55 56 #define ASCTIME_BUF_LEN 26 56 #define ASCTIME_BUF_LEN 26 57 58 #define HOURS_PER_DAY 24 59 #define MINS_PER_HOUR 60 60 #define SECS_PER_MIN 60 61 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 62 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 63 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 57 64 58 65 /** Pointer to kernel shared variables with time */ … … 63 70 } *ktime = NULL; 64 71 65 /* Helper functions ***********************************************************/ 66 67 #define HOURS_PER_DAY (24) 68 #define MINS_PER_HOUR (60) 69 #define SECS_PER_MIN (60) 70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 73 74 /** 75 * Checks whether the year is a leap year. 72 static async_sess_t *clock_conn = NULL; 73 74 /** Check whether the year is a leap year. 76 75 * 77 76 * @param year Year since 1900 (e.g. for 1970, the value is 70). 77 * 78 78 * @return true if year is a leap year, false otherwise 79 */ 80 static bool _is_leap_year(time_t year) 79 * 80 */ 81 static bool is_leap_year(time_t year) 81 82 { 82 83 year += 1900; 83 84 84 85 if (year % 400 == 0) 85 86 return true; 87 86 88 if (year % 100 == 0) 87 89 return false; 90 88 91 if (year % 4 == 0) 89 92 return true; 93 90 94 return false; 91 95 } 92 96 93 /** 94 * Returns how many days there are in the given month of the given year. 97 /** How many days there are in the given month 98 * 99 * Return how many days there are in the given month of the given year. 95 100 * Note that year is only taken into account if month is February. 96 101 * 97 102 * @param year Year since 1900 (can be negative). 98 * @param mon Month of the year. 0 for January, 11 for December. 103 * @param mon Month of the year. 0 for January, 11 for December. 104 * 99 105 * @return Number of days in the specified month. 100 */ 101 static int _days_in_month(time_t year, time_t mon) 102 { 103 assert(mon >= 0 && mon <= 11); 104 105 static int month_days[] = 106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 107 106 * 107 */ 108 static int days_in_month(time_t year, time_t mon) 109 { 110 assert(mon >= 0); 111 assert(mon <= 11); 112 113 static int month_days[] = { 114 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 115 }; 116 108 117 if (mon == 1) { 118 /* February */ 109 119 year += 1900; 110 /* february */111 return _is_leap_year(year) ? 29 : 28;112 } else {113 return month_days[mon];114 }115 } 116 117 /**118 * For specified year, month and day of month, return swhich day of that year120 return is_leap_year(year) ? 29 : 28; 121 } 122 123 return month_days[mon]; 124 } 125 126 /** Which day of that year it is. 127 * 128 * For specified year, month and day of month, return which day of that year 119 129 * it is. 120 130 * 121 131 * For example, given date 2011-01-03, the corresponding expression is: 122 * _day_of_year(111, 0, 3) == 2132 * day_of_year(111, 0, 3) == 2 123 133 * 124 134 * @param year Year (year 1900 = 0, can be negative). 125 * @param mon Month (January = 0).135 * @param mon Month (January = 0). 126 136 * @param mday Day of month (First day is 1). 137 * 127 138 * @return Day of year (First day is 0). 128 */ 129 static int _day_of_year(time_t year, time_t mon, time_t mday) 130 { 131 static int mdays[] = 132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 133 static int leap_mdays[] = 134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; 135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 137 } 138 139 /** 140 * Integer division that rounds to negative infinity. 141 * Used by some functions in this file. 139 * 140 */ 141 static int day_of_year(time_t year, time_t mon, time_t mday) 142 { 143 static int mdays[] = { 144 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 145 }; 146 147 static int leap_mdays[] = { 148 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 149 }; 150 151 return (is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 152 } 153 154 /** Integer division that rounds to negative infinity. 155 * 156 * Used by some functions in this module. 142 157 * 143 158 * @param op1 Dividend. 144 159 * @param op2 Divisor. 160 * 145 161 * @return Rounded quotient. 146 */ 147 static time_t _floor_div(time_t op1, time_t op2) 148 { 149 if (op1 >= 0 || op1 % op2 == 0) { 162 * 163 */ 164 static time_t floor_div(time_t op1, time_t op2) 165 { 166 if ((op1 >= 0) || (op1 % op2 == 0)) 150 167 return op1 / op2; 151 } else { 152 return op1 / op2 - 1; 153 } 154 } 155 156 /** 157 * Modulo that rounds to negative infinity. 158 * Used by some functions in this file. 168 169 return op1 / op2 - 1; 170 } 171 172 /** Modulo that rounds to negative infinity. 173 * 174 * Used by some functions in this module. 159 175 * 160 176 * @param op1 Dividend. 161 177 * @param op2 Divisor. 178 * 162 179 * @return Remainder. 163 */ 164 static time_t _floor_mod(time_t op1, time_t op2) 165 { 166 int div = _floor_div(op1, op2); 167 168 /* (a / b) * b + a % b == a */ 169 /* thus, a % b == a - (a / b) * b */ 170 171 int result = op1 - div * op2; 172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */ 180 * 181 */ 182 static time_t floor_mod(time_t op1, time_t op2) 183 { 184 time_t div = floor_div(op1, op2); 185 186 /* 187 * (a / b) * b + a % b == a 188 * Thus: a % b == a - (a / b) * b 189 */ 190 191 time_t result = op1 - div * op2; 192 193 /* Some paranoid checking to ensure there is mistake here. */ 174 194 assert(result >= 0); 175 195 assert(result < op2); … … 179 199 } 180 200 181 /** 182 * Number of days since the Epoch.201 /** Number of days since the Epoch. 202 * 183 203 * Epoch is 1970-01-01, which is also equal to day 0. 184 204 * 185 205 * @param year Year (year 1900 = 0, may be negative). 186 * @param mon Month (January = 0).206 * @param mon Month (January = 0). 187 207 * @param mday Day of month (first day = 1). 208 * 188 209 * @return Number of days since the Epoch. 189 */ 190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) 191 { 192 return (year - 70) * 365 + _floor_div(year - 69, 4) - 193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) + 194 _day_of_year(year, mon, mday); 195 } 196 197 /** 198 * Seconds since the Epoch. see also _days_since_epoch(). 199 * 210 * 211 */ 212 static time_t days_since_epoch(time_t year, time_t mon, time_t mday) 213 { 214 return (year - 70) * 365 + floor_div(year - 69, 4) - 215 floor_div(year - 1, 100) + floor_div(year + 299, 400) + 216 day_of_year(year, mon, mday); 217 } 218 219 /** Seconds since the Epoch. 220 * 221 * See also days_since_epoch(). 222 * 200 223 * @param tm Normalized broken-down time. 224 * 201 225 * @return Number of seconds since the epoch, not counting leap seconds. 202 */ 203 static time_t _secs_since_epoch(const struct tm *tm) 204 { 205 return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) * 226 * 227 */ 228 static time_t secs_since_epoch(const struct tm *tm) 229 { 230 return days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) * 206 231 SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR + 207 232 tm->tm_min * SECS_PER_MIN + tm->tm_sec; 208 233 } 209 234 210 /** 211 * Which day of week the specified date is. 212 * 235 /** Which day of week the specified date is. 236 * 213 237 * @param year Year (year 1900 = 0). 214 * @param mon Month (January = 0).238 * @param mon Month (January = 0). 215 239 * @param mday Day of month (first = 1). 240 * 216 241 * @return Day of week (Sunday = 0). 217 */ 218 static int _day_of_week(time_t year, time_t mon, time_t mday) 242 * 243 */ 244 static time_t day_of_week(time_t year, time_t mon, time_t mday) 219 245 { 220 246 /* 1970-01-01 is Thursday */ 221 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);222 } 223 224 /** 225 * Normalizes the broken-down time and optionally adds specified amount of226 * seconds.227 * 228 * @param tm Broken-down time to normalize.247 return floor_mod(days_since_epoch(year, mon, mday) + 4, 7); 248 } 249 250 /** Normalize the broken-down time. 251 * 252 * Optionally add specified amount of seconds. 253 * 254 * @param tm Broken-down time to normalize. 229 255 * @param sec_add Seconds to add. 256 * 230 257 * @return 0 on success, -1 on overflow 231 */ 232 static int _normalize_time(struct tm *tm, time_t sec_add) 258 * 259 */ 260 static int normalize_time(struct tm *tm, time_t sec_add) 233 261 { 234 262 // TODO: DST correction 235 263 236 264 /* Set initial values. */ 237 265 time_t sec = tm->tm_sec + sec_add; … … 241 269 time_t mon = tm->tm_mon; 242 270 time_t year = tm->tm_year; 243 271 244 272 /* Adjust time. */ 245 min += _floor_div(sec, SECS_PER_MIN);246 sec = _floor_mod(sec, SECS_PER_MIN);247 hour += _floor_div(min, MINS_PER_HOUR);248 min = _floor_mod(min, MINS_PER_HOUR);249 day += _floor_div(hour, HOURS_PER_DAY);250 hour = _floor_mod(hour, HOURS_PER_DAY);251 273 min += floor_div(sec, SECS_PER_MIN); 274 sec = floor_mod(sec, SECS_PER_MIN); 275 hour += floor_div(min, MINS_PER_HOUR); 276 min = floor_mod(min, MINS_PER_HOUR); 277 day += floor_div(hour, HOURS_PER_DAY); 278 hour = floor_mod(hour, HOURS_PER_DAY); 279 252 280 /* Adjust month. */ 253 year += _floor_div(mon, 12);254 mon = _floor_mod(mon, 12);255 281 year += floor_div(mon, 12); 282 mon = floor_mod(mon, 12); 283 256 284 /* Now the difficult part - days of month. */ 257 285 258 286 /* First, deal with whole cycles of 400 years = 146097 days. */ 259 year += _floor_div(day, 146097) * 400;260 day = _floor_mod(day, 146097);287 year += floor_div(day, 146097) * 400; 288 day = floor_mod(day, 146097); 261 289 262 290 /* Then, go in one year steps. */ … … 264 292 /* January and February. */ 265 293 while (day > 365) { 266 day -= _is_leap_year(year) ? 366 : 365;294 day -= is_leap_year(year) ? 366 : 365; 267 295 year++; 268 296 } … … 270 298 /* Rest of the year. */ 271 299 while (day > 365) { 272 day -= _is_leap_year(year + 1) ? 366 : 365;300 day -= is_leap_year(year + 1) ? 366 : 365; 273 301 year++; 274 302 } … … 276 304 277 305 /* Finally, finish it off month per month. */ 278 while (day >= _days_in_month(year, mon)) {279 day -= _days_in_month(year, mon);306 while (day >= days_in_month(year, mon)) { 307 day -= days_in_month(year, mon); 280 308 mon++; 309 281 310 if (mon >= 12) { 282 311 mon -= 12; … … 286 315 287 316 /* Calculate the remaining two fields. */ 288 tm->tm_yday = _day_of_year(year, mon, day + 1);289 tm->tm_wday = _day_of_week(year, mon, day + 1);317 tm->tm_yday = day_of_year(year, mon, day + 1); 318 tm->tm_wday = day_of_week(year, mon, day + 1); 290 319 291 320 /* And put the values back to the struct. */ … … 296 325 tm->tm_mon = (int) mon; 297 326 298 /* Casts to work around libcbrain-damage. */299 if (year > ((int) INT_MAX) || year < ((int)INT_MIN)) {300 tm->tm_year = (year < 0) ? ((int) INT_MIN) : ((int)INT_MAX);327 /* Casts to work around POSIX brain-damage. */ 328 if (year > ((int) INT_MAX) || year < ((int) INT_MIN)) { 329 tm->tm_year = (year < 0) ? ((int) INT_MIN) : ((int) INT_MAX); 301 330 return -1; 302 331 } … … 306 335 } 307 336 308 /** 309 * Which day the week-based year starts on, relative to the first calendar day. 310 * E.g. if the year starts on December 31st, the return value is -1. 337 /** Which day the week-based year starts on. 338 * 339 * Relative to the first calendar day. E.g. if the year starts 340 * on December 31st, the return value is -1. 311 341 * 312 342 * @param Year since 1900. 343 * 313 344 * @return Offset of week-based year relative to calendar year. 314 */ 315 static int _wbyear_offset(int year) 316 { 317 int start_wday = _day_of_week(year, 0, 1); 318 return _floor_mod(4 - start_wday, 7) - 3; 319 } 320 321 /** 322 * Returns week-based year of the specified time. 345 * 346 */ 347 static int wbyear_offset(int year) 348 { 349 int start_wday = day_of_week(year, 0, 1); 350 351 return floor_mod(4 - start_wday, 7) - 3; 352 } 353 354 /** Week-based year of the specified time. 323 355 * 324 356 * @param tm Normalized broken-down time. 357 * 325 358 * @return Week-based year. 326 */ 327 static int _wbyear(const struct tm *tm) 328 { 329 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 359 * 360 */ 361 static int wbyear(const struct tm *tm) 362 { 363 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 364 330 365 if (day < 0) { 331 366 /* Last week of previous year. */ 332 367 return tm->tm_year - 1; 333 368 } 334 if (day > 364 + _is_leap_year(tm->tm_year)) { 369 370 if (day > 364 + is_leap_year(tm->tm_year)) { 335 371 /* First week of next year. */ 336 372 return tm->tm_year + 1; 337 373 } 374 338 375 /* All the other days are in the calendar year. */ 339 376 return tm->tm_year; 340 377 } 341 378 342 /** 343 * Week number of the year, assuming weeks start on sunday.379 /** Week number of the year (assuming weeks start on Sunday). 380 * 344 381 * The first Sunday of January is the first day of week 1; 345 382 * days in the new year before this are in week 0. 346 383 * 347 384 * @param tm Normalized broken-down time. 385 * 348 386 * @return The week number (0 - 53). 349 */ 350 static int _sun_week_number(const struct tm *tm) 351 { 352 int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7; 387 * 388 */ 389 static int sun_week_number(const struct tm *tm) 390 { 391 int first_day = (7 - day_of_week(tm->tm_year, 0, 1)) % 7; 392 353 393 return (tm->tm_yday - first_day + 7) / 7; 354 394 } 355 395 356 /** 357 * Week number of the year, assuming weeks start on monday. 358 * If the week containing January 1st has four or more days in the new year, 359 * then it is considered week 1. Otherwise, it is the last week of the previous 360 * year, and the next week is week 1. Both January 4th and the first Thursday 396 /** Week number of the year (assuming weeks start on Monday). 397 * 398 * If the week containing January 1st has four or more days 399 * in the new year, then it is considered week 1. Otherwise, 400 * it is the last week of the previous year, and the next week 401 * is week 1. Both January 4th and the first Thursday 361 402 * of January are always in week 1. 362 403 * 363 404 * @param tm Normalized broken-down time. 405 * 364 406 * @return The week number (1 - 53). 365 */ 366 static int _iso_week_number(const struct tm *tm) 367 { 368 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 407 * 408 */ 409 static int iso_week_number(const struct tm *tm) 410 { 411 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 412 369 413 if (day < 0) { 370 414 /* Last week of previous year. */ 371 415 return 53; 372 416 } 373 if (day > 364 + _is_leap_year(tm->tm_year)) { 417 418 if (day > 364 + is_leap_year(tm->tm_year)) { 374 419 /* First week of next year. */ 375 420 return 1; 376 421 } 422 377 423 /* All the other days give correct answer. */ 378 424 return (day / 7 + 1); 379 425 } 380 426 381 /** 382 * Week number of the year, assuming weeks start on monday.427 /** Week number of the year (assuming weeks start on Monday). 428 * 383 429 * The first Monday of January is the first day of week 1; 384 * days in the new year before this are in week 0. 430 * days in the new year before this are in week 0. 385 431 * 386 432 * @param tm Normalized broken-down time. 433 * 387 434 * @return The week number (0 - 53). 388 */ 389 static int _mon_week_number(const struct tm *tm) 390 { 391 int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7; 435 * 436 */ 437 static int mon_week_number(const struct tm *tm) 438 { 439 int first_day = (1 - day_of_week(tm->tm_year, 0, 1)) % 7; 440 392 441 return (tm->tm_yday - first_day + 7) / 7; 393 442 } 394 395 /******************************************************************************/396 397 443 398 444 /** Add microseconds to given timeval. … … 468 514 } 469 515 470 /** Get time of day 516 /** Get time of day. 471 517 * 472 518 * The time variables are memory mapped (read-only) from kernel which … … 482 528 * 483 529 */ 484 int gettimeofday(struct timeval *tv, struct timezone *tz) 485 { 486 int rc; 487 struct tm t; 488 category_id_t cat_id; 489 size_t svc_cnt; 490 service_id_t *svc_ids = NULL; 491 service_id_t svc_id; 492 char *svc_name = NULL; 493 494 static async_sess_t *clock_conn = NULL; 495 530 void gettimeofday(struct timeval *tv, struct timezone *tz) 531 { 496 532 if (tz) { 497 533 tz->tz_minuteswest = 0; 498 534 tz->tz_dsttime = DST_NONE; 499 535 } 500 536 501 537 if (clock_conn == NULL) { 502 rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING); 538 category_id_t cat_id; 539 int rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING); 503 540 if (rc != EOK) 504 goto ret_uptime; 505 541 goto fallback; 542 543 service_id_t *svc_ids; 544 size_t svc_cnt; 506 545 rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt); 507 546 if (rc != EOK) 508 goto ret_uptime;509 547 goto fallback; 548 510 549 if (svc_cnt == 0) 511 goto ret_uptime; 512 550 goto fallback; 551 552 char *svc_name; 513 553 rc = loc_service_get_name(svc_ids[0], &svc_name); 554 free(svc_ids); 514 555 if (rc != EOK) 515 goto ret_uptime; 516 556 goto fallback; 557 558 service_id_t svc_id; 517 559 rc = loc_service_get_id(svc_name, &svc_id, 0); 560 free(svc_name); 518 561 if (rc != EOK) 519 goto ret_uptime;520 562 goto fallback; 563 521 564 clock_conn = loc_service_connect(EXCHANGE_SERIALIZE, 522 565 svc_id, IPC_FLAG_BLOCKING); 523 566 if (!clock_conn) 524 goto ret_uptime; 525 } 526 527 rc = clock_dev_time_get(clock_conn, &t); 567 goto fallback; 568 } 569 570 struct tm time; 571 int rc = clock_dev_time_get(clock_conn, &time); 528 572 if (rc != EOK) 529 goto ret_uptime;530 573 goto fallback; 574 531 575 tv->tv_usec = 0; 532 tv->tv_sec = mktime(&t); 533 534 free(svc_name); 535 free(svc_ids); 536 537 return EOK; 538 539 ret_uptime: 540 541 free(svc_name); 542 free(svc_ids); 543 544 return getuptime(tv); 545 } 546 547 int getuptime(struct timeval *tv) 576 tv->tv_sec = mktime(&time); 577 578 return; 579 580 fallback: 581 getuptime(tv); 582 } 583 584 void getuptime(struct timeval *tv) 548 585 { 549 586 if (ktime == NULL) { … … 552 589 if (rc != EOK) { 553 590 errno = rc; 554 return -1;591 goto fallback; 555 592 } 556 593 … … 561 598 as_area_destroy(addr); 562 599 errno = rc; 563 return -1;600 goto fallback; 564 601 } 565 602 … … 580 617 } else 581 618 tv->tv_sec = s1; 582 583 return 0; 619 620 return; 621 622 fallback: 623 tv->tv_sec = 0; 624 tv->tv_usec = 0; 584 625 } 585 626 … … 587 628 { 588 629 struct timeval tv; 589 if (gettimeofday(&tv, NULL)) 590 return (time_t) -1; 630 gettimeofday(&tv, NULL); 591 631 592 632 if (tloc) … … 631 671 } 632 672 633 /** 634 * This function first normalizes the provided broken-down time 635 * (moves all values to their proper bounds) and then tries to 636 * calculate the appropriate time_t representation. 673 /** Get time from broken-down time. 674 * 675 * First normalize the provided broken-down time 676 * (moves all values to their proper bounds) and 677 * then try to calculate the appropriate time_t 678 * representation. 637 679 * 638 680 * @param tm Broken-down time. 639 * @return time_t representation of the time, undefined value on overflow. 681 * 682 * @return time_t representation of the time. 683 * @return Undefined value on overflow. 684 * 640 685 */ 641 686 time_t mktime(struct tm *tm) … … 643 688 // TODO: take DST flag into account 644 689 // TODO: detect overflow 645 646 _normalize_time(tm, 0); 647 return _secs_since_epoch(tm); 648 } 649 650 /** 651 * Convert time and date to a string, based on a specified format and 652 * current locale. 653 * 654 * @param s Buffer to write string to. 690 691 normalize_time(tm, 0); 692 return secs_since_epoch(tm); 693 } 694 695 /* 696 * FIXME: This requires POSIX-correct snprintf. 697 * Otherwise it won't work with non-ASCII chars. 698 */ 699 #define APPEND(...) \ 700 { \ 701 consumed = snprintf(ptr, remaining, __VA_ARGS__); \ 702 if (consumed >= remaining) \ 703 return 0; \ 704 \ 705 ptr += consumed; \ 706 remaining -= consumed; \ 707 } 708 709 #define RECURSE(fmt) \ 710 { \ 711 consumed = strftime(ptr, remaining, fmt, tm); \ 712 if (consumed == 0) \ 713 return 0; \ 714 \ 715 ptr += consumed; \ 716 remaining -= consumed; \ 717 } 718 719 #define TO_12H(hour) \ 720 (((hour) > 12) ? ((hour) - 12) : \ 721 (((hour) == 0) ? 12 : (hour))) 722 723 /** Convert time and date to a string. 724 * 725 * @param s Buffer to write string to. 655 726 * @param maxsize Size of the buffer. 656 * @param format Format of the output. 657 * @param tm Broken-down time to format. 727 * @param format Format of the output. 728 * @param tm Broken-down time to format. 729 * 658 730 * @return Number of bytes written. 731 * 659 732 */ 660 733 size_t strftime(char *restrict s, size_t maxsize, … … 664 737 assert(format != NULL); 665 738 assert(tm != NULL); 666 739 667 740 // TODO: use locale 741 668 742 static const char *wday_abbr[] = { 669 743 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 670 744 }; 745 671 746 static const char *wday[] = { 672 747 "Sunday", "Monday", "Tuesday", "Wednesday", 673 748 "Thursday", "Friday", "Saturday" 674 749 }; 750 675 751 static const char *mon_abbr[] = { 676 752 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 677 753 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 678 754 }; 755 679 756 static const char *mon[] = { 680 757 "January", "February", "March", "April", "May", "June", "July", … … 682 759 }; 683 760 684 if (maxsize < 1) {761 if (maxsize < 1) 685 762 return 0; 686 }687 763 688 764 char *ptr = s; … … 690 766 size_t remaining = maxsize; 691 767 692 #define append(...) { \693 /* FIXME: this requires POSIX-correct snprintf */ \694 /* otherwise it won't work with non-ascii chars */ \695 consumed = snprintf(ptr, remaining, __VA_ARGS__); \696 if (consumed >= remaining) { \697 return 0; \698 } \699 ptr += consumed; \700 remaining -= consumed; \701 }702 703 #define recurse(fmt) { \704 consumed = strftime(ptr, remaining, fmt, tm); \705 if (consumed == 0) { \706 return 0; \707 } \708 ptr += consumed; \709 remaining -= consumed; \710 }711 712 #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \713 (((hour) == 0) ? 12 : (hour)))714 715 768 while (*format != '\0') { 716 769 if (*format != '%') { 717 append("%c", *format);770 APPEND("%c", *format); 718 771 format++; 719 772 continue; … … 721 774 722 775 format++; 723 if ( *format == '0' || *format == '+') {776 if ((*format == '0') || (*format == '+')) { 724 777 // TODO: padding 725 778 format++; 726 779 } 780 727 781 while (isdigit(*format)) { 728 782 // TODO: padding 729 783 format++; 730 784 } 731 if (*format == 'O' || *format == 'E') { 785 786 if ((*format == 'O') || (*format == 'E')) { 732 787 // TODO: locale's alternative format 733 788 format++; … … 736 791 switch (*format) { 737 792 case 'a': 738 append("%s", wday_abbr[tm->tm_wday]); break; 793 APPEND("%s", wday_abbr[tm->tm_wday]); 794 break; 739 795 case 'A': 740 append("%s", wday[tm->tm_wday]); break; 796 APPEND("%s", wday[tm->tm_wday]); 797 break; 741 798 case 'b': 742 append("%s", mon_abbr[tm->tm_mon]); break; 799 APPEND("%s", mon_abbr[tm->tm_mon]); 800 break; 743 801 case 'B': 744 append("%s", mon[tm->tm_mon]); break; 802 APPEND("%s", mon[tm->tm_mon]); 803 break; 745 804 case 'c': 746 805 // TODO: locale-specific datetime format 747 recurse("%Y-%m-%d %H:%M:%S"); break; 806 RECURSE("%Y-%m-%d %H:%M:%S"); 807 break; 748 808 case 'C': 749 append("%02d", (1900 + tm->tm_year) / 100); break; 809 APPEND("%02d", (1900 + tm->tm_year) / 100); 810 break; 750 811 case 'd': 751 append("%02d", tm->tm_mday); break; 812 APPEND("%02d", tm->tm_mday); 813 break; 752 814 case 'D': 753 recurse("%m/%d/%y"); break; 815 RECURSE("%m/%d/%y"); 816 break; 754 817 case 'e': 755 append("%2d", tm->tm_mday); break; 818 APPEND("%2d", tm->tm_mday); 819 break; 756 820 case 'F': 757 recurse("%+4Y-%m-%d"); break; 821 RECURSE("%+4Y-%m-%d"); 822 break; 758 823 case 'g': 759 append("%02d", _wbyear(tm) % 100); break; 824 APPEND("%02d", wbyear(tm) % 100); 825 break; 760 826 case 'G': 761 append("%d", _wbyear(tm)); break; 827 APPEND("%d", wbyear(tm)); 828 break; 762 829 case 'h': 763 recurse("%b"); break; 830 RECURSE("%b"); 831 break; 764 832 case 'H': 765 append("%02d", tm->tm_hour); break; 833 APPEND("%02d", tm->tm_hour); 834 break; 766 835 case 'I': 767 append("%02d", TO_12H(tm->tm_hour)); break; 836 APPEND("%02d", TO_12H(tm->tm_hour)); 837 break; 768 838 case 'j': 769 append("%03d", tm->tm_yday); break; 839 APPEND("%03d", tm->tm_yday); 840 break; 770 841 case 'k': 771 append("%2d", tm->tm_hour); break; 842 APPEND("%2d", tm->tm_hour); 843 break; 772 844 case 'l': 773 append("%2d", TO_12H(tm->tm_hour)); break; 845 APPEND("%2d", TO_12H(tm->tm_hour)); 846 break; 774 847 case 'm': 775 append("%02d", tm->tm_mon); break; 848 APPEND("%02d", tm->tm_mon); 849 break; 776 850 case 'M': 777 append("%02d", tm->tm_min); break; 851 APPEND("%02d", tm->tm_min); 852 break; 778 853 case 'n': 779 append("\n"); break; 854 APPEND("\n"); 855 break; 780 856 case 'p': 781 append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break; 857 APPEND("%s", tm->tm_hour < 12 ? "AM" : "PM"); 858 break; 782 859 case 'P': 783 append("%s", tm->tm_hour < 12 ? "am" : "PM"); break; 860 APPEND("%s", tm->tm_hour < 12 ? "am" : "PM"); 861 break; 784 862 case 'r': 785 recurse("%I:%M:%S %p"); break; 863 RECURSE("%I:%M:%S %p"); 864 break; 786 865 case 'R': 787 recurse("%H:%M"); break; 866 RECURSE("%H:%M"); 867 break; 788 868 case 's': 789 append("%ld", _secs_since_epoch(tm)); break; 869 APPEND("%ld", secs_since_epoch(tm)); 870 break; 790 871 case 'S': 791 append("%02d", tm->tm_sec); break; 872 APPEND("%02d", tm->tm_sec); 873 break; 792 874 case 't': 793 append("\t"); break; 875 APPEND("\t"); 876 break; 794 877 case 'T': 795 recurse("%H:%M:%S"); break; 878 RECURSE("%H:%M:%S"); 879 break; 796 880 case 'u': 797 append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);881 APPEND("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); 798 882 break; 799 883 case 'U': 800 append("%02d", _sun_week_number(tm)); break; 884 APPEND("%02d", sun_week_number(tm)); 885 break; 801 886 case 'V': 802 append("%02d", _iso_week_number(tm)); break; 887 APPEND("%02d", iso_week_number(tm)); 888 break; 803 889 case 'w': 804 append("%d", tm->tm_wday); break; 890 APPEND("%d", tm->tm_wday); 891 break; 805 892 case 'W': 806 append("%02d", _mon_week_number(tm)); break; 893 APPEND("%02d", mon_week_number(tm)); 894 break; 807 895 case 'x': 808 896 // TODO: locale-specific date format 809 recurse("%Y-%m-%d"); break; 897 RECURSE("%Y-%m-%d"); 898 break; 810 899 case 'X': 811 900 // TODO: locale-specific time format 812 recurse("%H:%M:%S"); break; 901 RECURSE("%H:%M:%S"); 902 break; 813 903 case 'y': 814 append("%02d", tm->tm_year % 100); break; 904 APPEND("%02d", tm->tm_year % 100); 905 break; 815 906 case 'Y': 816 append("%d", 1900 + tm->tm_year); break; 907 APPEND("%d", 1900 + tm->tm_year); 908 break; 817 909 case 'z': 818 910 // TODO: timezone … … 822 914 break; 823 915 case '%': 824 append("%%");916 APPEND("%%"); 825 917 break; 826 918 default: 827 919 /* Invalid specifier, print verbatim. */ 828 while (*format != '%') {920 while (*format != '%') 829 921 format--; 830 }831 append("%%");922 923 APPEND("%%"); 832 924 break; 833 925 } 926 834 927 format++; 835 928 } 836 929 837 #undef append838 #undef recurse839 840 930 return maxsize - remaining; 841 931 } 842 932 843 844 /** Converts a time value to a broken-down UTC time 845 * 846 * @param time Time to convert847 * @param result Structure to store the result to848 * 849 * @return EOK or a negative error code933 /** Convert a time value to a broken-down UTC time/ 934 * 935 * @param time Time to convert 936 * @param result Structure to store the result to 937 * 938 * @return EOK or a negative error code 939 * 850 940 */ 851 941 int time_utc2tm(const time_t time, struct tm *restrict result) 852 942 { 853 943 assert(result != NULL); 854 944 855 945 /* Set result to epoch. */ 856 946 result->tm_sec = 0; … … 860 950 result->tm_mon = 0; 861 951 result->tm_year = 70; /* 1970 */ 862 863 if ( _normalize_time(result, time) == -1)952 953 if (normalize_time(result, time) == -1) 864 954 return EOVERFLOW; 865 955 866 956 return EOK; 867 957 } 868 958 869 /** Converts a time value to a null terminated string of the form 870 * "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 871 * 872 * @param time Time to convert. 873 * @param buf Buffer to store the string to, must be at least 874 * ASCTIME_BUF_LEN bytes long. 875 * 876 * @return EOK or a negative error code. 959 /** Convert a time value to a NULL-terminated string. 960 * 961 * The format is "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 962 * 963 * @param time Time to convert. 964 * @param buf Buffer to store the string to, must be at least 965 * ASCTIME_BUF_LEN bytes long. 966 * 967 * @return EOK or a negative error code. 968 * 877 969 */ 878 970 int time_utc2str(const time_t time, char *restrict buf) 879 971 { 880 struct tm t; 881 int r; 882 883 if ((r = time_utc2tm(time, &t)) != EOK) 884 return r; 885 886 time_tm2str(&t, buf); 972 struct tm tm; 973 int ret = time_utc2tm(time, &tm); 974 if (ret != EOK) 975 return ret; 976 977 time_tm2str(&tm, buf); 887 978 return EOK; 888 979 } 889 980 890 891 /** 892 * Converts broken-down time to a string in format 893 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 981 /** Convert broken-down time to a NULL-terminated string. 982 * 983 * The format is "Sun Jan 1 00:00:00 1970\n". (Obsolete) 894 984 * 895 985 * @param timeptr Broken-down time structure. 896 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 897 * bytes long. 986 * @param buf Buffer to store string to, must be at least 987 * ASCTIME_BUF_LEN bytes long. 988 * 898 989 */ 899 990 void time_tm2str(const struct tm *restrict timeptr, char *restrict buf) … … 901 992 assert(timeptr != NULL); 902 993 assert(buf != NULL); 903 994 904 995 static const char *wday[] = { 905 996 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 906 997 }; 998 907 999 static const char *mon[] = { 908 1000 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 909 1001 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 910 1002 }; 911 1003 912 1004 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 913 1005 wday[timeptr->tm_wday], … … 918 1010 } 919 1011 920 /** 921 * Converts a time value to a broken-down local time, expressed relative 922 * to the user's specified timezone. 923 * 924 * @param timer Time to convert. 925 * @param result Structure to store the result to. 926 * 927 * @return EOK on success or a negative error code. 1012 /** Converts a time value to a broken-down local time. 1013 * 1014 * Time is expressed relative to the user's specified timezone. 1015 * 1016 * @param timer Time to convert. 1017 * @param result Structure to store the result to. 1018 * 1019 * @return EOK on success or a negative error code. 1020 * 928 1021 */ 929 1022 int time_local2tm(const time_t time, struct tm *restrict result) 930 1023 { 931 // TODO: deal with timezone932 // currently assumes system and all times are in GMT933 1024 // TODO: Deal with timezones. 1025 // Currently assumes system and all times are in UTC 1026 934 1027 /* Set result to epoch. */ 935 1028 result->tm_sec = 0; … … 939 1032 result->tm_mon = 0; 940 1033 result->tm_year = 70; /* 1970 */ 941 942 if ( _normalize_time(result, time) == -1)1034 1035 if (normalize_time(result, time) == -1) 943 1036 return EOVERFLOW; 944 1037 945 1038 return EOK; 946 1039 } 947 1040 948 /** 949 * Converts the calendar time to a null terminated string950 * of the form"Wed Jun 30 21:49:08 1993\n" expressed relative to the1041 /** Convert the calendar time to a NULL-terminated string. 1042 * 1043 * The format is "Wed Jun 30 21:49:08 1993\n" expressed relative to the 951 1044 * user's specified timezone. 952 * 953 * @param timer Time to convert. 954 * @param buf Buffer to store the string to. Must be at least 955 * ASCTIME_BUF_LEN bytes long. 956 * 957 * @return EOK on success or a negative error code. 1045 * 1046 * @param timer Time to convert. 1047 * @param buf Buffer to store the string to. Must be at least 1048 * ASCTIME_BUF_LEN bytes long. 1049 * 1050 * @return EOK on success or a negative error code. 1051 * 958 1052 */ 959 1053 int time_local2str(const time_t time, char *buf) 960 1054 { 961 1055 struct tm loctime; 962 int r; 963 964 if ((r = time_local2tm(time, &loctime)) != EOK) 965 return r; 966 1056 int ret = time_local2tm(time, &loctime); 1057 if (ret != EOK) 1058 return ret; 1059 967 1060 time_tm2str(&loctime, buf); 968 969 1061 return EOK; 970 1062 } 971 1063 972 /** 973 * Calculate the difference between two times, in seconds. 974 * 1064 /** Calculate the difference between two times, in seconds. 1065 * 975 1066 * @param time1 First time. 976 1067 * @param time0 Second time. 977 * @return Time in seconds. 1068 * 1069 * @return Time difference in seconds. 1070 * 978 1071 */ 979 1072 double difftime(time_t time1, time_t time0) -
uspace/lib/c/include/fourcc.h
ref3da5a rb412168 38 38 #include <libarch/common.h> 39 39 40 typedef uint32_t fourcc_t; 41 40 42 #define FOURCC(a, b, c, d) \ 41 43 (((UINT32_T) (a)) | (((UINT32_T) (b)) << 8) | \ -
uspace/lib/c/include/stats.h
ref3da5a rb412168 43 43 #include <abi/sysinfo.h> 44 44 45 #define LOAD_UNIT 65536 46 45 47 extern stats_cpu_t *stats_get_cpus(size_t *); 46 48 extern stats_physmem_t *stats_get_physmem(void); 47 49 extern load_t *stats_get_load(size_t *); 48 extern sysarg_t stats_get_uptime(void);49 50 50 51 extern stats_task_t *stats_get_tasks(size_t *); -
uspace/lib/c/include/stddef.h
ref3da5a rb412168 42 42 #endif 43 43 44 #define offsetof(type,member) ((size_t) &(((type *) 0)->member)) 44 45 45 46 #endif -
uspace/lib/c/include/sys/time.h
ref3da5a rb412168 40 40 #include <sys/types.h> 41 41 42 #define DST_NONE 043 #define ASCTIME_BUF_LEN 2642 #define DST_NONE 0 43 #define ASCTIME_BUF_LEN 26 44 44 45 45 typedef long time_t; … … 50 50 51 51 struct tm { 52 int tm_sec; /* Seconds [0,60]. */53 int tm_min; /* Minutes [0,59]. */54 int tm_hour; /* Hour [0,23]. */55 int tm_mday; /* Day of month [1,31]. */56 int tm_mon; /* Month of year [0,11]. */57 int tm_year; /* Years since 1900. */58 int tm_wday; /* Day of week [0,6] (Sunday = 0). */59 int tm_yday; /* Day of year [0,365]. */60 int tm_isdst; /* Daylight Savings flag. */52 int tm_sec; /* Seconds [0,60]. */ 53 int tm_min; /* Minutes [0,59]. */ 54 int tm_hour; /* Hour [0,23]. */ 55 int tm_mday; /* Day of month [1,31]. */ 56 int tm_mon; /* Month of year [0,11]. */ 57 int tm_year; /* Years since 1900. */ 58 int tm_wday; /* Day of week [0,6] (Sunday = 0). */ 59 int tm_yday; /* Day of year [0,365]. */ 60 int tm_isdst; /* Daylight Savings flag. */ 61 61 }; 62 62 … … 71 71 }; 72 72 73 extern void tv_add(struct timeval * tv, suseconds_t usecs);74 extern suseconds_t tv_sub(struct timeval * tv1, struct timeval *tv2);75 extern int tv_gt(struct timeval * tv1, struct timeval *tv2);76 extern int tv_gteq(struct timeval * tv1, struct timeval *tv2);77 extern int gettimeofday(struct timeval *tv, struct timezone *tz);78 extern int getuptime(struct timeval *tv);73 extern void tv_add(struct timeval *, suseconds_t); 74 extern suseconds_t tv_sub(struct timeval *, struct timeval *); 75 extern int tv_gt(struct timeval *, struct timeval *); 76 extern int tv_gteq(struct timeval *, struct timeval *); 77 extern void gettimeofday(struct timeval *, struct timezone *); 78 extern void getuptime(struct timeval *); 79 79 80 80 extern void udelay(useconds_t); 81 81 82 extern time_t mktime(struct tm * tm);83 extern int time_utc2tm(const time_t time, struct tm *result);84 extern int time_utc2str(const time_t time, char *buf);85 extern void time_tm2str(const struct tm * timeptr, char *buf);86 extern int time_local2tm(const time_t time, struct tm *result);87 extern int time_local2str(const time_t time, char *buf);88 extern double difftime(time_t time1, time_t time0);89 extern size_t strftime(char *restrict s, size_t maxsize,90 const char *restrict format, const struct tm *restrict tm);82 extern time_t mktime(struct tm *); 83 extern int time_utc2tm(const time_t, struct tm *); 84 extern int time_utc2str(const time_t, char *); 85 extern void time_tm2str(const struct tm *, char *); 86 extern int time_local2tm(const time_t, struct tm *); 87 extern int time_local2str(const time_t, char *); 88 extern double difftime(time_t, time_t); 89 extern size_t strftime(char *restrict, size_t, const char *restrict, 90 const struct tm *restrict); 91 91 92 92 #endif -
uspace/lib/draw/Makefile
ref3da5a rb412168 31 31 SLIBRARY = libdraw.so.0.0 32 32 LSONAME = libdraw.so0 33 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) 33 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) -I$(LIBCOMPRESS_PREFIX) 34 34 35 35 SOURCES = \ 36 36 codec/tga.c \ 37 codec/tga.gz.c \ 38 codec/webp.c \ 37 39 cursor/embedded.c \ 38 40 font/embedded.c \ -
uspace/lib/draw/codec/tga.c
ref3da5a rb412168 110 110 * @return True on succesful decoding. 111 111 * @return False on failure. 112 * 112 113 */ 113 114 static bool decode_tga_header(void *data, size_t size, tga_t *tga) … … 174 175 * @return Newly allocated surface with the decoded content. 175 176 * @return NULL on error or unsupported format. 177 * 176 178 */ 177 179 surface_t *decode_tga(void *data, size_t size, surface_flags_t flags) … … 264 266 * @return True on succesful encoding. 265 267 * @return False on failure. 268 * 266 269 */ 267 270 bool encode_tga(surface_t *surface, void **pdata, size_t *psize) -
uspace/lib/trackmod/Makefile
ref3da5a rb412168 32 32 SOURCES = \ 33 33 protracker.c \ 34 trackmod.c 34 trackmod.c \ 35 xm.c 35 36 36 37 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/trackmod/protracker.c
ref3da5a rb412168 113 113 } 114 114 115 116 /** Decode pattern cell. 117 * 118 * @param pattern Pattern 119 * @param row Row number 120 * @param channel Channel number 121 * @param cell Place to store decoded cell 122 */ 123 static void protracker_decode_cell(uint32_t cdata, trackmod_cell_t *cell) 124 { 125 uint32_t code; 126 127 code = uint32_t_be2host(cdata); 128 cell->period = (code >> (4 * 4)) & 0xfff; 129 cell->instr = (((code >> (7 * 4)) & 0xf) << 4) | 130 ((code >> (3 * 4)) & 0xf); 131 cell->effect = code & 0xfff; 132 } 133 134 /** Load Protracker patterns. 135 * 136 * @param f File to read from 137 * @param module Module being loaded to 138 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error. 139 */ 140 static int protracker_load_patterns(FILE *f, trackmod_module_t *module) 141 { 142 size_t cells; 143 size_t i, j; 144 int rc; 145 size_t nread; 146 uint32_t *buf = NULL; 147 148 cells = module->channels * protracker_pattern_rows; 149 buf = calloc(sizeof(uint32_t), cells); 150 151 if (buf == NULL) { 152 rc = ENOMEM; 153 goto error; 154 } 155 156 for (i = 0; i < module->patterns; i++) { 157 module->pattern[i].rows = protracker_pattern_rows; 158 module->pattern[i].channels = module->channels; 159 module->pattern[i].data = calloc(sizeof(trackmod_cell_t), cells); 160 if (module->pattern[i].data == NULL) { 161 rc = ENOMEM; 162 goto error; 163 } 164 165 nread = fread(buf, sizeof(uint32_t), cells, f); 166 if (nread != cells) { 167 printf("Error reading pattern.\n"); 168 rc = EIO; 169 goto error; 170 } 171 172 /* Decode cells */ 173 for (j = 0; j < cells; j++) { 174 protracker_decode_cell(buf[j], 175 &module->pattern[i].data[j]); 176 } 177 } 178 179 free(buf); 180 return EOK; 181 error: 182 free(buf); 183 return rc; 184 } 185 186 /** Load protracker samples. 187 * 188 * @param f File being read from 189 * @param sample Sample header 190 * @param module Module being loaded to 191 * @return EOk on success, ENOMEM if out of memory, EIO on I/O error. 192 */ 193 static int protracker_load_samples(FILE *f, protracker_smp_t *smp, 194 trackmod_module_t *module) 195 { 196 int rc; 197 size_t i; 198 uint8_t ftval; 199 size_t nread; 200 trackmod_sample_t *sample; 201 202 for (i = 0; i < module->instrs; i++) { 203 module->instr[i].samples = 1; 204 module->instr[i].sample = calloc(1, sizeof(trackmod_sample_t)); 205 if (module->instr[i].sample == NULL) { 206 printf("Error allocating sample.\n"); 207 rc = ENOMEM; 208 goto error; 209 } 210 211 sample = &module->instr[i].sample[0]; 212 sample->length = 213 uint16_t_be2host(smp[i].length) * 2; 214 sample->bytes_smp = 1; 215 sample->data = calloc(1, sample->length); 216 if (sample->data == NULL) { 217 printf("Error allocating sample.\n"); 218 rc = ENOMEM; 219 goto error; 220 } 221 222 nread = fread(sample->data, 1, sample->length, f); 223 if (nread != sample->length) { 224 printf("Error reading sample.\n"); 225 rc = EIO; 226 goto error; 227 } 228 229 sample->def_vol = smp[i].def_vol; 230 231 sample->loop_start = 232 uint16_t_be2host(smp[i].loop_start) * 2; 233 sample->loop_len = 234 uint16_t_be2host(smp[i].loop_len) * 2; 235 if (sample->loop_len <= 2) 236 sample->loop_type = tl_no_loop; 237 else 238 sample->loop_type = tl_forward_loop; 239 240 /* Finetune is a 4-bit signed value. */ 241 ftval = smp[i].finetune & 0x0f; 242 sample->finetune = 243 (ftval & 0x8) ? (ftval & 0x7) - 8 : ftval; 244 } 245 246 return EOK; 247 error: 248 return rc; 249 } 250 115 251 /** Load protracker module. 116 252 * … … 128 264 protracker_order_list_t *order_list; 129 265 protracker_smp_t *sample; 130 size_t nread;131 266 size_t samples; 132 267 size_t channels; 133 268 size_t patterns; 134 size_t cells;135 size_t i, j;269 size_t i; 270 size_t nread; 136 271 int rc; 137 272 … … 192 327 module->channels = channels; 193 328 194 module-> samples = samples;195 module-> sample = calloc(sizeof(trackmod_sample_t), samples);196 if (module-> sample== NULL) {329 module->instrs = samples; 330 module->instr = calloc(sizeof(trackmod_instr_t), samples); 331 if (module->instr == NULL) { 197 332 printf("Out of memory.\n"); 198 333 rc = ENOMEM; … … 221 356 } 222 357 358 /* The 'mark' byte may or may not contain a valid restart position */ 359 if (order_list->mark < order_list->order_list_len) { 360 module->restart_pos = order_list->mark; 361 } 362 223 363 /* Load patterns */ 224 225 cells = channels * protracker_pattern_rows; 226 227 for (i = 0; i < patterns; i++) { 228 module->pattern[i].rows = protracker_pattern_rows; 229 module->pattern[i].channels = channels; 230 module->pattern[i].data = calloc(sizeof(uint32_t), cells); 231 232 nread = fread(module->pattern[i].data, 233 sizeof(uint32_t), cells, f); 234 if (nread != cells) { 235 printf("Error reading pattern.\n"); 236 rc = EIO; 237 goto error; 238 } 239 240 /* Convert byte order */ 241 for (j = 0; j < cells; j++) { 242 module->pattern[i].data[j] = uint32_t_be2host( 243 module->pattern[i].data[j]); 244 } 245 } 364 rc = protracker_load_patterns(f, module); 365 if (rc != EOK) 366 goto error; 246 367 247 368 /* Load samples */ 248 for (i = 0; i < samples; i++) { 249 module->sample[i].length = 250 uint16_t_be2host(sample[i].length) * 2; 251 module->sample[i].data = calloc(1, module->sample[i].length); 252 if (module->sample[i].data == NULL) { 253 printf("Error allocating sample.\n"); 254 rc = ENOMEM; 255 goto error; 256 } 257 258 nread = fread(module->sample[i].data, 1, module->sample[i].length, 259 f); 260 if (nread != module->sample[i].length) { 261 printf("Error reading sample.\n"); 262 rc = EIO; 263 goto error; 264 } 265 266 module->sample[i].def_vol = sample[i].def_vol; 267 module->sample[i].loop_start = 268 uint16_t_be2host(sample[i].loop_start) * 2; 269 module->sample[i].loop_len = 270 uint16_t_be2host(sample[i].loop_len) * 2; 271 if (module->sample[i].loop_len <= 2) 272 module->sample[i].loop_len = 0; 273 } 369 rc = protracker_load_samples(f, sample, module); 370 if (rc != EOK) 371 goto error; 274 372 275 373 (void) fclose(f); 374 375 module->def_bpm = protracker_def_bpm; 376 module->def_tpr = protracker_def_tpr; 276 377 277 378 *rmodule = module; -
uspace/lib/trackmod/trackmod.c
ref3da5a rb412168 40 40 41 41 #include "macros.h" 42 #include "protracker.h" 42 43 #include "trackmod.h" 44 #include "xm.h" 43 45 44 46 /** Tunables */ … … 52 54 base_clock = 8363 * 428, 53 55 /** Maximum sample volume */ 54 vol_max = 6 3,55 /** Default TPR*/56 def_tpr = 6,57 /** Default BPM*/58 def_bpm = 12556 vol_max = 64, 57 /** Minimum period */ 58 period_min = 113, 59 /** Maxium period */ 60 period_max = 856 59 61 }; 60 62 63 /** Table for finetune computation. 64 * 65 * Finetune is a number ft in [-8 .. 7]. The pitch should be adjusted by 66 * ft/8 semitones. To adjust pitch by 1/8 semitone down we can mutiply the 67 * period by 2^(1/12/8) =. 1.0072, one semitone up: 2^-(1/12/8) =. 0.9928, 68 * to adjust by ft/8 semitones, multiply by 2^(-ft/12/8). 69 * 70 * finetune_factor[ft] := 10000 * 2^(-ft/12/8) 71 * res_period = clip(period * fineture_factor[ft+8] / 10000) 72 */ 73 static unsigned finetune_factor[16] = { 74 10595, 10518, 10443, 10368, 10293, 10219, 10145, 10072, 75 10000, 9928, 9857, 9786, 9715, 9645, 9576, 9507 76 }; 77 78 static unsigned period_table[12 * 8] = { 79 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814, 80 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725, 81 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646, 82 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575, 83 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513, 84 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457 85 }; 86 61 87 static size_t trackmod_get_next_ord_idx(trackmod_modplay_t *); 62 88 … … 70 96 } 71 97 98 /** Destroy instrument. 99 * 100 * @param instr Intrument 101 */ 102 static void trackmod_instr_destroy(trackmod_instr_t *instr) 103 { 104 size_t i; 105 106 for (i = 0; i < instr->samples; i++) 107 trackmod_sample_destroy(&instr->sample[i]); 108 } 109 72 110 /** Destroy pattern. 73 111 * … … 97 135 98 136 /* Destroy samples */ 99 if (module-> sample!= NULL) {100 for (i = 0; i < module-> samples; i++)101 trackmod_ sample_destroy(&module->sample[i]);102 free(module-> sample);137 if (module->instr != NULL) { 138 for (i = 0; i < module->instrs; i++) 139 trackmod_instr_destroy(&module->instr[i]); 140 free(module->instr); 103 141 } 104 142 … … 114 152 } 115 153 154 int trackmod_module_load(char *fname, trackmod_module_t **rmodule) 155 { 156 int rc; 157 158 rc = trackmod_xm_load(fname, rmodule); 159 if (rc == EOK) 160 return EOK; 161 162 rc = trackmod_protracker_load(fname, rmodule); 163 return rc; 164 } 165 166 116 167 /** Return current pattern. 117 168 * … … 137 188 size_t row, size_t channel, trackmod_cell_t *cell) 138 189 { 139 uint32_t code; 140 141 code = pattern->data[row * pattern->channels + channel]; 142 cell->period = (code >> (4 * 4)) & 0xfff; 143 cell->sample = (((code >> (7 * 4)) & 0xf) << 4) | 144 ((code >> (3 * 4)) & 0xf); 145 cell->effect = code & 0xfff; 146 } 147 148 /** Process note (period, sample index) 190 *cell = pattern->data[row * pattern->channels + channel]; 191 } 192 193 /** Compute floor(a / b), and the remainder. 194 * 195 * Unlike standard integer division this rounds towars negative infinity, 196 * not towards zero. 197 * 198 * @param a Dividend 199 * @param b Divisor 200 * @param quot Place to store 'quotient' (floor (a/b)) 201 * @param rem Place to store 'remainder' (a - floor(a/b) * b) 202 */ 203 static void divmod_floor(int a, int b, int *quot, int *rem) 204 { 205 if (b < 0) { 206 a = -a; 207 b = -b; 208 } 209 210 if (a >= 0) { 211 *quot = a / b; 212 *rem = a % b; 213 } else { 214 *quot = - (-a + (b - 1)) / b; 215 *rem = a - (*quot * b); 216 } 217 } 218 219 /** Process note (period) 149 220 * 150 221 * @param modplay Module playback … … 156 227 { 157 228 trackmod_chan_t *chan = &modplay->chan[i]; 158 size_t smpidx; 159 160 smpidx = (cell->sample - 1) % modplay->module->samples; 161 chan->sample = &modplay->module->sample[smpidx]; 229 int period; 230 int pitch; 231 int octave; 232 int opitch; 233 234 if (chan->sample == NULL) 235 return; 236 237 if (cell->period == 0) { 238 pitch = 8 * (cell->note + chan->sample->rel_note) + 239 chan->sample->finetune; 240 divmod_floor(pitch, 8 * 12, &octave, &opitch); 241 242 if (octave >= 0) 243 period = period_table[opitch] * 8 / (1 << octave); 244 else 245 period = period_table[opitch] * 8 * (1 << (-octave)); 246 } else { 247 period = cell->period; 248 period = period * 249 finetune_factor[chan->sample->finetune + 8] / 10000; 250 if (period > period_max) 251 period = period_max; 252 if (period < period_min) 253 period = period_min; 254 } 255 256 chan->period_new = period; 257 } 258 259 /** Process instrument number (this is what triggers the note playback) 260 * 261 * @param modplay Module playback 262 * @param i Channel number 263 * @param cell Cell 264 */ 265 static void trackmod_process_instr(trackmod_modplay_t *modplay, size_t i, 266 trackmod_cell_t *cell) 267 { 268 trackmod_chan_t *chan = &modplay->chan[i]; 269 trackmod_instr_t *instr; 270 size_t iidx; 271 size_t sidx; 272 273 if (cell->instr == 0) 274 return; 275 276 iidx = (cell->instr - 1) % modplay->module->instrs; 277 instr = &modplay->module->instr[iidx]; 278 sidx = instr->key_smp[cell->note] % instr->samples; 279 chan->sample = &instr->sample[sidx]; 162 280 chan->smp_pos = 0; 163 281 chan->lsmp = 0; 164 chan->period = cell->period; 282 165 283 chan->volume = modplay->chan[i].sample->def_vol; 284 } 285 286 /** Process keyoff note 287 * 288 * @param modplay Module playback 289 * @param i Channel number 290 * @param cell Cell 291 */ 292 static void trackmod_process_keyoff_note(trackmod_modplay_t *modplay, size_t i) 293 { 294 trackmod_chan_t *chan = &modplay->chan[i]; 295 296 chan->sample = NULL; 297 chan->period = 0; 298 chan->smp_pos = 0; 299 chan->lsmp = 0; 166 300 } 167 301 … … 175 309 uint8_t param) 176 310 { 177 modplay->chan[chan].volume = param & vol_max;311 modplay->chan[chan].volume = param % (vol_max + 1); 178 312 } 179 313 … … 189 323 size_t next_idx; 190 324 trackmod_pattern_t *next_pat; 325 unsigned row; 326 327 /* Strangely the parameter is BCD */ 328 row = (param >> 4) * 10 + (param & 0xf); 191 329 192 330 next_idx = trackmod_get_next_ord_idx(modplay); … … 194 332 195 333 modplay->pat_break = true; 196 modplay->pat_break_row = param% next_pat->rows;334 modplay->pat_break_row = row % next_pat->rows; 197 335 } 198 336 … … 212 350 } 213 351 352 /** Process Fine volume slide down effect. 353 * 354 * @param modplay Module playback 355 * @param chan Channel number 356 * @param param Effect parameter 357 */ 358 static void trackmod_effect_fine_vol_slide_down(trackmod_modplay_t *modplay, 359 size_t chan, uint8_t param) 360 { 361 int nv; 362 363 nv = modplay->chan[chan].volume - param; 364 if (nv < 0) 365 nv = 0; 366 modplay->chan[chan].volume = nv; 367 } 368 369 /** Process Fine volume slide up effect. 370 * 371 * @param modplay Module playback 372 * @param chan Channel number 373 * @param param Effect parameter 374 */ 375 static void trackmod_effect_fine_vol_slide_up(trackmod_modplay_t *modplay, 376 size_t chan, uint8_t param) 377 { 378 int nv; 379 380 nv = modplay->chan[chan].volume + param; 381 if (nv > vol_max) 382 nv = vol_max; 383 modplay->chan[chan].volume = nv; 384 } 385 386 /** Process Volume slide effect. 387 * 388 * @param modplay Module playback 389 * @param chan Channel number 390 * @param param Effect parameter 391 */ 392 static void trackmod_effect_vol_slide(trackmod_modplay_t *modplay, 393 size_t chan, uint8_t param) 394 { 395 if ((param & 0xf0) != 0) 396 modplay->chan[chan].vol_slide = param >> 4; 397 else 398 modplay->chan[chan].vol_slide = -(int)(param & 0xf); 399 } 400 401 /** Process Volume slide down effect. 402 * 403 * @param modplay Module playback 404 * @param chan Channel number 405 * @param param Effect parameter 406 */ 407 static void trackmod_effect_vol_slide_down(trackmod_modplay_t *modplay, 408 size_t chan, uint8_t param4) 409 { 410 modplay->chan[chan].vol_slide = -(int)param4; 411 } 412 413 /** Process Volume slide up effect. 414 * 415 * @param modplay Module playback 416 * @param chan Channel number 417 * @param param Effect parameter 418 */ 419 static void trackmod_effect_vol_slide_up(trackmod_modplay_t *modplay, 420 size_t chan, uint8_t param4) 421 { 422 modplay->chan[chan].vol_slide = param4; 423 } 424 425 /** Process Fine portamento down effect. 426 * 427 * @param modplay Module playback 428 * @param chan Channel number 429 * @param param Effect parameter 430 */ 431 static void trackmod_effect_fine_porta_down(trackmod_modplay_t *modplay, 432 size_t chan, uint8_t param) 433 { 434 int np; 435 436 np = modplay->chan[chan].period + param; 437 if (np > period_max) 438 np = period_max; 439 modplay->chan[chan].period = np; 440 } 441 442 /** Process Fine portamento up effect. 443 * 444 * @param modplay Module playback 445 * @param chan Channel number 446 * @param param Effect parameter 447 */ 448 static void trackmod_effect_fine_porta_up(trackmod_modplay_t *modplay, 449 size_t chan, uint8_t param) 450 { 451 int np; 452 453 np = modplay->chan[chan].period - param; 454 if (np < period_min) 455 np = period_min; 456 modplay->chan[chan].period = np; 457 } 458 459 /** Process Portamento down effect. 460 * 461 * @param modplay Module playback 462 * @param chan Channel number 463 * @param param Effect parameter 464 */ 465 static void trackmod_effect_porta_down(trackmod_modplay_t *modplay, 466 size_t chan, uint8_t param) 467 { 468 modplay->chan[chan].portamento = -(int)param; 469 } 470 471 /** Process Portamento up effect. 472 * 473 * @param modplay Module playback 474 * @param chan Channel number 475 * @param param Effect parameter 476 */ 477 static void trackmod_effect_porta_up(trackmod_modplay_t *modplay, 478 size_t chan, uint8_t param) 479 { 480 modplay->chan[chan].portamento = param; 481 } 482 483 /** Process Tone portamento effect. 484 * 485 * @param modplay Module playback 486 * @param chan Channel number 487 * @param param Effect parameter 488 */ 489 static void trackmod_effect_tone_porta(trackmod_modplay_t *modplay, 490 size_t chan, uint8_t param) 491 { 492 /* Set up tone portamento effect */ 493 modplay->chan[chan].portamento = param; 494 if (modplay->chan[chan].period_new != 0) 495 modplay->chan[chan].period_tgt = modplay->chan[chan].period_new; 496 497 /* Prevent going directly to new period */ 498 modplay->chan[chan].period_new = 0; 499 } 500 501 /** Process volume column. 502 * 503 * @param modplay Module playback 504 * @param chan Channel number 505 * @param cell Cell 506 */ 507 static void trackmod_process_volume(trackmod_modplay_t *modplay, size_t chan, 508 trackmod_cell_t *cell) 509 { 510 uint8_t param4; 511 512 if (cell->volume >= 0x10 && cell->volume <= 0x10 + vol_max) 513 trackmod_effect_set_volume(modplay, chan, cell->volume - 0x10); 514 515 param4 = cell->volume & 0xf; 516 517 switch (cell->volume & 0xf0) { 518 case 0x60: 519 trackmod_effect_vol_slide_down(modplay, chan, param4); 520 break; 521 case 0x70: 522 trackmod_effect_vol_slide_up(modplay, chan, param4); 523 break; 524 case 0x80: 525 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 526 break; 527 case 0x90: 528 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 529 break; 530 case 0xf0: 531 trackmod_effect_tone_porta(modplay, chan, param4 << 4); 532 break; 533 default: 534 break; 535 } 536 } 537 214 538 /** Process effect. 215 539 * … … 222 546 { 223 547 uint8_t param8; 548 uint8_t param4; 224 549 225 550 param8 = cell->effect & 0xff; 226 551 227 552 switch (cell->effect & 0xf00) { 553 case 0x100: 554 trackmod_effect_porta_up(modplay, chan, param8); 555 break; 556 case 0x200: 557 trackmod_effect_porta_down(modplay, chan, param8); 558 break; 559 case 0x300: 560 trackmod_effect_tone_porta(modplay, chan, param8); 561 break; 562 case 0xa00: 563 trackmod_effect_vol_slide(modplay, chan, param8); 564 break; 228 565 case 0xc00: 229 566 trackmod_effect_set_volume(modplay, chan, param8); … … 238 575 break; 239 576 } 577 578 param4 = cell->effect & 0xf; 579 580 switch (cell->effect & 0xff0) { 581 case 0xe10: 582 trackmod_effect_fine_porta_up(modplay, chan, param4); 583 break; 584 case 0xe20: 585 trackmod_effect_fine_porta_down(modplay, chan, param4); 586 break; 587 case 0xea0: 588 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 589 break; 590 case 0xeb0: 591 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 592 break; 593 } 240 594 } 241 595 … … 249 603 trackmod_cell_t *cell) 250 604 { 251 if (cell->period != 0 && cell->sample != 0) 605 modplay->chan[chan].period_new = 0; 606 607 trackmod_process_instr(modplay, chan, cell); 608 609 if (cell->period != 0 || (cell->note != 0 && cell->note != keyoff_note)) { 252 610 trackmod_process_note(modplay, chan, cell); 253 611 } else if (cell->note == keyoff_note && cell->instr == 0) { 612 trackmod_process_keyoff_note(modplay, chan); 613 } 614 615 trackmod_process_volume(modplay, chan, cell); 254 616 trackmod_process_effect(modplay, chan, cell); 617 618 if (modplay->chan[chan].period_new != 0) 619 modplay->chan[chan].period = modplay->chan[chan].period_new; 255 620 } 256 621 … … 267 632 pattern = trackmod_cur_pattern(modplay); 268 633 634 if (modplay->debug) 635 printf("%02zx: ", modplay->row); 636 269 637 for (i = 0; i < modplay->module->channels; i++) { 270 638 trackmod_pattern_get_cell(pattern, modplay->row, i, &cell); 271 if (modplay->debug) 272 printf("%4d %02x %03x |", cell.period, cell.sample, cell.effect); 639 640 if (modplay->debug) { 641 printf("%4d %02x %02x %03x |", cell.period ? 642 cell.period : cell.note, cell.instr, 643 cell.volume, cell.effect); 644 } 645 273 646 trackmod_process_cell(modplay, i, &cell); 274 647 } … … 289 662 ord_idx = modplay->ord_idx + 1; 290 663 if (ord_idx >= modplay->module->ord_list_len) 291 ord_idx = 0; /* XXX */664 ord_idx = modplay->module->restart_pos; 292 665 293 666 return ord_idx; … … 313 686 } 314 687 688 /** Clear effects at end of row. */ 689 static void trackmod_clear_effects(trackmod_modplay_t *modplay) 690 { 691 size_t i; 692 693 for (i = 0; i < modplay->module->channels; i++) { 694 modplay->chan[i].vol_slide = 0; 695 modplay->chan[i].portamento = 0; 696 } 697 } 698 699 /** Process effects at beginning of tick. */ 700 static void trackmod_process_tick(trackmod_modplay_t *modplay) 701 { 702 trackmod_chan_t *chan; 703 size_t i; 704 int nv; 705 int np; 706 707 for (i = 0; i < modplay->module->channels; i++) { 708 chan = &modplay->chan[i]; 709 710 /* Volume slides */ 711 nv = (int)chan->volume + chan->vol_slide; 712 if (nv < 0) 713 nv = 0; 714 if (nv > vol_max) 715 nv = vol_max; 716 717 chan->volume = nv; 718 719 /* Portamentos */ 720 if (chan->period_tgt == 0) { 721 /* Up or down portamento */ 722 np = (int)chan->period - chan->portamento; 723 } else { 724 /* Tone portamento */ 725 if (chan->period_tgt < chan->period) 726 np = max((int)chan->period_tgt, (int)chan->period - chan->portamento); 727 else 728 np = min((int)chan->period_tgt, (int)chan->period + chan->portamento); 729 } 730 731 /* if (np < period_min) 732 np = period_min; 733 if (np > period_max) 734 np = period_max; 735 */ 736 modplay->chan[i].period = np; 737 } 738 } 739 315 740 /** Advance to next row. 316 741 * … … 320 745 { 321 746 trackmod_pattern_t *pattern; 747 748 /* Clear effect state at end of row */ 749 trackmod_clear_effects(modplay); 322 750 323 751 pattern = trackmod_cur_pattern(modplay); … … 328 756 trackmod_next_pattern(modplay); 329 757 758 trackmod_process_tick(modplay); 330 759 trackmod_process_row(modplay); 331 760 } … … 341 770 if (modplay->tick >= modplay->tpr) 342 771 trackmod_next_row(modplay); 772 else 773 trackmod_process_tick(modplay); 343 774 } 344 775 … … 366 797 modplay->smp = 0; 367 798 368 modplay->tpr = def_tpr;369 modplay->bpm = def_bpm;799 modplay->tpr = module->def_tpr; 800 modplay->bpm = module->def_bpm; 370 801 371 802 modplay->chan = calloc(module->channels, … … 374 805 goto error; 375 806 807 trackmod_process_tick(modplay); 376 808 trackmod_process_row(modplay); 377 809 … … 416 848 } 417 849 850 /** Get sample frame. 851 * 852 * Get frame at the specified sample position. 853 * 854 * @param sample Sample 855 * @param pos Position (frame index) 856 * @return Frame value 857 */ 858 int trackmod_sample_get_frame(trackmod_sample_t *sample, size_t pos) 859 { 860 int8_t *i8p; 861 int16_t *i16p; 862 863 if (sample->bytes_smp == 1) { 864 i8p = (int8_t *)sample->data; 865 return i8p[pos]; 866 } else { 867 /* chan->sample->bytes_smp == 2 */ 868 i16p = (int16_t *)sample->data; 869 return i16p[pos] / 256; /* XXX Retain full precision */ 870 } 871 } 872 418 873 /** Advance sample position to next frame. 419 874 * … … 422 877 static void chan_smp_next_frame(trackmod_chan_t *chan) 423 878 { 424 chan->lsmp = chan->sample->data[chan->smp_pos];879 chan->lsmp = trackmod_sample_get_frame(chan->sample, chan->smp_pos); 425 880 ++chan->smp_pos; 426 881 427 if (chan->sample->loop_len == 0) { 428 /* No looping */ 882 switch (chan->sample->loop_type) { 883 case tl_pingpong_loop: 884 /** XXX Pingpong loop */ 885 case tl_no_loop: 886 /* No loop */ 429 887 if (chan->smp_pos >= chan->sample->length) { 430 888 chan->sample = NULL; 431 889 chan->smp_pos = 0; 432 890 } 433 } else { 434 /** Looping */ 891 break; 892 case tl_forward_loop: 893 /** Forward loop */ 435 894 if (chan->smp_pos >= chan->sample->loop_start + 436 895 chan->sample->loop_len) { … … 455 914 trackmod_chan_t *chan = &modplay->chan[cidx]; 456 915 457 if (chan->sample == NULL )916 if (chan->sample == NULL || chan->period == 0) 458 917 return 0; 459 918 … … 464 923 */ 465 924 sl = (int)chan->lsmp * amp_factor * chan->volume / vol_max; 466 sn = (int) chan->sample->data[chan->smp_pos] * amp_factor*467 chan->volume / vol_max;925 sn = (int)trackmod_sample_get_frame(chan->sample, chan->smp_pos) * 926 amp_factor * chan->volume / vol_max; 468 927 469 928 period = (int)chan->period; -
uspace/lib/trackmod/trackmod.h
ref3da5a rb412168 40 40 41 41 extern trackmod_module_t *trackmod_module_new(void); 42 extern int trackmod_module_load(char *, trackmod_module_t **); 42 43 extern void trackmod_module_destroy(trackmod_module_t *); 43 44 extern int trackmod_modplay_create(trackmod_module_t *, unsigned, … … 45 46 extern void trackmod_modplay_destroy(trackmod_modplay_t *); 46 47 extern void trackmod_modplay_get_samples(trackmod_modplay_t *, void *, size_t); 48 extern int trackmod_sample_get_frame(trackmod_sample_t *, size_t); 47 49 48 50 #endif -
uspace/lib/trackmod/types/protracker.h
ref3da5a rb412168 47 47 protracker_olist_len = 128, 48 48 /** Number of rows in a pattern */ 49 protracker_pattern_rows = 64 49 protracker_pattern_rows = 64, 50 /** Default TPR */ 51 protracker_def_tpr = 6, 52 /** Default BPM */ 53 protracker_def_bpm = 125 50 54 }; 51 55 -
uspace/lib/trackmod/types/trackmod.h
ref3da5a rb412168 41 41 #include <stdint.h> 42 42 43 enum { 44 max_key = 96, 45 keyoff_note = 97 46 }; 47 48 typedef enum { 49 /** No loop */ 50 tl_no_loop, 51 /** Forward loop */ 52 tl_forward_loop, 53 /** Pingpong loop */ 54 tl_pingpong_loop 55 } trackmod_looptype_t; 56 43 57 /** Sample */ 44 58 typedef struct { 45 59 /** Length in frames */ 46 60 size_t length; 61 /** Bytes per sample */ 62 size_t bytes_smp; 47 63 /** Sample data */ 48 int8_t *data; 64 void *data; 65 /** Loop type */ 66 trackmod_looptype_t loop_type; 49 67 /** Loop start position in frames */ 50 68 size_t loop_start; 51 /** Loop length in frames or 0 - no looping*/69 /** Loop length in frames (> 0) */ 52 70 size_t loop_len; 53 71 /** Default volume (0..63) */ 54 72 uint8_t def_vol; 73 /** Relative note */ 74 int rel_note; 75 /** Finetune value (-8..7) in 1/8 semitones */ 76 int finetune; 55 77 } trackmod_sample_t; 78 79 /** Instrument */ 80 typedef struct { 81 /** Number of samples */ 82 size_t samples; 83 /** Samples */ 84 trackmod_sample_t *sample; 85 /** Sample index for each key */ 86 int key_smp[max_key]; 87 } trackmod_instr_t; 88 89 /** Pattern cell */ 90 typedef struct { 91 /** Note */ 92 unsigned note; 93 /** Sample period */ 94 unsigned period; 95 /** Instrument number */ 96 unsigned instr; 97 /** Volume */ 98 uint8_t volume; 99 /** Effect */ 100 uint16_t effect; 101 } trackmod_cell_t; 56 102 57 103 /** Pattern */ … … 62 108 size_t channels; 63 109 /** Pattern data */ 64 uint32_t *data;110 trackmod_cell_t *data; 65 111 } trackmod_pattern_t; 66 112 … … 70 116 size_t channels; 71 117 /** Number of samples */ 72 size_t samples;73 /** Samples */74 trackmod_ sample_t *sample;118 size_t instrs; 119 /** Instruments */ 120 trackmod_instr_t *instr; 75 121 /** Number of patterns */ 76 122 size_t patterns; … … 81 127 /** Order list */ 82 128 size_t *ord_list; 129 /** Restart pos */ 130 size_t restart_pos; 131 /** Default BPM */ 132 unsigned def_bpm; 133 /** Default TPR */ 134 unsigned def_tpr; 83 135 } trackmod_module_t; 84 136 … … 92 144 /** Sample position (clock ticks within frame) */ 93 145 size_t smp_clk; 94 /** Period */146 /** Current period */ 95 147 unsigned period; 148 /** Period after note was processed, zero if no note */ 149 unsigned period_new; 96 150 /** Volume */ 97 151 uint8_t volume; 152 /** Volume slide amount */ 153 int vol_slide; 154 /** Portamento amount (positive for tone and up portamento, 155 * negative for down portamento. */ 156 int portamento; 157 /** Tone portamento target period. */ 158 unsigned period_tgt; 98 159 } trackmod_chan_t; 99 160 … … 132 193 } trackmod_modplay_t; 133 194 134 /** Pattern cell (decoded) */135 typedef struct {136 /** Sample period */137 unsigned period;138 /** Sample number */139 unsigned sample;140 /** Effect */141 unsigned effect;142 } trackmod_cell_t;143 144 195 #endif 145 196
Note:
See TracChangeset
for help on using the changeset viewer.
