mirror of
https://github.com/pevans/erc-c.git
synced 2025-01-15 05:31:38 +00:00
Missing some reorg changes; move reflect into event, debug
This commit is contained in:
parent
74aafb0d01
commit
a913668c02
@ -8,8 +8,8 @@
|
||||
struct apple2;
|
||||
typedef struct apple2 apple2;
|
||||
|
||||
#include "apple2.dd.h"
|
||||
#include "mos6502.h"
|
||||
#include "apple2/dd.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "vm_bitfont.h"
|
||||
#include "vm_screen.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_BANK_H_
|
||||
#define _APPLE2_BANK_H_
|
||||
|
||||
#include "apple2.mem.h"
|
||||
#include "apple2/mem.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
extern SEGMENT_READER(apple2_bank_read);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_DBUF_H_
|
||||
#define _APPLE2_DBUF_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
extern SEGMENT_READER(apple2_dbuf_read);
|
||||
|
@ -12,7 +12,7 @@ typedef struct apple2dd apple2dd;
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_bits.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_DRAW_H_
|
||||
#define _APPLE2_DRAW_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_bits.h"
|
||||
|
||||
extern void apple2_draw(apple2 *);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_HIRES_H_
|
||||
#define _APPLE2_HIRES_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_bits.h"
|
||||
|
||||
extern void apple2_hires_draw(apple2 *, int);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_KB_H_
|
||||
#define _APPLE2_KB_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_screen.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_LORES_H_
|
||||
#define _APPLE2_LORES_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
|
||||
extern void apple2_lores_draw(apple2 *, size_t);
|
||||
extern vm_color apple2_lores_color(vm_8bit);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_MEM_H_
|
||||
#define _APPLE2_MEM_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_PC_H_
|
||||
#define _APPLE2_PC_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
extern SEGMENT_READER(apple2_pc_read);
|
||||
|
@ -1,13 +1,9 @@
|
||||
#ifndef _APPLE2_REFLECT_H_
|
||||
#define _APPLE2_REFLECT_H_
|
||||
|
||||
#include "vm_reflect.h"
|
||||
#include "vm_event.h"
|
||||
|
||||
extern void apple2_reflect_init();
|
||||
|
||||
extern REFLECT(apple2_reflect_cpu_info);
|
||||
extern REFLECT(apple2_reflect_disasm);
|
||||
extern REFLECT(apple2_reflect_machine_info);
|
||||
extern REFLECT(apple2_reflect_pause);
|
||||
extern void apple2_event_init();
|
||||
extern EVENT_DO(apple2_event_pause);
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_TESTS_H_
|
||||
#define _APPLE2_TESTS_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
static apple2 *mach = NULL;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _APPLE2_TEXT_H_
|
||||
#define _APPLE2_TEXT_H_
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_bitfont.h"
|
||||
#include "vm_bits.h"
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
#ifndef _MOS6502_DIS_H_
|
||||
#define _MOS6502_DIS_H_
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "vm_bits.h"
|
||||
|
||||
extern bool mos6502_dis_is_jump_label(int);
|
||||
extern int mos6502_dis_expected_bytes(int);
|
||||
extern int mos6502_dis_opcode(mos6502 *, FILE *, int);
|
||||
extern void mos6502_dis_instruction(char *, int, int);
|
||||
extern void mos6502_dis_jump_label(mos6502 *, vm_16bit, int, int);
|
||||
extern void mos6502_dis_jump_unlabel(int);
|
||||
extern void mos6502_dis_label(char *, int, int);
|
||||
extern void mos6502_dis_operand(mos6502 *, char *, int, int, int, vm_16bit);
|
||||
extern void mos6502_dis_scan(mos6502 *, FILE *, int, int);
|
||||
|
||||
#endif
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* mos6502.enums.h
|
||||
* Enums and other symbols for use with the mos 6502
|
||||
*
|
||||
* We have separated the definitions of address mode types, instruction
|
||||
* types, etc. into their own file so that we can include it in our main
|
||||
* source file, as well as from our unit test suite, without necessarily
|
||||
* adding them to the global namespace throughout the application.
|
||||
*/
|
||||
|
||||
#ifndef _MOS6502_ENUMS_H_
|
||||
#define _MOS6502_ENUMS_H_
|
||||
|
||||
/*
|
||||
* This defines all of the flags that are possible within the status (P)
|
||||
* register. Note that there is intentionally _no_ definition for the
|
||||
* 6th bit.
|
||||
*/
|
||||
enum status_flags {
|
||||
MOS_CARRY = 1,
|
||||
MOS_ZERO = 2,
|
||||
MOS_INTERRUPT = 4,
|
||||
MOS_DECIMAL = 8,
|
||||
MOS_BREAK = 16,
|
||||
MOS_OVERFLOW = 64,
|
||||
MOS_NEGATIVE = 128,
|
||||
};
|
||||
|
||||
#define MOS_NVZ (MOS_NEGATIVE | MOS_OVERFLOW | MOS_ZERO)
|
||||
#define MOS_NVZC (MOS_NEGATIVE | MOS_OVERFLOW | MOS_ZERO | MOS_CARRY)
|
||||
#define MOS_NZ (MOS_NEGATIVE | MOS_ZERO)
|
||||
#define MOS_NZC (MOS_NEGATIVE | MOS_ZERO | MOS_CARRY)
|
||||
#define MOS_ZC (MOS_ZERO | MOS_CARRY)
|
||||
|
||||
#define MOS_STATUS_DEFAULT (MOS_NEGATIVE | MOS_OVERFLOW | \
|
||||
MOS_INTERRUPT | MOS_ZERO | MOS_CARRY)
|
||||
|
||||
/*
|
||||
* Here we define the various address modes that are possible. These do
|
||||
* not map to any significant numbers that are documented for the 6502
|
||||
* processor; the position of these symbols don't really matter, and are
|
||||
* generally (except for `NOA`, no address mode) in alphabetical order.
|
||||
*/
|
||||
enum addr_mode {
|
||||
NOA, // no address mode
|
||||
ACC, // accumulator
|
||||
ABS, // absolute
|
||||
ABX, // absolute x-index
|
||||
ABY, // absolute y-index
|
||||
BY2, // Consume 2 bytes (for NP2)
|
||||
BY3, // Consume 3 bytes (for NP3)
|
||||
IMM, // immediate
|
||||
IMP, // implied
|
||||
IND, // indirect
|
||||
IDX, // x-index indirect
|
||||
IDY, // indirect y-index
|
||||
REL, // relative
|
||||
ZPG, // zero page
|
||||
ZPX, // zero page x-index
|
||||
ZPY, // zero page y-index
|
||||
};
|
||||
|
||||
/*
|
||||
* These define the various instructions as enum symbols; again, like
|
||||
* for address modes, the values of these enums are not actually
|
||||
* significant to the 6502 processor, and are only useful to we, the
|
||||
* programmers.
|
||||
*/
|
||||
enum instruction {
|
||||
ADC, // ADd with Carry
|
||||
AND, // bitwise AND
|
||||
ASL, // Arithmetic Shift Left
|
||||
BAD, // bad instruction
|
||||
BCC, // Branch on Carry Clear
|
||||
BCS, // Branch on Carry Set
|
||||
BEQ, // Branch on EQual to zero
|
||||
BIT, // BIT test
|
||||
BIM, // BIt test (imMediate mode) (* not a real instruction in the processor; just used by us)
|
||||
BMI, // Branch on MInus
|
||||
BNE, // Branch on Not Equal to zero
|
||||
BPL, // Branch on PLus
|
||||
BRA, // BRanch Always
|
||||
BRK, // BReaK (interrupt)
|
||||
BVC, // Branch on oVerflow Clear
|
||||
BVS, // Branch on oVerflow Set
|
||||
CLC, // CLear Carry
|
||||
CLD, // CLear Decimal
|
||||
CLI, // CLear Interrupt disable
|
||||
CLV, // CLear oVerflow
|
||||
CMP, // CoMPare
|
||||
CPX, // ComPare with X register
|
||||
CPY, // ComPare with Y register
|
||||
DEC, // DECrement
|
||||
DEX, // DEcrement X
|
||||
DEY, // DEcrement Y
|
||||
EOR, // Exclusive OR
|
||||
INC, // INCrement
|
||||
INX, // INcrement X
|
||||
INY, // INcrement Y
|
||||
JMP, // JuMP
|
||||
JSR, // Jump to SubRoutine
|
||||
LDA, // LoaD Accumulator
|
||||
LDX, // LoaD X
|
||||
LDY, // LoaD Y
|
||||
LSR, // Logical Shift Right
|
||||
NOP, // NO oPeration
|
||||
NP2, // No oPeration (2 bytes consumed)
|
||||
NP3, // No oPeration (3 bytes consumed)
|
||||
ORA, // OR with Accumulator
|
||||
PHA, // PusH Accumulator
|
||||
PHP, // PusH Predicate register
|
||||
PHX, // PusH X register
|
||||
PHY, // PusH Y register
|
||||
PLA, // PulL Accumulator
|
||||
PLP, // PulL Predicate register
|
||||
PLX, // PulL X register
|
||||
PLY, // PulL Y register
|
||||
ROL, // ROtate Left
|
||||
ROR, // ROtate Right
|
||||
RTI, // ReTurn from Interrupt
|
||||
RTS, // ReTurn from Subroutine
|
||||
SBC, // SuBtract with Carry
|
||||
SEC, // SEt Carry
|
||||
SED, // SEt Decimal
|
||||
SEI, // SEt Interrupt disable
|
||||
STA, // STore Accumulator
|
||||
STX, // STore X
|
||||
STY, // STore Y
|
||||
STZ, // STore Zero
|
||||
TAX, // Transfer Accumulator to X
|
||||
TAY, // Transfer Accumulator to Y
|
||||
TRB, // Test and Reset Bits
|
||||
TSB, // Test and Set Bits
|
||||
TSX, // Transfer Stack register to X
|
||||
TXA, // Transfer X to Accumulator
|
||||
TXS, // Transfer X to Stack register
|
||||
TYA, // Transfer Y to Accumulator
|
||||
};
|
||||
|
||||
#endif
|
@ -1,278 +0,0 @@
|
||||
#ifndef _MOS6502_H_
|
||||
#define _MOS6502_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "vm_bits.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
/*
|
||||
* The size of memory that the MOS 6502 supports is 64k (the limit of
|
||||
* values that a 16-bit address could possibly map to).
|
||||
*/
|
||||
#define MOS6502_MEMSIZE 65536
|
||||
|
||||
/*
|
||||
* This is a small macro to make it a bit simpler to set bytes ahead of
|
||||
* the PC register position; useful in testing.
|
||||
*/
|
||||
#define SET_PC_BYTE(cpu, off, byte) \
|
||||
mos6502_set(cpu, cpu->PC + off, byte)
|
||||
|
||||
/*
|
||||
* This macro is used to define new instruction handler functions.
|
||||
*/
|
||||
#define DEFINE_INST(inst) \
|
||||
void mos6502_handle_##inst (mos6502 *cpu, vm_8bit oper)
|
||||
|
||||
/*
|
||||
* In some address mode resolution, we must factor the carry bit into
|
||||
* the arithmetic we perform. In all those cases, if the carry bit is
|
||||
* set, we must only add 1 to the addition. The carry variable is,
|
||||
* therefore, the literal value we are adding, rather than a boolean
|
||||
* signifier.
|
||||
*/
|
||||
#define MOS_CARRY_BIT() \
|
||||
vm_8bit carry = 0; \
|
||||
if (cpu->P & MOS_CARRY) carry = 1
|
||||
|
||||
#define SET_RESULT(op) \
|
||||
int result = op
|
||||
|
||||
/*
|
||||
* A uniform way of declaring resolve functions for address modes, which
|
||||
* is useful in the event that we need to change the function signature.
|
||||
*/
|
||||
#define DECL_ADDR_MODE(x) \
|
||||
extern vm_8bit mos6502_resolve_##x (mos6502 *)
|
||||
|
||||
/*
|
||||
* Similarly, a uniform way of declaring instruction handler functions,
|
||||
* for the same reasons.
|
||||
*/
|
||||
#define DECL_INST(x) \
|
||||
extern void mos6502_handle_##x (mos6502 *, vm_8bit)
|
||||
|
||||
#define MOS_CHECK_Z(result) \
|
||||
cpu->P &= ~MOS_ZERO; \
|
||||
if ((vm_8bit)(result) == 0) cpu->P |= MOS_ZERO
|
||||
|
||||
#define MOS_CHECK_N(result) \
|
||||
cpu->P &= ~MOS_NEGATIVE; \
|
||||
if ((vm_8bit)(result) & 0x80) cpu->P |= MOS_NEGATIVE
|
||||
|
||||
#define MOS_CHECK_V(orig, result) \
|
||||
cpu->P &= ~MOS_OVERFLOW; \
|
||||
do { \
|
||||
vm_8bit r = result; \
|
||||
vm_8bit o = orig; \
|
||||
if ((o & 0x80) ^ (r & 0x80)) { \
|
||||
cpu->P |= MOS_OVERFLOW; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MOS_CHECK_NV(orig, result) \
|
||||
MOS_CHECK_N(result); \
|
||||
MOS_CHECK_V(orig, result)
|
||||
|
||||
#define MOS_CHECK_NZ(result) \
|
||||
MOS_CHECK_N(result); \
|
||||
MOS_CHECK_Z(result)
|
||||
|
||||
#define MOS_CHECK_NVZ(orig, result) \
|
||||
MOS_CHECK_N(result); \
|
||||
MOS_CHECK_V(orig, result); \
|
||||
MOS_CHECK_Z(result)
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* There are two different segment pointers for reading and writing,
|
||||
* because it's possible for there to be two different banks in
|
||||
* which an action occurs. These memory segments must be injected at
|
||||
* creation time, and can be changed later.
|
||||
*/
|
||||
vm_segment *rmem;
|
||||
vm_segment *wmem;
|
||||
|
||||
/*
|
||||
* This contains the _effective_ address we've resolved in one
|
||||
* of our address modes. In absolute mode, this would be the literal
|
||||
* operand we read from memory; in indirect mode, this will be the
|
||||
* address we _find_ after dereferencing the operand we read from
|
||||
* memory. Another way of thinking of this is, this address is where
|
||||
* we found the value we care about.
|
||||
*/
|
||||
vm_16bit eff_addr;
|
||||
|
||||
/*
|
||||
* These are the last opcode and last effective address that was
|
||||
* used in the instruction previous to the one currently being
|
||||
* executed. Some things (notably soft switches) may need to
|
||||
* the last opcode.
|
||||
*/
|
||||
vm_8bit last_opcode;
|
||||
vm_8bit last_operand;
|
||||
vm_16bit last_addr;
|
||||
|
||||
/*
|
||||
* Our program counter register; this is what we'll use to determine
|
||||
* where we're "at" in memory while executing opcodes. We use a
|
||||
* 16-bit register because our memory is 64k large.
|
||||
*/
|
||||
vm_16bit PC;
|
||||
|
||||
/*
|
||||
* This is the accumulator register. It's used in most arithmetic
|
||||
* operations, and anything like that which you need to do will end
|
||||
* up storing the value here.
|
||||
*/
|
||||
vm_8bit A;
|
||||
|
||||
/*
|
||||
* The X and Y registers are our index registers. They're provided
|
||||
* to aid looping over tables, but they can also be used for other
|
||||
* purposes.
|
||||
*/
|
||||
vm_8bit X, Y;
|
||||
|
||||
/*
|
||||
* The P register is our status flag register. (I presume 'P' means
|
||||
* 'predicate'.) Each bit stands for some kind of status.
|
||||
*/
|
||||
vm_8bit P;
|
||||
|
||||
/*
|
||||
* The S register is our stack counter register. It indicates how
|
||||
* far into the stack we've gone.
|
||||
*/
|
||||
vm_8bit S;
|
||||
} mos6502;
|
||||
|
||||
/*
|
||||
* This is a small convenience so that we don't need to expose the
|
||||
* somewhat regrettable syntax for function pointers to any main source
|
||||
* file
|
||||
*/
|
||||
typedef vm_8bit (*mos6502_address_resolver)(mos6502 *);
|
||||
|
||||
/*
|
||||
* Another convenience; this type definition is for the functions we
|
||||
* write to handle instruction logic.
|
||||
*/
|
||||
typedef void (*mos6502_instruction_handler)(mos6502 *, vm_8bit);
|
||||
|
||||
extern bool mos6502_would_jump(int);
|
||||
extern int mos6502_cycles(mos6502 *, vm_8bit);
|
||||
extern int mos6502_instruction(vm_8bit);
|
||||
extern mos6502 *mos6502_create(vm_segment *, vm_segment *);
|
||||
extern mos6502_instruction_handler mos6502_get_instruction_handler(vm_8bit);
|
||||
extern vm_16bit mos6502_get16(mos6502 *, size_t);
|
||||
extern vm_8bit mos6502_get(mos6502 *, size_t);
|
||||
extern vm_8bit mos6502_pop_stack(mos6502 *);
|
||||
extern void mos6502_execute(mos6502 *);
|
||||
extern void mos6502_free(mos6502 *);
|
||||
extern void mos6502_last_executed(mos6502 *, vm_8bit *, vm_8bit *, vm_16bit *);
|
||||
extern void mos6502_push_stack(mos6502 *, vm_8bit);
|
||||
extern void mos6502_set(mos6502 *, size_t, vm_8bit);
|
||||
extern void mos6502_set16(mos6502 *, size_t, vm_16bit);
|
||||
extern void mos6502_set_memory(mos6502 *, vm_segment *, vm_segment *);
|
||||
extern void mos6502_set_status(mos6502 *, vm_8bit);
|
||||
|
||||
/*
|
||||
* Below are some functions that are defined in mos6502.addr.c
|
||||
*/
|
||||
extern int mos6502_addr_mode(vm_8bit);
|
||||
extern mos6502_address_resolver mos6502_get_address_resolver(int);
|
||||
|
||||
/*
|
||||
* All of our address modes
|
||||
*/
|
||||
DECL_ADDR_MODE(acc);
|
||||
DECL_ADDR_MODE(abs);
|
||||
DECL_ADDR_MODE(abx);
|
||||
DECL_ADDR_MODE(aby);
|
||||
DECL_ADDR_MODE(imm);
|
||||
DECL_ADDR_MODE(ind);
|
||||
DECL_ADDR_MODE(idx);
|
||||
DECL_ADDR_MODE(idy);
|
||||
DECL_ADDR_MODE(rel);
|
||||
DECL_ADDR_MODE(zpg);
|
||||
DECL_ADDR_MODE(zpx);
|
||||
DECL_ADDR_MODE(zpy);
|
||||
|
||||
/*
|
||||
* And now, our instruction handlers; held generally in mos6502.*.c
|
||||
* (excepting mos6502.addr.c).
|
||||
*/
|
||||
DECL_INST(adc);
|
||||
DECL_INST(adc_dec);
|
||||
DECL_INST(and);
|
||||
DECL_INST(asl);
|
||||
DECL_INST(bad);
|
||||
DECL_INST(bcc);
|
||||
DECL_INST(bcs);
|
||||
DECL_INST(beq);
|
||||
DECL_INST(bit);
|
||||
DECL_INST(bim);
|
||||
DECL_INST(bmi);
|
||||
DECL_INST(bne);
|
||||
DECL_INST(bpl);
|
||||
DECL_INST(bra);
|
||||
DECL_INST(brk);
|
||||
DECL_INST(bvc);
|
||||
DECL_INST(bvs);
|
||||
DECL_INST(clc);
|
||||
DECL_INST(cld);
|
||||
DECL_INST(cli);
|
||||
DECL_INST(clv);
|
||||
DECL_INST(cmp);
|
||||
DECL_INST(cpx);
|
||||
DECL_INST(cpy);
|
||||
DECL_INST(dec);
|
||||
DECL_INST(dex);
|
||||
DECL_INST(dey);
|
||||
DECL_INST(eor);
|
||||
DECL_INST(inc);
|
||||
DECL_INST(inx);
|
||||
DECL_INST(iny);
|
||||
DECL_INST(jmp);
|
||||
DECL_INST(jsr);
|
||||
DECL_INST(lda);
|
||||
DECL_INST(ldx);
|
||||
DECL_INST(ldy);
|
||||
DECL_INST(lsr);
|
||||
DECL_INST(nop);
|
||||
DECL_INST(np2);
|
||||
DECL_INST(np3);
|
||||
DECL_INST(ora);
|
||||
DECL_INST(pha);
|
||||
DECL_INST(php);
|
||||
DECL_INST(phx);
|
||||
DECL_INST(phy);
|
||||
DECL_INST(pla);
|
||||
DECL_INST(plp);
|
||||
DECL_INST(plx);
|
||||
DECL_INST(ply);
|
||||
DECL_INST(rol);
|
||||
DECL_INST(ror);
|
||||
DECL_INST(rti);
|
||||
DECL_INST(rts);
|
||||
DECL_INST(sbc);
|
||||
DECL_INST(sbc_dec);
|
||||
DECL_INST(sec);
|
||||
DECL_INST(sed);
|
||||
DECL_INST(sei);
|
||||
DECL_INST(sta);
|
||||
DECL_INST(stx);
|
||||
DECL_INST(sty);
|
||||
DECL_INST(stz);
|
||||
DECL_INST(tax);
|
||||
DECL_INST(tay);
|
||||
DECL_INST(trb);
|
||||
DECL_INST(tsb);
|
||||
DECL_INST(tsx);
|
||||
DECL_INST(txa);
|
||||
DECL_INST(txs);
|
||||
DECL_INST(tya);
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
#ifndef _MOS6502_TESTS_H
|
||||
#define _MOS6502_TESTS_H
|
||||
|
||||
static mos6502 *cpu;
|
||||
static vm_segment *mem;
|
||||
|
||||
static void
|
||||
setup()
|
||||
{
|
||||
mem = vm_segment_create(MOS6502_MEMSIZE);
|
||||
cpu = mos6502_create(mem, mem);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown()
|
||||
{
|
||||
mos6502_free(cpu);
|
||||
vm_segment_free(mem);
|
||||
}
|
||||
|
||||
#endif
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "apple2.mem.h"
|
||||
#include "apple2/mem.h"
|
||||
#include "vm_bits.h"
|
||||
|
||||
typedef struct {
|
||||
|
@ -7,6 +7,13 @@ enum vm_di_entry {
|
||||
VM_REFLECT,
|
||||
VM_OUTPUT,
|
||||
|
||||
// This is a function which can be used to pause the running machine
|
||||
VM_PAUSE_FUNC,
|
||||
|
||||
// This function will both 1) pause the machine, and 2) open the
|
||||
// debugger
|
||||
VM_DEBUG_FUNC,
|
||||
|
||||
// These are the physical width and height of the emulator window
|
||||
VM_WIDTH,
|
||||
VM_HEIGHT,
|
||||
|
@ -8,9 +8,15 @@ typedef struct {
|
||||
vm_screen *screen;
|
||||
} vm_event;
|
||||
|
||||
typedef void (*vm_event_fn) (void *);
|
||||
|
||||
#define EVENT_DO(x) \
|
||||
void x(void *_mach)
|
||||
|
||||
extern int vm_event_do(int);
|
||||
extern void vm_event_keyboard(vm_event *);
|
||||
extern void vm_event_poll(vm_screen *);
|
||||
extern void vm_event_keyboard_normal(vm_event *, char);
|
||||
extern void vm_event_keyboard_special(vm_event *, char);
|
||||
extern void vm_event_poll(vm_screen *);
|
||||
|
||||
#endif
|
||||
|
@ -1,28 +1,28 @@
|
||||
set(erc_sources
|
||||
apple2.c
|
||||
apple2.bank.c
|
||||
apple2.dbuf.c
|
||||
apple2.dd.c
|
||||
apple2.dec.c
|
||||
apple2.draw.c
|
||||
apple2.enc.c
|
||||
apple2.hires.c
|
||||
apple2.kb.c
|
||||
apple2.lores.c
|
||||
apple2.mem.c
|
||||
apple2.pc.c
|
||||
apple2.reflect.c
|
||||
apple2.text.c
|
||||
apple2/apple2.c
|
||||
apple2/bank.c
|
||||
apple2/dbuf.c
|
||||
apple2/dd.c
|
||||
apple2/dec.c
|
||||
apple2/draw.c
|
||||
apple2/enc.c
|
||||
apple2/hires.c
|
||||
apple2/kb.c
|
||||
apple2/lores.c
|
||||
apple2/mem.c
|
||||
apple2/pc.c
|
||||
apple2/reflect.c
|
||||
apple2/text.c
|
||||
log.c
|
||||
mos6502.c
|
||||
mos6502.addr.c
|
||||
mos6502.arith.c
|
||||
mos6502.bits.c
|
||||
mos6502.branch.c
|
||||
mos6502.dis.c
|
||||
mos6502.exec.c
|
||||
mos6502.loadstor.c
|
||||
mos6502.stat.c
|
||||
mos6502/mos6502.c
|
||||
mos6502/addr.c
|
||||
mos6502/arith.c
|
||||
mos6502/bits.c
|
||||
mos6502/branch.c
|
||||
mos6502/dis.c
|
||||
mos6502/exec.c
|
||||
mos6502/loadstor.c
|
||||
mos6502/stat.c
|
||||
objstore.c
|
||||
option.c
|
||||
vm_area.c
|
||||
|
@ -8,11 +8,11 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.draw.h"
|
||||
#include "apple2.mem.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502.dis.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/draw.h"
|
||||
#include "apple2/mem.h"
|
||||
#include "mos6502/enums.h"
|
||||
#include "mos6502/dis.h"
|
||||
#include "objstore.h"
|
||||
#include "option.h"
|
||||
#include "vm_debug.h"
|
||||
|
@ -13,9 +13,9 @@
|
||||
* Are you confused yet? Keep reading!
|
||||
*/
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.bank.h"
|
||||
#include "apple2.mem.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/bank.h"
|
||||
#include "apple2/mem.h"
|
||||
#include "objstore.h"
|
||||
|
||||
/*
|
||||
|
@ -8,8 +8,8 @@
|
||||
* when writes do happen.
|
||||
*/
|
||||
|
||||
#include "apple2.dbuf.h"
|
||||
#include "apple2.draw.h"
|
||||
#include "apple2/dbuf.h"
|
||||
#include "apple2/draw.h"
|
||||
#include "vm_reflect.h"
|
||||
|
||||
static size_t switch_reads[] = {
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "apple2.dd.h"
|
||||
#include "apple2.dec.h"
|
||||
#include "apple2.enc.h"
|
||||
#include "apple2.h"
|
||||
#include "apple2/dd.h"
|
||||
#include "apple2/dec.h"
|
||||
#include "apple2/enc.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "vm_di.h"
|
||||
#include "vm_reflect.h"
|
||||
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "apple2.dd.h"
|
||||
#include "apple2.dec.h"
|
||||
#include "apple2.enc.h"
|
||||
#include "apple2/dd.h"
|
||||
#include "apple2/dec.h"
|
||||
#include "apple2/enc.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
/*
|
||||
|
@ -6,10 +6,10 @@
|
||||
* further into development.
|
||||
*/
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.hires.h"
|
||||
#include "apple2.lores.h"
|
||||
#include "apple2.text.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/hires.h"
|
||||
#include "apple2/lores.h"
|
||||
#include "apple2/text.h"
|
||||
|
||||
/*
|
||||
* Draw a pixel on screen at the given address.
|
||||
|
@ -11,8 +11,8 @@
|
||||
* is _crazy_. Hence the crazy code below.
|
||||
*/
|
||||
|
||||
#include "apple2.enc.h"
|
||||
#include "apple2.dd.h"
|
||||
#include "apple2/enc.h"
|
||||
#include "apple2/dd.h"
|
||||
#include "vm_segment.h"
|
||||
|
||||
/*
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "apple2.hires.h"
|
||||
#include "apple2.text.h"
|
||||
#include "apple2/hires.h"
|
||||
#include "apple2/text.h"
|
||||
|
||||
enum hires_color {
|
||||
HIRES_GREEN,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* to determine if you've read last key pressed before or not).
|
||||
*/
|
||||
|
||||
#include "apple2.kb.h"
|
||||
#include "apple2/kb.h"
|
||||
|
||||
/*
|
||||
* This mapper is considerably simpler than most, because it handles
|
||||
|
@ -13,9 +13,9 @@
|
||||
* would have been rendered in full graphical mode will be skipped.
|
||||
*/
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.lores.h"
|
||||
#include "apple2.text.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/lores.h"
|
||||
#include "apple2/text.h"
|
||||
|
||||
/*
|
||||
* These are the color codes for the lo-res colors that are available.
|
||||
|
@ -7,13 +7,13 @@
|
||||
* right! FIXME: we should break this file up into smaller parts.
|
||||
*/
|
||||
|
||||
#include "apple2.bank.h"
|
||||
#include "apple2.dbuf.h"
|
||||
#include "apple2.dd.h"
|
||||
#include "apple2.h"
|
||||
#include "apple2.kb.h"
|
||||
#include "apple2.mem.h"
|
||||
#include "apple2.pc.h"
|
||||
#include "apple2/bank.h"
|
||||
#include "apple2/dbuf.h"
|
||||
#include "apple2/dd.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/kb.h"
|
||||
#include "apple2/mem.h"
|
||||
#include "apple2/pc.h"
|
||||
#include "objstore.h"
|
||||
|
||||
static size_t switch_reads[] = {
|
||||
|
@ -7,7 +7,7 @@
|
||||
* (apple2.dd.c).
|
||||
*/
|
||||
|
||||
#include "apple2.pc.h"
|
||||
#include "apple2/pc.h"
|
||||
|
||||
static size_t switch_reads[] = {
|
||||
0xC015,
|
||||
|
@ -5,9 +5,8 @@
|
||||
* apple2 machine is being emulated.
|
||||
*/
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.reflect.h"
|
||||
#include "mos6502.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/reflect.h"
|
||||
#include "vm_di.h"
|
||||
|
||||
/*
|
||||
@ -15,59 +14,19 @@
|
||||
* all of the reflect methods we may want to use.
|
||||
*/
|
||||
void
|
||||
apple2_reflect_init()
|
||||
apple2_event_init()
|
||||
{
|
||||
vm_reflect *ref = (vm_reflect *)vm_di_get(VM_REFLECT);
|
||||
|
||||
ref->cpu_info = apple2_reflect_cpu_info;
|
||||
ref->machine_info = apple2_reflect_machine_info;
|
||||
ref->pause = apple2_reflect_pause;
|
||||
ref->disasm = apple2_reflect_disasm;
|
||||
vm_di_set(VM_PAUSE_FUNC, apple2_event_pause);
|
||||
}
|
||||
|
||||
/*
|
||||
* Show some information about the CPU registers.
|
||||
*/
|
||||
REFLECT(apple2_reflect_cpu_info)
|
||||
EVENT_DO(apple2_event_pause)
|
||||
{
|
||||
mos6502 *cpu = (mos6502 *)vm_di_get(VM_CPU);
|
||||
FILE *out = (FILE *)vm_di_get(VM_OUTPUT);
|
||||
|
||||
fprintf(out, "CPU: A:%02x X:%02x Y:%02x P:%02x S:%02x PC:%04x\n",
|
||||
cpu->A, cpu->X, cpu->Y, cpu->P, cpu->S, cpu->PC);
|
||||
apple2 *mach = (apple2 *)_mach;
|
||||
mach->paused = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Show information about the apple2 machine--mostly some of the
|
||||
* metadata variables, like what the bank switch status is, or what
|
||||
* memory mode we're in.
|
||||
*/
|
||||
REFLECT(apple2_reflect_machine_info)
|
||||
EVENT_DO(apple2_event_debug)
|
||||
{
|
||||
apple2 *mach = (apple2 *)vm_di_get(VM_MACHINE);
|
||||
FILE *out = (FILE *)vm_di_get(VM_OUTPUT);
|
||||
|
||||
fprintf(out, "MACH: BS:%02x CM:%02x DM:%02x MM:%02x STROBE:%02x\n",
|
||||
mach->bank_switch, mach->color_mode, mach->display_mode,
|
||||
mach->memory_mode, mach->strobe);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are paused, we will unpause; if we are not paused, we will
|
||||
* pause.
|
||||
*/
|
||||
REFLECT(apple2_reflect_pause)
|
||||
{
|
||||
apple2 *mach = (apple2 *)vm_di_get(VM_MACHINE);
|
||||
mach->paused = !mach->paused;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable disassembly output, toggling from one state to the
|
||||
* other for each invocation.
|
||||
*/
|
||||
REFLECT(apple2_reflect_disasm)
|
||||
{
|
||||
apple2 *mach = (apple2 *)vm_di_get(VM_MACHINE);
|
||||
mach->disasm = !mach->disasm;
|
||||
apple2 *mach = (apple2 *)_mach;
|
||||
mach->paused = true;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "apple2.text.h"
|
||||
#include "apple2/text.h"
|
||||
|
||||
/*
|
||||
* This table maps display buffer addresses for 40-column text to the
|
||||
|
@ -11,9 +11,9 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.draw.h"
|
||||
#include "apple2.reflect.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/draw.h"
|
||||
#include "apple2/reflect.h"
|
||||
#include "log.h"
|
||||
#include "option.h"
|
||||
#include "vm_di.h"
|
||||
@ -120,7 +120,7 @@ main(int argc, char **argv)
|
||||
ref = vm_reflect_create();
|
||||
vm_di_set(VM_REFLECT, ref);
|
||||
|
||||
apple2_reflect_init();
|
||||
apple2_event_init();
|
||||
|
||||
// Ok, it's time to boot this up!
|
||||
err = apple2_boot(mach);
|
||||
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* mos6502.branch.c
|
||||
*
|
||||
* This is all the logic we use for branch instructions, which are used
|
||||
* for conditional expressions.
|
||||
*/
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
|
||||
/*
|
||||
* This is just a minor convenience macro to wrap the logic we use in
|
||||
* branch situations, which is if `cond` is true, then we set the
|
||||
* program counter to the last effective address.
|
||||
*/
|
||||
#define JUMP_IF(cond) \
|
||||
if (cond) cpu->PC = cpu->eff_addr; else cpu->PC += 2
|
||||
|
||||
/*
|
||||
* Branch if the carry flag is clear.
|
||||
*/
|
||||
DEFINE_INST(bcc)
|
||||
{
|
||||
JUMP_IF(~cpu->P & MOS_CARRY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if carry is set.
|
||||
*/
|
||||
DEFINE_INST(bcs)
|
||||
{
|
||||
JUMP_IF(cpu->P & MOS_CARRY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the zero flag is set (that is, if our last instruction
|
||||
* resulted in something being _equal to zero_).
|
||||
*/
|
||||
DEFINE_INST(beq)
|
||||
{
|
||||
JUMP_IF(cpu->P & MOS_ZERO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the negative ("minus") flag is set.
|
||||
*/
|
||||
DEFINE_INST(bmi)
|
||||
{
|
||||
JUMP_IF(cpu->P & MOS_NEGATIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the zero flag is not set; which is to say, that the last
|
||||
* operation was _not equal_ to zero.
|
||||
*/
|
||||
DEFINE_INST(bne)
|
||||
{
|
||||
JUMP_IF(~cpu->P & MOS_ZERO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the negative flag is not set (meaning the last operation
|
||||
* was "plus", which includes zero).
|
||||
*/
|
||||
DEFINE_INST(bpl)
|
||||
{
|
||||
JUMP_IF(~cpu->P & MOS_NEGATIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This instruction will branch in all cases. It's not a true
|
||||
* conditional; it's analagous to a relative address mode JMP.
|
||||
*/
|
||||
DEFINE_INST(bra)
|
||||
{
|
||||
// Always jump!
|
||||
JUMP_IF(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the overflow bit is clear.
|
||||
*/
|
||||
DEFINE_INST(bvc)
|
||||
{
|
||||
JUMP_IF(~cpu->P & MOS_OVERFLOW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch if the overflow bit is set.
|
||||
*/
|
||||
DEFINE_INST(bvs)
|
||||
{
|
||||
JUMP_IF(cpu->P & MOS_OVERFLOW);
|
||||
}
|
@ -9,8 +9,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* This is a table of all the possible opcodes the 6502 understands,
|
||||
|
@ -5,8 +5,8 @@
|
||||
* processor.
|
||||
*/
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* The adc instruction will add a number to the accumulator, "with
|
||||
|
@ -5,8 +5,8 @@
|
||||
* specifically on bits of values.
|
||||
*/
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* The and instruction will assign the bitwise-and of the accumulator
|
||||
|
@ -26,9 +26,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.dis.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/dis.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
static char s_bytes[10],
|
||||
s_inst[4],
|
||||
|
@ -6,8 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* Log the attempt to execute a "bad" (which is to say, _undefined_)
|
||||
|
@ -5,8 +5,8 @@
|
||||
* various registers and places in memory.
|
||||
*/
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* The LDA instruction will assign ("load") an operand into the
|
||||
|
@ -12,12 +12,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.dis.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/dis.h"
|
||||
#include "vm_debug.h"
|
||||
|
||||
// All of our address modes, instructions, etc. are defined here.
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* This is a table which defines what instruction each opcode is mapped
|
||||
|
@ -5,8 +5,8 @@
|
||||
* directly modify the status (P) register.
|
||||
*/
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.enums.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/enums.h"
|
||||
|
||||
/*
|
||||
* Clear the carry bit in the status register.
|
||||
|
@ -9,10 +9,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "apple2.h"
|
||||
#include "apple2.hires.h"
|
||||
#include "mos6502.h"
|
||||
#include "mos6502.dis.h"
|
||||
#include "apple2/apple2.h"
|
||||
#include "apple2/hires.h"
|
||||
#include "mos6502/mos6502.h"
|
||||
#include "mos6502/dis.h"
|
||||
#include "vm_debug.h"
|
||||
#include "vm_di.h"
|
||||
#include "vm_reflect.h"
|
||||
@ -335,8 +335,16 @@ DEBUG_CMD(resume)
|
||||
*/
|
||||
DEBUG_CMD(printstate)
|
||||
{
|
||||
vm_reflect_cpu_info(NULL);
|
||||
vm_reflect_machine_info(NULL);
|
||||
apple2 *mach = (apple2 *)vm_di_get(VM_MACHINE);
|
||||
mos6502 *cpu = mach->cpu;
|
||||
FILE *out = (FILE *)vm_di_get(VM_OUTPUT);
|
||||
|
||||
fprintf(out, "CPU: A:%02x X:%02x Y:%02x P:%02x S:%02x PC:%04x\n",
|
||||
cpu->A, cpu->X, cpu->Y, cpu->P, cpu->S, cpu->PC);
|
||||
|
||||
fprintf(out, "MACH: BS:%02x CM:%02x DM:%02x MM:%02x STROBE:%02x\n",
|
||||
mach->bank_switch, mach->color_mode, mach->display_mode,
|
||||
mach->memory_mode, mach->strobe);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7,6 +7,8 @@
|
||||
* mouse events, and more.
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
#include "vm_di.h"
|
||||
#include "vm_event.h"
|
||||
#include "vm_reflect.h"
|
||||
|
||||
@ -107,18 +109,29 @@ vm_event_keyboard_special(vm_event *ev, char ch)
|
||||
ev->screen->should_exit = true;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
vm_reflect_cpu_info(NULL);
|
||||
vm_reflect_machine_info(NULL);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
vm_reflect_pause(NULL);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
vm_reflect_disasm(NULL);
|
||||
vm_event_do(VM_PAUSE_FUNC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a DI identifier, assume that we have registered a function that
|
||||
* does something with the also-registered machine object. If the result
|
||||
* of the lookup from difunc is NULL, return ERR_INVALID; otherwise,
|
||||
* execute the function and return OK.
|
||||
*/
|
||||
int
|
||||
vm_event_do(int difunc)
|
||||
{
|
||||
vm_event_fn func = (vm_event_fn)vm_di_get(difunc);
|
||||
void *mach = vm_di_get(VM_MACHINE);
|
||||
|
||||
if (func == NULL) {
|
||||
return ERR_INVALID;
|
||||
}
|
||||
|
||||
func(mach);
|
||||
return OK;
|
||||
}
|
||||
|
21
tools/write-table
Executable file
21
tools/write-table
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
def map400(frm, off):
|
||||
row = off
|
||||
written = 0
|
||||
per_row = 0
|
||||
for addr in range(frm, frm + 0x400):
|
||||
sys.stdout.write("{0:>4d}, ".format(row))
|
||||
per_row += 1
|
||||
written += 1
|
||||
|
||||
if per_row == 40:
|
||||
row += 1
|
||||
per_row = 0
|
||||
|
||||
if written % 16 == 0:
|
||||
sys.stdout.write("${0:04X}\n".format(frm + written - 16))
|
||||
|
||||
map400(0x2000, 0)
|
Loading…
x
Reference in New Issue
Block a user