Allow address input (#78)

Allow address input
This commit is contained in:
Will Scullin 2021-04-25 09:37:55 -07:00 committed by GitHub
parent f28641df32
commit 66d8fdc2c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 19 deletions

View File

@ -17,9 +17,6 @@ jobs:
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- uses: webfactory/ssh-agent@v0.5.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: npm install, build, and test - name: npm install, build, and test
run: | run: |
npm ci npm ci

View File

@ -240,11 +240,15 @@
</table> </table>
<form action="#"> <form action="#">
<input type="file" id="local_file" /> <input type="file" id="local_file" />
<div id="local_file_address_input" style="display: none">
$
<input id="local_file_address" />
</div>
</form> </form>
</main> </main>
<footer class="modal__footer"> <footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button> <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button>
<button class="modal__btn" onclick="Apple2.doLoad()" aria-label="Open the selected disk">Open</button> <button class="modal__btn" onclick="Apple2.doLoad(event)" aria-label="Open the selected disk">Open</button>
</footer> </footer>
</div> </div>
</div> </div>

View File

@ -249,11 +249,15 @@
</table> </table>
<form action="#"> <form action="#">
<input type="file" id="local_file" /> <input type="file" id="local_file" />
<div id="local_file_address_input" style="display: none">
$
<input id="local_file_address" />
</div>
</form> </form>
</main> </main>
<footer class="modal__footer"> <footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button> <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button>
<button class="modal__btn" onclick="Apple2.doLoad()" aria-label="Open the selected disk">Open</button> <button class="modal__btn" onclick="Apple2.doLoad(event)" aria-label="Open the selected disk">Open</button>
</footer> </footer>
</div> </div>
</div> </div>

View File

@ -517,6 +517,8 @@ export class HiresPageGL implements HiresPage {
} }
} else if (bank === 0) { } else if (bank === 0) {
const hbs = val & 0x80; const hbs = val & 0x80;
const lastCol = col === 39;
const cropLastPixel = hbs && lastCol;
const dx = col * 14; const dx = col * 14;
let offset = dx * 4 + dy * 560 * 4; let offset = dx * 4 + dy * 560 * 4;
if (hbs) { if (hbs) {
@ -530,22 +532,25 @@ export class HiresPageGL implements HiresPage {
} }
let bits = val; let bits = val;
for (let idx = 0; idx < 7; idx++, offset += 8) { for (let idx = 0; idx < 7; idx++, offset += 8) {
const drawPixel = cropLastPixel && idx == 6
? this._drawHalfPixel
: this._drawPixel;
if (bits & 0x01) { if (bits & 0x01) {
this._drawPixel(data, offset, whiteCol); drawPixel(data, offset, whiteCol);
} else { } else {
this._drawPixel(data, offset, blackCol); drawPixel(data, offset, blackCol);
} }
bits >>= 1; bits >>= 1;
} }
} if (!this._refreshing) {
}
if (!this._refreshing && !doubleHiresMode && bank === 0) {
this._refreshing = true; this._refreshing = true;
const after = addr + 1; const after = addr + 1;
this._write(after >> 8, after & 0xff, this._buffer[0][after & 0x1fff], 0); this._write(after >> 8, after & 0xff, this._buffer[0][after & 0x1fff], 0);
this._refreshing = false; this._refreshing = false;
} }
} }
}
}
refresh() { refresh() {
let addr = 0x2000 * this.page; let addr = 0x2000 * this.page;

View File

@ -49,6 +49,8 @@ type DiskCollection = {
[name: string]: DiskDescriptor[] [name: string]: DiskDescriptor[]
}; };
const KNOWN_FILE_TYPES = [...DISK_FORMATS, ...TAPE_TYPES] as readonly string[];
const disk_categories: DiskCollection = { 'Local Saves': [] }; const disk_categories: DiskCollection = { 'Local Saves': [] };
const disk_sets: DiskCollection = {}; const disk_sets: DiskCollection = {};
// Disk names // Disk names
@ -239,7 +241,7 @@ export function loadAjax(drive: DriveNumber, url: string) {
}); });
} }
export function doLoad() { export function doLoad(event: MouseEvent|KeyboardEvent) {
MicroModal.close('load-modal'); MicroModal.close('load-modal');
const select = document.querySelector<HTMLSelectElement>('#disk_select')!; const select = document.querySelector<HTMLSelectElement>('#disk_select')!;
const urls = select.value; const urls = select.value;
@ -255,7 +257,8 @@ export function doLoad() {
const localFile = document.querySelector<HTMLInputElement>('#local_file')!; const localFile = document.querySelector<HTMLInputElement>('#local_file')!;
const files = localFile.files; const files = localFile.files;
if (files && files.length == 1) { if (files && files.length == 1) {
doLoadLocal(_currentDrive, files[0]); const runOnLoad = event.shiftKey;
doLoadLocal(_currentDrive, files[0], { runOnLoad });
} else if (url) { } else if (url) {
let filename; let filename;
MicroModal.close('load-modal'); MicroModal.close('load-modal');
@ -316,9 +319,20 @@ function doLoadLocal(drive: DriveNumber, file: File, options: Partial<LoadOption
tape.doLoadLocalTape(file); tape.doLoadLocalTape(file);
} else if (BIN_TYPES.includes(ext) || type === '06' || options.address) { } else if (BIN_TYPES.includes(ext) || type === '06' || options.address) {
doLoadBinary(file, { address: parseInt(aux || '2000', 16), ...options }); doLoadBinary(file, { address: parseInt(aux || '2000', 16), ...options });
} else {
const addressInput = document.querySelector<HTMLInputElement>('#local_file_address');
const addressStr = addressInput?.value;
if (addressStr) {
const address = parseInt(addressStr, 16);
if (isNaN(address)) {
openAlert('Invalid address: ' + addressStr);
return;
}
doLoadBinary(file, { address, ...options });
} else { } else {
openAlert('Unknown file type: ' + ext); openAlert('Unknown file type: ' + ext);
} }
}
} }
function doLoadBinary(file: File, options: LoadOptions) { function doLoadBinary(file: File, options: LoadOptions) {
@ -523,7 +537,8 @@ export function reset() {
} }
function loadBinary(bin: JSONBinaryImage) { function loadBinary(bin: JSONBinaryImage) {
for (let idx = 0; idx < bin.length; idx++) { const maxLen = Math.min(bin.length, 0x10000 - bin.start);
for (let idx = 0; idx < maxLen; idx++) {
const pos = bin.start + idx; const pos = bin.start + idx;
cpu.write(pos, bin.data[idx]); cpu.write(pos, bin.data[idx]);
} }
@ -559,8 +574,8 @@ export function selectDisk() {
localFile.value = ''; localFile.value = '';
} }
export function clickDisk() { export function clickDisk(event: MouseEvent|KeyboardEvent) {
doLoad(); doLoad(event);
} }
/** Called to load disks from the local catalog. */ /** Called to load disks from the local catalog. */
@ -854,6 +869,22 @@ function onLoaded(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer:
_apple2.run(); _apple2.run();
}); });
} }
document.querySelector<HTMLInputElement>('#local_file')?.addEventListener(
'change',
(event: Event) => {
const target = event.target as HTMLInputElement;
const address = document.querySelector<HTMLInputElement>('#local_file_address_input')!;
const parts = target.value.split('.');
const ext = parts[parts.length - 1];
if (KNOWN_FILE_TYPES.includes(ext)) {
address.style.display = 'none';
} else {
address.style.display = 'inline-block';
}
}
);
} }
export function initUI(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer: Printer, e: boolean) { export function initUI(apple2: Apple2, disk2: DiskII, smartPort: SmartPort, printer: Printer, e: boolean) {