mirror of
https://github.com/fadden/6502bench.git
synced 2024-09-10 13:54:52 +00:00
The implementation was mapping labels to addresses, then formatting inline data at the matching address. This may be incorrect when there are multiple sections of the file mapped to the same address. The correct approach is to record the offsets of the matching labels, and then do an address-to-offset translation for each JSR. Also, show a note in the Info window when a JSR has been marked no-continue by an extension script. Also, updated Daily Tips.
180 lines
6.3 KiB
C#
180 lines
6.3 KiB
C#
/*
|
|
* Copyright 2021 faddenSoft
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Web.Script.Serialization;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace SourceGen {
|
|
/// <summary>
|
|
/// Holds the collection of daily tips and associated images.
|
|
/// </summary>
|
|
public class DailyTips {
|
|
private static string TIPS_FILE = "daily-tips.json";
|
|
private static string TIPS_DIR = "Tips";
|
|
|
|
/// <summary>
|
|
/// A tip is a text string with an optional bitmap.
|
|
/// </summary>
|
|
public class Tip {
|
|
public string Text { get; private set; }
|
|
public string ImageFileName { get; private set; }
|
|
public BitmapSource Bitmap { get; }
|
|
|
|
public Tip(string text, string imageFileName) {
|
|
Text = text;
|
|
ImageFileName = imageFileName;
|
|
|
|
if (!string.IsNullOrEmpty(imageFileName)) {
|
|
Bitmap = LoadImage(imageFileName);
|
|
}
|
|
}
|
|
|
|
private static BitmapSource LoadImage(string fileName) {
|
|
string pathName = RuntimeDataAccess.GetPathName(TIPS_DIR);
|
|
pathName = Path.Combine(pathName, fileName);
|
|
try {
|
|
BitmapImage bitmap = new BitmapImage();
|
|
bitmap.BeginInit();
|
|
bitmap.UriSource = new Uri(pathName);
|
|
bitmap.CacheOption = BitmapCacheOption.OnLoad; // don't hold file open
|
|
bitmap.EndInit();
|
|
return bitmap;
|
|
} catch (Exception ex) {
|
|
Debug.WriteLine("Unable to load bitmap '" + fileName + "': " + ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static BitmapSource LoadImage1(string fileName) {
|
|
string pathName = RuntimeDataAccess.GetPathName(TIPS_DIR);
|
|
pathName = Path.Combine(pathName, fileName);
|
|
try {
|
|
// From "How to: Encode and Decode a PNG Image".
|
|
// Note: this holds the file open (try deleting the file).
|
|
BitmapSource bitmapSource;
|
|
Stream imageStreamSource = new FileStream(pathName, FileMode.Open,
|
|
FileAccess.Read, FileShare.Read);
|
|
PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource,
|
|
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
|
|
bitmapSource = decoder.Frames[0];
|
|
//imageStreamSource.Dispose(); // image becomes blank
|
|
return bitmapSource;
|
|
} catch (IOException ex) {
|
|
Debug.WriteLine("Unable to load image '" + fileName + "': " + ex);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// List of tips.
|
|
/// </summary>
|
|
private List<Tip> mTips = new List<Tip>();
|
|
|
|
public DailyTips() { }
|
|
|
|
/// <summary>
|
|
/// Loads the list of tips. The list will always have at least one element.
|
|
/// </summary>
|
|
public bool Load() {
|
|
mTips.Clear();
|
|
if (!DoLoadTips()) {
|
|
mTips.Add(new Tip(Res.Strings.TIPS_NOT_AVAILABLE, null));
|
|
return false;
|
|
} else {
|
|
Debug.WriteLine("Loaded " + mTips.Count + " tips");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public int DailyNumber {
|
|
get {
|
|
// We show a different tip every day by taking the day-of-year value and
|
|
// modding it by the number of tips we have.
|
|
if (mTips.Count > 0) {
|
|
DateTime now = DateTime.Now;
|
|
int dayIndex = now.Year * 365 + now.DayOfYear;
|
|
return dayIndex % mTips.Count;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Count { get { return mTips.Count; } }
|
|
|
|
/// <summary>
|
|
/// Returns the Nth tip.
|
|
/// </summary>
|
|
public Tip Get(int index) {
|
|
if (mTips.Count == 0) {
|
|
// Load tips, or at least generate a "not available" entry.
|
|
Load();
|
|
}
|
|
if (index < 0 || index >= mTips.Count) {
|
|
Debug.WriteLine("Invalid request for tip " + index);
|
|
return mTips[0];
|
|
}
|
|
|
|
return mTips[index];
|
|
}
|
|
|
|
|
|
[Serializable]
|
|
internal class SerTip {
|
|
public string Text { get; set; }
|
|
public string Image { get; set; }
|
|
}
|
|
internal class SerTipFile {
|
|
public List<SerTip> Tips { get; set; }
|
|
}
|
|
|
|
private bool DoLoadTips() {
|
|
string pathName = RuntimeDataAccess.GetPathName(TIPS_DIR);
|
|
pathName = Path.Combine(pathName, TIPS_FILE);
|
|
string cereal;
|
|
try {
|
|
cereal = File.ReadAllText(pathName);
|
|
} catch (IOException ex) {
|
|
Debug.WriteLine("Failed reading tip file '" + pathName + "': " + ex.Message);
|
|
return false;
|
|
}
|
|
|
|
JavaScriptSerializer ser = new JavaScriptSerializer();
|
|
SerTipFile tipFile;
|
|
try {
|
|
tipFile = ser.Deserialize<SerTipFile>(cereal);
|
|
} catch (Exception ex) {
|
|
Debug.WriteLine("Failed deserializing tip JSON: " + ex.Message);
|
|
return false;
|
|
}
|
|
if (tipFile == null) {
|
|
Debug.WriteLine("Failed to find tip list");
|
|
return false;
|
|
}
|
|
|
|
foreach (SerTip serTip in tipFile.Tips) {
|
|
mTips.Add(new Tip(serTip.Text, serTip.Image));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|